Merge pull request #3641 from pat26-dotcom/fix/3623-pdf-import-word-gap

Fix #3623: a word gap between two sizes reads as a space in PDF import
This commit is contained in:
BFlat authored and GitHub committed 2026-10-22 23:41:26 +07:00
commit dbf6258eae
3 files changed
+32 -4

No files matched your search

+8 -3
View File
@@ -1,6 +1,6 @@
//! Text as editable point type: glyphs drawn one after another on the same baseline make one //! Text as editable point type: glyphs drawn one after another on the same baseline make one
//! point text object of their Unicode text, a run per font, size and paint (a gap wider than a //! point text object of their Unicode text, a run per font, size and paint (a gap wider than a
//! fifth of the size reads as a space). Fonts are named from the file's base font name (its //! fifth of the smaller size beside it reads as a space). Fonts are named from the file's base font name (its
//! subset prefix dropped, the family matched against the fonts available); a font that isn't //! subset prefix dropped, the family matched against the fonts available); a font that isn't
//! available keeps its name, and the text shows in the fallback font until it is. //! available keeps its name, and the text shows in the fallback font until it is.
//! //!
@@ -124,7 +124,8 @@ struct Gap {
at: usize, at: usize,
/// From the end of the glyph before to the start of the next (points). /// From the end of the glyph before to the start of the next (points).
width: f64, width: f64,
/// The larger of the two glyphs' sizes (points). /// The smaller of the two glyphs' sizes (points): a word gap beside a much larger glyph is
/// narrow for the large size (#3623).
em: f64, em: f64,
/// Along the line, not turned along a curve. /// Along the line, not turned along a curve.
on_line: bool, on_line: bool,
@@ -156,6 +157,8 @@ pub(crate) struct TextLine {
visible: Point, visible: Point,
/// The last glyph's baseline direction. /// The last glyph's baseline direction.
last_dir: Vec2, last_dir: Vec2,
/// The last glyph's size (points).
last_size: f64,
/// Each glyph's baseline origin, then where the last one ends. /// Each glyph's baseline origin, then where the last one ends.
baseline: Vec<Point>, baseline: Vec<Point>,
runs: Vec<(Look, String)>, runs: Vec<(Look, String)>,
@@ -207,6 +210,7 @@ impl TextLine {
last: at.origin, last: at.origin,
visible: at.origin, visible: at.origin,
last_dir: at.dir, last_dir: at.dir,
last_size: at.size,
baseline: vec![], baseline: vec![],
runs: vec![], runs: vec![],
upright: None, upright: None,
@@ -297,7 +301,7 @@ impl TextLine {
return false; return false;
} }
if !run.ends_with(' ') && !text.starts_with(' ') { if !run.ends_with(' ') && !text.starts_with(' ') {
self.gaps.push(Gap { at: bytes, width: gap, em: size, on_line }); self.gaps.push(Gap { at: bytes, width: gap, em: self.last_size.min(at.size), on_line });
} }
// A space the file draws between two glyphs spans the gaps on both sides of it. // A space the file draws between two glyphs spans the gaps on both sides of it.
let drawn = self.drawn_space.take(); let drawn = self.drawn_space.take();
@@ -322,6 +326,7 @@ impl TextLine {
} }
self.last = at.origin; self.last = at.origin;
self.last_dir = at.dir; self.last_dir = at.dir;
self.last_size = at.size;
self.baseline.push(at.origin); self.baseline.push(at.origin);
self.advances.push(advance); self.advances.push(advance);
true true
+21
View File
@@ -164,6 +164,27 @@ fn evenly_wide_gaps_stay_spaces() {
} }
} }
/// A word set beside a much larger one, apart by a gap and no space glyph (as a browser prints a
/// margin between two sizes), reads as two words: the gap is measured against the smaller size
/// (#3623). Set close, the two sizes stay one word.
#[test]
fn a_gap_between_two_sizes_is_measured_against_the_smaller() {
let font = vectorcraft_text::FontDb::global().find_postscript("SourceSans3-Regular").unwrap();
let advance = |c: char, size: f32| font.advance(font.glyph_for(c)) as f32 / font.units_per_em() as f32 * size;
// 3.4 pt: 0.17 em of the 20 pt "4", 0.43 em of the 8 pt "hours".
for (gap, want) in [(3.4_f32, "4 hours"), (0.4, "4hours")] {
let lines = [(20.0, 60.0, 20.0, "4"), (20.0 + advance('4', 20.0) + gap, 60.0, 8.0, "hours")];
let d = import_with_report(&text_pdf(&lines, false), &ImportOptions::default()).unwrap().document;
let t = texts(&d);
assert_eq!(t.len(), 1, "gap {gap} pt: {t:?}");
assert_eq!(t[0].plain_text(), want, "gap {gap} pt");
}
// The small size first.
let lines = [(20.0, 60.0, 8.0, "ca"), (20.0 + advance('c', 8.0) + advance('a', 8.0) + 3.4, 60.0, 20.0, "4")];
let t = texts(&import_with_report(&text_pdf(&lines, false), &ImportOptions::default()).unwrap().document);
assert_eq!(t.iter().map(TextObject::plain_text).collect::<Vec<_>>(), ["ca 4"]);
}
/// Embedded font data is untrusted: anything that isn't a CID-keyed CFF is no table, never a panic. /// Embedded font data is untrusted: anything that isn't a CID-keyed CFF is no table, never a panic.
#[test] #[test]
fn cid_tables_ignore_fonts_that_are_not_cid_keyed_cff() { fn cid_tables_ignore_fonts_that_are_not_cid_keyed_cff() {
+3 -1
View File
@@ -1,6 +1,6 @@
# Parity with Adobe Illustrator # Parity with Adobe Illustrator
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-22 · **Change:** minor (G13: gradient Dither (Illustrator 30.0): a Dither box in the Gradient panel (`paint.editGradient`/`paint.setFill` `dither`, saved in the native file) draws a linear or radial gradient fill with seeded fine noise that hides banding, on the canvas and in raster exports; SVG and PDF exports write the fill as an image at the Document Raster Effects resolution, as the public documentation describes dither; fills only, as documented; score and hours unchanged; #3546: `--automation-read-root` and `--automation-write-root` may each be given more than once (`vectorcraft-cli mcp` and the desktop app); a path inside any root of its kind is allowed, every confinement check unchanged. Scores and estimates unchanged; #3147: `vectorcraft-cli run --commands FILE` (or `-`) reads the steps from a JSON file or standard input (an array or JSON Lines, at most 64 MiB and 100,000 steps), among `--cmd` and `--export` in order; errors name the step. Scores and estimates unchanged; G2: Effect › Sketch › Conté Crayon (Foreground Level, Background Level, Texture, Scaling, Relief, Light Direction, Invert; a black crayon in the dark areas and a white one in the light areas on textured mid-grey paper; ranges and defaults unverified VectorCraft choices); measured Photoshop-style filters 57/57, the Effect Gallery remains (4–6 h); Affinity import AF.5: master pages, tables, paragraph formats, shadows, glows, outlines, overlays and embedded documents; Recolor Artwork Edit chips scroll within the available screen height (#3416); small palettes retain their tab height; scores and estimates unchanged; #3515: recent-font groups in font pickers; PDF/X-1a and PDF/X-3 flattening keeps a CMYK document's inks where it rasterizes, #2160; Blend panel Type and Ramp control step easing with a separate color Shift (#2539); Blend Options retains spacing and orientation; polynomial curves are original approximation; UI chrome: panels dock into any dock group or the icon column by dragging (UI.6), workspaces keep their layout changes (UI.7), dock groups collapse to their tabs by a double-click (UI.8); scores and hours unchanged; Shape Builder Gap Detection shares Live Paint’s spatial gap finder and temporary merge bridges (#2526); Custom is capped at 72 pt in the existing options dialog; Recolor model selection is available through the engine and MCP only (#2520); the dialog retains its existing controls; filter plug-ins read and set effect records and stroke joins, caps and miter limits, G17; the Print dialog's Media list has the Japanese papers: JIS B4 257 × 364 mm, JIS B5 182 × 257 mm and JIS B6 beside the ISO B4/B5, which keep their ISO 216 sizes, and はがき, 往復はがき, 封筒 長形3号/長形4号/角形2号/角形3号 and 四六判; a paper is named by its JSON id or its dialog label, any case and spacing; imported PDF type that is letter-spaced keeps its word spaces and no others; Fractional Widths: Character panel menu, per type object, on by default; System Layout remains a panel stub; scores unchanged; G4: manual Tate-chu-yoko; G4: No Break; scores unchanged; the selection tools take a clipping path on its outline, G1; Polygon and Star exact-size placement remembers the chosen count for later drags and dialog openings; Cancel preserves the previous count; Live trace result bounds and selection highlights exclude the retained bitmap except in source-image views; CSS swatch libraries retain fractional gradient stop positions; scores and hours unchanged; live-effect plug-ins given their object's fills and strokes and the item they sit on, G17; plug-in parameters: labels, units, groups, help and conditions in their dialogs, text and number-list parameters, up to 256 of them, G17; exporter plug-ins: plug-in file formats in Export As and document.export, G17; G2: Effect › Artistic › Smudge Stick, Sponge and Watercolor; Sketch › Bas Relief, Charcoal, Photocopy and Stamp, #2533; Photoshop filters 45/57, 12 remaining (8–14 h); interactive Mirror Repeat axis; bounding-box handles take priority over the axis body while the center and end handles retain their move and rotation actions; Libraries panel: the list scrolls, items and groups reorder by dragging, items drag into and out of groups (`library.moveItem` before/after, `library.moveGroup`); scores unchanged; PDF invisible text opens as type with no fill or stroke and is written back invisible, #2675; status-readout sample widths cached by language, document unit and pixels per point; status messages and readouts use stable responsive allocations sized for localized labels and ordinary coordinates; cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; cached canvas reprojection preserves scale during resize, rotation and DPI changes; interactive Mirror Repeat axis; bounding-box handles take priority over the axis body while the ceLine truncated > **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-22 · **Change:** minor (imported PDF type keeps a word space between two sizes (#3623); G13: gradient Dither (Illustrator 30.0): a Dither box in the Gradient panel (`paint.editGradient`/`paint.setFill` `dither`, saved in the native file) draws a linear or radial gradient fill with seeded fine noise that hides banding, on the canvas and in raster exports; SVG and PDF exports write the fill as an image at the Document Raster Effects resolution, as the public documentation describes dither; fills only, as documented; score and hours unchanged; #3546: `--automation-read-root` and `--automation-write-root` may each be given more than once (`vectorcraft-cli mcp` and the desktop app); a path inside any root of its kind is allowed, every confinement check unchanged. Scores and estimates unchanged; #3147: `vectorcraft-cli run --commands FILE` (or `-`) reads the steps from a JSON file or standard input (an array or JSON Lines, at most 64 MiB and 100,000 steps), among `--cmd` and `--export` in order; errors name the step. Scores and estimates unchanged; G2: Effect › Sketch › Conté Crayon (Foreground Level, Background Level, Texture, Scaling, Relief, Light Direction, Invert; a black crayon in the dark areas and a white one in the light areas on textured mid-grey paper; ranges and defaults unverified VectorCraft choices); measured Photoshop-style filters 57/57, the Effect Gallery remains (4–6 h); Affinity import AF.5: master pages, tables, paragraph formats, shadows, glows, outlines, overlays and embedded documents; Recolor Artwork Edit chips scroll within the available screen height (#3416); small palettes retain their tab height; scores and estimates unchanged; #3515: recent-font groups in font pickers; PDF/X-1a and PDF/X-3 flattening keeps a CMYK document's inks where it rasterizes, #2160; Blend panel Type and Ramp control step easing with a separate color Shift (#2539); Blend Options retains spacing and orientation; polynomial curves are original approximation; UI chrome: panels dock into any dock group or the icon column by dragging (UI.6), workspaces keep their layout changes (UI.7), dock groups collapse to their tabs by a double-click (UI.8); scores and hours unchanged; Shape Builder Gap Detection shares Live Paint’s spatial gap finder and temporary merge bridges (#2526); Custom is capped at 72 pt in the existing options dialog; Recolor model selection is available through the engine and MCP only (#2520); the dialog retains its existing controls; filter plug-ins read and set effect records and stroke joins, caps and miter limits, G17; the Print dialog's Media list has the Japanese papers: JIS B4 257 × 364 mm, JIS B5 182 × 257 mm and JIS B6 beside the ISO B4/B5, which keep their ISO 216 sizes, and はがき, 往復はがき, 封筒 長形3号/長形4号/角形2号/角形3号 and 四六判; a paper is named by its JSON id or its dialog label, any case and spacing; imported PDF type that is letter-spaced keeps its word spaces and no others; Fractional Widths: Character panel menu, per type object, on by default; System Layout remains a panel stub; scores unchanged; G4: manual Tate-chu-yoko; G4: No Break; scores unchanged; the selection tools take a clipping path on its outline, G1; Polygon and Star exact-size placement remembers the chosen count for later drags and dialog openings; Cancel preserves the previous count; Live trace result bounds and selection highlights exclude the retained bitmap except in source-image views; CSS swatch libraries retain fractional gradient stop positions; scores and hours unchanged; live-effect plug-ins given their object's fills and strokes and the item they sit on, G17; plug-in parameters: labels, units, groups, help and conditions in their dialogs, text and number-list parameters, up to 256 of them, G17; exporter plug-ins: plug-in file formats in Export As and document.export, G17; G2: Effect › Artistic › Smudge Stick, Sponge and Watercolor; Sketch › Bas Relief, Charcoal, Photocopy and Stamp, #2533; Photoshop filters 45/57, 12 remaining (8–14 h); interactive Mirror Repeat axis; bounding-box handles take priority over the axis body while the center and end handles retain their move and rotation actions; Libraries panel: the list scrolls, items and groups reorder by dragging, items drag into and out of groups (`library.moveItem` before/after, `library.moveGroup`); scores unchanged; PDF invisible text opens as type with no fill or stroke and is written back invisible, #2675; status-readout sample widths cached by language, document unit and pixels per point; status messages and readouts use stable responsive allocations sized for localized labels and ordinary coordinates; cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; cached canvas reprojection preserves scale during resize, rotation and DPI changes; interactive Mirror Repeat axis; boLine truncated
## Feature submission evidence ## Feature submission evidence
@@ -33,6 +33,7 @@ the work list made from it. Deep areas have their own checklists: [UI and intera
| Number | Value | Kind | | Number | Value | Kind |
|---|---|---| |---|---|---|
| 2026-10-22 | minor | PDF import: a gap between glyphs of two sizes reads as a space measured against the smaller size (#3623); mixed-size regression. Scores and hours unchanged. |
| 2026-10-21 | minor | PDF import: letter-spaced type keeps its word spaces and gains none between letters; synthetic Tc and glyph-by-glyph regressions. Scores and hours unchanged. | | 2026-10-21 | minor | PDF import: letter-spaced type keeps its word spaces and gains none between letters; synthetic Tc and glyph-by-glyph regressions. Scores and hours unchanged. |
| 2026-10-15 | minor | Image Trace retains nonzero positioned boundaries when a fixed-end returning piece has fewer than two fitted cubics. Source-generated tests check survival, winding, shared-edge reversal and Noise controls; see `image-trace-quality.md`. Scores and hours unchanged. | | 2026-10-15 | minor | Image Trace retains nonzero positioned boundaries when a fixed-end returning piece has fewer than two fitted cubics. Source-generated tests check survival, winding, shared-edge reversal and Noise controls; see `image-trace-quality.md`. Scores and hours unchanged. |
| **Feature breadth** (does each Illustrator menu item, tool, effect and format exist?) | **~88%** | measured in part: menu tree 353 of 375 items wired (94.1%), tools 89 of 92 (97%), vector effects 44 of 50 (88%), Photoshop-style effects 57 of 57 (100%), 3D 4 of 4 (initial: Extrude & Bevel, Revolve, Inflate, Rotate); blended by the area weights below | | **Feature breadth** (does each Illustrator menu item, tool, effect and format exist?) | **~88%** | measured in part: menu tree 353 of 375 items wired (94.1%), tools 89 of 92 (97%), vector effects 44 of 50 (88%), Photoshop-style effects 57 of 57 (100%), 3D 4 of 4 (initial: Extrude & Bevel, Revolve, Inflate, Rotate); blended by the area weights below |
@@ -827,6 +828,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- SVG/SVGZ in and out with SVG Options, Preserve Editing, symbols, filters, rich text and physical units (SVG type under a transform or `viewBox` scale opens at the size it draws at, the scale moved into its size, leading, baseline shift and strokes, a stretch, skew or rotation kept as its transform: #396; a top-level group with a clip path, such as a clipped Inkscape layer, opens as a layer with a clipping mask, its name kept: #420; hidden objects written hidden on Save and `convert`, and `data-*` attributes kept as the objects' own data: #522; top-level groups open as layers named from `data-name`, else the id, also when one more group (a transform on all the art, a `<switch>`) wraps them, hidden ones hidden, and a file whose art sits loose under a root `<svg>` with an id (or `data-name`), as one-layer exports write it, opens with its one layer named from it; nested groups stay groups, except the sublayers VectorCraft writes, marked `data-vc-layer`, and Inkscape sublayers, which open as sublayers in their layer's colour: #372); PDF and PDF-compatible `.ai` in and out (layers, with hidden ones kept hidden with their art and nested ones as sublayers, on pages of up to 64 million operators, art whose layer can't be told going to a hidden, non-printing layer rather than showing or printing: #419; strokes kept live, a fill and a stroke of one outline as one object; a type object's stroke written as each glyph's outline stroked back on the type, so it stays one editable object; lines wrapped in a frame (each wrapped line ending in a space, one left edge, leading and font) back as one area type object, left aligned or justified with its paragraph spacing, where laying it out breaks the lines where the file does; glyphs set apart by gaps wider than a space (a barcode's digit groups) keeping their places; layers stacked as the pages mark them even when one first paints on a later page, art ending a layer's marked content or a clip closing in a later layer kept in its own layer, and layers with no art kept empty: #508; art reaching past a plain PDF's page clipped to its crop box, as PDF viewers show it, each such object in a clip group of its own (a PDF-compatible `.ai` opens whole: #675); a `.ai` on its trim boxes with the bleed boxes round them as the document's bleed, as Crop To › Trim opens a PDF (#1266); masks, editable text with type set along a curve coming back as type on a path, each artboard's art on its own page only, an `.ai`'s white page under its layers left out rather than coming in as art, spot colours, presets, security, marks and bleed, ICC output intents, raster effects, subset fonts, PDF/X, PDF layers, overprint, page thumbnails, fast web view, PDF 1.3). CMYK images keep their ink amounts from PDF import (and from placed CMYK TIFFs and the images in an `.ai` or EPS file's editing data, an alpha channel coming in as a grayscale opacity mask) to PDF export: a CMYK JPEG passes through unchanged, others stay CMYK (DeviceCMYK, or ICC-based CMYK in PDF/X-3/X-4) unless the Output settings convert them; the canvas shows them through the working CMYK profile (#320). Overprint is kept from PDF import (opened, the PDF part of an `.ai`, placed) to PDF export: the graphics state's `/OP` and `/op` become the overprint of fills, strokes and type, so a spot colour over a process colour still overprints; a page whose overprint can't be read for certain knocks out with a note, as does `/OPM 0` being read as nonzero overprint (#1388; hand-written fixtures, `pdf/src/tests_import_overprint.rs`). A masked CMYK image (`/SMask`, `/Mask` or a colour key) keeps its inks too, its alpha coming in as a greyscale opacity mask. - SVG/SVGZ in and out with SVG Options, Preserve Editing, symbols, filters, rich text and physical units (SVG type under a transform or `viewBox` scale opens at the size it draws at, the scale moved into its size, leading, baseline shift and strokes, a stretch, skew or rotation kept as its transform: #396; a top-level group with a clip path, such as a clipped Inkscape layer, opens as a layer with a clipping mask, its name kept: #420; hidden objects written hidden on Save and `convert`, and `data-*` attributes kept as the objects' own data: #522; top-level groups open as layers named from `data-name`, else the id, also when one more group (a transform on all the art, a `<switch>`) wraps them, hidden ones hidden, and a file whose art sits loose under a root `<svg>` with an id (or `data-name`), as one-layer exports write it, opens with its one layer named from it; nested groups stay groups, except the sublayers VectorCraft writes, marked `data-vc-layer`, and Inkscape sublayers, which open as sublayers in their layer's colour: #372); PDF and PDF-compatible `.ai` in and out (layers, with hidden ones kept hidden with their art and nested ones as sublayers, on pages of up to 64 million operators, art whose layer can't be told going to a hidden, non-printing layer rather than showing or printing: #419; strokes kept live, a fill and a stroke of one outline as one object; a type object's stroke written as each glyph's outline stroked back on the type, so it stays one editable object; lines wrapped in a frame (each wrapped line ending in a space, one left edge, leading and font) back as one area type object, left aligned or justified with its paragraph spacing, where laying it out breaks the lines where the file does; glyphs set apart by gaps wider than a space (a barcode's digit groups) keeping their places; layers stacked as the pages mark them even when one first paints on a later page, art ending a layer's marked content or a clip closing in a later layer kept in its own layer, and layers with no art kept empty: #508; art reaching past a plain PDF's page clipped to its crop box, as PDF viewers show it, each such object in a clip group of its own (a PDF-compatible `.ai` opens whole: #675); a `.ai` on its trim boxes with the bleed boxes round them as the document's bleed, as Crop To › Trim opens a PDF (#1266); masks, editable text with type set along a curve coming back as type on a path, each artboard's art on its own page only, an `.ai`'s white page under its layers left out rather than coming in as art, spot colours, presets, security, marks and bleed, ICC output intents, raster effects, subset fonts, PDF/X, PDF layers, overprint, page thumbnails, fast web view, PDF 1.3). CMYK images keep their ink amounts from PDF import (and from placed CMYK TIFFs and the images in an `.ai` or EPS file's editing data, an alpha channel coming in as a grayscale opacity mask) to PDF export: a CMYK JPEG passes through unchanged, others stay CMYK (DeviceCMYK, or ICC-based CMYK in PDF/X-3/X-4) unless the Output settings convert them; the canvas shows them through the working CMYK profile (#320). Overprint is kept from PDF import (opened, the PDF part of an `.ai`, placed) to PDF export: the graphics state's `/OP` and `/op` become the overprint of fills, strokes and type, so a spot colour over a process colour still overprints; a page whose overprint can't be read for certain knocks out with a note, as does `/OPM 0` being read as nonzero overprint (#1388; hand-written fixtures, `pdf/src/tests_import_overprint.rs`). A masked CMYK image (`/SMask`, `/Mask` or a colour key) keeps its inks too, its alpha coming in as a greyscale opacity mask.
In imported PDF type, a space glyph the file draws between two words also keeps the next word where the file has it when the gap beside the space is wide, as VectorCraft's own export draws a tracked space: the space gets tracking of its own, and the wrapped lines of a justified paragraph still come back as one area type object when the word gaps on each line are alike (part of #2384). In imported PDF type, a space glyph the file draws between two words also keeps the next word where the file has it when the gap beside the space is wide, as VectorCraft's own export draws a tracked space: the space gets tracking of its own, and the wrapped lines of a justified paragraph still come back as one area type object when the word gaps on each line are alike (part of #2384).
Letter-spaced PDF type, whether set with character spacing (`Tc`) or glyph by glyph, keeps its word spaces and gains none between its letters: the spacing a line's letters share is taken off each gap before a gap reads as a space. That holds on a line that also shows where its words break, with spaces the file draws or gaps wider than the rest; evenly spaced glyphs alone, which could be words of one letter, keep every gap as a space, as do glyphs set more than half an em apart, such as figures in columns. Letter-spaced PDF type, whether set with character spacing (`Tc`) or glyph by glyph, keeps its word spaces and gains none between its letters: the spacing a line's letters share is taken off each gap before a gap reads as a space. That holds on a line that also shows where its words break, with spaces the file draws or gaps wider than the rest; evenly spaced glyphs alone, which could be words of one letter, keep every gap as a space, as do glyphs set more than half an em apart, such as figures in columns.
A gap between glyphs of two sizes is measured against the smaller one, so a word set beside a much larger one with no space glyph between them (a browser's margin between two sizes, as in `≤ 4` and a small `hours`) keeps its word space (#3623).
SVG import's style cascade, used for hidden objects, non-scaling strokes and type, tests each element only against the `<style>` rules for its id, its classes and its element name, and the rules whose selector ends in none of these (`*`, `[x]`). SVG import's style cascade, used for hidden objects, non-scaling strokes and type, tests each element only against the `<style>` rules for its id, its classes and its element name, and the rules whose selector ends in none of these (`*`, `[x]`).
A `.svgz` file copied in a file manager pastes as its art, as a copied `.svg` file does. A `.svgz` file copied in a file manager pastes as its art, as a copied `.svg` file does.
In a `.ai` or EPS opened from its editing data, type has its text object's opacity and blend mode, whether it is made from the file's text document or taken from the page. Where such type has transparency and comes in with other art (the rest of its look, or page type and strokes that go with it), a group of them has it. Where the page draws its type, or the strokes around it, with transparency that is neither its text object's nor its text object's combined with that of the objects around it, the page's type and strokes keep their own instead (`crates/eps/src/import/tests_native.rs`). Where the page draws type of no text object over text objects made from the text document, that type is left out only when, for each piece of it, one of those text objects has the piece's Latin letters and digits in its text, in capitals or not; other such type is kept as the page's other type of no text object is. In a `.ai` or EPS opened from its editing data, type has its text object's opacity and blend mode, whether it is made from the file's text document or taken from the page. Where such type has transparency and comes in with other art (the rest of its look, or page type and strokes that go with it), a group of them has it. Where the page draws its type, or the strokes around it, with transparency that is neither its text object's nor its text object's combined with that of the objects around it, the page's type and strokes keep their own instead (`crates/eps/src/import/tests_native.rs`). Where the page draws type of no text object over text objects made from the text document, that type is left out only when, for each piece of it, one of those text objects has the piece's Latin letters and digits in its text, in capitals or not; other such type is kept as the page's other type of no text object is.