Modules

The Ink API is modularized, so you can use only what you need.

Strokes

The Strokes module serves as the foundation of the Ink library, offering the primary API interface and containing the core data types for interacting with the library. Key data types within this module include:

  • StrokeInputBatch: Represents a series of pointer inputs, encompassing position, timestamp, and optionally pressure, tilt, and orientation. This data can be utilized with the Stroke or InProgressStroke classes, and is the type that would provide the inputs for a handwriting recognition library.
  • Stroke: An immutable representation of a finalized stroke with fixed geometry. Stroke comprises an ImmutableStrokeInputBatch (input points), a Brush (styling), and a PartitionedMesh (geometric shape). Strokes can be stored, manipulated, and rendered within your application.
  • InProgressStroke: A mutable counterpart to Stroke designed for incremental input handling and real-time rendering during the drawing process. While often used indirectly through InProgressStrokesView, InProgressStroke can be leveraged directly for advanced customization.

Geometry

The Geometry module provides a suite of geometry primitives for both basic and complex shapes along with operations for intersection detection and transformations. These primitives seamlessly integrate with Ink strokes, empowering you to build features like whole-stroke erasers and marquee selection tools.

While classes like Box and Vec primarily facilitate geometric operations, PartitionedMesh may also include rendering-specific data.

Brush

The Brush module acts as a declarative configuration for stroke creation and rendering, functioning similarly to a text font. A Brush object ha the following properties:

  • Color: Can be a solid color or the foundation for layered effects and textures.
  • Size: Can be fixed or serve as a base for dynamic size adjustments.
  • Family: Analogous to a text typeface, family defines the stroke's overall style.
  • Epsilon: Controls the level of detail in the stroke's vector geometry, representing the smallest unit of visual distinction.

The epsilon property plays a crucial role in defining the precision of your coordinate system. More guidance is provided in the Brush APIs section on how to choose an appropriate epsilon value.

The BrushFamily serves as a powerful configuration for creating expressive strokes without delving into complex geometry or rendering code. The library provides a set of predefined StockBrushes, including a pressure-sensitive pen, highlighter, and marker.

Authoring

The Authoring module enables developers to capture user touch input and render it as low-latency strokes on the screen in real-time. This is achieved through the InProgressStrokesView class, which processes motion events and visualizes the strokes as they're drawn.

Once a stroke is completed, the module notifies the client application using the onStrokesFinished() callback of InProgressStrokesFinishedListener. The callback allows the application to retrieve the finished stroke data for rendering or storage.

Rendering

The Rendering module simplifies the process of drawing ink strokes onto an Android Canvas. The module provides a CanvasStrokeRenderer for Compose and ViewStrokeRenderer for view-based layouts, both of which optimize rendering performance and ensure high-quality visuals, including anti-aliasing.

To render strokes to a canvas, obtain a CanvasStrokeRenderer instance using the create() method. Then, use the draw() method to render either finished or in-progress strokes. strokes onto a canvas.

The canvas can be transformed (panned, zoomed, or rotated) as part of drawing the stroke, but to make sure the stroke looks its best drawn on screen, the transform applied to the canvas must also be passed to CanvasStrokeRenderer#draw(). To avoid needing to keep track of this separately, use ViewStrokeRenderer instead.