exportDiagramSvg function

Future<SvgSnapshot> exportDiagramSvg(
  1. DiagramPublication publication, {
  2. required SvgOptions options,
  3. ImageProvider<Object> imageProvider(
    1. DiagramImageSource
    )?,
})

Prepares images through the canvas image loader for the pure SVG codec. Native text preserves line placement; mounted widgets use declared fallbacks.

Implementation

Future<SvgSnapshot> exportDiagramSvg(
  DiagramPublication publication, {
  required SvgOptions options,
  ImageProvider<Object> Function(DiagramImageSource)? imageProvider,
}) async {
  final document = publication.state.document;
  final scene = publication.scene;
  if (scene.documentId != document.id || scene.revision != document.revision) {
    throw StateError('SVG output requires a revision-matched publication.');
  }
  final bounds = options.bounds;
  options.validate();
  final fonts = DiagramSvgResources(fonts: options.fonts).fonts;
  var resourceBytes = 0;
  void admitResource(int bytes) {
    if (bytes > options.maximumResourceBytes - resourceBytes) {
      throw StateError('SVG prepared resources exceed maximumResourceBytes.');
    }
    resourceBytes += bytes;
  }

  for (final font in fonts) {
    admitResource(font.bytes.length);
  }
  final sources = DiagramSvgScene.imageSources(scene);
  final images = DiagramImageCache(
    provider: imageProvider,
    maximumConcurrentLoads: options.resourceConcurrency,
    loadTimeout: options.resourceTimeout,
    maximumDecodedBytes: options.maximumDecodedImageBytes,
  );
  final resources = <String, DiagramSvgImage>{};
  try {
    // Keep a private handle while encoding, even if another load fails and
    // disposes the cache. Release decoded storage before admitting another load.
    await loadOutputResources(
      sources,
      (source) async {
        final image = await images.loadOwned(source);
        try {
          final data = await encodeDiagramPngImage(image);
          admitResource(data.lengthInBytes);
          resources[source.uri] = DiagramSvgImage(data);
        } finally {
          image.dispose();
          images.release(source);
        }
        return null;
      },
      concurrency: options.resourceConcurrency,
      timeout: options.resourceTimeout,
    );
    return SvgSnapshot(
      svg: DiagramSvgScene.encode(
        scene,
        bounds: bounds,
        resources: DiagramSvgResources(images: resources, fonts: fonts),
      ),
      documentId: document.id,
      revision: document.revision,
      textLayoutRevision: scene.textLayoutRevision,
      bounds: bounds,
    );
  } finally {
    images.dispose();
  }
}