mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 11:14:47 +00:00
Type: Release Type on a Path keeps the size Dynamic Text drew the type at
Release Type on a Path copied the stored runs into point type with the Dynamic Text flag still set, so the text dropped back to its stored size and the file saved the flag on point type. The point type now gets the drawn sizes and the flag is turned off. The legacy .ai writer writes Dynamic Text type at its drawn sizes; it now also warns that the setting itself is not written, as the editing data writer does, whether the type is written as text or as outlines. docs/target-app-parity.md lists reshaping or scaling the path among VectorCraft's own rules, and a task bar comment marks leaving the item out for threaded type as VectorCraft's own rule.
This commit is contained in:
@@ -21,7 +21,7 @@ use super::super::menucmds::whole_or;
|
||||
use super::super::object::choice;
|
||||
use super::super::textedit::{CharChange, text_mut, text_ref, type_ranges};
|
||||
use super::super::typecmd::refresh_bounds;
|
||||
use super::super::typemenu::text_ids;
|
||||
use super::super::typemenu::{bake_dynamic_text, text_ids};
|
||||
use super::super::{CommandSpec, bad, cmd, has_selection, number_or, switch_or, targets};
|
||||
use crate::{EngineError, Result, Session};
|
||||
|
||||
@@ -61,7 +61,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Release Type on a Path…",
|
||||
["Object", "Plug-ins", "Type Tools"],
|
||||
None,
|
||||
"{mode?: \"both\" (point type and the path) | \"path\" (the path only) | \"text\" (point type only) (\"both\"), keepOriginal?: false (true: the type on a path stays and the released objects go just above it), ids?: [id…], id? (instead of ids; neither: the selection)} split each type on a path among the objects (inside groups too) into point type and the path it was set on. The point type holds the same text with the same character and paragraph attributes, on one straight line whose baseline starts where the first character sat on the path; Type on a Path Options (effect, align to path, spacing, flip, brackets) don't apply to point type and are dropped. The path keeps its exact shape (open or closed, anchors and handles, the object's transform) and comes out with no fill and no stroke, in the type's layer and place in the stacking order. Other objects are left alone, and with no type on a path among them nothing changes and no undo step is made. One undo step; the released objects are selected → {ids (released, bottom to top), paths, texts}",
|
||||
"{mode?: \"both\" (point type and the path) | \"path\" (the path only) | \"text\" (point type only) (\"both\"), keepOriginal?: false (true: the type on a path stays and the released objects go just above it), ids?: [id…], id? (instead of ids; neither: the selection)} split each type on a path among the objects (inside groups too) into point type and the path it was set on. The point type holds the same text with the same character and paragraph attributes, on one straight line whose baseline starts where the first character sat on the path; Type on a Path Options (effect, align to path, spacing, flip, brackets) don't apply to point type and are dropped; type with Dynamic Text on (type.dynamicText) comes out with it off, at the sizes it was drawn at. The path keeps its exact shape (open or closed, anchors and handles, the object's transform) and comes out with no fill and no stroke, in the type's layer and place in the stacking order. Other objects are left alone, and with no type on a path among them nothing changes and no undo step is made. One undo step; the released objects are selected → {ids (released, bottom to top), paths, texts}",
|
||||
has_selection,
|
||||
release_path
|
||||
),
|
||||
@@ -230,8 +230,9 @@ fn first_pen(lay: &vectorcraft_text::TextLayout) -> Option<Point> {
|
||||
|
||||
/// `t`, type on a path, as point type on one straight line: the same runs and character and
|
||||
/// paragraph attributes, its baseline starting where its first character sat on the path (in the
|
||||
/// object's own text space, so its transform stays). Type on a Path Options are dropped. None for
|
||||
/// other type, or when it can't be placed.
|
||||
/// object's own text space, so its transform stays). Type on a Path Options are dropped, and
|
||||
/// Dynamic Text is turned off at the sizes it draws the text at. None for other type, or when it
|
||||
/// can't be placed.
|
||||
fn released_text(t: &TextObject) -> Option<TextObject> {
|
||||
let TextKind::OnPath { path, .. } = &t.kind else { return None };
|
||||
let db = vectorcraft_text::FontDb::global();
|
||||
@@ -244,6 +245,8 @@ fn released_text(t: &TextObject) -> Option<TextObject> {
|
||||
(p.x.is_finite() && p.y.is_finite()).then_some(p)
|
||||
})?;
|
||||
let mut out = t.clone();
|
||||
// Point type has no brackets to fit: it keeps the sizes the path drew it at.
|
||||
bake_dynamic_text(&mut out);
|
||||
out.kind = TextKind::Point;
|
||||
out.path_effect = Default::default();
|
||||
out.path_align = Default::default();
|
||||
|
||||
@@ -238,6 +238,26 @@ fn svg_export_writes_the_drawn_size() {
|
||||
assert!(!sizes.iter().any(|v| (v - 12.0).abs() < 1e-3), "the stored size is not written: {sizes:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_type_on_a_path_keeps_the_drawn_size() {
|
||||
let mut s = session();
|
||||
let id = on_line(&mut s, "Release");
|
||||
s.execute("type.dynamicText", &json!({"on": true})).unwrap();
|
||||
let size = 12.0 * fit(&s, id);
|
||||
assert!(size > 24.0, "the text grows on the long line: {size}");
|
||||
let r = s.execute("addon.type.releasePath", &json!({"ids": [id.0], "mode": "text"})).unwrap();
|
||||
let released = NodeId(r["texts"][0].as_u64().unwrap());
|
||||
let t = text(&s, released);
|
||||
assert!(!t.dynamic_text, "point type does not keep Dynamic Text");
|
||||
assert!((t.runs[0].style.size - size).abs() < 1e-9, "{} vs the drawn {size}", t.runs[0].style.size);
|
||||
assert_eq!(fit(&s, released), 1.0);
|
||||
// Type on a path without Dynamic Text keeps its stored size.
|
||||
let plain = on_line(&mut s, "Plain");
|
||||
let r = s.execute("addon.type.releasePath", &json!({"ids": [plain.0], "mode": "text"})).unwrap();
|
||||
let t = text(&s, NodeId(r["texts"][0].as_u64().unwrap()));
|
||||
assert!(!t.dynamic_text && t.runs[0].style.size == 12.0);
|
||||
}
|
||||
|
||||
/// The id of the first text object in `s`'s document.
|
||||
fn first_text(s: &Session) -> NodeId {
|
||||
let mut found = None;
|
||||
|
||||
Reference in New Issue
Block a user