svg

Standalone SVG scene graph and renderer

svg
graphics
moon add Milky2018/svg@0.5.2
Download zip
Author
Version
0.5.2
License
Apache-2.0
Last updated
24 days ago
Downloads
227

Dependencies

README

#Milky2018/svg

A standalone SVG parser and deterministic CPU renderer for MoonBit. It renders SVG markup or an SVGDocument into an owned RGBA Image.

#Install

moon add Milky2018/svg

#Migrating from 0.3.x

Version 0.4.0 removes the combinatorial document, node, scene, and resolver rendering functions. Rendering now goes through an owned Image facade, and image resolution is configured with RenderOptions.

0.3.x API0.4.0 replacementNotes
parse_svg(source)parse_svg_document(source).map(fn(document) { document.root() })Use the document result when resources are needed.
parse_svg_document(source)UnchangedReturns SVGDocument?.
render_svg(source, width, height, options)UnchangedReturns RenderResult with an owned image and diagnostics.
render_svg_to_image(source, width, height)UnchangedRemains the simple Image? convenience.
render_svg_to_image_with_resolver(...)render_svg(source, width, height, RenderOptions::with_image_resolver(resolver))Read .image and inspect .diagnostics; parse failure is reported diagnostically.
render_svg_document_to_image(...)render_svg_document(document, width, height, RenderOptions::default()).imageUse the structured result when diagnostics matter.
render_svg_document_to_image_with_resolver(...)render_svg_document(document, width, height, RenderOptions::with_image_resolver(resolver)).imageResolver configuration is no longer a separate function family.
render_svg_node_to_image*render_svg_document(SVGDocument::new(node), width, height, options).imageRegister referenced resources on the document before rendering.
render_svg_scene_to_image* and SceneNo direct replacementMigrate authored content to SVGDocument and SVGNode.
PixelSetter, RenderContext, context-driven .render, and public raster_* functionsNo direct replacementThe renderer owns its target image; use the rendering facade.
render_path_commands_to_image(...)UnchangedRemains the expert direct-path entry point.

#Parse and Render

///|
test "README: render SVG markup" {
let source = "<svg width=\"10\" height=\"10\"><rect x=\"1\" y=\"1\" width=\"8\" height=\"8\" fill=\"red\"/></svg>"
let image = render_svg_to_image(source, 16, 16)
assert_true(image is Some(_))
}

Use the document API when the parsed resource tables or root node are needed:

///|
test "README: parse and render a document" {
let source = "<svg width=\"4\" height=\"4\"><circle cx=\"2\" cy=\"2\" r=\"2\"/></svg>"
match parse_svg_document(source) {
Some(document) => {
let result = render_svg_document(document, 4, 4, RenderOptions::default())
assert_eq(result.image.width(), 4)
}
None => fail("expected a valid SVG document")
}
}

#Structured Results

render_svg always returns an image and typed diagnostics. A malformed document produces a transparent image plus a ParseFailed diagnostic instead of requiring a separate error channel.

///|
test "README: inspect structured diagnostics" {
let result = render_svg("<svg><broken></svg>", 8, 8, RenderOptions::default())
assert_eq(result.image.width(), 8)
assert_true(result.diagnostics.length() > 0)
assert_eq(result.diagnostics[0].kind, ParseFailed)
}

#Host-Provided Raster Images

The renderer passes each <image href> string to the resolver. The host owns file or network access, decoding, caching, and policy; return None when a resource cannot be resolved.

///|
test "README: resolve a raster image" {
let options = RenderOptions::with_image_resolver(fn(href) {
if href == "asset.png" {
Some(Image::filled(2, 2, Color::rgba(255, 0, 0, 128)))
} else {
None
}
})
let result = render_svg(
"<svg width=\"2\" height=\"2\"><image href=\"asset.png\" width=\"2\" height=\"2\"/></svg>",
2, 2, options,
)
assert_eq(result.image.width(), 2)
assert_eq(result.diagnostics.length(), 0)
}

Resolved images participate in preserveAspectRatio, affine transforms, clipping, opacity, and compositing. External SVG resource documents are not resolved by this callback.

#Static Render Environment and Text Resources

RenderEnvironment makes every non-document input to a snapshot explicit: the document base URI, device pixel ratio, preferred color scheme, animation sample time, and per-element interaction state. text_resource_resolver supplies CSS or SVG text after URI resolution. The library never reads files or performs network requests.

///|
test "README: render with host text resources and static state" {
let options = RenderOptions::{
..RenderOptions::default(),
environment: {
..RenderEnvironment::default(),
base_uri: "mem:/document.svg",
color_scheme: Dark,
sample_time_seconds: 0.5,
element_state_resolver: Some(fn(id) {
if id == "target" {
{ ..ElementState::none(), hover: true }
} else {
ElementState::none()
}
}),
},
text_resource_resolver: Some(fn(uri, kind) {
match (uri, kind) {
("mem:/theme.css", Stylesheet) => Some("#target:hover { fill: red; }")
_ => None
}
}),
}
let source = "<?xml-stylesheet href=\"theme.css\"?><svg width=\"2\" height=\"2\"><rect id=\"target\" width=\"2\" height=\"2\"/></svg>"
let result = render_svg(source, 2, 2, options)
assert_eq(result.diagnostics.length(), 0)
}

External CSS supports xml-stylesheet processing instructions and recursive @import. External SVG fragments used by <use>, paint servers, clip paths, masks, filters, patterns, and markers share the same bounded, cached resolver. Relative references use the containing document or stylesheet URI. Missing, cyclic, oversized, over-deep, or over-count resources fail closed and produce typed diagnostics. Defaults allow 16 nested resources, 64 distinct resources, and 16 MiB of resolved text; callers may lower these limits in RenderOptions.

The explicit sample time evaluates CSS keyframes without a clock. The initial interpolation set covers geometry lengths, affine transforms, colors, opacity, and paint opacity; other properties are discrete. Paused animations have a deterministic hold time of zero because a static document has no prior running timeline. SMIL, scripting, DOM mutation, event dispatch, and live restyling are outside this API.

#Main API

  • Parsing: parse_svg_document, parse_path, parse_transform
  • Rendering: render_svg, render_svg_document, render_svg_to_image
  • Results: RenderResult, RenderDiagnostic, RenderOptions, RenderEnvironment
  • Data: SVGDocument, SVGNode, Shape, Image, Color
  • Direct paths: render_path_commands_to_image

The renderer owns its pixel target. Former low-level context and raster functions are implementation details and are not public APIs.

#Static CSS Support

Presentation attributes, embedded <style> rules, and inline declarations use the shared Milky2018/css cascade. Supported behavior includes selector specificity and source order, !important, inheritance, CSS-wide keywords, inherited custom properties and nested var() fallbacks, currentColor, and CSS Color 3 named, RGB/RGBA, HSL/HSLA, and hex colors.

The same computed path covers SVG paint and stroke properties, markers, paint order, fill and clip rules, geometry properties, transforms, gradient stops, and basic text font-size. Length expressions retain their unit and percentage semantics until an SVG axis, nested viewport, font context, and outer CSS viewport are available.

This is a static-document model, not a browser DOM. Host-provided external stylesheets, forced interaction pseudo-classes, media inputs, and sampled CSS keyframes are supported as immutable snapshot inputs. Scripting, dynamic restyling, cascade layers, SMIL, event dispatch, and a browser animation clock are intentionally excluded.

#Rendering Contract

The implementation aims for internally consistent SVG semantics and stable software output. It does not guarantee pixel-for-pixel parity with Chromium, Skia, or platform text engines. Nested SVG text layout remains outside the supported core.

#License and Attribution

Milky2018/svg is distributed under Apache-2.0 and depends on the separately published Milky2018/css module. See NOTICE for the CSS dependency's source origin and attribution.

#
Align

pub(all) enum Align {
None
XMinYMin
XMidYMin
XMaxYMin
XMinYMid
XMidYMid
XMaxYMid
XMinYMax
XMidYMax
XMaxYMax
} derive(Eq,
Debug
)

preserveAspectRatio alignment values
impl Show for Align

#
BlendMode

pub(all) enum BlendMode {
Normal
Multiply
Screen
Overlay
Darken
Lighten
ColorDodge
ColorBurn
HardLight
SoftLight
Difference
Exclusion
Hue
Saturation
ColorMode
Luminosity
} derive(Eq,
Debug
)

CSS mix-blend-mode values

#
BoundingBox

pub(all) struct BoundingBox {
min_x : Double
min_y : Double
max_x : Double
max_y : Double
}

Bounding box for a shape

#
BoundingBox::contains_point

fn BoundingBox::contains_point(self : BoundingBox, x : Double, y : Double) -> Bool

Check if this bounding box contains a point

#
BoundingBox::empty

fn BoundingBox::empty() -> BoundingBox

#
BoundingBox::expand_by_point

fn BoundingBox::expand_by_point(self : BoundingBox, x : Double, y : Double) -> BoundingBox

#
BoundingBox::from_rect

fn BoundingBox::from_rect(x : Double, y : Double, w : Double, h : Double) -> BoundingBox

#
BoundingBox::height

fn BoundingBox::height(self : BoundingBox) -> Double

#
BoundingBox::intersects

fn BoundingBox::intersects(self : BoundingBox, other : BoundingBox) -> Bool

Check if two bounding boxes intersect

#
BoundingBox::is_empty

fn BoundingBox::is_empty(self : BoundingBox) -> Bool

#
BoundingBox::union

fn BoundingBox::union(self : BoundingBox, other : BoundingBox) -> BoundingBox

#
BoundingBox::width

fn BoundingBox::width(self : BoundingBox) -> Double

#
ClipPath

pub(all) struct ClipPath {
id : String
shape : Shape
content : Array[SVGNode]
transform : Transform
clip_rule : FillRule
units : ClipPathUnits
}

Clip path definition

#
ClipPath::new

fn ClipPath::new(id : String, shape : Shape) -> ClipPath

#
ClipPath::with_transform

fn ClipPath::with_transform(id : String, shape : Shape, transform : Transform) -> ClipPath

#
ClipPathUnits

pub(all) enum ClipPathUnits {
UserSpaceOnUse
ObjectBoundingBox
} derive(Eq,
Debug
)

Clip path units for coordinate system

#
Color

pub(all) struct Color {
r : Int
g : Int
b : Int
a : Int
} derive(
Debug
)

RGB Color (0-255 range)

#
Color::black

fn Color::black() -> Color

#
Color::is_transparent

fn Color::is_transparent(self : Color) -> Bool

#
Color::rgb

fn Color::rgb(r : Int, g : Int, b : Int) -> Color

#
Color::rgba

fn Color::rgba(r : Int, g : Int, b : Int, a : Int) -> Color

#
Color::transparent

fn Color::transparent() -> Color

#
Color::white

fn Color::white() -> Color

#
ComponentTransferFunction

pub(all) enum ComponentTransferFunction {
TransferIdentity
TransferTable(Array[Double])
TransferDiscrete(Array[Double])
TransferLinear(slope~ : Double, intercept~ : Double)
TransferGamma(amplitude~ : Double, exponent~ : Double, offset~ : Double)
} derive(
Debug
)

#
ElementState

pub(all) struct ElementState {
hover : Bool
focus : Bool
active : Bool
focus_visible : Bool
focus_within : Bool
} derive(Eq,
Debug
)

#
ElementState::none

#
FillRule

pub(all) enum FillRule {
NonZero
EvenOdd
} derive(Eq,
Debug
)

Fill rule for paths and polygons
impl Show for FillRule

#
Filter

pub(all) enum Filter {
Blur(Double)
DropShadow(Double, Double, Double, Color)
Brightness(Double)
Contrast(Double)
Grayscale(Double)
Sepia(Double)
HueRotate(Double)
Invert(Double)
Saturate(Double)
ColorMatrix(FixedArray[Double])
}

Filter types

#
FilterChannel

pub(all) enum FilterChannel {
ChannelR
ChannelG
ChannelB
ChannelA
} derive(Eq,
Debug
)

#
FilterCompositeOperator

pub(all) enum FilterCompositeOperator {
CompositeOver
CompositeIn
CompositeOut
CompositeAtop
CompositeXor
CompositeArithmetic
} derive(Eq,
Debug
)

#
FilterEdgeMode

pub(all) enum FilterEdgeMode {
EdgeDuplicate
EdgeWrap
EdgeNone
} derive(Eq,
Debug
)

#
FilterGraph

pub(all) struct FilterGraph {
id : String
primitives : Array[FilterGraphPrimitive]
units : MaskUnits
primitive_units : MaskUnits
x : Double
y : Double
width : Double
height : Double
x_is_percent : Bool
y_is_percent : Bool
width_is_percent : Bool
height_is_percent : Bool
}

#
FilterGraphPrimitive

pub(all) enum FilterGraphPrimitive {
GraphColorMatrix(input~ : String, result~ : String, matrix~ : FixedArray[Double])
GraphGaussianBlur(input~ : String, result~ : String, radius_x~ : Double, radius_y~ : Double)
GraphOffset(input~ : String, result~ : String, dx~ : Double, dy~ : Double)
GraphBlend(input~ : String, input2~ : String, result~ : String, mode~ : BlendMode)
GraphComposite(input~ : String, input2~ : String, result~ : String, operator~ : FilterCompositeOperator, k1~ : Double, k2~ : Double, k3~ : Double, k4~ : Double)
GraphFlood(result~ : String, color~ : Color)
GraphMerge(result~ : String, inputs~ : Array[String])
GraphComponentTransfer(input~ : String, result~ : String, red~ : ComponentTransferFunction, green~ : ComponentTransferFunction, blue~ : ComponentTransferFunction, alpha~ : ComponentTransferFunction)
GraphMorphology(input~ : String, result~ : String, radius_x~ : Double, radius_y~ : Double, operator~ : MorphologyOperator)
GraphConvolveMatrix(input~ : String, result~ : String, order_x~ : Int, order_y~ : Int, kernel~ : Array[Double], divisor~ : Double, bias~ : Double, target_x~ : Int, target_y~ : Int, edge_mode~ : FilterEdgeMode, preserve_alpha~ : Bool)
GraphDisplacementMap(input~ : String, input2~ : String, result~ : String, scale~ : Double, x_channel~ : FilterChannel, y_channel~ : FilterChannel)
GraphTurbulence(result~ : String, base_x~ : Double, base_y~ : Double, octaves~ : Int, seed~ : Double, stitch~ : Bool, fractal_noise~ : Bool)
GraphTile(input~ : String, result~ : String)
GraphImage(result~ : String, href~ : String, x~ : Double, y~ : Double, width~ : Double, height~ : Double)
GraphDiffuseLighting(input~ : String, result~ : String, surface_scale~ : Double, diffuse_constant~ : Double, color~ : Color, light~ : FilterLight)
GraphSpecularLighting(input~ : String, result~ : String, surface_scale~ : Double, specular_constant~ : Double, specular_exponent~ : Double, color~ : Color, light~ : FilterLight)
} derive(
Debug
)

#
FilterLight

pub(all) enum FilterLight {
DistantLight(azimuth~ : Double, elevation~ : Double)
PointLight(x~ : Double, y~ : Double, z~ : Double)
SpotLight(x~ : Double, y~ : Double, z~ : Double, points_at_x~ : Double, points_at_y~ : Double, points_at_z~ : Double, exponent~ : Double, limiting_cone_angle~ : Double?)
} derive(
Debug
)

#
Gradient

pub(all) enum Gradient {
Linear(LinearGradient)
Radial(RadialGradient)
}

Gradient definitions

#
GradientStop

pub(all) struct GradientStop {
offset : Double
color : Color
}

Gradient stop (position 0.0-1.0 and color)

#
GradientUnits

pub(all) enum GradientUnits {
UserSpaceOnUse
ObjectBoundingBox
} derive(Eq,
Debug
)

Gradient units coordinate space

#
Image

pub struct Image {
// private fields
}

Image data (RGBA pixels)

#
Image::filled

fn Image::filled(width : Int, height : Int, color : Color) -> Image

Create an image filled with a color

#
Image::from_pixels

fn Image::from_pixels(width : Int, height : Int, source : Array[Color]) -> Image?

Create an image from row-major RGBA pixels when dimensions match exactly.

#
Image::get_pixel

fn Image::get_pixel(self : Image, x : Int, y : Int) -> Color

Get pixel at coordinates

#
Image::height

fn Image::height(self : Image) -> Int

#
Image::new

fn Image::new(width : Int, height : Int) -> Image

Create a new image with specified dimensions

#
Image::set_pixel

fn Image::set_pixel(self : Image, x : Int, y : Int, color : Color) -> Unit

Set pixel at coordinates

#
Image::width

fn Image::width(self : Image) -> Int

#
ImageSampling

pub(all) enum ImageSampling {
Nearest
Bilinear
Bicubic
} derive(Eq,
Debug
)

#
Isolation

pub(all) enum Isolation {
Auto
Isolate
} derive(Eq,
Debug
)

CSS isolation values

#
LineCap

pub(all) enum LineCap {
Butt
Round
Square
} derive(Eq,
Debug
)

impl Show for LineCap

#
LineJoin

pub(all) enum LineJoin {
Miter
Round
Bevel
} derive(Eq,
Debug
)

impl Show for LineJoin

#
LinearGradient

pub(all) struct LinearGradient {
x1 : Double
y1 : Double
x2 : Double
y2 : Double
stops : Array[GradientStop]
spread_method : SpreadMethod
units : GradientUnits
transform : Transform
}

Linear gradient definition

#
LinearGradient::new

fn LinearGradient::new(x1 : Double, y1 : Double, x2 : Double, y2 : Double, stops : Array[GradientStop]) -> LinearGradient

#
Marker

pub(all) struct Marker {
id : String
content : SVGNode
ref_x : Double
ref_y : Double
marker_width : Double
marker_height : Double
orient : MarkerOrient
marker_units : MarkerUnits
view_box : ViewBox?
preserve_aspect_ratio : PreserveAspectRatio
clip_overflow : Bool
}

Marker definition (for line endpoints)

#
Marker::new

fn Marker::new(id : String, content : SVGNode) -> Marker

#
MarkerOrient

pub(all) enum MarkerOrient {
Auto
AutoStartReverse
Angle(Double)
}

#
MarkerUnits

pub(all) enum MarkerUnits {
StrokeWidth
UserSpaceOnUse_
}

#
Mask

pub(all) struct Mask {
id : String
content : Array[SVGNode]
x : Double
y : Double
width : Double
height : Double
x_is_percent : Bool
y_is_percent : Bool
width_is_percent : Bool
height_is_percent : Bool
mask_units : MaskUnits
mask_content_units : MaskUnits
mask_type : MaskType
}

Mask definition for transparency masking

#
Mask::new

fn Mask::new(id : String, content : Array[SVGNode]) -> Mask

#
Mask::with_bounds

fn Mask::with_bounds(id : String, content : Array[SVGNode], x : Double, y : Double, width : Double, height : Double) -> Mask

#
MaskType

pub(all) enum MaskType {
Luminance
Alpha
} derive(Eq,
Debug
)

Mask type - how mask values are interpreted
impl Show for MaskType

#
MaskUnits

pub(all) enum MaskUnits {
UserSpaceOnUse
ObjectBoundingBox
} derive(Eq,
Debug
)

Mask content units

#
MeetOrSlice

pub(all) enum MeetOrSlice {
Meet
Slice
} derive(Eq,
Debug
)

preserveAspectRatio meet/slice
impl Show for MeetOrSlice

#
MorphologyOperator

pub(all) enum MorphologyOperator {
MorphologyErode
MorphologyDilate
} derive(Eq,
Debug
)

#
Paint

pub(all) enum Paint {
None
SolidColor(Color)
LinearGrad(LinearGradient)
RadialGrad(RadialGradient)
CurrentColor
PaintServerRef(String, PaintFallback)
}

Paint style (fill or stroke)

#
PaintFallback

pub(all) enum PaintFallback {
NoPaint
SolidColor(Color)
CurrentColor
}

Paint style (fill or stroke)

#
PaintOrder

pub(all) struct PaintOrder {
order : Array[PaintOrderItem]
} derive(Eq,
Debug
)

SVG paint-order specification.

#
PaintOrder::default

fn PaintOrder::default() -> PaintOrder

#
PaintOrderItem

pub(all) enum PaintOrderItem {
Fill
Stroke
Markers
} derive(Eq,
Debug
)

SVG paint-order components.

#
PathCommand

pub(all) enum PathCommand {
MoveTo(Double, Double)
LineTo(Double, Double)
HorizontalLineTo(Double)
VerticalLineTo(Double)
CurveTo(Double, Double, Double, Double, Double, Double)
SmoothCurveTo(Double, Double, Double, Double)
QuadraticCurveTo(Double, Double, Double, Double)
SmoothQuadraticCurveTo(Double, Double)
ArcTo(Double, Double, Double, Bool, Bool, Double, Double)
ClosePath
MoveToRel(Double, Double)
LineToRel(Double, Double)
HorizontalLineToRel(Double)
VerticalLineToRel(Double)
CurveToRel(Double, Double, Double, Double, Double, Double)
SmoothCurveToRel(Double, Double, Double, Double)
QuadraticCurveToRel(Double, Double, Double, Double)
SmoothQuadraticCurveToRel(Double, Double)
ArcToRel(Double, Double, Double, Bool, Bool, Double, Double)
} derive(
Debug
)

SVG path commands (full SVG 1.1 spec)

#
Pattern

pub(all) struct Pattern {
id : String
x : Double
y : Double
width : Double
height : Double
content : Array[SVGNode]
pattern_units : PatternUnits
pattern_content_units : PatternUnits
transform : Transform
view_box : ViewBox?
preserve_aspect_ratio : PreserveAspectRatio
}

Pattern definition for fills

#
Pattern::new

fn Pattern::new(id : String, width : Double, height : Double, content : Array[SVGNode]) -> Pattern

#
PatternUnits

pub(all) enum PatternUnits {
UserSpaceOnUse
ObjectBoundingBox
}

#
PreferredColorScheme

pub(all) enum PreferredColorScheme {
Light
Dark
} derive(Eq,
Debug
)

#
PreserveAspectRatio

pub(all) struct PreserveAspectRatio {
align : Align
meet_or_slice : MeetOrSlice
}

Complete preserveAspectRatio setting

#
PreserveAspectRatio::default

#
RadialGradient

pub(all) struct RadialGradient {
cx : Double
cy : Double
fx : Double
fy : Double
r : Double
stops : Array[GradientStop]
spread_method : SpreadMethod
units : GradientUnits
transform : Transform
}

Radial gradient definition

#
RadialGradient::new

fn RadialGradient::new(cx : Double, cy : Double, r : Double, stops : Array[GradientStop]) -> RadialGradient

#
RenderDiagnostic

pub(all) struct RenderDiagnostic {
kind : RenderDiagnosticKind
stage : RenderStage
resource : String
node_id : String
}

#
RenderDiagnosticKind

pub(all) enum RenderDiagnosticKind {
ParseFailed
ResourceUnresolved
ResourceCycle
ResourceLimitExceeded
} derive(Eq,
Debug
)

#
RenderEnvironment

pub(all) struct RenderEnvironment {
base_uri : String
device_pixel_ratio : Double
color_scheme : PreferredColorScheme
sample_time_seconds : Double
element_state_resolver : (String) -> ElementState?
}

Static inputs used while parsing and computing an SVG snapshot.

#
RenderEnvironment::default

#
RenderOptions

pub(all) struct RenderOptions {
image_resolver : (String) -> Image??
text_resource_resolver : (String, TextResourceKind) -> String??
environment : RenderEnvironment
max_external_depth : Int
max_external_resources : Int
max_external_bytes : Int
}

#
RenderOptions::default

fn RenderOptions::default() -> RenderOptions

#
RenderOptions::with_image_resolver

fn RenderOptions::with_image_resolver(image_resolver : (String) -> Image?) -> RenderOptions

Return these options with a host callback for decoded raster images.

#
RenderOptions::with_text_resource_resolver

fn RenderOptions::with_text_resource_resolver(text_resource_resolver : (String, TextResourceKind) -> String?) -> RenderOptions

Return these options with a host callback for CSS and SVG text resources.

#
RenderResult

pub(all) struct RenderResult {
image : Image
diagnostics : Array[RenderDiagnostic]
}

#
RenderStage

pub(all) enum RenderStage {
Document
Stylesheet
Paint
Image
Effects
} derive(Eq,
Debug
)

#
SVGDocument

pub struct SVGDocument {
// private fields
}

Parsed SVG document with reusable resources

#
SVGDocument::add_clip_path

fn SVGDocument::add_clip_path(self : SVGDocument, clip : ClipPath) -> Unit

#
SVGDocument::add_definition

fn SVGDocument::add_definition(self : SVGDocument, id : String, node : SVGNode) -> Unit

Register an ordinary SVG node for fragment references such as <use>.

#
SVGDocument::add_filter_graph

fn SVGDocument::add_filter_graph(self : SVGDocument, filter : FilterGraph) -> Unit

#
SVGDocument::add_gradient

fn SVGDocument::add_gradient(self : SVGDocument, id : String, gradient : Gradient) -> Unit

#
SVGDocument::add_marker

fn SVGDocument::add_marker(self : SVGDocument, marker : Marker) -> Unit

#
SVGDocument::add_mask

fn SVGDocument::add_mask(self : SVGDocument, mask : Mask) -> Unit

#
SVGDocument::add_pattern

fn SVGDocument::add_pattern(self : SVGDocument, pattern : Pattern) -> Unit

#
SVGDocument::add_symbol

fn SVGDocument::add_symbol(self : SVGDocument, symbol : Symbol) -> Unit

#
SVGDocument::instantiate_use

fn SVGDocument::instantiate_use(self : SVGDocument, element : UseElement) -> SVGNode?

Instantiate a reusable element registered on this document.

#
SVGDocument::new

fn SVGDocument::new(root : SVGNode) -> SVGDocument

#
SVGDocument::root

fn SVGDocument::root(self : SVGDocument) -> SVGNode

Return the authored root node.

#
SVGNode

pub(all) struct SVGNode {
id : String
shape : Shape
transform : Transform
view_box : ViewBox?
viewport_width : Double?
viewport_height : Double?
preserve_aspect_ratio : PreserveAspectRatio
image_sampling : ImageSampling
fill : Paint
color : Color?
paint_order : PaintOrder
fill_rule : FillRule
clip_rule : FillRule
fill_opacity : Double
stroke : StrokeStyle
stroke_opacity : Double
opacity : Double
blend_mode : BlendMode
isolation : Isolation
marker_start : String?
marker_mid : String?
marker_end : String?
clip_overflow : Bool
children : Array[SVGNode]
// private fields
}

SVG node (element in the scene graph)

#
SVGNode::add_filter

fn SVGNode::add_filter(self : SVGNode, filter : Filter) -> Unit

Add a filter to the node

#
SVGNode::clear_clip_path

fn SVGNode::clear_clip_path(self : SVGNode) -> Unit

Clear clip path reference

#
SVGNode::clear_filter_graph

fn SVGNode::clear_filter_graph(self : SVGNode) -> Unit

#
SVGNode::clear_filters

fn SVGNode::clear_filters(self : SVGNode) -> Unit

Clear all filters from the node

#
SVGNode::clear_mask

fn SVGNode::clear_mask(self : SVGNode) -> Unit

Clear mask reference

#
SVGNode::new

fn SVGNode::new(shape : Shape) -> SVGNode

#
SVGNode::set_clip_path

fn SVGNode::set_clip_path(self : SVGNode, clip_path_id : String) -> Unit

Set clip path reference by ID

#
SVGNode::set_filter_graph

fn SVGNode::set_filter_graph(self : SVGNode, filter_id : String) -> Unit

Set an SVG filter graph reference by ID.

#
SVGNode::set_mask

fn SVGNode::set_mask(self : SVGNode, mask_id : String) -> Unit

Set mask reference by ID

#
Shape

pub(all) enum Shape {
Rect(x~ : Double, y~ : Double, width~ : Double, height~ : Double, rx~ : Double, ry~ : Double)
Circle(cx~ : Double, cy~ : Double, r~ : Double)
Ellipse(cx~ : Double, cy~ : Double, rx~ : Double, ry~ : Double)
Line(x1~ : Double, y1~ : Double, x2~ : Double, y2~ : Double)
Polyline(points~ : Array[(Double, Double)])
Polygon(points~ : Array[(Double, Double)])
Path(commands~ : Array[PathCommand])
Text(x~ : Double, y~ : Double, text~ : String, font_size~ : Double)
Image(x~ : Double, y~ : Double, width~ : Double, height~ : Double, href~ : String)
Group
} derive(
Debug
)

SVG shape primitives

#
SpreadMethod

pub(all) enum SpreadMethod {
Pad
Repeat
Reflect
} derive(Eq,
Debug
)

How gradient extends beyond its bounds

#
StrokeStyle

pub(all) struct StrokeStyle {
paint : Paint
width : Double
linecap : LineCap
linejoin : LineJoin
miterlimit : Double
dasharray : Array[Double]?
dashoffset : Double
non_scaling : Bool
}

Stroke properties

#
StrokeStyle::default

fn StrokeStyle::default() -> StrokeStyle

#
Symbol

pub(all) struct Symbol {
id : String
content : SVGNode
view_box : ViewBox?
width : Double?
height : Double?
preserve_aspect_ratio : PreserveAspectRatio
display_none : Bool
}

Symbol definition (reusable graphic)

#
Symbol::new

fn Symbol::new(id : String, content : SVGNode) -> Symbol

#
Symbol::with_viewbox

fn Symbol::with_viewbox(id : String, content : SVGNode, view_box : ViewBox) -> Symbol

#
TextResourceKind

pub(all) enum TextResourceKind {
Stylesheet
SvgDocument
} derive(Eq,
Debug
)

#
Transform

pub(all) struct Transform {
a : Double
b : Double
c : Double
d : Double
e : Double
f : Double
}

2D affine transformation matrix | a c e | | b d f | | 0 0 1 |

#
Transform::apply

fn Transform::apply(self : Transform, x : Double, y : Double) -> (Double, Double)

Apply transform to a point

#
Transform::apply_bbox

fn Transform::apply_bbox(self : Transform, bbox : BoundingBox) -> BoundingBox

Transform a bounding box (returns axis-aligned bounding box of transformed corners)

#
Transform::apply_point

fn Transform::apply_point(self : Transform, point : (Double, Double)) -> (Double, Double)

Apply transform to a point (struct version)

#
Transform::determinant

fn Transform::determinant(self : Transform) -> Double

Compute the determinant of the transform

#
Transform::get_rotation

fn Transform::get_rotation(self : Transform) -> Double

Get the rotation angle in radians (approximate, assumes uniform scale)

#
Transform::get_scale

fn Transform::get_scale(self : Transform) -> (Double, Double)

Get the scale factors (approximate, assumes no rotation)

#
Transform::get_translate

fn Transform::get_translate(self : Transform) -> (Double, Double)

Get the translation component

#
Transform::inverse

fn Transform::inverse(self : Transform) -> Transform

Compute the inverse transform Returns identity if not invertible

#
Transform::is_invertible

fn Transform::is_invertible(self : Transform) -> Bool

Check if the transform is invertible

#
Transform::matrix

fn Transform::matrix(a : Double, b : Double, c : Double, d : Double, e : Double, f : Double) -> Transform

Create a transform from a full matrix specification

#
Transform::multiply

fn Transform::multiply(self : Transform, other : Transform) -> Transform

Multiply two transforms (self * other) Result: first apply other, then apply self

#
Transform::rotate

fn Transform::rotate(angle : Double) -> Transform

Create a rotation transform (angle in radians)

#
Transform::rotate_around

fn Transform::rotate_around(angle : Double, cx : Double, cy : Double) -> Transform

Create a rotation transform around a point (angle in radians)

#
Transform::scale

fn Transform::scale(sx : Double, sy : Double) -> Transform

Create a scaling transform

#
Transform::scale_uniform

fn Transform::scale_uniform(s : Double) -> Transform

Create a uniform scaling transform

#
Transform::skew_x

fn Transform::skew_x(angle : Double) -> Transform

Create a skewX transform (angle in radians)

#
Transform::skew_y

fn Transform::skew_y(angle : Double) -> Transform

Create a skewY transform (angle in radians)

#
Transform::translate

fn Transform::translate(tx : Double, ty : Double) -> Transform

Create a translation transform

#
UseElement

pub(all) struct UseElement {
href : String
x : Double
y : Double
width : Double?
height : Double?
transform : Transform
}

Use element (instance of a symbol)

#
UseElement::get_id

fn UseElement::get_id(self : UseElement) -> String

Get the href ID (strips leading #)

#
UseElement::new

fn UseElement::new(href : String, x : Double, y : Double) -> UseElement

#
UseElement::with_size

fn UseElement::with_size(href : String, x : Double, y : Double, width : Double, height : Double) -> UseElement

#
ViewBox

pub(all) struct ViewBox {
min_x : Double
min_y : Double
width : Double
height : Double
}

ViewBox specification for SVG coordinate system mapping

#
ViewBox::get_transform

fn ViewBox::get_transform(self : ViewBox, viewport_width : Double, viewport_height : Double, preserve_aspect_ratio : PreserveAspectRatio) -> Transform

Calculate the transform matrix to map viewBox coordinates to viewport viewport_width/height: the actual pixel dimensions of the SVG element

#
parse_path

fn parse_path(data : String) -> Array[PathCommand]

Parse a path data string into an array of path commands

#
parse_svg_document

fn parse_svg_document(svg_str : String) -> SVGDocument?

Parse SVG markup string into SVGDocument with resources

#
parse_transform

fn parse_transform(value : String) -> Transform

#
path_bbox

fn path_bbox(commands : Array[PathCommand]) -> BoundingBox

Compute bounding box of path commands

#
render_path_commands_to_image

fn render_path_commands_to_image(commands : Array[PathCommand], width : Int, height : Int, fill_color : Color, transform? : Array[Double]) -> Image

Render PathCommand array directly to an Image (no SVG string parsing). This is much faster than render_svg_to_image for programmatic paths (e.g., font glyph outlines) because it skips SVG serialization and parsing.

transform is a 6-element affine transform [a, b, c, d, e, f] or empty for identity.

#
render_svg

fn render_svg(svg_str : String, width : Int, height : Int, options : RenderOptions) -> RenderResult

Parse and render SVG markup with structured diagnostics.

#
render_svg_document

fn render_svg_document(document : SVGDocument, width : Int, height : Int, options : RenderOptions) -> RenderResult

Render a parsed SVG document with structured diagnostics.

#
render_svg_to_image

fn render_svg_to_image(svg_str : String, width : Int, height : Int) -> Image?

Parse and render an SVG markup string into an Image.