mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-31 22:16:59 -06:00
Merge PR #511 from NikitkaRa: UI: WordArt Transform gallery applies a text warp
This commit is contained in:
@@ -90,6 +90,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_text_or_shapes,
|
||||
text_outline
|
||||
),
|
||||
cmd!(
|
||||
"format.textWarp",
|
||||
"Text Transform",
|
||||
["Shape Format", "WordArt Styles"],
|
||||
None,
|
||||
"{preset: a prstTxWarp name or none, adj?: [finite raw guide values, at most 8]} — none clears the transform; omitted adj uses the preset's defaults",
|
||||
has_text_or_shapes,
|
||||
text_warp
|
||||
),
|
||||
cmd!(
|
||||
"format.align",
|
||||
"Align",
|
||||
@@ -381,6 +390,36 @@ fn text_outline(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
format_run(s, &move |r| r.outline = c.clone().map(|c| Line::solid(c, w)))
|
||||
}
|
||||
|
||||
fn text_warp(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let preset = str_param(p, "preset").ok_or_else(|| bad("format.textWarp", "missing `preset`"))?;
|
||||
let clear = preset == "none" || preset == "textNoShape";
|
||||
if !clear && !deckcraft_geom::warp::is_supported(preset) {
|
||||
return Err(bad("format.textWarp", format!("unknown text transform `{preset}`")));
|
||||
}
|
||||
let adj = match p.get("adj") {
|
||||
None => Vec::new(),
|
||||
Some(Value::Array(arr)) => {
|
||||
if arr.len() > 8 {
|
||||
return Err(bad("format.textWarp", "at most 8 adjust values"));
|
||||
}
|
||||
let mut v = Vec::with_capacity(arr.len());
|
||||
for a in arr {
|
||||
let Some(n) = a.as_f64().filter(|n| n.is_finite()) else {
|
||||
return Err(bad("format.textWarp", "adjust values must be finite numbers"));
|
||||
};
|
||||
v.push(n.clamp(-2.0e9, 2.0e9));
|
||||
}
|
||||
v
|
||||
}
|
||||
Some(_) => return Err(bad("format.textWarp", "`adj` must be an array of numbers")),
|
||||
};
|
||||
let stored = if clear { None } else { Some(preset.to_string()) };
|
||||
format_body(s, &|b| {
|
||||
b.warp.clone_from(&stored);
|
||||
b.warp_adj.clone_from(&adj);
|
||||
})
|
||||
}
|
||||
|
||||
fn case(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let mode = str_param(p, "mode").unwrap_or("cycle").to_string();
|
||||
let st = s.doc()?;
|
||||
|
||||
@@ -25,6 +25,34 @@ fn new_presentation_and_slides() {
|
||||
assert_eq!(s.doc().unwrap().doc.slides.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn text_transform_sets_and_clears_a_warp() {
|
||||
let mut s = session();
|
||||
let r = s.execute("shape.insert", &json!({"preset": "rect", "rect": [80.0, 80.0, 420.0, 160.0], "text": "ARCH"})).unwrap();
|
||||
let id = r["id"].as_u64().unwrap();
|
||||
let body = |s: &mut Session| s.execute("shape.inspect", &json!({"id": id})).unwrap()["shape"]["text"]["body"].clone();
|
||||
assert!(s.execute("format.textWarp", &json!({})).is_err());
|
||||
assert!(s.execute("format.textWarp", &json!({"preset": "notAWarp"})).is_err());
|
||||
assert!(s.execute("format.textWarp", &json!({"preset": "textArchUp", "adj": "wide"})).is_err());
|
||||
assert!(s.execute("format.textWarp", &json!({"preset": "textArchUp", "adj": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]})).is_err());
|
||||
assert!(s.execute("format.textWarp", &json!({"preset": "textArchUp", "adj": [null]})).is_err());
|
||||
assert!(body(&mut s)["warp"].is_null());
|
||||
s.execute("format.textWarp", &json!({"preset": "textArchUp"})).unwrap();
|
||||
assert_eq!(body(&mut s)["warp"], "textArchUp");
|
||||
assert!(body(&mut s).get("warpAdj").is_none());
|
||||
s.execute("format.textWarp", &json!({"preset": "textInflate", "adj": [20_000.0]})).unwrap();
|
||||
let b = body(&mut s);
|
||||
assert_eq!(b["warp"], "textInflate");
|
||||
assert_eq!(b["warpAdj"], json!([20_000.0]));
|
||||
s.execute("format.textWarp", &json!({"preset": "none"})).unwrap();
|
||||
assert!(body(&mut s)["warp"].is_null());
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(body(&mut s)["warp"], "textInflate");
|
||||
s.execute("text.edit", &json!({"id": id})).unwrap();
|
||||
s.execute("format.textWarp", &json!({"preset": "textCircle"})).unwrap();
|
||||
assert_eq!(body(&mut s)["warp"], "textCircle");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_shape_and_format() {
|
||||
let mut s = session();
|
||||
|
||||
Reference in New Issue
Block a user