mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 04:57:54 -06:00
Text: right-to-left point text with a justified paragraph sits flush right, as After Effects
After Effects 2026 lays out right-to-left point text whose paragraph carries a justified code (justify last left / centre / right, justify all) flush at its start, the right, like right-aligned text (EXPORTER read-back t7: point rows with codes 3-6 at -152..-8 from the anchor). EffectCraft placed it by the last-line side (left / centre / left). Left-to-right point text and box text are unchanged; AE's slightly wider right-to-left box wrapping (1-2 px narrower word gaps) stays open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8bc57bc7ad
commit
83b134cdc8
@@ -635,7 +635,11 @@ fn paragraph(text: &str, base: usize, runs: &[(Range<usize>, TextStyle)], primar
|
||||
first_ascent(primaries[si].face, st.size).unwrap_or_else(|| fonts::face(primaries[si].face).metrics(st.size).ascent)
|
||||
};
|
||||
let eff_align = |last: bool| -> Align {
|
||||
if (last || width.is_none()) && para.align == Align::Justify {
|
||||
if rtl_para && width.is_none() && para.align == Align::Justify {
|
||||
// Right-to-left point text with a justified paragraph sits flush at its start, the
|
||||
// right (After Effects 2026, every justify code; left-to-right not measured).
|
||||
Align::Right
|
||||
} else if (last || width.is_none()) && para.align == Align::Justify {
|
||||
if width.is_none() && para.justify_last == Align::Justify { Align::Left } else { para.justify_last }
|
||||
} else {
|
||||
para.align
|
||||
@@ -1499,6 +1503,25 @@ mod tests {
|
||||
assert!(r.lines[0].x + r.lines[0].width > 401.0, "closing quote hangs right");
|
||||
}
|
||||
|
||||
/// After Effects 2026 (EXPORTER read-back t7): right-to-left point text with any justified
|
||||
/// code (justify last left / centre / right, justify all) sits flush right at its anchor, as
|
||||
/// right-aligned text does.
|
||||
#[test]
|
||||
fn rtl_point_text_with_a_justified_paragraph_is_flush_at_its_start() {
|
||||
let text = "Right to left";
|
||||
let s = st(30.0);
|
||||
let at = |align: Align, last: Align| {
|
||||
let p = ParagraphStyle { align, justify_last: last, rtl: Some(true), ..Default::default() };
|
||||
let l = layout_rich_uncached(text, &[(0..text.len(), s.clone())], &[p]);
|
||||
(l.lines[0].x, l.lines[0].x + l.lines[0].width)
|
||||
};
|
||||
let right = at(Align::Right, Align::Left);
|
||||
for last in [Align::Left, Align::Center, Align::Right, Align::Justify] {
|
||||
let got = at(Align::Justify, last);
|
||||
assert!((got.0 - right.0).abs() < 1e-3 && (got.1 - right.1).abs() < 1e-3, "{last:?}: {got:?} vs right-aligned {right:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rtl_paragraph_carets_run_right_to_left() {
|
||||
let text = "\u{5d0}\u{5d1}\u{5d2}";
|
||||
|
||||
@@ -80,6 +80,16 @@ every-line composer ignored the last line's slack and left "twelve" alone on a s
|
||||
counts that slack for Justify All, and every word starts within 1 px of AE's. Regression test:
|
||||
`justify_all_balances_the_lines_with_the_every_line_composer`.
|
||||
|
||||
## Right-to-left point text with a justified paragraph
|
||||
|
||||
Measured on 19 October 2026 with After Effects 2026 (26.2) (EXPORTER read-back t7): right-to-left
|
||||
point text whose paragraph has a justified code (justify last left / centre / right, justify all)
|
||||
sits flush right at its anchor, like right-aligned text. EffectCraft placed it by the last-line
|
||||
side (left / centre / left). Now flush right; left-to-right point text is unchanged (not measured).
|
||||
Regression test: `rtl_point_text_with_a_justified_paragraph_is_flush_at_its_start`. Still open:
|
||||
AE wraps right-to-left box text slightly wider (its word gaps are 1–2 px narrower than in
|
||||
left-to-right text with the same font), so a 300 px box fits a word more per line.
|
||||
|
||||
## Still unmeasured
|
||||
|
||||
Rendered frame comparisons now have a deterministic `effectcraft_effects::fidelity::compare_frames`
|
||||
|
||||
Reference in New Issue
Block a user