mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 07:10:13 +00:00
EPS import: Ryumin-Light-H and GothicBBB-Medium-V read as Japanese type without their CIDFont
A name ending in the row-and-cell CMap H or V split only when the file defined the CIDFont or a face of that name was installed, so /Ryumin-Light-H findfont in a file that only names it read its strings byte by byte as a plain font: <467c> came in as "F|" instead of 日. Ryumin-Light and GothicBBB-Medium, the Japanese CIDFonts a printer carries (Adobe Technical Note #5014, appendix A.2), now split at H or V as well. Latin names such as Foo-Bold-H still stay whole.
This commit is contained in:
@@ -638,10 +638,11 @@ fn named_cid_type_in_charpath_cshow_and_glyphshow() {
|
||||
}
|
||||
|
||||
/// A font name ending in the row-and-cell CMap `H` or `V` stays a font of the whole name, its
|
||||
/// strings read byte by byte, unless the part before the CMap names a CIDFont the file defines (or
|
||||
/// an installed face that covers Japanese). Type in a predefined CMap whose mappings aren't
|
||||
/// available is left out with a warning, each code moving the point one em, and a long string in a
|
||||
/// CID-keyed font over a predefined CMap shown in a loop runs out of the budget.
|
||||
/// strings read byte by byte, unless the part before the CMap names a CIDFont the file defines, a
|
||||
/// Japanese CIDFont a printer carries (or an installed face that covers Japanese). Type in a
|
||||
/// predefined CMap whose mappings aren't available is left out with a warning, each code moving
|
||||
/// the point one em, and a long string in a CID-keyed font over a predefined CMap shown in a loop
|
||||
/// runs out of the budget.
|
||||
#[test]
|
||||
fn latin_names_ending_in_h_and_cmaps_that_cannot_be_read() {
|
||||
for (font, family, style) in [("Futura-H", "Futura", "H"), ("Foo-Bold-H", "Foo", "Bold-H"), ("Foo-Condensed-V", "Foo", "Condensed-V")] {
|
||||
@@ -665,6 +666,18 @@ fn latin_names_ending_in_h_and_cmaps_that_cannot_be_read() {
|
||||
let r = super::tests::read(&format!("{define} findfont 20 scalefont setfont 10 20 moveto <467c> show"));
|
||||
assert_eq!(texts(&r).iter().map(|t| t.plain_text()).collect::<Vec<_>>(), ["日"], "{define}: {:?}", r.warnings);
|
||||
}
|
||||
// The Japanese CIDFonts a printer carries (Adobe Technical Note #5014, appendix A.2) split at
|
||||
// `H` or `V` without the file defining them or a face of their name being installed. A face
|
||||
// with the whole name, when installed, is that face's.
|
||||
for (font, vertical) in [("Ryumin-Light-H", false), ("GothicBBB-Medium-V", true)] {
|
||||
if vectorcraft_text::FontDb::global().find_postscript(font).is_some() {
|
||||
continue;
|
||||
}
|
||||
let r = super::tests::read(&format!("/{font} findfont 20 scalefont setfont 10 20 moveto <467c> show"));
|
||||
let t = texts(&r);
|
||||
assert_eq!(t.iter().map(|t| t.plain_text()).collect::<Vec<_>>(), ["日"], "{font}: {:?}", r.warnings);
|
||||
assert_eq!(t[0].vertical, vertical, "{font}");
|
||||
}
|
||||
let r = super::tests::read("/Ryumin-Light-GBT-H findfont 20 scalefont setfont 10 20 moveto (AB) show 0 0 10 10 rectfill");
|
||||
assert!(texts(&r).is_empty(), "{:?}", all(&r.document));
|
||||
assert_eq!(super::tests::program_warnings(&r.warnings), [super::text::UNREAD_CMAP], "{:?}", r.warnings);
|
||||
|
||||
@@ -509,9 +509,11 @@ impl Interp<'_> {
|
||||
/// Font name `name` as a CIDFont's name and the name of a predefined CMap other than a Unicode
|
||||
/// CMap ([`super::predefined_cmap::composite_font`]), unless an installed face has the whole
|
||||
/// name. A name that ends in the row-and-cell CMap `H` or `V` splits only when the part before
|
||||
/// it names a CIDFont the file defines, or has a hyphen and names an installed face that covers
|
||||
/// Japanese; otherwise it stays a font of the whole name (`Futura-H`, `Foo-Bold-H`), its
|
||||
/// strings read byte by byte.
|
||||
/// it names a CIDFont the file defines, one of the Japanese CIDFonts a printer carries
|
||||
/// (`Ryumin-Light`, `GothicBBB-Medium`: Adobe Technical Note #5014, appendix A.2,
|
||||
/// <https://adobe-type-tools.github.io/font-tech-notes/pdfs/5014.CIDFont_Spec.pdf>), or has a
|
||||
/// hyphen and names an installed face that covers Japanese; otherwise it stays a font of the
|
||||
/// whole name (`Futura-H`, `Foo-Bold-H`), its strings read byte by byte.
|
||||
fn predefined_split<'a>(&mut self, name: &'a str) -> Option<(&'a str, &'a str)> {
|
||||
let (cid_font, cmap) = super::predefined_cmap::composite_font(name)?;
|
||||
let db = vectorcraft_text::FontDb::global();
|
||||
@@ -525,7 +527,8 @@ impl Interp<'_> {
|
||||
let defined = self.instances(&Obj::name("CIDFont")).is_ok_and(|d| d.borrow().contains_key(&key)) || cid_font_in(&self.fonts);
|
||||
// 日 is in the row-and-cell CMaps' character set (JIS X 0208).
|
||||
let installed = || db.find_postscript(cid_font).is_some_and(|face| face.covers('日'));
|
||||
if !(defined || (cid_font.contains('-') && installed())) {
|
||||
let printer = matches!(cid_font, "Ryumin-Light" | "GothicBBB-Medium");
|
||||
if !(defined || printer || (cid_font.contains('-') && installed())) {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ Names in the editing data that aren't UTF-8 (layers, objects, artboards, colors,
|
||||
| Illustrator template `.ait` | open, save | yes | PDF-compatible only, from Save as Template (`.vctemplate` stays its default) | New from Template opens a saved `.ait` untitled with its layers and art (`tests_pdfedit.rs`) |
|
||||
| Illustrator `.ai` | open, save | yes (PDF-compatible + editing-data structure with template layers and ruler guides, File Info) | PDF-compatible, or legacy version 7 (layers and groups) | see above; no real-file corpus |
|
||||
| PDF | open, place, save | yes (authored ActualText in editable import, #6165; layers, masks, editable text, security, overprint, File Info from the XMP packet and the document information dictionary; Crop To › Trim takes the bleed box as the document's bleed) | yes (presets, PDF/X-1a/3/4, layers, marks and bleed, ICC, fast web view, 1.3+; objects' URLs as link annotations, not in PDF/X) | fuzzed import; shared guarded writer and windowed reader ([pdf-backend.md](pdf-backend.md)), metadata, incomplete-content and dependency-source regressions; PDF text opens where the file draws it, glyph by glyph (#722: kerning or none, spacing per character, text rise as baseline shift, vertical writing, justified text boxes); alpha soft masks drawn as images import with the mask (#1551); a clip only counts as covering the page when its shape does (#1542); a PDF another app copied pastes as editable vector art (#1499); letter-spaced type on a path keeps its length and its glyph-by-glyph stroke comes in as one text object (#1586, #1585); a crafted name tree with shared nodes no longer takes exponential time on open (#1781); fonts named with hyphens (`Noto-Sans-Bold`) or with a composite font's CMap (`Name-Identity-H`) find the installed family; invisible text (rendering mode 3: a scanned page's recognized text) opens as type with no fill or stroke and saves back as invisible, searchable text (#2675); PDF/X-1a and X-3 flattening in a CMYK document keeps CMYK inks where it rasterizes (#2160); an image mask (`/ImageMask true`) painted in a solid color opens as a grayscale image colorized by that color, a spot color keeping its swatch and tint, so Fill and Recolor Artwork reach it, and the same mask painted again in another color keeps that color (#6313); an image in a Separation space opens as a grayscale image of its tints colorized by its ink at 100 % (a spot swatch, a process plate or Registration), its soft mask as its opacity mask (#6314); a DeviceN image of one colorant opens the same way, and one of process plates only (the ink `None` may be among them) opens in CMYK with each colorant's tint in its plate (#6348) PDF export keeps harakat and zero-advance Noto Arabic dot glyphs in one compatible batch per layout line, with per-glyph vertical offsets (#6309). `crates/pdf/src/tests/realtext.rs` (`mark_text_*`) checks decoded cluster mappings, mixed Arabic/Latin/digits, contour placement against outline export, vertical columns, differing path rotations and PDF/X-1a/3/4. Editable-text import preserves authored ActualText separately (#6165), with cross-line/style layout limits; separately styled or differently rotated clusters and external viewer search/copy remain outside this export-only evidence. |
|
||||
| EPS | open, place, save | yes (own PostScript L3 interpreter, Illustrator EPS editing data structure) | yes (L2/L3, TIFF previews) | CIDFonts the file doesn't carry not drawn, but for those over a predefined CMap (`UniJIS-UCS2-H`, `90ms-RKSJ-H`, `GBK-EUC-H`, `KSCms-UHC-H`, `ETen-B5-H`), set as type in the font of the CIDFont's name, vertical over a `-V` CMap; a name that ends in the row-and-cell CMap `H` or `V` splits off the CMap only when the file defines the CIDFont of that name, or the name has a hyphen and an installed face that covers Japanese has it; name-keyed fonts in a FontSet set as type by name; #505; images encoded with `CCITTFaxDecode` (ITU-T T.4 Group 3 and T.6 Group 4, with `K`, `Columns`, `Rows`, `EndOfBlock`, `EndOfLine`, `EncodedByteAlign` and `BlackIs1`) draw, and damaged data keeps the rows decoded before its first damaged row; Type 42 (TrueType) fonts set type at its size (#1553); an embedded Type 1 font's encrypted part is read for its glyphs, which space its type, outline it and draw glyphs without a character, in plain and composite fonts; a Type 42 font that carries its TrueType font gives each code its character by its glyph name or, for names that say nothing (`/g12`), by the glyph's entry in the font's own character map, spaces its type by its own widths and draws glyphs that stand for no character from its outlines; the show operators' spacing along the baseline (`ashow`, `widthshow`, `xshow`, `yshow`, `xyshow`, and the moves of `kshow`'s procedure, run between each two characters) is kept on live type as tracking, so type in a font that isn't installed keeps the file's line lengths (spacing that moves characters off the baseline, as `yshow`, `xyshow` or a `kshow` procedure can, places each character as its own text object); composite (Type 0) fonts with the 8/8 mapping, as PDF-to-PostScript converters write two-byte fonts, draw a Type 42 descendant's glyphs from the TrueType outlines it carries and an embedded Type 1 descendant's from its charstrings, and set other descendants' characters as type at the composite font's size (other mappings are still set as type in the font of their name); CID-keyed fonts (`composefont`, `FMapType` 9 over a CMap built with the CIDInit operators or `Identity-H`/`Identity-V`; `bfchar` and `bfrange` mappings give a base-font descendant its codes or glyph names) draw the glyphs of the Type 0 CIDFonts (Type 1 charstrings in their `StartData` binary data or `GlyphDirectory`) and Type 2 CIDFonts (TrueType glyphs through `CIDMap`) they carry, and the CID-keyed fonts of a FontSet's Compact Font Format data (Type 2 charstrings); a clip only counts as covering the page when its shape does (#1542); an EPS another app copied pastes as editable vector art (`clipboard.importEps`, #1499); a stitched shading keeps its hard colour changes on import (#1654); sampled functions (type 0) interpolate between their samples, multilinearly or by cubics with `Order 3`, and a sampled axial or radial gradient has a stop at each sample; a gradient the page paints as a row of abutting one-colour strips (as Level 2 writers draw smooth shades) imports as one linear gradient, without the seams the strips leave when each is drawn alone; CMYK images, CMYK JPEGs included, keep their ink amounts on import, as from PDF, and the pixels a `MaskColor` or `ImageType 3` mask hides become a grayscale opacity mask; ruzstd 0.9.1 for compressed editing data (#1807, RUSTSEC-2026-0344) |
|
||||
| EPS | open, place, save | yes (own PostScript L3 interpreter, Illustrator EPS editing data structure) | yes (L2/L3, TIFF previews) | CIDFonts the file doesn't carry not drawn, but for those over a predefined CMap (`UniJIS-UCS2-H`, `90ms-RKSJ-H`, `GBK-EUC-H`, `KSCms-UHC-H`, `ETen-B5-H`), set as type in the font of the CIDFont's name, vertical over a `-V` CMap; a name that ends in the row-and-cell CMap `H` or `V` splits off the CMap only when the file defines the CIDFont of that name, the CIDFont is `Ryumin-Light` or `GothicBBB-Medium` (the Japanese CIDFonts a printer carries), or the name has a hyphen and an installed face that covers Japanese has it; name-keyed fonts in a FontSet set as type by name; #505; images encoded with `CCITTFaxDecode` (ITU-T T.4 Group 3 and T.6 Group 4, with `K`, `Columns`, `Rows`, `EndOfBlock`, `EndOfLine`, `EncodedByteAlign` and `BlackIs1`) draw, and damaged data keeps the rows decoded before its first damaged row; Type 42 (TrueType) fonts set type at its size (#1553); an embedded Type 1 font's encrypted part is read for its glyphs, which space its type, outline it and draw glyphs without a character, in plain and composite fonts; a Type 42 font that carries its TrueType font gives each code its character by its glyph name or, for names that say nothing (`/g12`), by the glyph's entry in the font's own character map, spaces its type by its own widths and draws glyphs that stand for no character from its outlines; the show operators' spacing along the baseline (`ashow`, `widthshow`, `xshow`, `yshow`, `xyshow`, and the moves of `kshow`'s procedure, run between each two characters) is kept on live type as tracking, so type in a font that isn't installed keeps the file's line lengths (spacing that moves characters off the baseline, as `yshow`, `xyshow` or a `kshow` procedure can, places each character as its own text object); composite (Type 0) fonts with the 8/8 mapping, as PDF-to-PostScript converters write two-byte fonts, draw a Type 42 descendant's glyphs from the TrueType outlines it carries and an embedded Type 1 descendant's from its charstrings, and set other descendants' characters as type at the composite font's size (other mappings are still set as type in the font of their name); CID-keyed fonts (`composefont`, `FMapType` 9 over a CMap built with the CIDInit operators or `Identity-H`/`Identity-V`; `bfchar` and `bfrange` mappings give a base-font descendant its codes or glyph names) draw the glyphs of the Type 0 CIDFonts (Type 1 charstrings in their `StartData` binary data or `GlyphDirectory`) and Type 2 CIDFonts (TrueType glyphs through `CIDMap`) they carry, and the CID-keyed fonts of a FontSet's Compact Font Format data (Type 2 charstrings); a clip only counts as covering the page when its shape does (#1542); an EPS another app copied pastes as editable vector art (`clipboard.importEps`, #1499); a stitched shading keeps its hard colour changes on import (#1654); sampled functions (type 0) interpolate between their samples, multilinearly or by cubics with `Order 3`, and a sampled axial or radial gradient has a stop at each sample; a gradient the page paints as a row of abutting one-colour strips (as Level 2 writers draw smooth shades) imports as one linear gradient, without the seams the strips leave when each is drawn alone; CMYK images, CMYK JPEGs included, keep their ink amounts on import, as from PDF, and the pixels a `MaskColor` or `ImageType 3` mask hides become a grayscale opacity mask; ruzstd 0.9.1 for compressed editing data (#1807, RUSTSEC-2026-0344) |
|
||||
| PostScript `.ps` | open, place | yes (the EPS reader reads its first page; `.epsf` files open and place as EPS) | via Print to PostScript | `tests_epsimport.rs` |
|
||||
| DCS 1.0 / 2.0 | place linked | place linked only (one image of the plates; spot plates as spot swatches; the composite's clipping path; each plate on its own ink in Separations Preview and print separations) | no | `crates/eps/src/dcs/tests.rs`, `crates/engine/src/tests/dcs.rs` |
|
||||
| SVG / SVGZ | open, place, save | yes | yes (SVG Options, Preserve Editing, symbols, filters, rich text) | strongest format; tests in `crates/svg/tests`; text on a path follows basic shapes as their SVG 2 equivalent paths (#1527); CSS transforms and the `font` shorthand (#1565), percentage lengths in symbols (#1596), Inkscape flowed text as area type (#1568) and Inkscape pages as artboards (#1601) import; an unsupported filter is named in its warning (#1598); an artboard exported on its own (Export As with Use Artboards, Export for Screens, Asset Export) has the artboard's name as `<title>`, Save the document's (#3544); attributes in other applications' XML namespaces (`plotter:pen="2"`) kept on their objects from import to export, as `data-*` attributes are (`crates/svg/tests/it/foreign_attributes.rs`); simple shapes export as `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<polygon>` and `<polyline>` where they draw the same as the path (#4652, `crates/svg/tests/it/basic_shapes.rs`); the regions of exported masks and filters (opacity masks, inverted masks, knockout groups) cover the art they apply to, and over type keep a region that covers any artwork (#6401, `crates/svg/tests/it/blend_export.rs`); SVG Options › Include Variable Data writes the text variables, data sets and bound type objects, and opening the SVG reads them back (`tests::variables::an_svg_with_variable_data_opens_with_its_variables_data_sets_and_bindings`) |
|
||||
|
||||
Reference in New Issue
Block a user