mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 02:07:09 -06:00
M4.27: area type and rich text in SVG export
Every laid-out line of type is written at its own position (wraps, indents, tabs, hyphenation and all caps as on the canvas): a positioned tspan per style run and, on justified lines, per word. Centred and right-aligned lines are anchored at their centre or right end, so they stay aligned in a viewer whose font differs. Leading comes from the layout's baselines, baseline shift is written as dy, horizontal scale as textLength, vertical scale as the size, tracking and manual kerning as letter-spacing. The fewerTspans option (engine and dialog) writes one positioned tspan per line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4a3859c69b
commit
1982ecf98d
@@ -63,7 +63,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Export Document",
|
||||
[],
|
||||
None,
|
||||
"{path?, format?: svg|pdf|png|jpg|webp|vectorcraft (default: from the path's extension, else png), artboard?: 0, artboards?: [i…], range?: \"1-3, 5\" | \"all\" (1-based; PDF writes one page per artboard, default all; SVG writes one file per artboard, {stem}-{artboard}.svg; raster formats write one artboard), scale?: 1 (raster), quality?: 90 (jpg), SVG options flat or as svg: {styling, outlineText, images, objectIds, decimals, minify, responsive, useArtboards, preserveEditing, metadata} (see document.formats), …the PDF options of document.exportPdf} → {path, format, bytes, warnings, files?: [path…] (several), linked?: [path…] (linked images)}; no path → {dataBase64, format, bytes, warnings, files?: [{name, dataBase64}], linked?: [{name, dataBase64}]}. Never changes the document's path",
|
||||
"{path?, format?: svg|pdf|png|jpg|webp|vectorcraft (default: from the path's extension, else png), artboard?: 0, artboards?: [i…], range?: \"1-3, 5\" | \"all\" (1-based; PDF writes one page per artboard, default all; SVG writes one file per artboard, {stem}-{artboard}.svg; raster formats write one artboard), scale?: 1 (raster), quality?: 90 (jpg), SVG options flat or as svg: {styling, outlineText, images, objectIds, decimals, minify, responsive, useArtboards, preserveEditing, metadata, fewerTspans} (see document.formats), …the PDF options of document.exportPdf} → {path, format, bytes, warnings, files?: [path…] (several), linked?: [path…] (linked images)}; no path → {dataBase64, format, bytes, warnings, files?: [{name, dataBase64}], linked?: [{name, dataBase64}]}. Never changes the document's path",
|
||||
has_doc,
|
||||
export::export
|
||||
),
|
||||
|
||||
@@ -55,6 +55,12 @@ pub const OPTIONS: &[FormatOption] = &[
|
||||
description: "embed the native document in <metadata> so VectorCraft reopens the SVG with nothing lost",
|
||||
},
|
||||
FormatOption { name: "metadata", ty: "boolean", default: "false", description: "write <metadata> with the title and format (Dublin Core)" },
|
||||
FormatOption {
|
||||
name: "fewerTspans",
|
||||
ty: "boolean",
|
||||
default: "false",
|
||||
description: "type: one positioned <tspan> per line instead of one per style run, tab and justified word (smaller; viewers space the line themselves)",
|
||||
},
|
||||
FormatOption {
|
||||
name: "svg",
|
||||
ty: "object",
|
||||
|
||||
@@ -182,3 +182,13 @@ fn formats_list_the_svg_options_with_their_defaults() {
|
||||
assert!(svg["options"].get(k).is_some(), "{k}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fewer_tspans_reaches_the_writer() {
|
||||
let mut s = Session::new();
|
||||
let src = r##"<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100"><text x="10" y="40" font-size="12">plain <tspan fill="#ff0000">red</tspan> plain</text></svg>"##;
|
||||
s.execute("document.open", &json!({"name": "two-runs.svg", "dataBase64": vectorcraft_format::base64_encode(src.as_bytes())})).unwrap();
|
||||
let placed = |svg: &str| svg.matches("<tspan x=").count();
|
||||
assert_eq!(placed(&svg(&mut s, json!({}))), 3, "a tspan per style run");
|
||||
assert_eq!(placed(&svg(&mut s, json!({"fewerTspans": true}))), 1, "a tspan per line");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user