mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 21:16:52 -06:00
Merge pull request #1822 from kk376/fix/text-animator-tracking-pixels
fix(render): use pixel units for text animator tracking amount
This commit is contained in:
@@ -42,7 +42,7 @@ pub struct CharXf {
|
||||
pub stroke_hsb: [f64; 3],
|
||||
pub stroke_opacity: f64,
|
||||
pub stroke_width: f64,
|
||||
/// Tracking (1/1000 em) added before / after the character.
|
||||
/// Tracking (pixels) added before / after the character.
|
||||
pub track_before: f64,
|
||||
pub track_after: f64,
|
||||
/// Line Anchor (percent) and the selection weight it was set with.
|
||||
@@ -694,10 +694,9 @@ pub fn text_geom(ctx: &EvalCtx, layer: &Layer) -> Option<TextGeom> {
|
||||
let (mut la, mut la_k) = (50.0 * f64::from(align_index(justify)), 0.0);
|
||||
for gi in li_start..li_end {
|
||||
let x = &xfs[gi];
|
||||
let em = lay.styles.get(lay.glyphs[gi].run).map_or(doc.size, |s| s.size) / 1000.0;
|
||||
pen += x.track_before * em;
|
||||
pen += x.track_before;
|
||||
shift[gi] = pen;
|
||||
pen += x.track_after * em + vadv[gi];
|
||||
pen += x.track_after + vadv[gi];
|
||||
if x.line_anchor_k > la_k {
|
||||
la = x.line_anchor;
|
||||
la_k = x.line_anchor_k;
|
||||
|
||||
@@ -220,9 +220,9 @@ fn tracking_line_anchor_and_character_offset() {
|
||||
animator(&mut p, &mut l, &["tracking", "lineAnchor"], &["range"]);
|
||||
p.comp_mut(cid).unwrap().layers.push(l);
|
||||
let w0 = bounds_of(&glyph_paths(&ctx(&p, cid, 0.0), &p.comp(cid).unwrap().layers[0]));
|
||||
set(&mut p.comp_mut(cid).unwrap().layers[0], "text/animators/#1/properties/tracking", Value::Scalar(500.0));
|
||||
set(&mut p.comp_mut(cid).unwrap().layers[0], "text/animators/#1/properties/tracking", Value::Scalar(20.0));
|
||||
let w1 = bounds_of(&glyph_paths(&ctx(&p, cid, 0.0), &p.comp(cid).unwrap().layers[0]));
|
||||
// 4 chars × 500/1000 em × 40 px: the last glyph moves ~ 3.5 × 20 px further (before & after).
|
||||
// 4 chars with 20 px tracking: the last glyph moves ~ 3.5 × 20 px further (before & after).
|
||||
assert!((w1.width() - w0.width() - 3.0 * 20.0).abs() < 1.5, "{} {}", w0.width(), w1.width());
|
||||
assert!((w1.x0 - w0.x0 - 10.0).abs() < 1.0, "first char shifts by half its tracking: {} {}", w0.x0, w1.x0);
|
||||
// Line Anchor 100%: tracking grows to the left.
|
||||
@@ -262,10 +262,10 @@ fn tracking_grows_from_each_paragraphs_alignment() {
|
||||
p.comp_mut(cid).unwrap().layers.push(l);
|
||||
glyph_paths(&ctx(&p, cid, 0.0), &p.comp(cid).unwrap().layers[0])
|
||||
};
|
||||
// 4 chars × 500/1000 em × 40 px: 20 px of tracking each, half before and half after.
|
||||
// 4 chars with 20 px of tracking each, half before and half after.
|
||||
for (justify, x0, centre, x1) in [(Justify::Left, 10.0, 40.0, 70.0), (Justify::Center, -30.0, 0.0, 30.0), (Justify::Right, -70.0, -40.0, -10.0)] {
|
||||
let d = TextDoc { justify, ..doc("ABCD", 40.0) };
|
||||
let (w0, w1) = (bounds_of(&tracked(d.clone(), 0.0)), bounds_of(&tracked(d, 500.0)));
|
||||
let (w0, w1) = (bounds_of(&tracked(d.clone(), 0.0)), bounds_of(&tracked(d, 20.0)));
|
||||
let got = [w1.x0 - w0.x0, w1.center().x - w0.center().x, w1.x1 - w0.x1];
|
||||
assert!(got.iter().zip([x0, centre, x1]).all(|(g, w)| (g - w).abs() < 1.0), "{justify:?}: moved {got:?}, want {:?}", [x0, centre, x1]);
|
||||
}
|
||||
@@ -277,11 +277,36 @@ fn tracking_grows_from_each_paragraphs_alignment() {
|
||||
let (a, b): (Vec<_>, Vec<_>) = paths.into_iter().partition(|g| bounds_of(std::slice::from_ref(g)).center().y < 10.0);
|
||||
[bounds_of(&a), bounds_of(&b)]
|
||||
};
|
||||
let ([a0, b0], [a1, b1]) = (lines(tracked(d.clone(), 0.0)), lines(tracked(d, 500.0)));
|
||||
let ([a0, b0], [a1, b1]) = (lines(tracked(d.clone(), 0.0)), lines(tracked(d, 20.0)));
|
||||
assert!((a1.x0 - a0.x0 - 10.0).abs() < 1.0, "the left paragraph grows right: {} {}", a0.x0, a1.x0);
|
||||
assert!((b1.x1 - b0.x1 + 10.0).abs() < 1.0, "the right paragraph grows left: {} {}", b0.x1, b1.x1);
|
||||
}
|
||||
|
||||
/// #1798: After Effects adds Tracking Amount in absolute pixels between neighbouring characters,
|
||||
/// independent of font size.
|
||||
#[test]
|
||||
fn text_animator_tracking_amount_uses_pixels_independent_of_font_size() {
|
||||
let width_diff = |font_size: f64, amount: f64| {
|
||||
let (mut p, cid, comp) = setup(2000, 400);
|
||||
let mut l = text_layer(&mut p, &comp, doc("ABCDE", font_size));
|
||||
animator(&mut p, &mut l, &["tracking"], &["range"]);
|
||||
set(&mut l, "text/animators/#1/properties/tracking", Value::Scalar(amount));
|
||||
p.comp_mut(cid).unwrap().layers.push(l);
|
||||
let w = bounds_of(&glyph_paths(&ctx(&p, cid, 0.0), &p.comp(cid).unwrap().layers[0])).width();
|
||||
let (mut p0, cid0, comp0) = setup(2000, 400);
|
||||
let l0 = text_layer(&mut p0, &comp0, doc("ABCDE", font_size));
|
||||
p0.comp_mut(cid0).unwrap().layers.push(l0);
|
||||
let w0 = bounds_of(&glyph_paths(&ctx(&p0, cid0, 0.0), &p0.comp(cid0).unwrap().layers[0])).width();
|
||||
w - w0
|
||||
};
|
||||
// 5 characters = 4 gaps. In After Effects, Tracking Amount 100 adds 100 px per gap = 400 px total width delta,
|
||||
// regardless of whether font size is 50 px or 200 px.
|
||||
let diff_50 = width_diff(50.0, 100.0);
|
||||
let diff_200 = width_diff(200.0, 100.0);
|
||||
assert!((diff_50 - 400.0).abs() < 1.0, "font_size 50 px width delta: {diff_50}");
|
||||
assert!((diff_200 - 400.0).abs() < 1.0, "font_size 200 px width delta: {diff_200}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anchor_grouping_line_rotates_around_line_centre() {
|
||||
let (mut p, cid, comp) = setup(600, 300);
|
||||
|
||||
Reference in New Issue
Block a user