Nothing

Chromium SVG Pipeline Overview

Chromium SVG Pipeline Overview

The end-to-end pipeline for rendering SVG inside Blink. Emphasis on where the SVG pipeline diverges from HTML.

Parsing         Style             Layout                Paint               Composite
───────         ─────             ──────                ─────               ─────────
<svg …>  ──▶   CSS cascade  ──▶  LayoutSVGRoot    ──▶  SVGRootPainter  ──▶ cc::PaintRecord
  │             on SVGElements    │                     │                   │
  │             + presentation    ├── LayoutSVG         ├── SVGContainer    ├── property trees
  │             attributes         ├── Container         ├── Painter         │   (transform/
  │             aliased to CSS    ├── LayoutSVGShape    ├── SVGShape        │    effect/clip)
  │                                ├── LayoutSVGText     ├── Painter         │
  │                                └── …                 └── …               └── RenderSurfaces
  ▼                                 ▲                     ▲                      for filter/mask
SVGElement tree                     │                     │
                        SVG resources resolved         paint servers resolved
                        (clipPath, mask, filter,      via SVGResources::GetClient
                         marker, pattern, gradient)   → shader on PaintFlags

Phases

1. Parsing → SVGElement tree

Blink's XML/HTML parser constructs a DOM where <svg> and its descendants become concrete SVGElement subclasses:

  • Structural: SVGSVGElement, SVGGElement, SVGDefsElement, SVGSymbolElement
  • Shapes: SVGPathElement, SVGRectElement, SVGCircleElement, SVGEllipseElement, SVGLineElement, SVGPolygonElement, SVGPolylineElement
  • Text: SVGTextElement, SVGTSpanElement, SVGTextPathElement
  • Paint servers: SVGLinearGradientElement, SVGRadialGradientElement, SVGPatternElement
  • Effects: SVGClipPathElement, SVGMaskElement, SVGFilterElement, SVGMarkerElement
  • Filter primitives: SVGFEGaussianBlurElement, SVGFEColorMatrixElement, 20+ more
  • Structural refs: SVGUseElement, SVGImageElement, SVGForeignObjectElement

Presentation attributes (fill="red") and typed attributes (width="100") are stored as SVGAnimated* wrappers around a base value and an animated value — SVGAnimatedLength, SVGAnimatedNumber, SVGAnimatedTransformList, etc.

// third_party/blink/renderer/core/svg/svg_animated_length.h
class SVGAnimatedLength : public ScriptWrappable,
                          public SVGAnimatedProperty<SVGLength> {
 public:
  SVGAnimatedLength(SVGElement* context_element,
                    const QualifiedName& attribute_name,
                    SVGLengthMode mode,
                    SVGLength::Initial initial_value,
                    CSSPropertyID css_property_id = CSSPropertyID::kInvalid);
  const CSSValue* CssValue() const final;   // bridges SVG value → CSS cascade
};

The css_property_id argument is the bridge: SVG presentation attributes that have a CSS counterpart (fill, stroke, opacity, font-family, …) are fed into the CSS cascade as if they were inline styles. The cascade also accepts real CSS rules (rect { fill: red; }).

2. Style → ComputedStyle

SVG reuses the HTML style system. ComputedStyle is the same type for HTML and SVG; SVG-specific properties live in SVGComputedStyle (third_party/blink/renderer/core/style/svg_computed_style.h), accessed via style.SvgStyle(). Fields include:

  • fill, stroke, stroke_dasharray, fill_rule, clip_rule
  • marker_start, marker_mid, marker_end
  • stop_color, stop_opacity, flood_color, flood_opacity
  • paint_order (for controlling fill/stroke/marker order)

The style cascade runs the same way as for HTML. The only SVG-specific step is that presentation attributes are parsed as CSS values before entering the cascade.

3. Layout → LayoutSVG* tree

SVG has its own layout tree that grafts into Blink's layout tree at LayoutSVGRoot. LayoutSVGRoot extends LayoutReplaced (a CSS-sized replaced element), and everything below it is SVG-native.

LayoutObject
├── LayoutSVGRoot                  extends LayoutReplaced; CSS box ↔ SVG viewport
│   └── (SVG subtree below)
├── LayoutSVGModelObject           abstract base for SVG content
│   ├── LayoutSVGContainer         <g>, <symbol> — groups children
│   │   ├── LayoutSVGTransformableContainer  <g transform=…>
│   │   ├── LayoutSVGViewportContainer       nested <svg>
│   │   ├── LayoutSVGHiddenContainer         <defs>, <clipPath>, <mask>, <filter>, <marker>
│   │   │   └── LayoutSVGResourceContainer   base for all resource containers
│   │   │       ├── LayoutSVGResourcePaintServer    abstract
│   │   │       │   ├── LayoutSVGResourcePattern
│   │   │       │   └── LayoutSVGResourceGradient   (linear + radial concrete)
│   │   │       ├── LayoutSVGResourceClipper
│   │   │       ├── LayoutSVGResourceMasker
│   │   │       ├── LayoutSVGResourceFilter
│   │   │       └── LayoutSVGResourceMarker
│   │   └── …
│   ├── LayoutSVGShape             <path>, <rect>, <circle>, <ellipse>, <line>, <polygon>, <polyline>
│   │   └── LayoutSVGPath          specialization where path can be complex
│   ├── LayoutSVGImage             <image>
│   └── LayoutSVGForeignObject     <foreignObject> — bridges back to HTML layout
└── LayoutSVGText                  <text> — extends LayoutSVGBlock (reuses LayoutNG inline layout)
    └── LayoutSVGInline            <tspan>, <textPath>
        └── LayoutSVGInlineText    text runs

Unlike HTML layout (which produces rectangular fragments), SVG layout produces paths and bounding boxes in the element's local coordinate system, plus a transform to the parent SVG coordinate system (LocalToSVGParentTransform()). The tree is then walked during paint with these transforms composed.

Source: third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h and sibling files.

4. Paint → PaintRecord

Each LayoutSVG* object has a matching painter:

Layout classPainter
LayoutSVGRootSVGRootPainter
LayoutSVGContainer (+ subclasses)SVGContainerPainter
LayoutSVGShapeSVGShapePainter
LayoutSVGImageSVGImagePainter
LayoutSVGForeignObjectSVGForeignObjectPainter
LayoutSVGTextSVGTextPainter

All painters emit into the same PaintRecord (display list) machinery used by HTML — see paint-recording.md. A painter:

  1. Checks paint phase (only kForeground for most SVG content).
  2. Runs ScopedSVGTransformState — concats this element's LocalSVGTransform() onto the GraphicsContext CTM.
  3. Runs ScopedSVGPaintState — prepares fill/stroke cc::PaintFlags, applying paint servers (shaders), clip paths, masks, filters.
  4. Records DrawPath / DrawRect / text ops into the PaintRecord.

Paint order inside a shape respects the paint-order CSS property; default is fill, stroke, markers.

// third_party/blink/renderer/core/paint/svg_shape_painter.cc
void SVGShapePainter::Paint(const PaintInfo& paint_info) {
  if (paint_info.phase != PaintPhase::kForeground ||
      layout_svg_shape_.IsShapeEmpty())
    return;

  // cull-rect skip
  if (SVGModelObjectPainter::CanUseCullRect(layout_svg_shape_.StyleRef())) {
    if (!paint_info.GetCullRect().IntersectsTransformed(
            layout_svg_shape_.LocalSVGTransform(),
            layout_svg_shape_.VisualRectInLocalSVGCoordinates()))
      return;
  }

  ScopedSVGTransformState transform_state(paint_info, layout_svg_shape_);
  ScopedSVGPaintState paint_state(layout_svg_shape_, …);
  if (!DrawingRecorder::UseCachedDrawingIfPossible(…)) {
    SVGDrawingRecorder recorder(…);
    PaintShape(content_paint_info);   // fill → stroke → markers
  }
}

5. Composite → cc property trees

Once PaintRecords exist, Blink hands them to the compositor (cc/). SVG content participates in the same property trees (transform / effect / clip / scroll) as HTML. SVG-specific wrinkles:

  • Most SVG transforms are baked into the PaintRecord via canvas->concat(local_transform) rather than as a compositor transform node. Compositor transforms are reserved for elements that opt into compositing (e.g., an animated <svg> root, or an ancestor with will-change: transform).
  • <filter>, <mask>, and explicit blend modes can force a render surface (offscreen buffer). See render-surfaces.md.
  • Paint servers (pattern, gradient) never create compositor layers — they are always resolved as shaders at paint time. See svg-pattern.md for the pattern case.

How SVG diverges from HTML

AspectHTMLSVG
Layout tree rootLayoutViewLayoutSVGRoot (attached under HTML LayoutView like any replaced element)
Layout resultRectangular fragments (PhysicalFragment)Local paths + bounding boxes + LocalToSVGParentTransform()
Coordinate systemCSS pixels, one per element boxArbitrary user units; <svg viewBox> establishes a new coordinate space; nested <svg> nest viewports
Transform ownershipCompositor transform treeBaked into PaintRecord by default; compositor only for promoted layers
Paint orderStacking contexts (CSS §9.9)Document order within a group; paint-order controls fill/stroke/marker within a shape
Text layoutLayoutNG inline flowLayoutNG inline flow followed by SvgTextLayoutAlgorithm that rewrites per-glyph positions
Resource resolutionURL → resource loader (for background-image)url(#id) → same-document SVGElementResourceClient lookup; resolved at paint time, cached per-client
Replaced elements<img>, <video>, iframes<foreignObject> (HTML inside SVG); <image> (raster image in SVG); <use> (subtree clone)
Hit testingBox-basedPath-based for shapes; pointer-events decides fill-vs-stroke-vs-both

Source files

FileRole
third_party/blink/renderer/core/svg/svg_element.hBase SVGElement class, CTM scope enum
third_party/blink/renderer/core/svg/svg_animated_length.hTyped animated attribute wrapper; CSS bridge
third_party/blink/renderer/core/style/svg_computed_style.hSVG-specific ComputedStyle fields (fill, stroke, markers, …)
third_party/blink/renderer/core/layout/svg/layout_svg_root.hOuter <svg> — bridges CSS replaced-element layout to SVG coords
third_party/blink/renderer/core/layout/svg/layout_svg_model_object.hAbstract base for all SVG layout objects
third_party/blink/renderer/core/layout/svg/layout_svg_shape.hGeometry shapes; owns Path cache
third_party/blink/renderer/core/layout/svg/layout_svg_container.h<g> / container hierarchy
third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.hBase for all resource containers (hidden from visual tree)
third_party/blink/renderer/core/layout/svg/svg_resources.hSVGResources::GetClient(), ReferenceBoxForEffects()
third_party/blink/renderer/core/paint/svg_shape_painter.ccCore shape paint path
third_party/blink/renderer/core/paint/svg_container_painter.ccGroup paint traversal
third_party/blink/renderer/core/paint/svg_object_painter.hShared utilities: paint server application, resource subtree painting

On this page