Skip to content

SVG <circle> without cx/cy attributes crashes in SvgPath.fromCircleXml #1918

@tornadoblue

Description

@tornadoblue

Describe the bug

The SVG spec defines cx and cy as optional attributes on <circle>, defaulting to 0 (SVG spec ref). However, SvgPath.fromCircleXml in pdf/src/svg/path.dart:105 uses null assertions (!) on the return value of SvgParser.getNumeric() for these attributes, causing a crash when they're omitted.

To Reproduce

Code snippet to reproduce the behavior:

import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;

void main() async {
  final pdf = pw.Document();

  // Valid SVG per spec — cx and cy are optional, default to 0
  const svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">'
      '<circle r="20" fill="red"/>'
      '</svg>';

  pdf.addPage(
    pw.Page(
      build: (context) => pw.SvgImage(svg: svg, width: 100, height: 100),
    ),
  );

  await pdf.save(); // Crashes here during paint phase
}

Expected behavior

The <circle r="20"/> element should render as a circle at (0, 0) with radius 20, matching browser SVG rendering behavior. Instead, pdf.save() throws Null check operator used on a null value.

Suggested fix in pdf/src/svg/path.dart:

// Current (crashes):
final cx = SvgParser.getNumeric(element, 'cx', _brush)!.sizeValue;
final cy = SvgParser.getNumeric(element, 'cy', _brush)!.sizeValue;

// Fixed (defaults to 0 per SVG spec):
final cx = SvgParser.getNumeric(element, 'cx', _brush)?.sizeValue ?? 0;
final cy = SvgParser.getNumeric(element, 'cy', _brush)?.sizeValue ?? 0;

Screenshots

N/A — server-side PDF generation, no UI.

Flutter Doctor

N/A — Dart-only server environment (Serverpod v3.3), not a Flutter app.
pdf package version: 3.11.3
Dart SDK: 3.5

Desktop (please complete the following information):

  • Linux

Additional context

This affects real-world SVG flag files (e.g. from flag-icons) where <circle> elements commonly omit cx/cy when centered at the origin. Examples: India's flag (<circle r="20" fill="#008"/>), Uruguay, Rwanda.

Our workaround is pre-processing SVGs to inject the missing attributes before passing them to pw.SvgImage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions