Skip to content

Output ​

Both Flutter and pure Dart hosts use controller.exportSvg(options) and controller.exportPng(options). Flutter supplies image loading and raster rendering. Pure Dart supplies SVG output with prepared resources; PNG requires a host DiagramOutput raster adapter and otherwise throws UnsupportedError.

The playground includes an Export diagram menu for SVG and PNG downloads. Both are generated locally in the app. Exports contain the diagram bounds with padding, without selection handles, the minimap or other editor controls. Embedded widgets use their declared portable fallback.

On this page ​

CategoryWhat you can do
Export PNGCapture the drawing as an image.
PNG optionsChoose bounds, scale and background.
Export SVGExport vector geometry and text.
ResourcesProvide images and fonts for output.
FailuresHandle unavailable or invalid resources.

SVG import ​

DiagramSvgInput from package:vyuh_diagram_codec_svg/input.dart imports a supported subset into editable paths. Decode first, then add the returned elements in one batch, so the import is one undo step. Each import needs a unique idPrefix.

dart
import 'package:vyuh_diagram_codec_svg/input.dart';

final result = const DiagramSvgInput().decode(svg, idPrefix: 'logo');
controller.edits.batch('Import SVG', () {
  for (final element in result.elements) {
    controller.edits.add(element, select: false);
  }
});

The result also includes warnings: unsupported text, images, references and effects are omitted; groups are flattened and compound-path holes may differ. No scripts execute and no resources are fetched. Rectangles, ellipses, circles, lines, polylines, polygons, curve paths and basic transforms are supported. Export subsequently writes the imported diagram's supported geometry.

The playground header offers Import JSON from a file and Export JSON in the same compact menu as SVG and PNG. JSON import replaces the canvas as one undoable edit.

controller.exportPng ​

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

The committed drawing snapshot (controller.diagram.snapshot) is captured when called, before asynchronous image loading.

Both exports validate finite, positive crop dimensions and positive resource limits before invoking the output backend. PNG also requires a finite, positive scale and finite, positive scaled dimensions. Invalid options fail the returned future with an ArgumentError, without loading resources or changing the drawing. Custom backends receive the same validation; backend-specific allocation limits still apply.

PngOptions ​

dart
const PngOptions({
  required DiagramRect bounds,
  double pixelRatio = 1,
  DiagramColor? background,
  Duration resourceTimeout = const Duration(seconds: 30),
  int resourceConcurrency = 4,
  int maximumDecodedImageBytes = 256 * 1024 * 1024,
  int maximumOutputPixels = 64 * 1024 * 1024,
})
PropertyDefaultContract
boundsRequiredFinite world-space crop with positive width and height. Negative world positions are allowed.
pixelRatio1Finite, positive raster scale; does not reflow text.
maximumOutputPixels64 × 1024 × 1024Positive limit on rounded output width × height. Oversized requests fail with ArgumentError before invoking the output backend. Hosts may configure this limit. Flutter additionally caps output at 8192 pixels per side and 16 × 1024 × 1024 pixels overall; raising this option does not raise those limits.
backgroundnullTransparent when omitted.
resourceTimeout30 secondsPositive image-loading timeout, not a deadline for the complete render.
resourceConcurrency4Positive maximum number of simultaneous image loads. Failure or timeout stops queued loads.
maximumDecodedImageBytes256 MiBPositive budget for decoded source-image RGBA bytes retained during PNG output, deduplicated by URI. Exceeding it rejects export with StateError; images are never silently downsampled or omitted.

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

PngSnapshot ​

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
import 'package:vyuh_diagram_flutter/extension_api.dart';
import 'package:vyuh_diagram_flutter/vyuh_diagram_flutter.dart';

final controller = DiagramController(
  document: document,
  configuration: DiagramConfiguration(
    extensions: [
      DiagramExtension(
        id: 'app.backends',
        textLayout: FlutterDiagramTextLayoutEngine(),
        output: FlutterDiagramOutput(),
      ),
    ],
  ),
);
final snapshot = await controller.exportPng(
  const PngOptions(
    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 define a world-space crop; pixel ratio changes raster resolution without reflowing text. Background defaults to transparent. Empty documents use the requested background. Flutter limits output to 8192 pixels per side and 16 × 1024 × 1024 pixels overall, alongside the configured budget. Invalid or oversized requests fail before allocation. Headless adapters may impose different limits.

The result contains immutable PNG bytes, pixel dimensions, world bounds, document ID, document revision and text-layout revision. Malformed PNG bytes from a custom output adapter throw ArgumentError; dimensions that disagree with the requested crop and scale throw StateError. Export captures the committed drawing snapshot when called, excluding uncommitted interaction previews from any controller. Later edits, navigation or controller disposal do not retarget an in-flight export. Calling it after disposal fails.

Export draws shapes, connectors, labels, ports and clipping exactly as the canvas does, 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 ​

Images load the same way they do on the canvas. Export waits for them and rejects the first failed load immediately (even while other images remain pending), 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 DiagramController instances provide this. Custom integrations must supply compatible text layout; see API reference. Load application fonts before constructing the controller or calling controller.diagram.refreshLayout(); 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 controller disposalSynchronous StateError.
Invalid crop, scale, timeout, or excessive pixel allocationFuture fails with ArgumentError.
Mismatched document and geometry 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.

For custom renderers that already own a resolved document, see API reference.

Output limits ​

Exports capture a static drawing. Runtime animation and arbitrary native widget pixels are excluded; widgets use their portable content. The host owns file names, saving and sharing. PNG output is limited to the dimensions described above and does not tile oversized images.

controller.exportSvg ​

dart
Future<SvgSnapshot> exportSvg(
  SvgOptions options, {
  Object Function(DiagramImageSource)? imageProvider,
})

Captures the committed drawing snapshot before asynchronous image loading. Later edits, navigation, and controller disposal do not change the export. Calling after disposal throws StateError. Images load the same way they do on the canvas and in PNG export.

ArgumentContract
optionsRequired positional SvgOptions.
imageProviderOptional resolver for authenticated or application-owned images; in Flutter, return an ImageProvider<Object>. Decoded images are embedded as PNGs.

SvgOptions ​

PropertyType / defaultContract
boundsRequired DiagramRectFinite, positive world-space crop. Does not reflow content.
resourceTimeoutDuration(seconds: 30)Positive deadline for image loading and encoding into embedded PNG resources; excludes final SVG serialization.
resourceConcurrency4Positive maximum number of simultaneous image loads. Failure or timeout stops queued loads.
maximumDecodedImageBytes256 * 1024 * 1024Positive budget for decoded source images during export. Exceeding it fails export with StateError; images are not replaced with placeholders.
maximumResourceBytes64 * 1024 * 1024Positive combined byte budget for all supplied font faces and embedded images, before base64 expansion. Images are counted once per URI. Exceeding it fails export with StateError.
fontsEmpty Iterable<SvgFont>Host-prepared faces, copied into an immutable list. The codec embeds referenced weight/style faces. If an exact face is unavailable, supplied family variants remain available for viewer fallback.

SvgSnapshot ​

PropertyTypeContract
svgStringSelf-contained SVG source. The host owns saving/downloading.
documentIdStringCaptured document identity.
revisionintCaptured document revision.
textLayoutRevisionintCaptured scene text-layout revision.
boundsDiagramRectRequested crop.
dart
final snapshot = await controller.exportSvg(
  SvgOptions(bounds: DiagramRect.fromLTWH(0, 0, 1200, 800)),
);
final svgSource = snapshot.svg;

Invalid XML text rejects before image loading begins. Resource errors propagate immediately, even if another image is still pending; a loading deadline fails with TimeoutException. Temporary images are released on success or failure. No document commands or camera changes occur. Widget slots export their declared portable fallback, not a screenshot of the mounted widget. Native text inside those fallbacks is included.

For a publication already captured by the host, package:vyuh_diagram_flutter/adapter.dart exposes exportDiagramSvg(publication, options: options, imageProvider: provider) and exportDiagramPng with the same result and lifetime contract.

Pure Dart SVG export ​

Import package:vyuh_diagram_core/vyuh_diagram_core.dart and package:vyuh_diagram_codec_svg/vyuh_diagram_codec_svg.dart, install SvgExtension(), and use the same controller export verb:

dart
final result = await controller.exportSvg(
  SvgOptions(
    bounds: DiagramRect.fromLTWH(0, 0, 1200, 800),
  ),
);
// result.svg contains the SVG document.

For image content, install SvgExtension(resources: preparedResources) in the configuration's extensions. DiagramSvgResources contains prepared PNG images and font bytes. This adapter does not fetch or decode resources. Missing required images and unsupported content reject the export, including outside the crop. Resource preparation remains the host's responsibility. The result captures the committed document and text-layout revision before asynchronous export begins.

Custom DiagramOutput adapters must return that captured document identity, document revision, text-layout revision and requested crop. The controller rejects mismatched metadata with StateError, including when an adapter completes after the diagram changes or is disposed.

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

Native <text>/<tspan> output includes standalone text, shape stories, list markers and connector labels. It preserves captured line breaks, alphabetic baselines, text-region and ancestor clips, foreground colors, font sizes/families and run marks. Label badges retain fill, border and corner geometry in the final label pass. Runtime animations, grids, hover and selection are excluded. Unknown resolved element/outline implementations and XML-incompatible characters reject export.

The SVG viewer shapes the native characters. Glyphs, font fallback, ligatures and spacing can differ from Flutter; this is not an outline-level or pixel-identical text snapshot. Export does not ask SVG to wrap paragraphs again. Justified lines use the captured line width with SVG textLength/spacing adjustment; the viewer's gap distribution may differ. Superscript/subscript retain the same OpenType sups/subs features used by the canvas, so support depends on the font. Pure-Dart bootstrap measurements remain approximate; provide a font-aware layout backend when exact host line breaks are required. PDF output is not implemented.

Image resources ​

DiagramSvgScene.imageSources(scene) validates supported scene content and returns an immutable, URI-deduplicated list of DiagramImageSource values to prepare. It performs no I/O and rejects unsupported content even outside the crop.

dart
import 'package:vyuh_diagram_codec_svg/vyuh_diagram_codec_svg.dart';

final resources = DiagramSvgResources(images: {
  imageSource.uri: DiagramSvgImage(decodedPngBytes),
});
final svg = DiagramSvgScene.encode(scene, bounds: crop, resources: resources);
Object / propertyContract
DiagramSvgImage(pngBytes)Snapshots static PNG bytes; rejects malformed containers, invalid dimensions, CRC errors, APNG and unknown critical chunks with ArgumentError.
image.width, image.heightIntrinsic PNG pixel dimensions.
image.pngBytes, image.dataUriImmutable bytes and self-contained data:image/png;base64,... content.
DiagramSvgResources(images: ...)Immutable URI-to-image map. The codec does not fetch URLs or load files.

The producer must supply decodable PNG pixels; container validation does not inflate or validate the IDAT pixel stream. Decode/transcode other image formats before constructing a resource. The original URI is only an identity key and is never emitted as a remote SVG image reference. Declared contain, cover and fill behavior uses the same resolved layer rectangle and clipping. An image slot without an authored source retains the canvas's portable placeholder.

Shadows use the declared color, local offset and Gaussian sigma before the shape fill, under the same owner and ancestor transforms. Independent SVG rendering has been checked for image fitting and shadows; exhaustive renderer and font parity across viewers remain open.

Embedded font resources ​

dart
final face = SvgFont(
  family: 'IBM Plex Sans',
  bytes: fontBytes,
  format: SvgFontFormat.ttf,
  weight: 400,
);
final snapshot = await controller.exportSvg(
  SvgOptions(bounds: crop, fonts: [face]),
);
MemberContract
SvgFont(family:, bytes:, format:, weight: 400, style: SvgFontStyle.normal)Immutable font bytes. Malformed or mismatched font containers are rejected.
formatttf, otf, woff, or woff2; must match the supplied container.
familyNonempty name matching the authored TextRun.fontFamily.
weight / styleWeight from 1 to 1000; style normal or italic. Supply separate faces as needed.
bytes / dataUri / cssRuleImmutable bytes, embedded data URI and safely escaped @font-face declaration.
DiagramSvgResources(fonts: [...])Pure codec resource collection. Family matching and duplicate detection ignore casing; duplicate family/weight/style faces reject.

The host supplies valid font bytes it can embed; neither codec nor controller fetches fonts. Without a supplied face, the viewer resolves the named family; runs without a family use sans-serif. Embedded font support varies by SVG consumer. The encoder escapes family names as literal CSS strings and never accepts raw CSS or remote font URLs. Image loading uses imageProvider; it does not resolve fonts.

Applications export through controller.exportSvg or controller.exportPng.