Active Foundation

Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Export guarantees

What each export format guarantees for international text and fonts.

@workspace/active-charts 6.0.0Status unknowncontent differs from the recorded release 6.0.0baseline ce081dc3

The package's own guide

This page is the package's docs/EXPORT-GUARANTEES.md, included unchanged from the package as it is in Foundation. Links to the package's internal design documents keep their text.

What each export of @workspace/active-charts guarantees for international text, who owns that guarantee, and which route a consumer takes when the package does not guarantee what it needs. Decided in ADR-060; the font model is ADR-058 (PDF) and ADR-059 (SVG, PNG); the API is API.md § 4. active-grid carries the same tiers in its own words for its own formats.

The tiers#

TierOwnerFormatsScript guaranteeLimitation
L0packageCSVevery script, including supplementary-plane characters and ZWJ sequences: the logical Unicode text, no direction or isolation controlsdata only: no font, no layout
L1package + browserthe live chartwhat the browser shapes (joining, reordering, marks, bidi) with the fonts the page loadsa glyph no loaded font has is the browser's fallback
L2package + browserSVG, PNGwhat the exporting browser shapessee SVG and PNG: the file depends on fonts, and an SVG depends on its viewer
L3apackagePDFLatin, Greek, Cyrillic, Armenian, Georgian, Han (BMP), Kana, Hangul (precomposed), each text element fully covered by one embedded TrueType family; WinAnsi without a setrefused with a code, never drawn broken: complex and right-to-left scripts, combining marks, joiners and selectors, emoji, supplementary-plane characters, uncovered text
L3b-rasterhosta PDF the host builds with a PNG imageeverything the host's browser shapesthe chart is a picture: its text is not selectable or searchable
L3b-printhosta PDF the host's browser printseverything the host's browser shapes, as selectable texta host recipe, not a package route; valid only as far as the host has verified it with its own browser and fonts

No tier promises more than it says. "Supported" in any row below means the tier named, under its condition.

SVG and PNG#

ModeSVGPNG
No set (inherit)names the live font stack; embeds nothing; the viewer draws with the fonts it hasthe page's same-origin web fonts of the live stack, embedded best effort; a glyph outside them draws in the browser's default font
Explicit set, embedInSvg absent/falsenames the host's families, then the live stack; embeds nothing; the viewer needs those fonts installedevery face of every family embedded; the browser falls back per glyph across the host's families, in order, before any system font (deterministic)
Explicit set, embedInSvg: truethe same names, plus one @font-face data URL per face; browsers honour it, other viewers may notas above

In every mode the browser shapes: the package lays text out in the live font and never again in the export font, so a family with other metrics can shift text. Put the live family first.

What an export shows#

Every export and print shows the chart at rest (ADR-064, ADR-065): its static polish (geometry, typography, axis layout, grid, theme) is in it; interaction state is not. No hover, recede or inactive paint, keyboard cue, legend preview, crosshair, emphasised node, gutter mark, tooltip or selection mark reaches an SVG, PNG, PDF or print, in any family: the state is painted by the package stylesheet, which an export never copies, and the transient marks carry one attribute the composer drops. A report that needs highlighted data encodes it in the data, as a series or an annotation.

Never mid-motion (ADR-104). An export waits until the chart is still: two frames without a change, no running web animation, and past the end of every scripted motion the chart declared on its scope (an update, a path morph, a count-up or gauge replay, a grouped slot reflow, a discrete zoom), because an eased tail that snaps to whole pixels leaves quiet frames before it ends. It waits at most the chart's motion budget (the longest motion its animation allows) plus one second, and at least four seconds; a chart that never comes to rest within that rejects the export. An export started during an entrance, an update, a reflow or a replay therefore writes the resting geometry, and the tooltip, the crosshair, the cues, attention and the colour-key marker are not in it (asserted in Chromium and Firefox for SVG, with PNG and PDF waiting the same way).

An export means the same thing whichever route starts it (ADR-085). The handle (ChartHandle.exportAs*) and the context menu run one composed export per chart: the same legend on the side it is painted (its entries, keys, colours and hidden items as on the screen), the same export fonts and the same rows. The menu writes its PNG at contextMenu.pngScale and offers CSV on every chart with a menu, the export-only menu of the scalars included (ADR-087); the Sparkline has no menu and exports through its handle. A PDF draws the whole chart on every route: the export clone always carries a viewBox, so svg2pdf scales the drawing into its box instead of clipping it (ADR-088). A drawing that shows only part of its content says so in the image too: a partial org chart view carries its note in the export's caption, after the host's own.

Per script#

Script or dataLive (L1)CSV (L0)SVG (L2)PNG (L2)PDF, no setPDF, host set that covers it
Latinbrowserpackageviewer-dependentbrowser; set per glyph when givenHelvetica (WinAnsi)drawn (L3a)
Cyrillic, Greekbrowserpackageviewer-dependentbrowser; set per glyph when givenEXPORT_FONT_REQUIREDdrawn (L3a)
Han, Kana, Hangul (BMP)browserpackageviewer-dependentbrowser; set per glyph when givenEXPORT_FONT_REQUIREDdrawn (L3a)
Arabic, Hebrewbrowserpackageviewer-dependentbrowser; set per glyph when givenEXPORT_TEXT_UNSUPPORTEDEXPORT_TEXT_UNSUPPORTED; host L3b
Devanagari and other Indicbrowserpackageviewer-dependentbrowser; set per glyph when givenEXPORT_TEXT_UNSUPPORTEDEXPORT_TEXT_UNSUPPORTED; host L3b
Combining mark in the textbrowserpackageviewer-dependentbrowserEXPORT_TEXT_UNSUPPORTEDEXPORT_TEXT_UNSUPPORTED (normalizable says whether NFC would help)
Emoji, ZWJ sequencesbrowserpackageviewer-dependentbrowser (colour emoji font of the OS)EXPORT_TEXT_UNSUPPORTEDEXPORT_TEXT_UNSUPPORTED; host L3b
Supplementary planebrowserpackageviewer-dependentbrowserEXPORT_TEXT_UNSUPPORTEDEXPORT_TEXT_UNSUPPORTED; host L3b
A script no family coversbrowserpackageviewer-dependentbrowser default fontEXPORT_FONT_REQUIREDEXPORT_GLYPH_COVERAGE

Thai, Lao, Khmer, Myanmar, Tibetan, Mongolian, Syriac, Thaana and N'Ko are refused in PDF like Arabic. A refusal names one code point and, for a script, its name; it never carries the text.

Which route#

The consumer needsRoute
the dataCSV (L0)
an image exactly as the browser shows itPNG (L2); with an export font set for a deterministic font
a scalable, editable pictureSVG (L2), knowing the viewer draws the fonts; embedInSvg for browsers
a PDF with selectable text in a supported scriptPDF (L3a) with an export font set that covers the text
a PDF with Arabic, Hebrew, Indic, emoji or other shaped texta host route: L3b-raster (image in a PDF) or L3b-print (browser print)

The package never hands over to a host route by itself: it refuses, and the host decides.

Errors#

ChartExportError.code separates four kinds of failure; none carries the exported text (at most one code point and a script name, the host's family name, the detected font format, the missing module, the families tried).

KindCodesWhat the host does
a refusal of the text (L3a)EXPORT_TEXT_UNSUPPORTED, EXPORT_FONT_REQUIRED, EXPORT_GLYPH_COVERAGEsupply or extend fonts, or take a host route
a font set the export cannot useEXPORT_FONT_FACE_MISSING, EXPORT_FONT_SOURCE_INVALID, EXPORT_FONT_FORMAT_UNSUPPORTEDfix the configuration
a font that did not arriveEXPORT_FONT_LOAD_FAILED (the host loader's error is the cause)retry; the next export calls the loader again
the export itself could not runEXPORT_DEPENDENCY_MISSING (missingModule), EXPORT_CAPTURE_FAILED, EXPORT_NO_DATAinstall the module, or offer no such export

active-grid's GridExportError uses the same codes for the same meaning.

Configuring export fonts in a host#

The host owns its fonts: which families, which faces, where the bytes come from and the right to embed them. A typical enterprise set is a corporate Latin family first and a CJK family as its fallback, with faces loaded only when an export needs them:

typescript
const load = (path: string) => () =>  fetch(path, {signal: AbortSignal.timeout(15_000)}).then((response) => {    if (!response.ok) throw new Error(`font ${response.status}`);    return response.arrayBuffer();  });
const exportFonts: ChartExportFonts = {  families: [    {      family: 'Corporate Sans',      faces: [        {source: load('/fonts/corporate-sans-regular.ttf')},        {source: load('/fonts/corporate-sans-bold.ttf'), weight: 700},        {source: load('/fonts/corporate-sans-italic.ttf'), style: 'italic'},      ],    },    {      family: 'Example CJK Sans',      faces: [{source: load('/fonts/example-cjk-sans-regular.ttf')}],    },  ],};
<ChartDefaults exportFonts={exportFonts}>{children}</ChartDefaults>;
  • PDF needs static TrueType (glyf) faces. A WOFF or WOFF2 web font, a CFF-flavoured OpenType font or a variable font cannot be embedded; SVG and PNG take TrueType, CFF, WOFF and WOFF2.

  • Keep the object stable (a module constant): the package loads each face object once and shares the load between concurrent exports.

  • Name the live family first, so export metrics match the live layout.

  • The same object is an active-grid GridExportFonts.

Host routes (L3b)#

These are recipes for a host. The package provides neither.

L3b-raster: a browser image in a PDF#

  1. Render the chart in a browser or headless browser that has the fonts the text needs (installed in the image, or loaded as web fonts).

  2. Wait for document.fonts.ready and for the chart to be still.

  3. Take a PNG at a scale for print (for example 2x device pixels), with exportAsPng or a screenshot of the chart element.

  4. Place the image in the host's PDF.

The browser shapes every script it has fonts for, and the image looks like the screen. The chart's text is pixels: it cannot be selected, searched or read by assistive technology from the PDF, so the host adds any text it needs in its own PDF layer.

L3b-print: the browser prints a PDF#

  1. Launch a browser the host controls (for example headless Chromium) with the fonts installed or loaded.

  2. Render a page that contains the live chart, or its SVG export.

  3. Wait for document.fonts.ready and for the chart to be still.

  4. Print with the browser's PDF mechanism (in Chromium, page.pdf()).

  5. Verify before relying on it: extract the text from the PDF (for example with pdftotext) and render the PDF back to an image, for each script the host serves.

The browser shapes the text and writes it as selectable text with a Unicode mapping. This was verified once in a research harness (Chromium 153 on Windows with the operating system's fonts): Arabic, Hebrew and Devanagari came back from pdftotext in logical order, and the rendered PDF showed joined Arabic, right-to-left Hebrew and formed Devanagari conjuncts. That is evidence the recipe works, not a guarantee for another browser version, operating system or font set. A host claims L3b-print only for what it has verified itself.

This page as Markdown