M9.1: Character panel parity (V/H scale, baseline shift, stroke order, small caps); layer.setText keys for them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5a308a6964
commit
fb6b3aa680
|
|
@ -110,6 +110,21 @@ fn text_doc_from(p: &Value, base: TextDoc) -> TextDoc {
|
|||
if let Some(v) = b_p(p, "allCaps") {
|
||||
d.all_caps = v;
|
||||
}
|
||||
if let Some(v) = b_p(p, "smallCaps") {
|
||||
d.small_caps = v;
|
||||
}
|
||||
if let Some(v) = f_p(p, "hScale") {
|
||||
d.h_scale = v.clamp(1.0, 1000.0);
|
||||
}
|
||||
if let Some(v) = f_p(p, "vScale") {
|
||||
d.v_scale = v.clamp(1.0, 1000.0);
|
||||
}
|
||||
if let Some(v) = f_p(p, "baselineShift") {
|
||||
d.baseline_shift = v;
|
||||
}
|
||||
if let Some(v) = b_p(p, "strokeOverFill") {
|
||||
d.stroke_over_fill = v;
|
||||
}
|
||||
if let Some(v) = b_p(p, "fauxBold") {
|
||||
d.faux_bold = v;
|
||||
}
|
||||
|
|
@ -940,7 +955,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
"Edit Text",
|
||||
[],
|
||||
None,
|
||||
"{layer?, text?, size?, font?, style?, fill?, stroke?, applyFill?, applyStroke?, strokeWidth?, tracking?, leading?: px|\"auto\", justify?: left|center|right|justifyLeft|justifyCenter|justifyRight|justifyAll, allCaps?, fauxBold?, fauxItalic?}",
|
||||
"{layer?, text?, size?, font?, style?, fill?, stroke?, applyFill?, applyStroke?, strokeWidth?, tracking?, leading?: px|\"auto\", justify?: left|center|right|justifyLeft|justifyCenter|justifyRight|justifyAll, allCaps?, smallCaps?, fauxBold?, fauxItalic?, hScale? %, vScale? %, baselineShift? px, strokeOverFill?}",
|
||||
has_layers,
|
||||
set_text
|
||||
),
|
||||
|
|
|
|||
|
|
@ -168,6 +168,9 @@ fn set_text_paragraph_fill_and_leading() {
|
|||
assert_eq!((d.leading, d.apply_fill, d.apply_stroke), (Some(50.0), false, true));
|
||||
s.execute("layer.setText", json!({"layer": t, "leading": "auto"})).unwrap();
|
||||
assert_eq!(doc(&s).leading, None);
|
||||
s.execute("layer.setText", json!({"layer": t, "hScale": 120, "vScale": 80, "baselineShift": 4, "smallCaps": true, "strokeOverFill": true})).unwrap();
|
||||
let d = doc(&s);
|
||||
assert_eq!((d.h_scale, d.v_scale, d.baseline_shift, d.small_caps, d.stroke_over_fill), (120.0, 80.0, 4.0, true, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -57,16 +57,21 @@ pub fn character(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
|||
actions.push(json!({"style": styles[i]}));
|
||||
}
|
||||
y += 34.0;
|
||||
// Numeric fields in a 2-column grid.
|
||||
let fields: [(&str, &str, f64, (f64, f64), &str); 6] = [
|
||||
// Numeric fields in AE's two-column grid.
|
||||
let fields: [(&str, &str, f64, (f64, f64), &str); 8] = [
|
||||
("size", "T", doc.size, (1.0, 2000.0), " px"),
|
||||
("leading", "A", doc.leading.unwrap_or(doc.size * 1.2), (0.0, 5000.0), " px"),
|
||||
("tracking", "VA", doc.tracking, (-1000.0, 10000.0), ""),
|
||||
("strokeWidth", "≡", doc.stroke_width, (0.0, 500.0), " px"),
|
||||
("strokeWidth", "W", doc.stroke_width, (0.0, 500.0), " px"),
|
||||
("vScale", "↕T", doc.v_scale, (1.0, 1000.0), " %"),
|
||||
("hScale", "↔T", doc.h_scale, (1.0, 1000.0), " %"),
|
||||
("baselineShift", "A↑", doc.baseline_shift, (-1000.0, 1000.0), " px"),
|
||||
("hScale", "↔", doc.h_scale, (1.0, 1000.0), "%"),
|
||||
("", "", 0.0, (0.0, 0.0), ""),
|
||||
];
|
||||
for (i, (key, glyph, v, range, suffix)) in fields.into_iter().enumerate() {
|
||||
if key.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let col = i % 2;
|
||||
let row = i / 2;
|
||||
let fx = x0 + col as f32 * (w / 2.0);
|
||||
|
|
@ -77,13 +82,25 @@ pub fn character(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
|||
if let Some(nv) = nv
|
||||
&& enabled
|
||||
{
|
||||
let k = if key == "baselineShift" || key == "hScale" { "tracking" } else { key };
|
||||
if k == key {
|
||||
actions.push(json!({key: nv, "merge": format!("char-{key}")}));
|
||||
}
|
||||
actions.push(json!({key: nv, "merge": format!("char-{key}")}));
|
||||
}
|
||||
}
|
||||
y += 3.0 * 28.0 + 8.0;
|
||||
// Stroke Over Fill / Fill Over Stroke (bottom-right cell).
|
||||
{
|
||||
let fx = x0 + w / 2.0;
|
||||
let fy = y + 3.0 * 28.0;
|
||||
let dr = Rect::from_min_size(pos2(fx, fy), vec2(w / 2.0, 20.0));
|
||||
let labels = vec!["Fill Over Stroke".to_string(), "Stroke Over Fill".to_string()];
|
||||
let pop = egui::Id::new("char-stroke-order-pop");
|
||||
if widgets::dropdown(ui, dr, &labels[doc.stroke_over_fill as usize], &t, egui::Id::new("char-stroke-order")).clicked() && enabled {
|
||||
widgets::open_popup(ui, pop);
|
||||
}
|
||||
app.auto.add("character.strokeOverFill", dr, "Stroke order");
|
||||
if let Some(i) = widgets::popup_menu(ui, pop, dr.left_bottom(), &labels, Some(doc.stroke_over_fill as usize)) {
|
||||
actions.push(json!({"strokeOverFill": i == 1}));
|
||||
}
|
||||
}
|
||||
y += 4.0 * 28.0 + 8.0;
|
||||
// Fill / stroke swatches.
|
||||
p.text(pos2(x0, y + 10.0), Align2::LEFT_CENTER, "Fill", Tokens::ui(11.5), t.text_dim);
|
||||
let fs = Rect::from_min_size(pos2(x0 + 34.0, y), vec2(26.0, 20.0));
|
||||
|
|
@ -107,7 +124,8 @@ pub fn character(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) {
|
|||
}
|
||||
y += 32.0;
|
||||
// Style toggles.
|
||||
let toggles = [("fauxBold", "T", doc.faux_bold), ("fauxItalic", "T", doc.faux_italic), ("allCaps", "TT", doc.all_caps)];
|
||||
let toggles =
|
||||
[("fauxBold", "T", doc.faux_bold), ("fauxItalic", "T", doc.faux_italic), ("allCaps", "TT", doc.all_caps), ("smallCaps", "Tт", doc.small_caps)];
|
||||
for (i, (key, label, on)) in toggles.into_iter().enumerate() {
|
||||
let r = Rect::from_min_size(pos2(x0 + i as f32 * 34.0, y), vec2(30.0, 24.0));
|
||||
let resp = ui.interact(r, egui::Id::new(("char-t", key)), Sense::click());
|
||||
|
|
|
|||
Loading…
Reference in New Issue