KiteCanvas

interface KiteCanvas

High-level drawing target. Implement this to add a new render backend; use PdfPage.renderTo to drive an existing one.

The PageRenderer walks the content stream, maintains the graphics-state stack, accumulates paths, and finally calls one of these device methods with a complete, ready-to-paint primitive. Backends therefore don't need to track the CTM, the current path, or text positioning. They receive only the final geometry plus the transform to apply.

Concrete implementations shipped:

  • ComposeCanvas (:kitepdf-compose-viewer): paints into a Compose DrawScope.

  • SkiaCanvas (:kitepdf-skia-renderer): paints into a Skia Canvas.

  • AwtCanvas / AndroidNativeCanvas / CoreGraphicsCanvas / Canvas2dCanvas (:kitepdf-native-renderer): host-platform raster backends.

Inheritors

Properties

Link copied to clipboard

True when this canvas needs resolved glyph outlines (TextGlyph.outline), i.e. it actually paints (a render backend). Extraction canvases that only read text + advances override this to false, letting the driver skip the cost of resolving glyph outlines.

Functions

Link copied to clipboard
open fun applySoftMask(kind: SoftMask.Kind, maskBBox: Rectangle, maskCtm: Matrix, render: () -> Unit, renderMask: (KiteCanvas) -> Unit)

Apply a soft mask to the content rendered inside render (ISO 32000-1 §11.6.5). The default implementation just calls render. Backends without offscreen compositing fall back to painting through the mask.

Link copied to clipboard
abstract fun beginPage(widthPt: Double, heightPt: Double, deviceCtm: Matrix)

Set up for a page render. The renderer calls this once before any draw call, with the page dimensions (in PDF user units, 1pt = 1/72 inch) and the desired device CTM (e.g. flip Y and scale to fit a target rectangle).

Link copied to clipboard
open fun beginTransparencyGroup(bbox: Rectangle, ctm: Matrix, isolated: Boolean = false, knockout: Boolean = false, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal)

Open a transparency group (ISO 32000-1 §11.4). Subsequent paints accumulate into an offscreen layer; endTransparencyGroup composites the layer back onto the parent with blendMode + alpha.

Link copied to clipboard
abstract fun drawGlyphs(glyphs: List<TextGlyph>, fontSize: Double, unitsPerEm: Int, hasOutlines: Boolean, fontSpec: FontSpec, textToDevice: Matrix, color: RgbColor, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal)

Paint one text run, already laid out into glyphs by the document handler. Format-neutral: no PDF (or other) font object crosses the seam, so every handler (PDF, EPUB, and others) drives text the same way.

Link copied to clipboard
open fun drawImage(image: ImageXObject, ctm: Matrix, alpha: Double = 1.0)

Paint an XObject Image under ctm. PDF defines the image's bounds as the unit square (0..1, 0..1); the CTM already encodes the scale + position. Backends that can decode image paint the pixels; others draw a placeholder rather than throw.

Link copied to clipboard
abstract fun endPage()
Link copied to clipboard
Link copied to clipboard
abstract fun fillPath(path: KitePath, ctm: Matrix, color: RgbColor, evenOdd: Boolean, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal)

Fill path under ctm with color at alpha (0..1) under the given blendMode. The default alpha = 1.0 + blendMode = Normal is the plain over-paint that PDF assumes when no ExtGState modifies the state.

Link copied to clipboard
open fun fillShading(shading: KiteShading, ctm: Matrix, clipPath: KitePath?, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal)

Fill clipPath (under ctm) with the gradient defined by shading. If clipPath is null the shading covers the current clip region (or the page, when no clip is active). That is the spec's sh operator.

Link copied to clipboard
fun KiteCanvas.paintComplexShading(shading: KiteShading, ctm: Matrix, clipPath: KitePath?, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal): Boolean

Renders the T-40 shading types through plain KiteCanvas.fillPath calls, so every backend supports them identically with zero bespoke code:

Link copied to clipboard
abstract fun popClip()
Link copied to clipboard
abstract fun pushClip(path: KitePath, ctm: Matrix, evenOdd: Boolean)

Push a clip to path under ctm. Matched 1:1 by popClip.

Link copied to clipboard
abstract fun strokePath(path: KitePath, ctm: Matrix, color: RgbColor, lineWidth: Double, alpha: Double = 1.0, blendMode: BlendMode = BlendMode.Normal, dashArray: List<Double>? = null, dashPhase: Double = 0.0, lineCap: Int = 0, lineJoin: Int = 0, miterLimit: Double = 10.0)

Stroke path under ctm with color at lineWidth user-units, alpha, blendMode. lineCap 0/1/2 = butt/round/square; lineJoin 0/1/2 = miter/round/bevel.