svg/svg renders <text>/<tspan> by converting text to path
geometry via dc-path%’s own text-outline (not
dc<%>’s draw-text), so text gets the same
gradient/pattern/dasharray/opacity support as any other shape, for free.
<textPath> (laying text along a referenced shape’s own geometry, via an
arc-length parameterization of the path) and xml:space="preserve"
(disabling the default whitespace-collapsing behavior, with correct
XML-style inheritance down the tree) are both supported as well. None of
this rendering logic is exported directly, though — there is no single
"parse/render a whole <text> element" function in this API, since it
involves rendering-time context (pen position or arc-length position along a
path, inherited font state) beyond what a standalone parser can usefully
capture. The functions in this group are the small, self-contained parsers
that turn SVG/CSS text-related attribute values into the symbols and
structures font% and the rest of that internal pipeline expect.
parse-number-list and collapse-whitespace, while used
elsewhere in the file for text-specific purposes (<text>’s
x/y/dx/dy attributes, which accept a list of numbers —
one per character — and collapsing runs of whitespace in text content per
SVG’s whitespace-handling rules), are general-purpose enough to be useful
outside text too; parse-number-list in particular is reused for
filter primitive attributes like stdDeviation and radius elsewhere
in the file.
Parses a
font-family value —
a comma-separated list such as
"Georgia, 'Times New Roman', serif" —
into two values: a specific
font
face (the first non-generic name in the list, quotes stripped,
or
#f if the list is all generic keywords), and a
family
(one of
'roman,
'swiss,
'modern,
'script,
'decorative, or
'default) —
the two pieces
font%’s constructor wants separately, since it distinguishes an
actual installed font name from an abstract fallback bucket. The family is
taken from the first CSS generic keyword found anywhere in the list
(
"serif" →
'roman,
"sans-serif" →
'swiss,
"monospace" →
'modern,
"cursive" →
'script,
"fantasy" →
'decorative), defaulting to
'default
if none appears.
Examples:
Text rendered with the results of parse-font-family/
parse-font-weight/parse-font-style — normal, bold, and
italic:

Parses a
font-weight value:
"bold"/
"normal" give the
matching symbol; a numeric CSS weight (e.g.
"600") is passed through
as an integer, since
racket/draw’s
font% accepts an integer
weight directly rather than only the two named levels. Anything else
(including an absent value) gives
'normal.
Parses a
font-style value:
"italic" gives
'italic,
"oblique" gives
'slant (the symbol
font% uses for
the same concept), anything else gives
'normal.
Parses a text-anchor value ("start", "middle", or
"end") into the matching symbol; anything else (including an absent
value) gives 'start, SVG’s default.
The same text, anchored 'start, 'middle, and 'end
relative to the same reference point (the black dot; the dashed line marks
its x position):

Parses a comma-or-whitespace-separated list of numbers — the
format used by <text>’s x/y/dx/dy attributes, and by
filter-primitive numeric attributes like stdDeviation and radius
(which accept either one number or two, for separate x/y values). Non-numeric
tokens are silently dropped rather than raising; #f or an
empty/whitespace-only string give '().
Examples:
Collapses every run of one or more spaces, tabs, carriage returns, or
newlines in s into a single space — SVG’s default
xml:space="default" whitespace handling for text content —
without trimming leading or trailing whitespace (trimming is handled
separately, only at the true start of a whole <text> subtree, since a
leading space on an inner <tspan> still needs to be preserved as the
word-separator it is when concatenated after a previous run of text).
Example: