mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-13 18:54:31 +00:00
* Expressions: a text style's justification and direction use After Effects' names
After Effects reads a paragraph's justification as alignLeft, alignCenter,
alignRight, justifyLastLeft, justifyLastCenter, justifyLastRight or
justifyFull, and its direction as left-to-right or right-to-left; its
setters take those names. EffectCraft returned its own keys (left, ltr,
justifyAll...), and the document refused alignLeft/alignCenter/alignRight
and justifyFull. The getters now return After Effects' names and the
parser accepts them; EffectCraft's own names are still accepted.
* Expressions: every accepted justification spelling reads back as After Effects' name
setJustification('CENTER_JUSTIFY').justification returned CENTER_JUSTIFY.
The setter and getter now share one table of the spellings Justify::parse
accepts, looked up as own properties only, so an alias reads back as
alignCenter and an inherited name such as toString is never matched.
This commit is contained in:
@@ -987,6 +987,22 @@ var __mkProp = (function (P) {
|
||||
// attributes at, and the setter calls made on it ([key, value, start, count]). Setters return
|
||||
// new objects; returning a style from a Source Text expression applies it.
|
||||
|
||||
// After Effects' names for a paragraph's justification, which its expressions read and write,
|
||||
// from every spelling `Justify::parse` accepts (case, '_', '-' and spaces ignored).
|
||||
var __AE_JUSTIFY = {
|
||||
left: 'alignLeft', leftjustify: 'alignLeft', alignleft: 'alignLeft',
|
||||
center: 'alignCenter', centre: 'alignCenter', centerjustify: 'alignCenter', aligncenter: 'alignCenter',
|
||||
right: 'alignRight', rightjustify: 'alignRight', alignright: 'alignRight',
|
||||
justify: 'justifyLastLeft', justifyleft: 'justifyLastLeft', justifylastleft: 'justifyLastLeft', fulljustifylastlineleft: 'justifyLastLeft',
|
||||
justifycenter: 'justifyLastCenter', justifylastcenter: 'justifyLastCenter', fulljustifylastlinecenter: 'justifyLastCenter',
|
||||
justifyright: 'justifyLastRight', justifylastright: 'justifyLastRight', fulljustifylastlineright: 'justifyLastRight',
|
||||
justifyall: 'justifyFull', justifyfull: 'justifyFull', fulljustifylastlinefull: 'justifyFull', fulljustify: 'justifyFull',
|
||||
};
|
||||
function __aeJustify(v) {
|
||||
var k = String(v).toLowerCase().replace(/[_ -]/g, '');
|
||||
return Object.prototype.hasOwnProperty.call(__AE_JUSTIFY, k) ? __AE_JUSTIFY[k] : String(v);
|
||||
}
|
||||
|
||||
function __TextStyle(doc, idx, ops, empty) { this.__d = doc; this.__i = idx; this.__ops = ops; this.__empty = empty; }
|
||||
|
||||
function __styleSetter(key, conv) {
|
||||
@@ -1062,13 +1078,13 @@ __TextStyle.prototype = {
|
||||
get kerningType() { var k = this.__get('kerning'); return typeof k === 'number' ? 'manual' : k; },
|
||||
get kerning() { var k = this.__get('kerning'); return typeof k === 'number' ? k : 0; },
|
||||
get isLigature() { return this.__get('ligatures'); },
|
||||
get justification() { return this.__get('justify', true); },
|
||||
get justification() { return __aeJustify(this.__get('justify', true)); },
|
||||
get firstLineIndent() { return this.__get('indentFirst', true); },
|
||||
get startIndent() { return this.__get('indentLeft', true); },
|
||||
get endIndent() { return this.__get('indentRight', true); },
|
||||
get spaceBefore() { return this.__get('spaceBefore', true); },
|
||||
get spaceAfter() { return this.__get('spaceAfter', true); },
|
||||
get direction() { return this.__get('direction', true); },
|
||||
get direction() { var d = this.__get('direction', true); return d === 'rtl' ? 'right-to-left' : d === 'ltr' ? 'left-to-right' : d; },
|
||||
get isEveryLineComposer() { return this.__get('composer', true) === 'everyLine'; },
|
||||
get isHangingRoman() { return this.__get('hangingPunctuation', true); },
|
||||
setText: __styleSetter('text', function (v) { return String(v); }),
|
||||
@@ -1099,7 +1115,7 @@ __TextStyle.prototype = {
|
||||
setKerningType: __styleSetter('kerning', function (v) { v = String(v).toLowerCase(); return v === 'manual' ? 0 : v; }),
|
||||
setKerning: __styleSetter('kerning', Number),
|
||||
setLigature: __styleSetter('ligatures', Boolean),
|
||||
setJustification: __styleSetter('justify', function (v) { return String(v); }),
|
||||
setJustification: __styleSetter('justify', __aeJustify),
|
||||
setFirstLineIndent: __styleSetter('indentFirst'),
|
||||
setStartIndent: __styleSetter('indentLeft'),
|
||||
setEndIndent: __styleSetter('indentRight'),
|
||||
|
||||
@@ -1258,6 +1258,41 @@ fn source_text_style_api() {
|
||||
assert!(f.ev(f.a, ROT, "transform.rotation.style.fontSize", 0.0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paragraph_settings_read_and_write_after_effects_names() {
|
||||
// After Effects 26.3 reads justification as alignLeft / alignCenter / alignRight /
|
||||
// justifyLastLeft / justifyLastCenter / justifyLastRight / justifyFull and direction as
|
||||
// left-to-right / right-to-left, and its setters take those names.
|
||||
let f = fx();
|
||||
let doc = |f: &Fx, e: &str| -> TextDoc {
|
||||
match f.ev(f.title, "text/sourceText", e, 0.0) {
|
||||
Ok(Value::Text(d)) => *d,
|
||||
r => panic!("{e}: {r:?}"),
|
||||
}
|
||||
};
|
||||
let s = |e: &str| doc(&f, e).text;
|
||||
assert_eq!(s("text.sourceText.style.justification + ' ' + text.sourceText.style.direction"), "alignLeft left-to-right");
|
||||
for (ae, want) in [
|
||||
("alignLeft", effectcraft_keyframe::Justify::Left),
|
||||
("alignCenter", effectcraft_keyframe::Justify::Center),
|
||||
("alignRight", effectcraft_keyframe::Justify::Right),
|
||||
("justifyLastLeft", effectcraft_keyframe::Justify::JustifyLastLeft),
|
||||
("justifyLastCenter", effectcraft_keyframe::Justify::JustifyLastCenter),
|
||||
("justifyLastRight", effectcraft_keyframe::Justify::JustifyLastRight),
|
||||
("justifyFull", effectcraft_keyframe::Justify::JustifyAll),
|
||||
] {
|
||||
let d = doc(&f, &format!("text.sourceText.style.setJustification('{ae}')"));
|
||||
assert_eq!(d.justify, want, "{ae}");
|
||||
}
|
||||
let d = doc(&f, "text.sourceText.style.setDirection('right-to-left').setJustification('justifyLastRight')");
|
||||
assert_eq!(d.direction, effectcraft_keyframe::Direction::Rtl);
|
||||
assert_eq!(s("text.sourceText.style.setJustification('alignRight').justification"), "alignRight");
|
||||
// Every accepted alias reads back as After Effects' name; an inherited name isn't one.
|
||||
assert_eq!(s("text.sourceText.style.setJustification('CENTER_JUSTIFY').justification"), "alignCenter");
|
||||
assert_eq!(s("text.sourceText.style.setJustification('justifyAll').justification"), "justifyFull");
|
||||
assert_eq!(s("String(text.sourceText.style.setJustification('toString').justification)"), "toString");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numbers_to_source_text() {
|
||||
let f = fx();
|
||||
|
||||
@@ -85,13 +85,13 @@ impl Justify {
|
||||
}
|
||||
pub fn parse(s: &str) -> Option<Justify> {
|
||||
Some(match s.to_ascii_lowercase().replace(['_', ' ', '-'], "").as_str() {
|
||||
"left" | "leftjustify" => Justify::Left,
|
||||
"center" | "centre" | "centerjustify" => Justify::Center,
|
||||
"right" | "rightjustify" => Justify::Right,
|
||||
"left" | "leftjustify" | "alignleft" => Justify::Left,
|
||||
"center" | "centre" | "centerjustify" | "aligncenter" => Justify::Center,
|
||||
"right" | "rightjustify" | "alignright" => Justify::Right,
|
||||
"justify" | "justifyleft" | "justifylastleft" | "fulljustifylastlineleft" => Justify::JustifyLastLeft,
|
||||
"justifycenter" | "justifylastcenter" | "fulljustifylastlinecenter" => Justify::JustifyLastCenter,
|
||||
"justifyright" | "justifylastright" | "fulljustifylastlineright" => Justify::JustifyLastRight,
|
||||
"justifyall" | "fulljustifylastlinefull" | "fulljustify" => Justify::JustifyAll,
|
||||
"justifyall" | "justifyfull" | "fulljustifylastlinefull" | "fulljustify" => Justify::JustifyAll,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user