ComposeCanvas

KiteCanvas backed by a Compose Multiplatform DrawScope.

Three rendering paths:

  • Embedded outlines: when hasOutlines is true, each byte/CID becomes a Compose Path filled at the right position.

  • System-font fallback: when no outlines are available, decode to text and hand to Compose's TextMeasurer.

  • Transparency groups: open a saveLayer on the underlying Canvas when the renderer requests one; later restore composites the layer back with the requested blend mode + alpha.

Clips and transparency groups use the lower-level Canvas.save, clipPath and saveLayer, so they span many DrawScope operations, and each clip is applied once however many paints it covers.

On the desktop JVM, iOS, macOS and Android, system-font text and host glyph outlines are shaped by the platform's own text engine, not by Compose's text stack, so they draw on any thread (#131, #487). In a browser they go through Compose's text and require the UI thread; a call on another thread throws IllegalStateException before accessing the host text stack. For background exports use KitePageRasterizer.rasterizeOffMain. A canvas that skips system text can probe on a worker, but that incomplete bitmap is not an export (#428). The canvas of a Vectorized page in KiteDocView draws inside its scene's own draw pass, so its host text takes the thread that scene draws on (#464).

Constructors

Link copied to clipboard
constructor(drawScope: DrawScope, textMeasurer: TextMeasurer, hairlineWidthPx: Float = 1.0f, skipSystemFontText: Boolean = false)

A canvas that draws into drawScope.

Properties

Link copied to clipboard

Functions

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

open override fun applySoftMask(kind: SoftMask.Kind, maskBBox: KiteRectangle, maskCtm: KiteMatrix, transfer: KiteMaskTransfer?, render: () -> Unit, renderMask: (KiteCanvas) -> Unit)

Soft-mask compositing (ISO 32000-1 §11.6.5). We open a saveLayer for the content, render it, then over-paint the mask group with ComposeBlendMode.DstIn so the mask's alpha clips the content.

Link copied to clipboard
open override fun beginPage(widthPt: Double, heightPt: Double, deviceCtm: KiteMatrix)
Link copied to clipboard
open override fun beginTransparencyGroup(bbox: KiteRectangle, ctm: KiteMatrix, isolated: Boolean, knockout: Boolean, alpha: Double, blendMode: KiteBlendMode)

Transparency groups: open a Compose saveLayer on the active Canvas with a Paint that carries the requested alpha + blend mode. Subsequent draws accumulate into the offscreen layer; matching endTransparencyGroup calls restore, which composites the layer onto the parent.

Link copied to clipboard
open override fun drawGlyphs(glyphs: List<TextGlyph>, fontSize: Double, unitsPerEm: Int, hasOutlines: Boolean, fontSpec: FontSpec, textToDevice: KiteMatrix, color: RgbColor, alpha: Double, blendMode: KiteBlendMode)
Link copied to clipboard
open override fun drawImage(image: KiteImageData, ctm: KiteMatrix, alpha: Double)
open override fun drawImage(image: KiteImageData, ctm: KiteMatrix, alpha: Double, blendMode: KiteBlendMode)
Link copied to clipboard
open override fun endPage()
Link copied to clipboard
open override fun endTransparencyGroup()
Link copied to clipboard
open override fun fillPath(path: KitePath, ctm: KiteMatrix, color: RgbColor, evenOdd: Boolean, alpha: Double, blendMode: KiteBlendMode)
Link copied to clipboard
open override fun fillShading(shading: KiteShading, ctm: KiteMatrix, clipPath: KitePath?, alpha: Double, blendMode: KiteBlendMode)
Link copied to clipboard
open override fun hostGlyphOutline(text: String, fontSpec: FontSpec): KitePath?

The outline of text in the host face drawGlyphs draws a font without embedded outlines in, at 1000 units per em with y up (#85). Off the main thread it only records the run, as the system-font path does, so the page renders again on Main.

Link copied to clipboard
open override fun popClip()
Link copied to clipboard
open override fun pushClip(path: KitePath, ctm: KiteMatrix, evenOdd: Boolean)
Link copied to clipboard
open override fun rasterStep(region: KiteRectangle, ctm: KiteMatrix, step: KiteRasterStep): Boolean

The raster step (#209, #308): its box is region under ctm, in the units of the draw scope, cut to the clip and rounded out to whole units. It works at magnification pixels a unit, so a step on a zoomed Vectorized page keeps the detail on screen, and past STEP_MAX_PIXELS at a lower resolution. Only a rasterizer's canvas, which knows the bitmap it draws into, reads a backdrop, and only outside every layer.

Link copied to clipboard
open override fun strokePath(path: KitePath, ctm: KiteMatrix, color: RgbColor, lineWidth: Double, alpha: Double, blendMode: KiteBlendMode, dashArray: List<Double>?, dashPhase: Double, lineCap: Int, lineJoin: Int, miterLimit: Double)