Typography and Text
Text is one of the most complex parts of any graphics library. Skija provides a high-level API to handle everything from simple labels to complex multi-line text layout.
The Typeface (The "What")
A Typeface represents a specific font file (like "Inter-Bold.ttf"). It defines the shape of the glyphs.
Loading Typefaces
You can load them from files, resources, or the system font manager.
// From a file
Typeface inter = Typeface.makeFromFile("fonts/Inter.ttf");
// From system (safe way)
Typeface sans = FontMgr.getDefault().matchFamilyStyle("sans-serif", FontStyle.NORMAL);Common Pitfall: Don't assume a font exists on the user's system. Always provide a fallback or bundle your fonts as resources.
The Font (The "How")
A Font takes a Typeface and gives it a size and other rendering attributes.
Font font = new Font(inter, 14f);Positioning Text: Font Metrics
If you want to center text or align it precisely, you need to understand FontMetrics.
FontMetrics metrics = font.getMetrics();
// metrics.getAscent() -> Distance from baseline to top (negative)
// metrics.getDescent() -> Distance from baseline to bottom (positive)
// metrics.getLeading() -> Suggested space between linesExample: Perfect Vertical Centering To center text vertically at y, you usually want to offset it by half the height of the "cap height" (height of capital letters).
float centerY = rect.getMidY() - metrics.getCapHeight() / 2f;
canvas.drawString("HELLO", rect.getLeft(), centerY, font, paint);Advanced Text: Paragraph
For anything more complex than a single word or line, use the Paragraph API. It handles:
- Line wrapping
- Multiple styles (bold, italic, colors) in one block
- Right-to-Left (RTL) text
- Emoji support
See Paragraph API Reference for details.
Interactive Text: TextLine
If you need a single line of text but need to know exactly where each character is (e.g., for a cursor or selection in a text input), use TextLine.
TextLine line = TextLine.make("Interact with me", font);
// Get visual properties
float width = line.getWidth();
float height = line.getHeight();
// Hit-testing: Get character index at a pixel coordinate
int charIndex = line.getOffsetAtCoord(45.0f);
// Get pixel coordinate for a character index
float xCoord = line.getCoordAtOffset(5);
// Rendering
canvas.drawTextLine(line, 20, 50, paint);Visual Examples
Interactive Text Line: See examples/scenes/src/TextLineScene.java for a demo of cursor positioning, hit-testing, and multi-script text layout.
Text Blob Effects: See examples/scenes/src/TextBlobScene.java for examples of text-on-path, wavy text, and custom positioning.
Best Practices
- Cache your Fonts/Typefaces: Creating a
Typefaceinvolves parsing a file and can be slow. Keep them in a static cache or a theme manager. - Use Hinting/Anti-aliasing: For small text on screens, ensure anti-aliasing is enabled in your
Paintto keep it readable. - Measure before Drawing: Use
font.measureTextWidth(string)to calculate layouts before you actually commit to drawing them on the canvas.