Skip to content

SVG Support

Dragon edited this page Jun 4, 2026 · 2 revisions

SVG Support

PhpPdf includes a built-in SVG renderer that converts SVG markup into native PDF drawing operations. You embed an SVG the same way you embed a raster image - via the Images API - and the renderer handles the rest. The SVG fills its placement rectangle; if you pass only w or only h to $page->image(), the other dimension is derived from the viewBox aspect ratio so the output is undistorted.

use DragonOfMercy\PhpPdf\Image;

// Inline SVG string.
$icon = Image::fromSvgString(
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">'
    . '<path d="M12 2L2 22h20z" fill="currentColor"/>'
    . '</svg>',
);
$page->image($icon, x: 80, y: 20, w: 20);

// Base64 data URI (e.g. from a JS export).
$brand = Image::fromBase64('data:image/svg+xml;base64,...');
$page->image($brand, x: 20, y: 80, w: 60);

Supported features

Paths and shapes

  • All path commands: M, L, H, V, C, S, Q, T, A, Z and their lowercase relative variants.
  • Basic shapes: <rect> (with optional rx / ry rounded corners), <circle>, <ellipse>, <line>, <polyline>, <polygon>.

Transforms and structure

  • Transforms: matrix(), translate(), scale(), rotate() (with optional center point), skewX(), skewY(); composition is left-to-right.
  • viewBox on the root <svg> element: the SVG fills its placement rectangle. Passing only w or only h to $page->image() derives the other side from the viewBox aspect.
  • Groups (<g>), <defs> + <use> references with cycle detection.

Paint state

  • Solid fill and stroke: 147 named CSS colors, #abc / #aabbcc hex, rgb(), rgba(), currentColor.
  • stroke-width, stroke-linecap, stroke-linejoin, stroke-miterlimit.
  • stroke-dasharray + stroke-dashoffset.
  • fill-rule (nonzero | evenodd).
  • fill-opacity, stroke-opacity, opacity (multiplicative).

Gradients

  • <linearGradient> and <radialGradient>: objectBoundingBox and userSpaceOnUse units, gradientTransform, href stop inheritance.
  • Multi-stop gradients on fill and stroke.
  • spreadMethod pad (default), reflect, and repeat - all honored by rewriting non-pad gradients into an equivalent pad-mode gradient with extended coordinates and replicated stops.
  • Per-stop stop-opacity (including fade-to-transparent): rendered as a coupled grayscale alpha shading wrapped in a PDF /SMask /S /Luminosity soft mask Form. Works for linear, radial, fill, and stroke.

Styling

  • Presentation attributes AND inline style="..." (inline > direct > inherited precedence).
  • CSS: internal <style> stylesheets with type, class, id, universal, and compound selectors (comma-separated groups), cascaded by specificity then source order.

Images

  • Embedded raster <image> via PNG or JPEG data URI: x / y / width / height, preserveAspectRatio (meet / slice / none), transform, opacity, and intra-SVG dedup of identical data URIs.

Text

  • <text> and <tspan> rendered as real, selectable PDF text using the 14 standard fonts.
  • font-family (generic families serif / sans-serif / monospace and the standard family names), font-weight (bold), font-style (italic).
  • font-size (unitless / px / pt / em / %).
  • text-anchor (start / middle / end).
  • x / y / dx / dy positioning.
  • Fill and stroke (solid colors), opacity, transforms.
  • Font property inheritance through <g>.
  • Custom TTF/OTF fonts registered in the document via Document::registerFontFamily() are resolved by font-family name and automatically subsetted.

clipPath

  • clip-path="url(#id)" referencing a <clipPath> with clipPathUnits userSpaceOnUse or objectBoundingBox.
  • Applies to any element (shape, group, image, text).
  • Clip content: basic shapes plus <use>, with clip-rule nonzero / evenodd.
  • The clip is the union of the clip children, emitted via the native PDF clip (W / W*).

pattern

  • fill="url(#pat)" / stroke="url(#pat)" rendered via PDF native /PatternType 1 tiling.
  • patternUnits userSpaceOnUse or objectBoundingBox (default), patternTransform, href attribute inheritance, optional viewBox.
  • Pattern children: basic shapes, <g>, and <use> references.

symbol

  • <symbol viewBox="..." preserveAspectRatio="..."> referenced via <use href="#id" x y width height>.
  • Use's width / height (defaulting to the symbol's viewBox dimensions) and preserveAspectRatio (meet / slice / align) determine the viewBox-to-use-box matrix.
  • Symbol elements never render directly (defs-only).

marker

  • marker-start / marker-mid / marker-end and the marker shorthand on <line>, <polyline>, <polygon>, <path>.
  • <marker viewBox markerWidth markerHeight refX refY markerUnits orient> with markerUnits strokeWidth (default) or userSpaceOnUse.
  • orient: numeric angle, auto, or auto-start-reverse.
  • Tangents computed per shape: line endpoints, polyline/polygon bisectors at vertices, path with bezier endpoint tangents.

mask

  • mask="url(#id)" rendered as a PDF luminance soft mask (/SMask with /S /Luminosity).
  • maskUnits and maskContentUnits userSpaceOnUse or objectBoundingBox (defaults per SVG spec).
  • Mask region x / y / width / height honored.
  • Mask children: basic shapes, <g>, <use>, <image>, <text>.

filter

  • filter="url(#id)" rendered via a hybrid raster approach: the filtered region is rasterized to an embedded DeviceRGB image (+ DeviceGray /SMask alpha channel); the rest of the document stays vector.
  • filterUnits objectBoundingBox (default) and userSpaceOnUse.
  • Supported primitives: feGaussianBlur, feOffset, feFlood, feMerge, feBlend (normal / multiply / screen / darken / lighten), feComposite (over / in / out / atop / xor / arithmetic), feColorMatrix (matrix / saturate / hueRotate / luminanceToAlpha), feDropShadow.
  • SourceGraphic / SourceAlpha inputs and named result chaining.
  • Rasterized content inside a filter: shapes, paths, solid fills, opacity, groups / <use>, linear / radial gradients, and PNG <image>.
  • <text> inside a filtered element is drawn as sharp, unfiltered vector text on top (a documented approximation).
  • Resolution defaults to ~300 DPI relative to the SVG viewBox units, capped at 2000 px per side. Tune it via Document::setSvgFilterResolution(int $dpi).

Not supported (silently skipped per SVG spec fallback)

  • Per-character positioning (x="10 20 30" lists), letter-spacing / word-spacing, dominant-baseline / baseline-shift, xml:space="preserve". Characters outside WinAnsi encoding render as ?.
  • Mesh gradients.
  • <text> / <image> inside a <pattern>, patternContentUnits=objectBoundingBox, preserveAspectRatio on a pattern's viewBox, nested paint-server fills inside pattern children, and uncolored (PaintType 2) tiling.
  • fill="url(#x)" referencing an unsupported paint server falls back to black per spec.
  • Filter primitives not yet implemented: feTile, feImage, feMorphology, feConvolveMatrix, feTurbulence, feDisplacementMap, feDiffuseLighting, feSpecularLighting. Nested clipPath / mask / pattern / filter inside a filtered element are ignored.
  • color-interpolation-filters="sRGB" is not honored (filters always run in linearRGB).
  • BackgroundImage / BackgroundAlpha / FillPaint / StrokePaint filter inputs (treated as transparent).
  • JPEG <image> inside a filter requires ext-gd; without it that image is skipped.
  • <text> as clip content; nested clip-path on children of a <clipPath>.
  • transform on the same element that also carries clip-path: the transform applies to content but not to the clip region (resolved in the parent user space). CSS clip-path shape functions (inset(), circle(), polygon()); only url(#id) references are honored.
  • Nested markers (inner markers stripped). Markers on <rect> / <circle> / <ellipse>. Markers inside a <symbol>.
  • preserveAspectRatio (meet / slice / align) on the root <svg> element: the SVG always fills its placement rectangle. (preserveAspectRatio on <image> elements is supported.)
  • CSS combinators (g rect, g > rect), pseudo-classes / elements, and attribute selectors in <style>.
  • CSS !important, the CSS transform property (use the SVG transform attribute), at-rules (@media, @import, @font-face), and external stylesheets.
  • Symbol's intrinsic width / height attributes (use's width / height is required to size the symbol).
  • Scripts, animations, <foreignObject>.
  • <image> supports only PNG / JPEG data URIs. External href (file paths or URLs) is ignored. Other data URI formats (GIF, WebP, nested SVG) are ignored. Images with non-positive width or height are ignored.

Hard limits (raise PdfException)

Limit Value
SVG document size 5 MiB raw
Nesting depth 32 levels
Element count 50 000 elements
<use> cycle Any cycle raises immediately
Missing viewBox When both width and height are also absent
Malformed XML Root must be <svg> in the SVG namespace

See also

Clone this wiki locally