renderSvgToPng function

Future<Uint8List> renderSvgToPng(
  1. BytesLoader loader, {
  2. int? width,
  3. int? height,
})

Renders a vector graphic loaded by loader directly to PNG bytes.

This hides the ui.Canvas/ui.Image steps (and therefore the need to import 'package:pure_ui/pure_ui.dart') for callers who only need a PNG.

If width or height are omitted, the intrinsic size reported by the decoded picture (PictureInfo.size) is used.

If both are given and the SVG's intrinsic aspect ratio differs, the content is scaled to fit inside the requested size (like BoxFit.contain) and centered, instead of being clipped to the top-left corner of the canvas.

Implementation

Future<Uint8List> renderSvgToPng(
  BytesLoader loader, {
  int? width,
  int? height,
}) async {
  BytesLoader effectiveLoader = loader;
  if ((width != null || height != null) && loader is SvgLoader) {
    final String svgSource = await loader.resolveSvgSource();
    final String? scaledSvg = _scaleSvgToFit(
      svgSource,
      width: width,
      height: height,
    );
    if (scaledSvg != null) {
      effectiveLoader = SvgStringLoader(scaledSvg);
    }
  }

  final PictureInfo pictureInfo = await vg.loadPicture(effectiveLoader);
  try {
    final int targetWidth = width ?? pictureInfo.size.width.round();
    final int targetHeight = height ?? pictureInfo.size.height.round();
    final ui.Image image = await pictureInfo.picture.toImage(
      targetWidth,
      targetHeight,
    );
    try {
      final ByteData? byteData = await image.toByteData(
        format: ui.ImageByteFormat.png,
      );
      return byteData!.buffer.asUint8List();
    } finally {
      image.dispose();
    }
  } finally {
    pictureInfo.picture.dispose();
  }
}