mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 23:00:35 +00:00
.ai import: type with the older TS, Te and TM operators opens
The version 7 and version 3 file format specifications list three text operators the editing-data reader did not dispatch, so a file whose type used any of them on a visible layer did not open from its editing data: - `(text) justified TS` (special characters): the reader adds its characters to the story, as it does for `Tx` and `Tj`. - `Te` (end render) is read and ignored. The reader accepts it with any number of operands. - `TM` (pop text matrix) is read and ignored. Tests cover each operator in a text object, `TS` without a string and outside a text object, and `Te` inside a tab definition. The import fuzz tests add the operators to the legacy type tokens.
This commit is contained in:
@@ -4053,6 +4053,11 @@ fn arb_ai_token() -> impl Strategy<Value = String> {
|
||||
"(\\r) TX",
|
||||
"() Tj",
|
||||
"(x) Tx",
|
||||
"(\\t) 1 TS",
|
||||
"() /x TS",
|
||||
"Te",
|
||||
"0 0 1e308 -1e308 Te",
|
||||
"TM",
|
||||
"7 Tr",
|
||||
"-1e308 Ts",
|
||||
"1e308 0 Tz",
|
||||
|
||||
@@ -356,11 +356,15 @@ impl<'a> Reader<'a> {
|
||||
"Tp" => self.begin_text_path(&vals),
|
||||
"TP" => self.end_text_path(),
|
||||
"TO" => self.end_text(hidden)?,
|
||||
"Tx" | "Tj" | "TX" => self.text_body(w, &vals),
|
||||
// `(text) justified TS`, special characters (§22.6): the reader adds its characters like `Tx`.
|
||||
"Tx" | "Tj" | "TX" | "TS" => self.text_body(w, &vals),
|
||||
"Tr" | "Tf" | "Ts" | "Tz" | "Tt" | "TA" | "Tl" | "Ta" | "Ti" | "TC" | "TW" | "Tq" | "Th" => self.text_attr(w, &vals),
|
||||
// Attributes the reader doesn't keep (kerning pairs, Far-Eastern type) and final-form
|
||||
// positions (§15.3).
|
||||
"Tk" | "TK" | "Tc" | "Tw" | "Tm" | "Td" | "T*" | "TR" | "T+" | "T-" | "TV" | "Tv" | "Ty" | "TY" | "TG" | "Tg" | "Tu" | "Xu" => {}
|
||||
// `TM` (pop text matrix) and `Te` (end render), listed in §22.6, keep nothing either; the
|
||||
// reader takes `Te` with any number of operands.
|
||||
"TM" | "Te" => {}
|
||||
// The hyphenation language and tab rulers, which the reader doesn't keep either (§22): `XL`,
|
||||
// `Xb`/`XB` a tab definition (and the `Xe` tab descriptions between them).
|
||||
"XL" | "Xb" | "XB" | "Xe" => {}
|
||||
|
||||
@@ -3001,6 +3001,29 @@ fn legacy_type_attributes_with_bad_operands_stay_as_they_were() {
|
||||
assert_eq!(bad.xf, good.xf);
|
||||
}
|
||||
|
||||
/// `(text) justified TS` (special characters, §22.6) adds its characters to the story like `Tx`
|
||||
/// and `Tj`, whichever its flag. Without a string, or outside a text object, it adds nothing.
|
||||
#[test]
|
||||
fn legacy_special_characters_join_the_story() {
|
||||
let texts = legacy_texts(&point_type("", "One").replace("TO\n", "(\\t) 0 TS\n(Two\\r) 1 TS\n(Three) Tx\nTO\n"));
|
||||
let [t] = texts.as_slice() else { panic!("{texts:?}") };
|
||||
assert_eq!(t.plain_text(), "One\tTwo\nThree");
|
||||
let texts = legacy_texts(&format!("(x) 0 TS\n{}", point_type("0 TS", "Hi")));
|
||||
let [t] = texts.as_slice() else { panic!("{texts:?}") };
|
||||
assert_eq!(t.plain_text(), "Hi");
|
||||
}
|
||||
|
||||
/// `Te` (end render, §22.6) reads in a text object with no operands and with four, inside a tab
|
||||
/// definition too, and keeps nothing; so does `TM` (pop text matrix, §22.6).
|
||||
#[test]
|
||||
fn legacy_end_render_and_text_matrix_pop_read() {
|
||||
for te in ["Te", "0 0 1 36 Te", "36 0 Xb\n0 0 1 36 Te\nXB", "1 0 0 1 10 50 Tm\nTM"] {
|
||||
let texts = legacy_texts(&point_type(te, "Hi"));
|
||||
let [t] = texts.as_slice() else { panic!("{te}: {texts:?}") };
|
||||
assert_eq!(t.plain_text(), "Hi", "{te}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Spacing is kept to the ranges the Justification options take, a Minimum, Desired and Maximum
|
||||
/// out of order go back to their defaults, and hyphenation's letter counts and limit to the ranges
|
||||
/// `text.setFormat` takes.
|
||||
|
||||
@@ -122,7 +122,8 @@ private editing data. VectorCraft:
|
||||
without the prolog opens since #1027, its legacy type (`To` … `TO`) since #868. Graphs (`%_Gs` … `%_GS`)
|
||||
come in as their drawn art, as plain groups, paths and type, without their data or settings, with a note.
|
||||
without the prolog opens since #1027, its legacy type (`To` … `TO`) since #868, with its paragraphs' letter
|
||||
and word spacing (`TC`, `TW`), hanging punctuation (`Tq`) and hyphenation (`Th`). Its patterns in
|
||||
and word spacing (`TC`, `TW`), hanging punctuation (`Tq`) and hyphenation (`Th`); its special characters
|
||||
(`TS`) join the story, and end render (`Te`) and pop text matrix (`TM`) are read and ignored. Its patterns in
|
||||
the version 7 form (a list of `@` and `&` layers, `_ &` for the tile's background) open as pattern swatches,
|
||||
with a fill's offset, scale, rotation, reflection and shear applied before its matrix.
|
||||
Its area type with several linked areas opens as threaded frames, one for each area with its own matrix,
|
||||
|
||||
Reference in New Issue
Block a user