Packaged WMF / EMF / EMF+ renderer
TurtleGit packages metafile-convert and renderer.js in
Contents/Helpers/Metafile (the finalized application layout relocates executable
code and preserves the logical helper alias). It does not require Homebrew, Node,
npm, an installed Office application, or a network conversion service.
The renderer is WmfEmfViewer, package
wmf-emf-renderer 0.2.1, pinned at
4e0d6d6807349ebfc8f8c681009c14f9e57621ff under the MIT license. The archive
URL and SHA-256 are in Configuration/MetafileRuntime.json. Local compatibility,
state, clipping, font, and unsupported-record changes are reproduced by
patches/metafile-renderer.patch; the patch is part of the provenance input.
libwmf/libemf2svg were evaluated but are not linked or shipped: their SVG backends
contain unimplemented drawing callbacks, including EMF+ drawing in libemf2svg.
The region/pattern extension adds Wine’s
LGPL-2.1-or-later hatch cells at pinned commit
7298a818b79446bae153b8d5aa27235ab3703bf9. The isolated adapted table and original
copyright accompany the patch; LICENSE-Wine-hatches and NOTICE accompany the
runtime. Its full source hash, license hash and origin are pinned separately in
Configuration/MetafileRuntime.json. No Wine binary is linked or shipped.
The classic clipping extension adapts the
MIT-licensed BaseHmiTypes renderer's region-combine and metaregion/offset mask
lifecycle. Its immutable revision, original source hash and retained license hash
are recorded in Configuration/MetafileRuntime.json; LICENSE-BaseHmiTypes
accompanies the helper and its corresponding reconstruction sources. It adds no
runtime package dependency.
The EMF+ pen extension connects pen object parsing to native stroke outlines for the nine drawing record families. The existing brush pipeline paints solid, gradient, hatch and texture strokes. Linear pen transforms, compound bands, caps, joins, dashes and Center/Inset positioning have their own explicit scope and remaining compatibility list.
Rebuilding and embedding
Run python3 scripts/build-metafile-runtime.py; the default output is
build/metafile-runtime/Metafile. --output PATH chooses a different recognized
runtime output. The build needs the Xcode command line tools and Python 3; it
resolves only static, relative CommonJS imports into a deterministic module table,
without downloading executable npm build tools. The universal helper contains
arm64 and x86_64 slices targeting macOS 13 and links system JavaScriptCore,
CoreText, CoreGraphics and ImageIO. Before creating its JavaScriptCore VM the
helper sets JSC_useJIT=false, using the interpreter without an allow-JIT or
unsigned-executable-memory entitlement, following WebKit’s interpreter
configuration.
Runtime font metrics, formatted text glyph outlines
and positioned glyph geometry use CoreText; raw GDI+
BGR/BGRA bitmaps are converted to PNG using ImageIO. Platform font substitution
can differ from Windows when an original font is unavailable.
Raw glyph indices instead require the matching installed font and style,
because substituting a face changes the meaning of those indices.
The reconstruction cache incorporates pins, all build/adapter/patch script hashes,
architecture/deployment flags, compiler version and SDK version. Each runtime
contains the original source archive, exact local reconstruction inputs, MIT,
BaseHmiTypes MIT, Wine hatch LGPL and application licenses, binary/renderer/source/license hashes and toolchain metadata.
python3 scripts/validate-metafile-runtime.py PATH verifies those inputs and
reconstructs the renderer, checks slices/deployment/linkage, and executes a bounded
conversion and malformed-input checks. --all-architectures executes both slices
when the host supports them. --structure-only is used during embedding and does
not claim conversion acceptance. End-to-end native family fixtures provide the
WMF/EMF/EMF+ drawing evidence separately.
python3 scripts/embed-metafile-runtime.py RUNTIME APP copies a validated runtime
and signs its helper before the containing application. App Store builds apply
the existing inherited-sandbox helper entitlements. A signed inherited helper
requires invocation by its sandboxed parent; standalone structural validation does
not prove signed distribution or App Store acceptance.
Process contract and limits
The helper accepts exactly --wmf or --emf, reads binary standard input up to
64 MiB, and writes SVG standard output up to 128 MiB. Diagnostics go to stderr;
invalid input, mismatched formats, unsupported painting and failed native adapters
return nonzero without an SVG. The owning application supplies cancellation and a
15-second wall-clock limit, drains the exact child process, and reads output away
from the main thread. Input is not a filename or an authority grant. The helper
exposes no filesystem, DOM, Canvas, HTTP, module loader or process API to the JS
renderer. Bundled JS is loaded from the signed application resource location.
TextDecoder supports UTF-8, UTF-16LE, Windows-1252, Shift-JIS, EUC-KR, GBK/GB18030 and Big5. The bitmap callback accepts GDI+ RGB24, RGB32, ARGB32 and PARGB32 with signed stride; the bitmap extension also supports indexed palettes and RGB555/RGB565/ARGB1555. Oversized or malformed buffers are refused. Raster output is limited to 16,777,216 pixels. Unsupported drawing must fail explicitly rather than presenting a successful blank or incomplete comparison. This is a renderer port, not a claim of bit-exact Windows GDI/GDI+ coverage; unimplemented source records, font substitution, complex composition and physical visual acceptance remain tracked by the image-comparison parity documentation.
Painting compatibility inputs
The classic extended-pen family connects custom and alternate dashes, device/logical-width strokes, cap/join and miter state, hatch/DIB pen brushes, InsideFrame shapes, saved context and clipped ROP2 paint. Its native and format acceptance is separate from broader WMF/EMF completion.
The painting extension adds bounded parsers and
painting within the same captured-byte helper contract. Native CoreSVG does not
reliably implement the required gradient spread/colors or bitmap patterns, so
actual gradient paint uses analytically evaluated embedded PNGs with vector
clips/text luminance masks. SVG gradient definitions remain metadata. Each paint
raster is limited to 16,777,216 pixels/64 MiB raw data, with 67,108,864 generated
gradient pixels per conversion. Device paints use intrinsic pixel-center
sampling; the native consumer supplies an explicit intrinsic-size sRGB destination
instead of assuming a particular CoreSVG backing scale. Bitmap wrapping emits only visible image copies,
capped at 16,384 tiles per record and 65,536 per conversion. Before concatenation,
each tiled record reserves count * (escapedPNGhref.length + 4096) against a
64 MiB aggregate markup budget, preventing count-valid data-URI amplification.
Radial canonical-shape/Float32 uncertainty above 100 ppm of the conservative
minimum axis is refused before painting. RGB color plus
separate opacity avoids the observed native RGBA alpha ambiguity. These display
rasters have intrinsic output resolution; preview zoom is not unlimited vector
gradient rerendering. It retains the MIT
renderer pin and private adapter provenance; gradient/image-attribute support
must not introduce a browser, Node runtime or document-provided module loading.
Changes to local reconstruction inputs require a new runtime provenance/cache
identity. Existing standalone execution evidence below predates this extension
and does not validate its new records, pixels or platform raster output. The
painting checkpoint separately records the
latest reconstructed universal runtime, successful Debug app build, 18 passing
metafile Core methods and native consumer passes with both Git engines on the
local arm64 host. It is not a full Intel painting-corpus execution result.
Recorded standalone checkpoint
On 2026-10-18 the universal runtime built successfully, and its reconstruction,
macOS 13 load commands, SDK-only dependencies, actual simple WMF rectangle
conversion and malformed/format rejection checks passed on both arm64 and x86_64.
The same execution checks passed on a private ad-hoc hardened copy without
allow-JIT or unsigned-executable-memory entitlements. That copy was removed after
validation. Local log: build/qa/metafile-runtime-2026-10-18.log. This focused
checkpoint does not establish the full EMF/EMF+ fixture matrix, native comparison
integration, physical visual parity, Developer ID notarization or inherited
sandbox invocation; those require their own recorded grouped evidence.