SVG Profile
Purpose
The SVG Profile defines the constrained subset of SVG that a Service uses to deliver 2D vector
graphics to Runtimes. It exists so that graphics semantics — how a stroke's ends look, how two
segments join, what "round" means — are data a Producer emits once, not logic each Runtime
re-implements. It is promoted into the shared vocabulary the same way Drawing Operation was
promoted out of Paint's own private mark format (see README.md, drawing-operation.md):
Paint is its first consumer, but the profile itself names no Service and assumes no Service.
A drawing_surface Object's own editable state remains a Drawing Operation list (see
drawing-operation.md). The SVG Profile is not a replacement for that state — it is a rendering
representation derived from it. The owning Service's canonical data is still the thing a member
edits, undoes, and searches; the SVG Profile is what a Runtime is handed to draw.
Ownership
> Producers author conforming SVG. Runtimes render conforming SVG. Runtimes do not reconstruct
> graphics semantics from Service-specific source data.
A Producer (the Service that owns the graphics being represented — Paint today, any future
Service with 2D vector content later) is responsible for emitting markup that conforms to this
profile. A Runtime's responsibility is limited to rendering conforming markup faithfully; it
never inspects a Producer's own operation/geometry data to decide how something should look, and
it never derives path data, joins, caps, or fill from anything other than the markup itself. This
is the same boundary Drawing Operation already draws between "Service owns semantics" and
"Runtime owns presentation" (see drawing-operation.md, Ownership) — the SVG Profile is what
that presentation-facing representation actually contains.
Structure
Root element
A conforming document is a single <svg> root element:
- xmlns — always http://www.w3.org/2000/svg. Required, so the markup is a well-formed
standalone SVG document regardless of how a Runtime chooses to parse or embed it.
- viewBox — always "0 0 {width} {height}", where width/height match the owning
drawing_surface Object's own content.width/content.height (see object.md, Recognized
content format: drawing_surface). This is the coordinate system every child element's
coordinates are expressed in — a Producer emits geometry coordinates unchanged from its own
canonical data; no coordinate transform is needed.
- width and height presentation attributes on the root element are not part of this profile
and must not be emitted. Presentation sizing is a Runtime layout concern, not part of the
representation; the viewBox alone defines the coordinate space.
No other root-level attribute is part of this profile.
Child elements
The only permitted child element in this revision is path:
- d — path data. Permitted commands in this revision are M (moveto) and L (lineto) only,
absolute form, one M followed by one or more L. This matches the polyline geometry a
Drawing Operation's geometry.points already stores; no curve fitting or smoothing happens at
this layer. Example: M10.00,20.00 L24.00,32.00 L40.00,35.50.
- stroke — a 6-digit hex color, ^#[0-9a-f]{6}$, lowercase. Matches the color form Drawing
Operation's style.color already validates (see drawing-operation.md).
- stroke-width — a positive finite number, in the same coordinate units as viewBox.
- stroke-linecap — permitted value in this revision: round only.
- stroke-linejoin — permitted value in this revision: round only.
- fill — permitted value in this revision: none only. This profile carries stroked marks
only; filled shapes are not part of this revision.
No other element and no other attribute is part of this profile. stroke-linecap and
stroke-linejoin are pinned to a single value rather than left open because leaving them open
is exactly the gap that let each Runtime's independent implementation diverge in the first
place — a later revision may widen the permitted value set, but a Producer never emits a value
outside what the current revision permits.
Ordering and layering
Each path element corresponds to exactly one Drawing Operation. path elements appear in the
same order as their source Drawing Operations. Document order is paint order: a later path
element layers on top of earlier ones. This matches how both of today's Runtime-specific
renderers already draw operations — in array order — so no visual behavior changes, only how a
Runtime arrives at the result.
Coordinates and numeric formatting
- Coordinates are plain numbers in the viewBox coordinate space: document pixels, origin at
the top-left, y increasing downward — the same convention geometry.points already uses.
- A Producer emits numbers with a fixed precision of 2 decimal places, using . as the decimal
separator, no thousands separators, no scientific notation, and no NaN/Infinity. A Runtime
is not required to accept any other numeric form.
Escaping and validation
A Producer emits only values it has already validated against this profile's permitted forms
(the hex color pattern, the positive-number pattern, the fixed literal values for linecap /
linejoin / fill). Nothing in this revision's permitted attribute set requires free-text
escaping, because nothing in it accepts free text — a Producer that later adds an attribute
accepting less constrained content is responsible for XML-escaping it and must not pass through
unvalidated data from any source, including its own stored operations, without revalidating
against this profile first. A Producer never emits, and a Runtime never renders, markup sourced
from anything other than the Producer's own already-validated canonical data.
Unsupported SVG
A Runtime that encounters an element or attribute outside this profile ignores that construct
and renders the remainder of an otherwise-conforming document; it does not refuse to render the
whole document, and it does not fail, over a single unrecognized addition. This covers a Runtime
lagging adoption of a later profile revision — the profile is expected to grow by widening
permitted values or adding elements over time, and a Runtime built against an earlier revision
stays correct by rendering what it understands. This is distinct from markup that is not
well-formed SVG/XML at all, which is a Producer defect, not a profile compatibility case, and is
handled the same way any other Service-side failure is (see error.md).
Resource content
A graphics.svg Resource (see resource.md) holds one rendered SVG document conforming to this
profile:
{
"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 768\"><path d=\"M10.00,20.00 L24.00,32.00\" stroke=\"#000000\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\" fill=\"none\"/></svg>"
}
Like drawing.marks and drawing.preview (see drawing-operation.md), a graphics.svg
Resource is immutable: a change to the underlying Drawing Operations produces a new
graphics.svg Resource, not a mutation of the existing one.
Characteristics
- A graphics.svg Resource is a projection, not additional state. Everything in it is fully
derived from its owning Object's own canonical data; nothing may appear in it that the owning
Service's canonical data does not already contain.
- This profile identifies no Service. A graphics.svg Resource carries no indication of which
Service produced it beyond the identity of the Object it belongs to.
- This profile is versioned by addition only: a later revision may add elements, attributes, or
permitted values; it does not repurpose or remove what an earlier revision already permits, so
a Producer and a Runtime built against different revisions remain compatible (see Unsupported
SVG, above).
- A Runtime renders conforming SVG; it does not author it, and it does not read a Producer's
Service-specific source data to decide what to draw.
Integration
A drawing_surface Object's content.graphics_resource names its current graphics.svg
Resource (see object.md, Recognized content format: drawing_surface). Paint is the first
Producer to populate it.