mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-09 10:47:27 +00:00
Merge pull request #5619 from dotCooCoo/fix/touch-type-upright-vertical-move
Type: Touch Type moves an upright character in vertical type down and across its column
This commit is contained in:
@@ -58,7 +58,8 @@ struct CharBox {
|
||||
pivot: Point,
|
||||
/// A unit vector along its line in reading order.
|
||||
along: Vec2,
|
||||
/// A unit vector up from its line, without its rotation: the way baseline shift moves it.
|
||||
/// A unit vector up from its line, without its rotation: the way baseline shift moves it. For
|
||||
/// a glyph standing upright in vertical type, the line's cross axis (right of its column).
|
||||
up: Vec2,
|
||||
/// The glyph's own x axis and its up axis (with its rotation), unit vectors.
|
||||
ex: Vec2,
|
||||
@@ -174,6 +175,11 @@ fn char_box(t: &TextObject, lay: &TextLayout, gi: usize) -> Option<CharBox> {
|
||||
}
|
||||
let quad = [m * Point::new(x0, y0), m * Point::new(x1, y0), m * Point::new(x1, y1), m * Point::new(x0, y1)];
|
||||
let d = Vec2::new(g.angle.cos(), g.angle.sin());
|
||||
// Up from the glyph's frame without its rotation. For a glyph standing upright in vertical
|
||||
// type, that up runs along the column, so the glyph takes the line's cross axis instead: the
|
||||
// way baseline shift moves the column's sideways glyphs.
|
||||
let up = unit(linear(m * g.unturned, Vec2::new(0.0, -1.0)));
|
||||
let up = if d.cross(up).abs() > 1e-6 { up } else { Vec2::new(d.y, -d.x) };
|
||||
let style = edit::slice_runs(&t.runs, g.byte, g.byte + g.len).first().map(|r| r.style.clone())?;
|
||||
Some(CharBox {
|
||||
start: g.byte,
|
||||
@@ -181,7 +187,7 @@ fn char_box(t: &TextObject, lay: &TextLayout, gi: usize) -> Option<CharBox> {
|
||||
pen,
|
||||
pivot: m * g.pivot,
|
||||
along: if g.rtl { -d } else { d },
|
||||
up: unit(linear(m * g.unturned, Vec2::new(0.0, -1.0))),
|
||||
up,
|
||||
ex,
|
||||
ey,
|
||||
kerned: lay.glyphs.iter().any(|h| h.line == g.line && h.len > 0 && h.byte + h.len == g.byte && h.rtl == g.rtl),
|
||||
|
||||
@@ -176,6 +176,35 @@ fn a_character_rotated_near_a_quarter_turn_moves_across_its_line() {
|
||||
}
|
||||
}
|
||||
|
||||
/// In vertical type, a character standing upright (§) still splits a drag into kerning down its
|
||||
/// column and baseline shift across it: down 10 pt and right 4 pt is `dx` 10 and `dy` 4. Every
|
||||
/// arrow key nudges it.
|
||||
#[test]
|
||||
fn an_upright_character_in_vertical_type_moves_down_and_across_its_column() {
|
||||
let (mut d, id, s) = doc_with_type();
|
||||
if let Some(NodeKind::Text(t)) = d.node_mut(id).map(|n| &mut n.kind) {
|
||||
**t = TextObject::point(Point::new(100.0, 200.0), "l§", CharStyle { size: 40.0, ..Default::default() });
|
||||
t.vertical = true;
|
||||
}
|
||||
let p = paint();
|
||||
let cx = cx(&d, &s, &p);
|
||||
let mut t = TouchTypeTool { target: Some((id, 1)), ..Default::default() };
|
||||
let q = quad(&t, &cx);
|
||||
let at = q[0].midpoint(q[2]);
|
||||
let acts = drag(&mut t, &cx, at, at + Vec2::new(4.0, 10.0));
|
||||
let p1 = preview(&acts[1]);
|
||||
assert!(close(p1["dx"].as_f64().unwrap_or(0.0), 10.0) && close(p1["dy"].as_f64().unwrap_or(0.0), 4.0), "{p1}");
|
||||
for key in [ToolKey::Up, ToolKey::Down, ToolKey::Left, ToolKey::Right] {
|
||||
let acts = t.key(&cx, key, Mods::default());
|
||||
let moved = match acts.first() {
|
||||
Some(Action::Exec(c, v)) if c == "text.touchType" => v,
|
||||
other => panic!("{key:?}: {other:?}"),
|
||||
};
|
||||
let parts = [&moved["dx"], &moved["dy"]].map(|v| v.as_f64().unwrap_or(0.0).abs());
|
||||
assert!(close(parts[0] + parts[1], 1.0) && (close(parts[0], 0.0) || close(parts[1], 0.0)), "{key:?}: {moved}");
|
||||
}
|
||||
}
|
||||
|
||||
/// In type scaled unevenly, a drag's parts are measured in document points: right 10 pt and up 4
|
||||
/// pt of a quarter-turned character is `dx` 10 and `dy` 4.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user