PeachDrawing.Win2D
Win2dCanvas Class
A Canvas that draws with Win2D: shapes, gradients, clips, layers, text and images go to a Microsoft.Graphics.Canvas.CanvasDrawingSession, either one the caller already has (FromSession(Win2dRenderContext, CanvasDrawingSession, Rect, Win2dLinkOptions)) or the offscreen bitmap of a Win2dComposer.
public sealed class Win2dCanvas : PeachDrawing.Core.Canvas
Inheritance System.Object → Canvas → Win2dCanvas
Remarks
Units. Like the SVG canvas, the session’s user space is the canvas’s layout units: rectangles, lines, polygons, image rectangles, brush geometry and text positions are used as given. What is in points (a GraphicsPath’s coordinates, a pen’s width and dashes) is multiplied by PixelsPerPoint first.
Lifetime. Everything native this canvas makes it releases: a clip pushed with PushClip holds a Win2D layer until the
matching PopClip; a brush, stroke style or geometry lives for the one draw call that needs it; a tile or layer owns a command
list. Dispose() pops whatever is still pushed, in reverse order, puts back the session state it changed (transform, blend,
anti-aliasing) and closes the session only if this canvas opened it. A session passed to FromSession(Win2dRenderContext, CanvasDrawingSession, Rect, Win2dLinkOptions) stays the caller’s: it
is never closed or disposed here, and is usable again once this canvas is disposed. A disposed canvas throws
System.ObjectDisposedException from every drawing call. A canvas must be used from one thread at a time.
| Properties | |
|---|---|
| CurrentTransform | The accumulated transform of every PushTransform(Matrix3x2) in effect, mapping this graphics’ current user space to the layout space it started in (the space page content is laid out in). Identity for a graphics that does not track transforms. Bookkeeping only, read by callers (gradient/pattern objectBoundingBox math, an SVG backdrop repaint, context-fill/ context-stroke’s coordinate-space mapping) - it plays no part in what this graphics actually draws, which a concrete backend positions its own way. A tile this graphics hands out (CreateTile(double, double)’s Graphics, or BeginRasterSurface(Rect, Nullable<double>)’s) starts seeded from this value, not System.Numerics.Matrix3x2.Identity, precisely so a reader can still relate the tile’s own coordinate space back to whatever space content outside the tile is measured in. |
| IsOffscreenTile | Whether this instance paints into an offscreen tile (e.g. one returned by CreateTile(double, double), used for group opacity and SVG pattern/mask content) rather than directly into the real page’s own content stream. Tagged-PDF output does not emit marked-content sequences into tile content streams in the current implementation (doing so correctly needs /MCR with /Stm//StmOwn pointing at the tile’s own content stream, not yet wired up) - callers use this to skip MCID/BDC emission while still creating the struct element itself, so the tree shape stays well-formed even though this particular occurrence contributes no reachable MCID. Defaults to false. |
| Links | The links and named places painted so far; see Win2dLinkMap. It survives Dispose(). |
| PixelsPerPoint | The scale between this graphics context’s own coordinate space and true points (1/72 inch): a backend whose coordinates are inflated relative to a point (for example a layout space running at a higher pixels-per-inch than 72) reports that inflation here. 1.0 (the base, no-op default) is correct for any Canvas whose coordinate space is not inflated this way; a backend whose space is overrides this with its real value. A caller that needs to compute a transform matrix whose *linear* (scale/rotation) part won’t itself be divided by this factor before use - a backend may divide only a matrix’s translation, not M11/M12/M21/M22 - reads this to pre-divide that part itself (an SVG viewBox-to-viewport transform is such a case: its “scale” is a ratio of an inflated length to a never-inflated, dimensionless user unit, so it is not already scale-neutral the way an ordinary scale() transform is). |
| TransformScale | How much the transforms pushed so far magnify a unit along each axis: the lengths of the images of the unit x and y vectors under the accumulated linear part. A raster region renders at the physical resolution the document asked for <em>after</em> those transforms are applied, so it needs this to pick its pixel pitch; a graphics that does not track transforms reports no magnification. |
| Methods | |
|---|---|
| AddDestination(string, double) | Names a place on the page this canvas draws, for AddDestinationLink(Rect, string, IReadOnlyList<PaintPoint>) to lead to. The default writes nothing. |
| AddDestinationLink(Rect, string, IReadOnlyList<PaintPoint>) | Makes bounds a clickable link to a place on a page of the document that was named with AddDestination(string, double) (on this canvas or on the canvas of another page). |
| AddLink(Rect, string, IReadOnlyList<PaintPoint>) | Makes bounds a clickable link to uri (a web address, or any other URI) on the page this canvas draws. A canvas for a format with hyperlinks (PDF, SVG) writes one; the default writes nothing, which is right for a canvas of pixels. Call it once the content the link covers has been drawn: where the link sits in the output is up to the format, but it is meant to lie over what is already there. |
| BeginArtifact() | Begins an artifact marked-content sequence - marks the content that follows as not part of the document’s logical structure (e.g. a decorative <hr>). Must be paired with EndMarkedContent(). |
| BeginLayer(LayerOptions) | Begins an isolated group of drawing that is composited onto this canvas as one piece when the returned layer is disposed: with the given opacity, blend mode and colour transform applied to the group as a whole rather than to each shape in it. This is what CSS opacity or SVG group opacity means - content that overlaps inside the group does not blend with itself. Draw onto Canvas in this canvas’s own coordinates. |
| BeginMarkedContent(string, int) | Begins a tagged marked-content sequence in the page content stream, associated with the given PDF structure type (e.g. “/H1”, “/P”) and marked-content identifier. Only called when tagged PDF output is enabled. Must be paired with EndMarkedContent(), wrapping a whole leaf box’s own paint calls - never part of one. |
| BeginRasterSurface(Rect, Nullable<double>) | Asks this graphics for a pixel surface to paint an effect PDF cannot express as vector content (a blur, a cross-channel colour filter, ...) into. The returned region has this graphics’ own coordinate system, so the same paint code that would have drawn to this graphics draws to it unchanged; when finished, hand the surface back through DrawRaster(RasterSurface). |
| BeginVariableText() | Begins the /Tx marked-content sequence ISO 32000-1 §12.7.3.3 requires around the value drawn into an interactive form field’s appearance stream, and EndVariableText() closes it. It is what tells a PDF reader which part of the generated appearance to replace when the user edits the field - without it the reader draws the new value over the generated one instead of in place of it. Deliberately a pair of its own rather than reusing EndMarkedContent(): these two must sit outside any text object, while that one has a caller that is legitimately inside one. |
| CountShapedGlyphs(string, Font, Nullable<ShapeSettings>) | The number of glyphs str shapes into once GSUB substitution is applied - always <= str’s character count, less whenever a ligature merges more than one character into a single glyph (single substitution never changes the count). Used to size the per-glyph letter-spacing gap count a word’s box must reserve (the PDF Tc operator adds one gap per glyph actually shown, not per source character), so it stays in sync with what DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>) paints for the same text/font/features. |
| CreateTile(double, double) | Creates a fresh, independent (width x height) drawing surface for tile-based content (e.g. an SVG <pattern>’s cell): draw into the returned Graphics using ordinary Canvas calls, then use the returned Image with DrawImage(Image, Rect) - repeated calls tile it, each one a real reference to the same underlying vector content (a PDF Form XObject), never rasterized. Null when creating one isn’t supported in the current rendering context (e.g. a measure-only pass with no real PDF page to own the new object). |
| Dispose() | Pops everything still pushed, puts back the session’s transform, blend and anti-aliasing, and closes the session if this canvas opened it. Safe to call more than once. A session passed to FromSession(Win2dRenderContext, CanvasDrawingSession, Rect, Win2dLinkOptions) is left open and usable. |
| DrawGlyphs(IReadOnlyList<GlyphPlacement>, Font, PaintColor) | Draws each of glyphs at its own explicit position, addressed directly by font glyph index rather than by Unicode character - unlike DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>), this never re-shapes/re-maps through cmap/GSUB, so it can draw a glyph with no Unicode mapping at all (e.g. an OpenType MATH table’s stretchy-operator assembly parts or pre-sized size variants, which are reached only via MathVariantsTable glyph ids, not through any character). Each GlyphPlacement’s X/Y is that glyph’s own baseline origin (not a bounding-box corner), in the same working unit space as DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>)’s own point parameter - unlike that method, there is no separate ascent-relative adjustment, since every glyph here already carries its own exact target baseline position. |
| DrawImage(Image, Rect) | Draws the specified Image at the specified location and with the specified size. |
| DrawImage(Image, Rect, ImageSampling) | Draws image into destRect, reading its pixels as sampling says. |
| DrawImage(Image, Rect, Rect) | Draws the specified portion of the specified Image at the specified location and with the specified size. |
| DrawImage(Image, Rect, Rect, ImageSampling) | Draws part of image into destRect, reading its pixels as sampling says. |
| DrawImageAlphaMasked(Image, Image, Rect, bool) | Draws image (a tile from CreateTile(double, double)) at destRect with maskImage (another same-adapter tile) attached as an /Alpha-subtype soft mask (ISO 32000-1 §11.6.4.3) - unlike DrawImageMasked(Image, Image, Rect)’s /Luminosity mask, which derives mask values from the mask tile’s rendered COLOR converted to grayscale, this derives them directly from the mask tile’s own computed ALPHA, disregarding whatever color it painted with. The motivating future use case is SVG’s SourceAlpha filter input and feComposite, both of which are defined in terms of a source’s alpha channel specifically, not a luminosity conversion of it. When invert is true, the mask’s /TR is set to 1 - x (a PDF Type 4 function), for a complemented alpha mask without needing a second tile painted with inverted alpha. A no-op if either image wasn’t created via CreateTile(double, double) on this same Canvas. |
| DrawImageBlendedOver(Image, Image, Rect, PaintBlendMode) | Paints bottom normally at destRect, then top on top of it at the same rect composited with blendMode - both same-adapter tiles from CreateTile(double, double), sized/positioned identically in their own local coordinate systems. The motivating future use case is SVG’s feBlend, which blends two independently-rendered filter inputs together inside a fresh tile rather than blending freshly-painted content against whatever the page already has underneath it (which is what PushBlendMode(PaintBlendMode)/PopBlendMode() do). A no-op if either image wasn’t created via CreateTile(double, double) on this same Canvas. |
| DrawImageMasked(Image, Image, Rect) | Draws image (a tile from CreateTile(double, double)) at destRect with maskImage (another same-adapter tile, sharing image’s own local width/height) applied as a luminosity soft mask, scoped to just this one placement. White areas of maskImage are fully visible, black fully transparent, matching PDF’s/SVG’s own <mask> semantics. Deliberately NOT a “push mask, draw normally, pop mask” pair (which an earlier version of this API was): a tile’s own content is Y-flipped relative to its own (small) size, not the page’s, so positioning it correctly requires the same explicit destRect placement DrawImage(Image, Rect) already uses for pattern tiles - relying on whatever transform happens to be ambient in the page’s own content stream at some arbitrary “push” point silently mispositions the mask relative to the content it’s meant to mask. A no-op if either image wasn’t created via CreateTile(double, double) on this same Canvas. |
| DrawImageWithColorMatrix(Image, Rect, ColorMatrix) | Draws image (a tile from CreateTile(double, double)) at destRect, composited through a CSS/SVG filter color-matrix transform (grayscale(), sepia(), saturate(), hue-rotate(), invert(), brightness(), contrast(), or feColorMatrix) expressed as matrix. Only representable when IsChannelIndependent is true - see ColorMatrix’s remarks for why a PDF ExtGState transfer function (the mechanism this goes through) cannot express a matrix that mixes color channels, and what a caller needs instead for one that does. A no-op if image wasn’t created via CreateTile(double, double) on this same Canvas. |
| DrawImageWithOpacity(Image, Rect, double, PaintBlendMode) | Draws image (a tile from CreateTile(double, double)) at destRect, composited as a single flattened result at constant opacity - the mechanism behind CSS/SVG group opacity. Unlike simply multiplying the alpha of each shape painted into the tile, this flattens the tile’s own (possibly overlapping) content once before applying opacity to the flattened result, so overlapping content doesn’t double-darken where it overlaps. A no-op if image wasn’t created via CreateTile(double, double) on this same Canvas. blendMode composites the flattened tile against the destination with a non-Normal PDF blend mode in the same gs as opacity - the mechanism behind CSS mix-blend-mode combined with group opacity, a single ExtGState rather than two nested ones. |
| DrawLine(Pen, double, double, double, double) | Draws a line connecting the two points specified by the coordinate pairs. |
| DrawPath(Brush, GraphicsPath) | Fills the interior of a GraphicsPath. |
| DrawPath(Pen, GraphicsPath) | Draws a GraphicsPath. |
| DrawPolygon(Brush, PaintPoint[]) | Fills the interior of a polygon defined by an array of points specified by PaintPoint structures. |
| DrawRaster(RasterSurface) | Draws a surface obtained from BeginRasterSurface(Rect, Nullable<double>) into this graphics at the rectangle the surface itself records, so its physical size is exact. Honours this graphics’ current transform, clip and blend mode. |
| DrawRectangle(Brush, double, double, double, double) | Fills the interior of a rectangle specified by a pair of coordinates, a width, and a height. |
| DrawRectangle(Pen, double, double, double, double) | Draws a rectangle specified by a coordinate pair, a width, and a height. |
| DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>) | Draw the given string using the given font and foreground color at given location. |
| EndMarkedContent() | Ends a marked-content sequence started by BeginMarkedContent(string, int) or BeginArtifact(). |
| EndVariableText() | Closes the sequence BeginVariableText() opened. |
| FromSession(Win2dRenderContext, CanvasDrawingSession, Rect, Win2dLinkOptions) | Makes a canvas that draws into a drawing session the caller already has: the one a CanvasControl hands its Draw handler, a render target’s, a swap chain’s. |
| GetGraphicsPath() | Get GraphicsPath object. |
| GetInkCrossings(string, Font, PaintPoint, double, double, double, Nullable<ShapeSettings>) | The horizontal ranges in which str’s glyph ink crosses the horizontal band between bandTop and bandBottom — what text-decoration-skip-ink ([CSS Text |
| Decoration 4 §2.5](https://www.w3.org/TR/css-text-decor-4/#text-decoration-skip-ink-property ‘https://www.w3.org/TR/css-text-decor-4/#text-decoration-skip-ink-property’)) removes from an underline or overline drawn through that band. | |
| GetTextOutline(string, Font, PaintPoint, double, Nullable<ShapeSettings>) | Builds the vector outline of a glyph run as a fillable/strokeable GraphicsPath, with the text baseline at baselineOrigin (user-space units) and glyphs advancing left-to-right. Unlike DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>) (a single-color PDF text show), the returned path can be filled with a gradient/pattern brush or stroked - used by the SVG renderer for gradient/pattern fill, stroke, and <textPath> on text. Returns null when the font produces no glyph outlines (a CID-keyed CFF font, or a bitmap font, neither of which this engine can decode outlines from) - the caller’s cue to fall back to DrawString(string, Font, PaintColor, PaintPoint, Size, double, FontPalette, Nullable<ShapeSettings>). |
| MeasureString(string, Font, double, int, double) | Measure the width of string under max width restriction calculating the number of characters that can fit and the width those characters take. Not relevant for platforms that don’t render HTML on UI element. |
| MeasureString(string, Font, Nullable<ShapeSettings>) | Measure the width and height of string str when drawn on device context HDC using the given font font. |
| PopAntiAlias() | Undoes the latest PushAntiAlias(bool). Does nothing when there is none to undo. |
| PopBlendMode() | Pop the most recent PushBlendMode(PaintBlendMode), restoring the prior blend mode. |
| PopClip() | Pop the latest clip push. |
| PopTransform() | Pop the most recent PushTransform(Matrix3x2), restoring the prior transform state. |
| PushAntiAlias(bool) | Turns anti-aliasing of the shapes drawn from now on on or off, until the matching PopAntiAlias(). Calls nest: each PushAntiAlias is undone by one PopAntiAlias, like PushClip(Rect) and PushTransform(Matrix3x2). This replaces the untyped SetAntiAliasSmoothingMode()/ReturnPreviousSmoothingMode(object) pair, which it is built on by default. |
| PushBlendMode(PaintBlendMode) | Push a PDF blend mode for subsequent drawing, saving state so it can later be undone by PopBlendMode() (stack-shaped, same convention as PushClip(Rect)/ PopClip()). Used e.g. to composite a fill against the content underneath it via Difference for a true color inversion (CSS outline-color: invert). |
| PushClip(GraphicsPath) | Push the clipping region of this Graphics to intersection of the current clip and the given (possibly non-rectangular) path. Used for SVG clip-path, where the clip region isn’t necessarily axis-aligned. |
| PushClip(Rect) | Push the clipping region of this Graphics to interception of current clipping rectangle and the given rectangle. |
| PushClipExclude(Rect) | Push the clipping region of this Graphics to exclude the given rectangle from the current clipping rectangle. |
| PushTransform(Matrix3x2) | Push a 2D affine transform (composed before/with the current transform), saving state so it can later be undone by PopTransform(). Used to implement the CSS transform property. |
| ReturnPreviousSmoothingMode(object) | Return to previous smooth mode before anti-alias was set as returned from SetAntiAliasSmoothingMode(). |
| SetAntiAliasSmoothingMode() | Set the graphics smooth mode to use anti-alias. Use ReturnPreviousSmoothingMode(object) to return back the mode used. |