Commit Graph
4 Commits
Author SHA1 Message Date
dotCooCoo 9efde43f1d Metafile import: EMF and WMF are read through craft-metafile, so EMF+ pictures open
EMF and WMF import now plays the records with the shared craft-metafile
reader (storytold/craft-libs#778, at the craft-libs rev the SVG, EPS and
DXF crates already use) and maps its picture onto the document here:
paths with their fills, strokes, caps, joins, miter limits and dashes,
clipping groups, images and point type. The EMF and WMF record players in
crates/metafile/src/import and the DIB decoder they used are removed. The
writers are unchanged, and the PICT reader keeps its own player.

What changes for a file being opened, placed or pasted, and for an EPS
file's Windows metafile preview (read when its PostScript can't be):

- An EMF that draws with EMF+ records is read from them. It opened empty,
  with a warning that EMF+ is not read. A file with both kinds of record
  is read from its EMF+ records too.
- Hatched and pattern brushes fill with the average color of the brush's
  tile, translucent where the tile has gaps. Hatches filled with the hatch
  color and pattern brushes with gray.
- Translucent fills, strokes and EMF+ text keep their alpha as opacity.
- Text keeps a stretch across from the world transform; it kept only the
  turn. Text the file clips to a rectangle is clipped to it, and an
  underlined or struck-through font gives underlined or struck-through
  type.
- A clip path whose bounding box holds the whole picture is kept unless
  it is that rectangle; a diamond or a bow tie around the picture was
  dropped.
- Images drawn with SRCAND, SRCPAINT or SRCINVERT are drawn as they look
  over white, and images drawn with other raster operations are drawn as
  a plain copy. They were left out with a warning.
- Excluded clip rectangles and the other clip region modes are applied.
  A clip path combined with RGN_OR, RGN_XOR or RGN_DIFF is ignored
  without the warning it gave.
- An image past the reader's size or pixel limits, or one that can't be
  decoded, is left out without a warning of its own. A file past the
  reader's limits (more than 32 nested clip paths, 200,000 drawn items,
  256 MiB held) is read up to that point without a warning.
- An EMF record whose size is not a multiple of 4 ends the file, with the
  "ends early" warning.

Tests: an EMF+ only picture imports its fill (it failed before), a dual
EMF+ file draws its translucent EMF+ fill and not its fallback, hatch and
pattern brush colors, clipped and underlined text, excluded clip
rectangles, a shared clipping group, an odd record size, WMF at 1440
units an inch without a placeable header and at its own units with an
inverted box, an EMF without a frame, diamond and bow-tie clips, text with a
stretch, clips nested past the stack and 200,000 clip records; the fuzz
test gains random EMF+ records.
2026-11-14 06:04:19 -08:00
dotCooCoo 71da62dab2 File formats: PICT pictures open and place
File > Open and File > Place read QuickDraw pictures, versions 1 and 2,
from .pct, .pic and .pict files, with or without the file's 512 bytes
of application data; a version 2 picture also opens by its content.
The reader plays the opcodes of Apple's Opcodes in Pictures table on
the metafile player: lines, rectangles, rounded rectangles, ovals,
arcs, polygons and regions become paths, text becomes point type in
the font the picture names, bitmaps, pixel maps and QuickTime JPEG
images become images, and the clip region clips what follows it.
Place puts the picture in one group clipped to its frame. What isn't
read comes back as warnings, and a picture cut short keeps what came
before it. PICT is not written.

Images whose transform flattens them no longer leave their pixel data
in the document. Formats whose signature starts the file are detected
before PICT, which is known by bytes 522 or 10.

Docs: docs/mcp.md, docs/file-format-parity.md, docs/target-app-parity.md.
2026-11-12 19:52:06 -08:00
Lucas LerouxandClaude Opus 5.5 55fadb6afe Text: a bundled-fonts feature (on by default) lets embedders that bring their own fonts leave ours out
The nine OFL faces in `assets/fonts` are compiled into every build of
vectorcraft-text: 3.4 MB of the binary, about 1.6 MB of a gzipped wasm.
An embedder that loads every font at run time with `FontDb::add_font`
(a web app serving its own font catalogue, say) ships them twice and
can't turn them off.

- vectorcraft-text: `bundled-fonts`, a default feature, holds the
  `include_bytes!` list. Off, a database starts without them (craft-fonts
  and system fonts are unaffected) and text has no glyphs until a font
  is added, as when the bundled fonts fail to parse.
- vectorcraft-engine: a `bundled-fonts` default feature forwards to it,
  so the apps and any embedder using the engine keep the fonts unless
  they build it with `default-features = false`.
- The workspace declares vectorcraft-text without default features, so
  no library crate turns the fonts back on. The tests of cad, metafile
  and tools, which lay type out, ask for the feature in their
  dev-dependencies; the other crates' tests get it through testkit.

`cargo test --workspace` builds with the fonts, as before. A new
integration test, `without_bundled_fonts`, covers the configuration
without them (`cargo test -p vectorcraft-text --no-default-features
--test without_bundled_fonts`): the database starts without them, text
in no font lays out with no glyphs, and a font added later is used and
is the fallback for families the database lacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:19:05 +07:00
bflatasticandClaude Opus 5.5 ab1c6b0516 M4.94: EMF and WMF export from Export As and document.export
New crates/metafile (L3, pure Rust): hand-written EMF and WMF writers over
one shared document walk. EMF keeps Bezier paths, solid brushes, geometric
pens (width, caps, joins, miter limit, user-style dashes), clipping masks as
path clips, images (StretchDIBits, or AlphaBlend with transparency) placed by
a world transform, type as outlines; gradients become images clipped to their
shape and pattern fills their tiles clipped to it. The header's frame is the
artboard in 0.01 mm on a 100 px/mm reference device. WMF flattens curves into
polygons in 16-bit units behind a placeable header (with its checksum),
numbers objects as players do, and reports what it leaves out (clipping,
transparency, gradients, rotated images).

document.export {format: emf|wmf} (and serialize, export) writes one artboard,
or one file per artboard with useArtboards (false: the art's bounds); raster
effects are rendered to images first, as for PDF. Export As lists EMF and WMF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:24:24 +07:00