CanvasPdfDevice class

Paints interpreter callbacks onto a Flutter Canvas.

Expects the canvas to be set up in page space (PDF user space, y-up); the renderer applies the global y-flip. Text is drawn with substituted system fonts, horizontally scaled to the PDF's own metrics, until the font engine produces real glyph outlines. Images must be pre-decoded into images (painting is synchronous).

Constructors

CanvasPdfDevice(Canvas canvas, {Map<Object, Image> images = const {}, double pixelRatio = 1, PdfCanvasPathCache? pathCache})

Properties

canvas → Canvas
final
hashCode → int
The hash code for this object.
no setterinherited
images → Map<Object, Image>
Decoded images keyed by pdfImageKey — stream identity for XObjects, value identity for inline images.
final
pathCache → PdfCanvasPathCache?
Reuses native path geometry when replaying an immutable retained scene. Direct interpretation leaves this null because its paths are one-shot.
final
pixelRatio → double
Device pixels per page unit at the scale this device is painting for.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited

Methods

beginGroup(double alpha, {bool knockout = false}) → void
Brackets a transparency-group form (§11.6.6) whose composite result paints at alpha. Inside the group, alpha starts over at 1.0; the group then blends as one object. Non-compositing devices can treat the pair as a no-op - the group's content still arrives through the normal callbacks in between.
beginSoftMaskComposite({required bool luminosity, required PdfRect backdrop, double backdropLuminance = 0, double transferScale = 1, double transferOffset = 0}) → void
First half of endSoftMasked's compositing: opens the dstIn layer the mask group's content paints into (with the luminance/transfer colour filter and the /BC backdrop). Split out for callers that must interleave their own work with the mask draws - the strip device flushes its batched quads between the mask content and finishSoftMaskComposite - while keeping the exact canvas sequence.
beginSoftMasked() → void
Starts capturing painted content that an ExtGState /SMask will mask. Visual devices open an offscreen layer; others can ignore the pair.
beginTransparencyGroup(double alpha, {required bool knockout, required bool isolated, PdfRect? bounds, PdfColor? backdropColor}) → void
clipPath(PdfPath path, PdfFillRule rule) → void
Intersects the current clip with path.
drawImage(PdfImageRequest request) → void
drawText(PdfTextRun run) → void
drawTextBatch(List<PdfRenderCommand> commands, int start, int endExclusive) → void
drawTiledCell(PdfDrawTiledCellCommand command) → void
endGroup() → void
Composites the group opened by beginGroup.
endSoftMasked({required bool luminosity, required PdfRect backdrop, required void drawMask(), double backdropLuminance = 0, double transferScale = 1, double transferOffset = 0}) → void
Ends the capture opened by beginSoftMasked. drawMask paints the mask group's content through this same device; for luminosity masks the device converts the result's luminance to alpha over the backdrop box, then composites it into the captured content (dstIn). Areas the mask group doesn't paint take backdropLuminance (the luminance of the /BC backdrop colour, default black). The mask value is remapped through the /TR transfer function, linearised here as value * transferScale + transferOffset (identity by default). Devices that collect content from drawMask (e.g. image collectors) should invoke it even if they do no compositing.
fillMesh(PdfMesh mesh, double alpha) → void
Paints a Gouraud triangle mesh (mesh shadings, types 4–7). Vertices arrive in page space. Non-painting devices can ignore it; simple devices may fall back to PdfMesh.averageColor.
fillPath(PdfPath path, PdfColor color, PdfFillRule rule, double alpha) → void
fillPathGradient(PdfPath path, PdfFillRule rule, PdfGradient gradient, double alpha) → void
Fills with a gradient (axial/radial shading patterns and sh). Non-painting devices can ignore it; simple devices may fall back to fillPath with PdfGradient.averageColor.
finishSoftMaskComposite() → void
Second half of endSoftMasked's compositing: composites the mask into the captured content (dstIn) and the masked content into the page.
glyphDarkeningFor(double emPageUnits) → double
The second composite's alpha for a glyph run whose em measures emPageUnits in page units, or 0 when the run must stay exact.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
restore() → void
Mirrors Q.
save() → void
Mirrors q. Saved state must include the clip.
setBlendMode(PdfBlendMode mode) → void
Sets the blend mode for subsequent painting (gs /BM). Non-compositing devices can ignore it.
setOverprint({required bool fill, required bool stroke, required int mode}) → void
Sets the overprint state for subsequent painting (gs /OP, /op, /OPM; PDF §8.6.7). fill is nonstroking overprint (/op), stroke is stroking overprint (/OP), and mode is the overprint mode (/OPM, 0 or 1).
strokePath(PdfPath path, PdfColor color, PdfStroke stroke, double alpha) → void
strokeWidthFor(double width) → double
Stroke width to paint, never thinner than one device pixel.
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Properties

batchEmbeddedTextOutlines ↔ bool
Coalesces adjacent embedded-outline text fills into one canvas path.
getter/setter pair
debugDefaultFontFallbacks → List<String>
Ordered fallbacks used for normal substituted text — test hook.
no setter
debugDrawSimpleLines ↔ bool
getter/setter pair
debugGlyphLayoutCacheLength → int
Number of cached per-character glyph layouts — test hook (#454).
no setter
debugOverprintCompositing ↔ bool
Overprint fallback-compositing kill switch (the A/B baseline is "off"). Off, setOverprint still records the state but fills/strokes composite normally, exactly as before overprint was consumed.
getter/setter pair
debugPieceLayoutCacheLength → int
Number of cached word-piece layouts — test hook.
no setter
debugReuseSolidPaints ↔ bool
Diagnostic kill switches for the command replay benchmark.
getter/setter pair
debugTextLayoutCacheLength → int
Number of cached text layouts — test hook.
no setter
debugTextPainterBuilds ↔ int
getter/setter pair
debugTextShapeHit ↔ int
getter/setter pair
debugTextShapeMiss ↔ int
getter/setter pair
debugTextShapeUs ↔ int
Within-replay substituted-text shaping split (#454). debugTextShapeUs is the time spent in cache-miss TextPainter layout — the "shaping" the replay-bound CAD pages are made of — and debugTextShapeMiss/ debugTextShapeHit are the run-cache miss/hit counts (unique labels miss, which is the whole problem). Only written while PdfPerfLog.enabled; the replay caller resets before a replay and reads after. Static because the device is constructed fresh per replay.
getter/setter pair
exactSubstitutedGlyphPlacement ↔ bool
Place substituted glyphs at the PDF's own per-character pen offsets (PdfTextRun.charOffsets) instead of letting the substitute distribute them (#649).
getter/setter pair
glyphStemDarkening ↔ bool
Darkens small glyph fills so their stems read as ink rather than haze (#912). Off by default - a deliberate deviation from exact coverage.
getter/setter pair
glyphStemDarkeningAlpha ↔ double
Alpha of the second composite, at or below glyphStemDarkeningMinEm.
getter/setter pair
glyphStemDarkeningMaxEm ↔ double
Em size, in device pixels, at and above which no darkening applies - display sizes resolve their own stems and must stay exact.
getter/setter pair
glyphStemDarkeningMinEm ↔ double
Em size, in device pixels, at and below which the full glyphStemDarkeningAlpha applies.
getter/setter pair
perGlyphSubstitutedText ↔ bool
Compose substituted-font runs from cached per-character layouts instead of shaping the whole run (#454). Unique labels (which miss the run cache and re-shape every time - the replay-bound CAD pathology) then reuse per-character shaping and drop toward the warm-cache floor. Restricted to pure-fill runs whose text has no kernable adjacency (see _composableRun); everything else keeps whole-run shaping. On by default: a real-Chrome probe across Helvetica/Arial/Courier put the composed-vs-whole-run pixel diff at 0% for every run this gate admits (kerning-pair uppercase words, the only divergent case, are excluded), so the speed-up carries no fidelity cost.
getter/setter pair

Static Methods

clearTextLayoutCache() → void
Drops every cached text layout (memory pressure / tests). The decoded-image cache (PdfImageCache) is separate.
debugEmbeddedGlyphPathBounds(PdfTextRun run) → Rect
Materializes the combined outline bounds used by the web regression test.
debugGlyphPathMatrixForEngine(Float64List matrix, {bool deferred = kIsWeb}) → Float64List
Returns the matrix representation appropriate for an immediate or lazy engine path command.
debugResetTextShape() → void
Zeroes the shaping accumulators before a measured replay.