Skip to content

Output

PNG rendering requires Flutter, even without a mounted canvas. It is not a standalone Dart server renderer.

session.exportPng

dart
Future<DiagramPngSnapshot> exportPng(
  DiagramPngOptions options, {
  ImageProvider<Object> Function(DiagramImageSource)? imageProvider,
})
ArgumentContract
optionsRequired positional crop, raster scale, background, and image-loading timeout.
imageProviderOptional resolver for authenticated or application-owned images.

The publication is captured when called, before asynchronous image loading.

DiagramPngOptions

dart
const DiagramPngOptions({
  required DiagramRect bounds,
  double pixelRatio = 1,
  DiagramColor? background,
  Duration resourceTimeout = const Duration(seconds: 30),
})
PropertyDefaultContract
boundsRequiredFinite world-space crop with positive width and height. Negative world positions are allowed.
pixelRatio1Finite, positive raster scale; does not reflow text.
backgroundnullTransparent when omitted.
resourceTimeout30 secondsPositive image-loading timeout, not a deadline for the complete render.

Options are immutable. Validation occurs during export, not in the const constructor.

DiagramPngSnapshot

PropertyTypeContract
bytesUint8ListCopied, unmodifiable PNG bytes.
documentIdStringCaptured document identity.
revisionintCaptured document revision.
textLayoutRevisionintCaptured scene's text-layout revision.
boundsDiagramRectRequested world crop.
widthintceil(bounds.width * pixelRatio) pixels.
heightintceil(bounds.height * pixelRatio) pixels.

Example

Export a captured document without mounting a canvas:

dart
final snapshot = await session.exportPng(
  const DiagramPngOptions(
    bounds: DiagramRect.fromLTWH(0, 0, 1200, 800),
    pixelRatio: 2,
    background: DiagramColor(0xffffffff),
  ),
);

// Hand these bytes to your application's save/share/download integration.
final pngBytes = snapshot.bytes;

Bounds are an explicit world-space crop. Pixel ratio scales raster resolution without changing text wrapping or layout. Omitting the background produces transparency. An empty document produces an empty crop with the requested background. Output is limited to 8192 pixels per side and 16 megapixels overall; invalid bounds/scales and oversized requests throw before raster allocation.

The result contains immutable PNG bytes, pixel dimensions, world bounds, document ID, document revision and text-layout revision. It captures the current publication when called, including any currently published preview. Later edits, navigation or session disposal do not retarget an in-flight export. Calling it after disposal fails.

The same scene painter renders canonical shapes, connectors, labels, ports and clipping at full detail. Grid, selection, hover, text-entry placeholders and editor overlays are excluded. Runtime animation effects and arbitrary Flutter widget overlays are not canonical document content and are not included.

Images and fonts

Required images share the canvas image-resolution implementation. Export waits for them and rejects failed loads or a resource timeout (30 seconds by default), rather than painting a loading placeholder. A host can pass imageProvider to supply an authenticated or application-owned Flutter ImageProvider for each DiagramImageSource.

Text must already have Flutter-shaped line and marker geometry in the captured scene. Normal DrawingSession instances provide this. A borrowed headless store with unshaped text is rejected. Load application fonts before constructing or refreshing the session; export preserves the captured shaping, including any font fallback already present, and does not silently reshape it after an asynchronous font load.

Failures

ConditionResult
Call after session disposalSynchronous StateError.
Invalid crop, scale, timeout, or excessive pixel allocationFuture fails with ArgumentError.
Mismatched publication or missing Flutter text geometryFuture fails with StateError.
Image loading failsFuture propagates the loading failure.
Image loading exceeds the timeoutFuture fails with TimeoutException.
PNG encoder returns no bytesFuture fails with StateError.

Rendering failures propagate. Temporary render resources are released on success or failure.

exportDiagramPng

The editor package also accepts an already captured publication:

dart
Future<DiagramPngSnapshot> exportDiagramPng(
  DiagramPublication publication, {
  required DiagramPngOptions options,
  ImageProvider<Object> Function(DiagramImageSource)? imageProvider,
})

The publication must contain matching canonical state and resolved geometry. Options, result, and asynchronous failure contracts match the session method. This function also requires Flutter.

Scope and verification

Snapshot lifetime, basic pixels, transparency, scaling, empty output and rejection behavior have automated coverage. A release-Wasm browser diagnostic verifies basic PNG generation, decoding, and pixels. Exhaustive nested/rotated/clipped content fidelity and host download integration remain open. Complete vector export, automatic document bounds with bleed, animation capture and tiled large-image output are not implemented. The host owns file naming, saving and sharing.

Geometry-only SVG scenes

DiagramSvgScene.encode runs in pure Dart, without a mounted canvas or Flutter renderer:

dart
final svg = DiagramSvgScene.encode(
  scene,
  bounds: const DiagramRect.fromLTWH(0, 0, 1200, 800),
);
Argument / resultContract
sceneRequired positional ResolvedScene. Uses its captured geometry and paint order; does not resolve another document or reflow content.
boundsRequired named DiagramRect; finite, positive world-space crop.
ResultSynchronous SVG String, with a transparent background and world-space viewBox. The host owns saving and file naming.
Invalid boundsArgumentError.
Unsupported contentUnsupportedError; no partial document is returned, including when unsupported content is outside the crop.

Supported content includes shape outlines, fills and styled borders, pressure ink, region fills, dividers, ports, connector bodies and terminal markers. Owner transforms, intersecting ancestor clips and the canvas's separate border/port/marker passes are preserved.

Text (including standalone text and connector labels), image layers and shadows are not supported yet. These reject export rather than disappear or use a different text layout. Unknown resolved element or outline implementations also reject export. Runtime animations, grids, hover and selection are editor presentation and are excluded. This is a limited static vector exporter, not full SVG/PDF output.

SVG geometry adapter

DiagramSvgGeometry in vyuh_diagram_codecs serializes resolved outlines to SVG path data in pure Dart. It is a geometry primitive, not a complete diagram SVG exporter.

MethodInputResult
outlinePath(outline)ResolvedOutlineSVG d data for a rectangle (including fitted circular corners), ellipse, polygon, or open authored path.
connectorBodyPath(connector)ResolvedConnectorVisible endpoint-trimmed body polyline in world coordinates; empty if fewer than two body points.
arrowheadPath(arrowhead)ResolvedArrowheadResolved terminal-marker path, preserving its open/closed contour. Use filled to select fill versus stroke.
inkHullPath(outline)AuthoredPathOutlineClosed filled pressure-stroke hull, or an empty string when no hull exists.

Arcs use SVG arc commands; coordinates are serialized without deliberate decimal rounding. Nonfinite coordinates and nonpositive outline bounds are rejected. Outline implementations outside the closed grammar throw UnsupportedError.

The output uses the same unrotated resolved coordinates as the canvas outline. A complete exporter must still compose owner transforms, ancestor and content clips, styles, connectors, text, images and document metadata. Stroke hulls are separate from authored centerlines so consumers can preserve the canvas's choice of filled pressure geometry or styled centerline. The adapter does not infer missing text shaping or emit a partial diagram while pretending to export it all.

Connector output serializes bodyPoints, exactly as the canvas does. Quadratic and cubic routes therefore retain the resolver's authoritative sampled polyline; the adapter does not rebuild curves from controls or use animation resampling. Marker trimming is already present in that body. Labels, their ink masks, ancestor clipping, color and dash styling still belong to scene composition.

SVG paint attributes

DiagramSvgPaint in vyuh_diagram_codecs supplies immutable SVG attribute maps for geometry composition:

MethodInputResult
shapeAttributes(style)ShapeStyleRegular surface fill, alpha, stroke width, dash rhythm and caps. Zero-width borders emit stroke="none".
connectorAttributes(connector)ConnectorElementUnfilled connector body stroke, with rounded joins and geometry-appropriate caps.

Both consume DiagramStrokeStyle.pattern, the same world-space dash/gap grammar used by committed and preview painting. Solid strokes have no dash pattern; dashed strokes use 8/5 with butt caps, and dotted strokes use 1/5 with round caps. Colors retain their alpha. Invalid color ranges and negative or non-finite widths are rejected.

These are composition primitives, not a complete SVG scene exporter. They do not apply transforms, ancestor clips, pressure-ink fill rules, text, labels, images, or decorative layers. Hosts must not apply regular shape surface paint to standalone text or pressure ink.

SVG placement and clips

MethodResult
DiagramSvgGeometry.outlineTransform(element)SVG rotation mapping a resolved framed element's outline to world space.
DiagramSvgGeometry.ancestorClips(element, scene)Immutable list of (path, transform) records for clipping ancestors, nearest first.

Use an element and scene from the same captured publication. Resolved framed sources already contain composed owner placement; applying parent transforms again would position them twice. Each ancestor clip is an independent intersection: nest clip groups instead of putting all paths into one SVG clip (which would union them). Missing or cyclic resolved ownership fails explicitly.

scene.clippingAncestorsOf(element) is also consumed by canvas painting, text/effect clipping, minimaps, accessibility bounds and hit testing. SVG maps those same outlines into world space. This provides placement primitives; complete scene serialization is still pending.