CanvasStrokeRenderer


interface CanvasStrokeRenderer


Renders strokes to a Canvas.

Instead of calling the draw methods here directly, it may be simpler to pass an instance of CanvasStrokeRenderer to androidx.ink.rendering.android.view.ViewStrokeRenderer and use it to calculate transform matrix values.

An example of how to use CanvasStrokeRenderer.draw directly:

class MyView {
// Update these according to app business logic, and call `MyView.invalidate()`
val worldToViewTransform = Matrix() // Call e.g. `setScale(2F)` to zoom in 2x
val strokesWithTransforms = mutableMapOf<Stroke, Matrix>()

private val strokeToViewTransform = Matrix() // reusable scratch object
private val renderer = CanvasStrokeRenderer.create()

fun onDraw(canvas: Canvas) {
for ((stroke, strokeToWorldTransform) in strokesWithTransforms) {
// Combine worldToViewTransform (drawing surface being panned/zoomed/rotated) with
// strokeToWorldTransform (stroke itself being moved/scaled/rotated within the drawing
// surface) to get the overall transform of this stroke.
strokeToViewTransform.set(strokeToWorldTransform)
strokeToViewTransform.postConcat(worldToViewTransform)

canvas.withMatrix(strokeToViewTransform) {
// If coordinates of MyView are scaled/rotated from screen coordinates, then those
// scale/rotation values should be multiplied into the strokeToScreenTransform
// argument to renderer.draw.
renderer.draw(canvas, stroke, strokeToViewTransform)
}
}
}
}

In almost all cases, a developer should use an implementation of this interface obtained from CanvasStrokeRenderer.create.

However, some developers may find it helpful to use their own implementation of this interface, possibly to draw other effects to the Canvas, typically delegating to a renderer from CanvasStrokeRenderer.create for part of the custom rendering behavior to have the additional effects add to or modify the standard stroke rendering behavior. Custom CanvasStrokeRenderer implementations are generally less efficient than effects that can be achieved with a custom androidx.ink.brush.BrushFamily. If a custom implementation draws to different screen locations than the standard implementation, for example surrounding a stroke with additional content, then that additional content will not be taken into account in geometry operations like androidx.ink.geometry.Intersection or androidx.ink.geometry.PartitionedMesh.computeCoverage.

If custom rendering is needed during live authoring of in-progress strokes and that custom rendering involves drawing content outside the stroke boundaries, then be sure to override strokeModifiedRegionOutsetPx.

Summary

Public companion functions

CanvasStrokeRenderer

Create a CanvasStrokeRenderer that is appropriate to the device's API version.

Public functions

Unit
draw(
    canvas: Canvas,
    inProgressStroke: InProgressStroke,
    strokeToScreenTransform: AffineTransform
)

Render a single inProgressStroke on the provided canvas.

Unit
draw(
    canvas: Canvas,
    inProgressStroke: InProgressStroke,
    strokeToScreenTransform: Matrix
)

Render a single inProgressStroke on the provided canvas.

Unit
draw(
    canvas: Canvas,
    stroke: Stroke,
    strokeToScreenTransform: AffineTransform
)

Render a single stroke on the provided canvas.

Unit
draw(canvas: Canvas, stroke: Stroke, strokeToScreenTransform: Matrix)

Render a single stroke on the provided canvas.

open @Px Int

The distance beyond a stroke geometry's bounds that rendering might affect.

Public companion functions

create

Added in 1.0.0-alpha01
fun create(): CanvasStrokeRenderer

Create a CanvasStrokeRenderer that is appropriate to the device's API version.

Public functions

draw

Added in 1.0.0-alpha01
fun draw(
    canvas: Canvas,
    inProgressStroke: InProgressStroke,
    strokeToScreenTransform: AffineTransform
): Unit

Render a single inProgressStroke on the provided canvas.

The strokeToScreenTransform should represent the complete transformation from stroke coordinates to the canvas, modulo translation. This transform will not be applied to the canvas in any way, as it may be made up of several individual transforms applied to the canvas during an app’s drawing logic. If this transform is inaccurate, strokes may appear blurry or aliased.

draw

Added in 1.0.0-alpha01
fun draw(
    canvas: Canvas,
    inProgressStroke: InProgressStroke,
    strokeToScreenTransform: Matrix
): Unit

Render a single inProgressStroke on the provided canvas.

The strokeToScreenTransform must be affine. It should represent the complete transformation from stroke coordinates to the canvas, modulo translation. This transform will not be applied to the canvas in any way, as it may be made up of several individual transforms applied to the canvas during an app’s drawing logic. If this transform is inaccurate, strokes may appear blurry or aliased.

draw

Added in 1.0.0-alpha01
fun draw(
    canvas: Canvas,
    stroke: Stroke,
    strokeToScreenTransform: AffineTransform
): Unit

Render a single stroke on the provided canvas.

To avoid needing to calculate and maintain strokeToScreenTransform, consider using androidx.ink.rendering.android.view.ViewStrokeRenderer instead.

The strokeToScreenTransform should represent the complete transformation from stroke coordinates to the screen, modulo translation. This transform will not be applied to the canvas in any way, as it may be made up of several individual transforms applied to the canvas during an app’s drawing logic. If this transform is inaccurate, strokes may appear blurry or aliased.

draw

Added in 1.0.0-alpha01
fun draw(canvas: Canvas, stroke: Stroke, strokeToScreenTransform: Matrix): Unit

Render a single stroke on the provided canvas.

To avoid needing to calculate and maintain strokeToScreenTransform, consider using androidx.ink.rendering.android.view.ViewStrokeRenderer instead.

The strokeToScreenTransform must be affine. It should represent the complete transformation from stroke coordinates to the canvas, modulo translation. This transform will not be applied to the canvas in any way, as it may be made up of several individual transforms applied to the canvas during an app’s drawing logic. If this transform is inaccurate, strokes may appear blurry or aliased.

strokeModifiedRegionOutsetPx

Added in 1.0.0-alpha01
open fun strokeModifiedRegionOutsetPx(): @Px Int

The distance beyond a stroke geometry's bounds that rendering might affect. This is currently only applicable to in-progress stroke rendering, where the smallest possible region of the screen is redrawn to optimize performance. But with a custom CanvasStrokeRenderer, certain effects like drop shadows or blurs may render beyond the stroke's geometry, and setting a higher value here can ensure that artifacts are not left on screen after an in-progress stroke has moved on from a particular region of the screen. This value should be set to the lowest value that avoids the artifacts, as larger values will be less performant, and effects that rely on larger values will be less compatible with stroke geometry operations.