Table of Contents

Class SvgDocument

Namespace
Egami.Svg
Assembly
Egami.Svg.dll

An SVG document: an editable element tree read from an .svg or .svgz file, which saves back to SVG and draws through Egami.Drawing's canvas.

public sealed class SvgDocument
Inheritance
SvgDocument
Inherited Members

Examples

// .svg and .svgz alike; nothing outside the file is opened unless a resolver allows it.
SvgDocument document = SvgDocument.Load(path);
Console.WriteLine($"{document.Title}: {document.Root.Descendants().Count()} elements");

// What a lenient load skipped is in Warnings, and in the context's diagnostics.
foreach (EgamiDiagnostic warning in document.Warnings)
{
    Console.WriteLine($"{warning.Id}: {warning.Message}");
}

Remarks

Loading is lenient, as browsers and resvg read SVG: what cannot be used is skipped and reported through the context's diagnostics, and the rest is kept. Strict throws instead. Nothing outside the file is opened unless Resolver allows it.

Constructors

SvgDocument(SvgElement, SvgLoadOptions?)

Initializes a new instance of the SvgDocument class around a root element made in code.

public SvgDocument(SvgElement root, SvgLoadOptions? options = null)

Parameters

root SvgElement

The root, an svg element without a parent or another document.

options SvgLoadOptions

How references, units and limits work, or null for the defaults.

Examples

// A document made in code: an svg root and its content.
SvgElement root = new("svg");
root.Attributes["viewBox"] = "0 0 100 100";
SvgElement circle = new("circle");
circle.Attributes["cx"] = "50";
circle.Attributes["cy"] = "50";
circle.Attributes["r"] = "40";
root.Children.Add(circle);
SvgDocument document = new(root);

Exceptions

ArgumentException

root already has a parent or a document.

Properties

Description

Gets the text of the root's first desc child, or null.

public string? Description { get; }

Property Value

string

Options

Gets the options the document was loaded with.

public SvgLoadOptions Options { get; }

Property Value

SvgLoadOptions

RenderTree

Gets the render tree: the elements resolved for drawing (styles applied, units in pixels, use expanded, shapes as paths), in the document's pixels (Size). It is built at load and again on first use after an edit; what an edit leaves undrawable is reported to the context's diagnostics then. It is immutable and safe to read from many threads.

public SvgGroup RenderTree { get; }

Property Value

SvgGroup

Examples

// The resolved tree: groups, paths with their paints and strokes, images; styles applied and units in pixels.
static void Walk(SvgNode node, int depth)
{
    string what = node switch
    {
        SvgPath path => $"path {path.Path.Bounds} fill {path.Fill}",
        SvgGroup group => $"group of {group.Children.Count}",
        SvgImage image => $"image {image.Destination}",
        _ => node.GetType().Name,
    };
    Console.WriteLine($"{new string(' ', depth * 2)}{node.Id} {what} opacity {node.Opacity}");
    if (node is SvgGroup g)
    {
        foreach (SvgNode child in g.Children)
        {
            Walk(child, depth + 1);
        }
    }
}

Walk(document.RenderTree, 0);

Root

Gets the root svg element.

public SvgElement Root { get; }

Property Value

SvgElement

Size

Gets the document's size in pixels: the root's width and height, a percentage (or a missing side) taken of the viewBox, or of 100 by 100 when there is no viewBox, as resvg sizes documents. Physical units use Dpi.

public Vector2 Size { get; }

Property Value

Vector2

Title

Gets the text of the root's first title child, or null.

public string? Title { get; }

Property Value

string

ViewBox

Gets the root's viewBox, or null when it has none (or an invalid one).

public RectF? ViewBox { get; }

Property Value

RectF?

Warnings

Gets what the load skipped, as also sent to the context's diagnostics; empty for a document made in code.

public IReadOnlyList<EgamiDiagnostic> Warnings { get; }

Property Value

IReadOnlyList<EgamiDiagnostic>

Methods

Draw(Canvas, RectF?, SvgRenderOptions?)

Draws the document on a canvas: at its own size from the canvas's origin, or fitted into box by the root's preserveAspectRatio. Drawing calls only the public canvas API, so a raster canvas, a PDF page, SvgCanvas or a PictureRecorder receive the same calls. It never throws on content.

public void Draw(Canvas canvas, RectF? box = null, SvgRenderOptions? options = null)

Parameters

canvas Canvas

The canvas.

box RectF?

The rectangle to fit the document into, in the canvas's coordinates, or null.

options SvgRenderOptions

Languages, text as paths and filter scale, or null for the defaults.

Examples

// Fitted into a box by the root's preserveAspectRatio; a PDF page or SvgCanvas receives the same calls.
document.Draw(canvas, new RectF(10, 10, 180, 180));

// One element of a sprite sheet, fitted into its own box.
document.Draw(canvas, "body", new RectF(200, 10, 48, 48));

Draw(Canvas, string, RectF?, SvgRenderOptions?)

Draws one element and what it holds, such as a symbol or g of a sprite sheet: fitted into box (a symbol's viewBox, else the element's bounding box, centered and scaled to fit), or, without a box, in the coordinates of its parent.

public void Draw(Canvas canvas, string id, RectF? box = null, SvgRenderOptions? options = null)

Parameters

canvas Canvas

The canvas.

id string

The element's id.

box RectF?

The rectangle to fit the element into, or null.

options SvgRenderOptions

Languages, text as paths and filter scale, or null for the defaults.

Examples

// Fitted into a box by the root's preserveAspectRatio; a PDF page or SvgCanvas receives the same calls.
document.Draw(canvas, new RectF(10, 10, 180, 180));

// One element of a sprite sheet, fitted into its own box.
document.Draw(canvas, "body", new RectF(200, 10, 48, 48));

Exceptions

ArgumentException

No element has the id.

FindById(string)

Finds the element with an id; the first in file order when several share it.

public SvgElement? FindById(string id)

Parameters

id string

The id, without a #.

Returns

SvgElement

The element, or null.

Load(Stream, SvgLoadOptions?)

Reads an .svg or .svgz stream from its current position.

public static SvgDocument Load(Stream stream, SvgLoadOptions? options = null)

Parameters

stream Stream

The stream; it is read to the end of the document and left open.

options SvgLoadOptions

How to read it, or null for the defaults.

Returns

SvgDocument

The document.

Examples

// Images, style sheets and fonts the file refers to open only through a resolver; data: URIs always work.
var options = new SvgLoadOptions
{
    Resolver = SvgResolvers.SameDirectory(folder),
    Dpi = 96,
    Context = EgamiContext.Default with { Limits = SafetyLimits.Default with { MaxTotalBytes = 64L << 20 } },
};
SvgDocument document = SvgDocument.Parse(Icon, options);

Exceptions

SvgException

The data is not well-formed XML, is not SVG, breaks a limit, or, in strict mode, has an error.

LimitExceededException

The data is larger than the context's MaxTotalBytes.

Load(string, SvgLoadOptions?)

Reads an .svg or .svgz file.

public static SvgDocument Load(string path, SvgLoadOptions? options = null)

Parameters

path string

The file. Relative references resolve against its folder (they open only through a resolver).

options SvgLoadOptions

How to read it, or null for the defaults.

Returns

SvgDocument

The document.

Examples

// .svg and .svgz alike; nothing outside the file is opened unless a resolver allows it.
SvgDocument document = SvgDocument.Load(path);
Console.WriteLine($"{document.Title}: {document.Root.Descendants().Count()} elements");

// What a lenient load skipped is in Warnings, and in the context's diagnostics.
foreach (EgamiDiagnostic warning in document.Warnings)
{
    Console.WriteLine($"{warning.Id}: {warning.Message}");
}

Exceptions

SvgException

The file is not well-formed XML, is not SVG, breaks a limit, or, in strict mode, has an error.

LimitExceededException

The file is larger than the context's MaxTotalBytes.

Parse(string, SvgLoadOptions?)

Reads SVG text.

public static SvgDocument Parse(string text, SvgLoadOptions? options = null)

Parameters

text string

The SVG markup.

options SvgLoadOptions

How to read it, or null for the defaults.

Returns

SvgDocument

The document.

Examples

// Strict turns everything a lenient load would skip into an exception with the line and column.
try
{
    SvgDocument.Parse("<svg>\n  <rect width='10' height='10'/>\n</svg>", new SvgLoadOptions { Strict = true });
}
catch (SvgException e)
{
    Console.WriteLine($"Line {e.Line}, column {e.Column}: {e.Problem}");
}

Exceptions

SvgException

The text is not well-formed XML, is not SVG, breaks a limit, or, in strict mode, has an error.

Rasterize<TPixel>(SvgRenderOptions?)

Draws the document into a new raster: at its own size times Scale, or at a target width and/or height (the other side keeps the aspect ratio), over Background.

public Raster<TPixel> Rasterize<TPixel>(SvgRenderOptions? options = null) where TPixel : unmanaged, IPixelType<TPixel>

Parameters

options SvgRenderOptions

The size, background and canvas options, or null for the defaults.

Returns

Raster<TPixel>

The raster.

Type Parameters

TPixel

The pixel type of the raster.

Examples

// At the document's own size, scaled, or at a target width (the height keeps the aspect ratio).
using Raster<Rgba8> icon = document.Rasterize<Rgba8>();
using Raster<Rgba8> large = document.Rasterize<Rgba8>(new SvgRenderOptions { Width = 512 });
using Raster<Rgba8> onWhite = document.Rasterize<Rgba8>(new SvgRenderOptions { Scale = 2, Background = new RgbaF32(1, 1, 1, 1) });

Exceptions

LimitExceededException

The raster would break the context's size limits.

Save(Stream, SvgSaveOptions?)

Writes the document as SVG: the element tree with everything read from the file (unknown elements, foreign namespaces, comments, the DOCTYPE), so a load and save without edits keeps the document's meaning; attribute order and whitespace inside tags may change, and entities are written out.

public void Save(Stream stream, SvgSaveOptions? options = null)

Parameters

stream Stream

The stream to write to; it is left open.

options SvgSaveOptions

How to write, or null for Default.

Examples

// Numbers and paths set in code are written with Precision decimals; what was read keeps its text.
document.FindById("body")!.Attributes.Set("width", 17.666666);
document.Save(path, new SvgSaveOptions { Precision = 2, Gzip = true });

using var stream = new MemoryStream();
document.Save(stream);

Save(string, SvgSaveOptions?)

Writes the document to a file, as Save(Stream, SvgSaveOptions?) does.

public void Save(string path, SvgSaveOptions? options = null)

Parameters

path string

The file; it is replaced if it exists. Use Gzip for .svgz.

options SvgSaveOptions

How to write, or null for Default.

Examples

// Numbers and paths set in code are written with Precision decimals; what was read keeps its text.
document.FindById("body")!.Attributes.Set("width", 17.666666);
document.Save(path, new SvgSaveOptions { Precision = 2, Gzip = true });

using var stream = new MemoryStream();
document.Save(stream);