On this page:
parse-length
parse-transform-list
parse-preserve-aspect-ratio
compute-viewbox-matrix
viewport-instantiation-matrix

5 Geometry, Viewports, and Transforms🔗ℹ

This group covers the pieces that turn SVG’s various coordinate-system concepts — length units, the transform attribute, viewBox, and preserveAspectRatio into plain numbers and the #(a b c d e f) matrix format dc<%>’s own transform method accepts.

Every matrix in this document and in svg/svg uses that same six-element vector format throughout, matching dc<%>’s convention exactly:

x' = a·x + c·y + e

y' = b·x + d·y + f

so a matrix produced by one of these functions can always be passed directly to (send dc transform matrix).

procedure

(parse-length s    
  [default    
  #:reference reference])  real?
  s : (or/c string? #f)
  default : real? = 0
  reference : (or/c real? #f) = #f
Parses an SVG/CSS length string — a number, optionally followed by a unit (px, pt, pc, in, cm, mm, em, or %) — into a plain number of user units (CSS pixels). em is treated as a fixed 16px rather than resolved against the current font size (a disclosed simplification: em in practice is rare outside font-size itself, which this library doesn’t parameterize this way). Returns default if s is #f or doesn’t match the length grammar at all.

A percentage resolves against reference if one is given ("50%" with reference 200 gives 100); with no reference, a percentage is treated as a literal number instead of raising or resolving to default (so "50%" with no reference gives 50) — a disclosed simplification for the cases in this library that don’t thread a containing-viewport length through to resolve percentages precisely.

Examples:
> (parse-length "10px")

10

> (parse-length "1in")

96.0

> (parse-length "50%" #:reference 200)

100.0

> (parse-length #f 42)

42

procedure

(parse-transform-list s)

  (listof (cons/c symbol? (listof real?)))
  s : (or/c string? #f)
Parses an SVG transform attribute value — a space-separated list of name(args...) function calls (translate, scale, rotate, skewX, skewY, matrix) — into a list of (name . args) pairs, in source order. Doesn’t build a matrix itself; combine with the transform semantics your own code needs, or see the file’s internal apply-transform-attr! for how svg/svg applies these to a dc<%> (not exported, since it mutates a dc<%> directly rather than returning a value).

Example:
> (parse-transform-list "translate(10,20) rotate(45)")

'((translate 10 20) (rotate 45))

a faint gray square at its original position, and the same square translated and rotated, in green

Note on rotate: SVG defines a positive angle as clockwise in its y-down coordinate system. dc<%>’s own rotate method turns out to spin the opposite direction for a positive angle (confirmed empirically) — code building a matrix from this list’s rotate entries directly, rather than using dc<%>’s rotate method, needs to account for that sign difference to match SVG’s convention. (svg/svg’s own internal transform-application code does this already; it’s only a concern if you’re building your own matrix from this parsed list.)

procedure

(parse-preserve-aspect-ratio s)  any/c

  s : (or/c string? #f)
Parses a preserveAspectRatio attribute value (e.g. "xMidYMid meet", "xMinYMax slice", "none") into an opaque value meant only to be passed to compute-viewbox-matrix’s par argument — there’s no public accessor for its fields, and no exported constructor other than this function. Defaults to "xMidYMid meet" (SVG’s own default) if s is #f or empty; the optional leading "defer" keyword is accepted and ignored (this library never has more than one applicable preserveAspectRatio in play, so deferring to another one never applies).

Examples:
> (parse-preserve-aspect-ratio "xMidYMid slice")

(preserve-ar "xMidYMid" 'slice)

> (parse-preserve-aspect-ratio #f)

(preserve-ar "xMidYMid" 'meet)

procedure

(compute-viewbox-matrix vb-x 
  vb-y 
  vb-w 
  vb-h 
  vp-w 
  vp-h 
  par) 
  (vector/c real? real? real? real? real? real?)
  vb-x : real?
  vb-y : real?
  vb-w : real?
  vb-h : real?
  vp-w : real?
  vp-h : real?
  par : any/c
Computes the transform matrix that maps a viewBox="vb-x vb-y vb-w vb-h" coordinate system into a vp-w×vp-h viewport, honoring par’s alignment and meet-or-slice behavior — the exact algorithm the SVG spec itself specifies. This is what read-svg-document calls for the document root, and what viewport-instantiation-matrix calls for nested viewports (<svg>, <symbol>, <marker>, <pattern>, <image>); call it directly if you’re building a custom nested-viewport mechanism of your own and want the exact same alignment/scaling semantics.

A non-positive vb-w or vb-h returns the identity matrix (an invalid viewBox per spec is treated as if there were none).

Example:
> (compute-viewbox-matrix 0 0 100 100 200 200 (parse-preserve-aspect-ratio #f))

'#(2 0 0 2 0 0)

A 100×100 viewBox mapped into a 140×100 viewport, under "xMidYMid meet" (left) versus "xMidYMid slice" (right) — the dashed outline is the viewport; the blue square and red circle are the viewBox content, identical in both:

meet: the content is scaled to fit entirely within the viewport, letterboxed left and right slice: the content is scaled to fill the viewport entirely, cropped left and right

procedure

(viewport-instantiation-matrix target-attrs 
  override-width 
  override-height) 
  (vector/c real? real? real? real? real? real?)
  target-attrs : (listof (list/c symbol? string?))
  override-width : (or/c real? #f)
  override-height : (or/c real? #f)
Computes the viewBox matrix for an element that establishes its own nested viewport (a <symbol> or <svg> referenced via <use>, or a nested <svg> directly) — reading viewBox, width, height, and preserveAspectRatio off target-attrs (an xexpr-style attribute list), with override-width/override-height taking precedence over the target’s own width/height attributes when given (used to implement <use width="..." height="..."> overriding a referenced <symbol>’s own dimensions). Returns the identity matrix if target-attrs has no viewBox at all.

Example:
> (viewport-instantiation-matrix '((viewBox "0 0 100 100") (width "50") (height "50"))
                                  #f #f)

'#(1/2 0 0 1/2 0 0)

Uses the exact same mapping algorithm as compute-viewbox-matrix above (see that entry’s images) — the two functions differ only in where their inputs come from: raw numbers there, an element’s own attribute list here.