text

package
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 23, 2025 License: MIT Imports: 15 Imported by: 2

README

text — GPU Text Pipeline for gg

Status: v0.10.0 (Released)

This package implements a modern GPU-ready text pipeline for gogpu/gg, inspired by Ebitengine text/v2 and go-text/typesetting.

Architecture

FontSource (heavyweight, shared)
    ↓
Face (lightweight, per-size)
    ↓
Segmenter → Shaper → Layout → GPU Renderer
    │           │        │
Bidi/Script  Cache    Lines

Features

Pluggable Shaper (v0.10.0)
  • Shaper interface — Converts text to positioned glyphs
  • BuiltinShaper — Default using golang.org/x/image
  • Custom shapers — Plug in go-text/typesetting or HarfBuzz
Bidi/Script Segmentation (v0.10.0)
  • 25+ Unicode scripts — Latin, Arabic, Hebrew, Han, Cyrillic, Thai, etc.
  • Full Unicode Bidi Algorithm — Via golang.org/x/text/unicode/bidi
  • Script inheritance — Common/Inherited characters resolved from context
Multi-line Layout (v0.10.0)
  • Alignment — Left, Center, Right, Justify (placeholder)
  • Line wrapping — At MaxWidth with word boundaries
  • Line spacing — Configurable multiplier
  • Bidi-aware — Proper RTL/LTR segment ordering
Shaping Cache (v0.10.0)
  • 16-shard LRU — Concurrent access without lock contention
  • 16K total entries — 1024 per shard
  • Zero-allocation hot path — Pre-allocated result storage

Usage

Basic Text Drawing
// Load font (heavyweight, do once)
source, err := text.NewFontSourceFromFile("Roboto-Regular.ttf")
if err != nil {
    log.Fatal(err)
}
defer source.Close()

// Create face at specific size (lightweight)
face := source.Face(24)

// Use with gg.Context
ctx := gg.NewContext(800, 600)
ctx.SetFont(face)
ctx.DrawString("Hello, GoGPU!", 100, 100)
Text Shaping
// Shape text to positioned glyphs
glyphs := text.Shape("Hello", face, 24)
for _, g := range glyphs {
    fmt.Printf("GID=%d X=%.1f Y=%.1f\n", g.GID, g.X, g.Y)
}
Bidi/Script Segmentation
// Segment mixed-direction text
segments := text.SegmentText("Hello שלום مرحبا")
for _, seg := range segments {
    fmt.Printf("'%s' Dir=%s Script=%s\n",
        seg.Text, seg.Direction, seg.Script)
}

// RTL base direction
segments = text.SegmentTextRTL("مرحبا Hello")
Multi-line Layout
// Layout with options
opts := text.LayoutOptions{
    MaxWidth:    400,
    LineSpacing: 1.2,
    Alignment:   text.AlignCenter,
    Direction:   text.DirectionLTR,
}
layout := text.LayoutText(longText, face, 16, opts)

// Access lines
for _, line := range layout.Lines {
    fmt.Printf("Y=%.1f Width=%.1f Glyphs=%d\n",
        line.Y, line.Width, len(line.Glyphs))
}

// Simple layout (no wrapping)
layout = text.LayoutTextSimple("Hello\nWorld", face, 16)
Custom Shaper
// Implement custom shaper (e.g., go-text/typesetting)
type MyShaper struct {
    // ...
}

func (s *MyShaper) Shape(text string, face text.Face, size float64) []text.ShapedGlyph {
    // Custom shaping logic
}

// Set as global shaper
text.SetShaper(&MyShaper{})
defer text.SetShaper(nil) // Reset to default

Types

ShapedGlyph
type ShapedGlyph struct {
    GID      GlyphID  // Glyph index in font
    Cluster  int      // Source character index
    X, Y     float64  // Position relative to origin
    XAdvance float64  // Horizontal advance
    YAdvance float64  // Vertical advance (for TTB)
}
Segment
type Segment struct {
    Text      string    // Segment text
    Start     int       // Byte offset in original text
    End       int       // End byte offset
    Direction Direction // LTR or RTL
    Script    Script    // Unicode script
    Level     int       // Bidi embedding level
}
Layout
type Layout struct {
    Lines  []Line   // Positioned lines
    Width  float64  // Maximum line width
    Height float64  // Total height
}

type Line struct {
    Runs    []ShapedRun   // Runs with uniform style
    Glyphs  []ShapedGlyph // All positioned glyphs
    Width   float64       // Line width
    Ascent  float64       // Max ascent
    Descent float64       // Max descent
    Y       float64       // Baseline Y position
}

Dependencies

  • golang.org/x/image/font/opentype — TTF/OTF parsing
  • golang.org/x/text/unicode/bidi — Unicode Bidirectional Algorithm

Test Coverage

  • text package: 87.0%
  • text/cache package: 93.7%
  • 0 linter issues

Roadmap

v0.10.0 (Current)
  • Pluggable Shaper interface
  • Extended shaping types
  • Sharded LRU shaping cache
  • Bidi/Script segmentation
  • Multi-line Layout Engine
v0.11.0 (Planned)
  • go-text/typesetting integration
  • Glyph-as-Path rendering
  • MSDF atlas for GPU
  • Emoji support (COLRv1)

Documentation

Overview

Package text provides text rendering for gg. It implements a modern text API inspired by Ebitengine text/v2.

The text rendering pipeline follows a separation of concerns:

  • FontSource: Heavyweight, shared font resource (parses TTF/OTF files)
  • Face: Lightweight font instance at a specific size
  • FontParser: Pluggable font parsing backend (default: golang.org/x/image)

Example usage

// Load font (do once, share across application)
source, err := text.NewFontSourceFromFile("Roboto-Regular.ttf")
if err != nil {
    log.Fatal(err)
}
defer source.Close()

// Create face at specific size (lightweight)
face := source.Face(24)

// Use with gg.Context
ctx := gg.NewContext(800, 600)
ctx.SetFont(face)
ctx.DrawString("Hello, GoGPU!", 100, 100)

Pluggable Parser Backend

The font parsing is abstracted through the FontParser interface. By default, golang.org/x/image/font/opentype is used. Custom parsers can be registered for alternative implementations:

// Register a custom parser
text.RegisterParser("myparser", myCustomParser)

// Use the custom parser
source, err := text.NewFontSource(data, text.WithParser("myparser"))

This design allows:

  • Easy migration to different font libraries
  • Pure Go implementations without external dependencies
  • Custom font formats or optimized parsers

Index

Constants

This section is empty.

Variables

View Source
var (
	// Latin Scripts
	RangeBasicLatin = UnicodeRange{0x0000, 0x007F} // ASCII
	RangeLatin1Sup  = UnicodeRange{0x0080, 0x00FF} // Latin-1 Supplement
	RangeLatinExtA  = UnicodeRange{0x0100, 0x017F} // Latin Extended-A
	RangeLatinExtB  = UnicodeRange{0x0180, 0x024F} // Latin Extended-B

	// Cyrillic Scripts
	RangeCyrillic = UnicodeRange{0x0400, 0x04FF} // Cyrillic

	// Greek Scripts
	RangeGreek = UnicodeRange{0x0370, 0x03FF} // Greek and Coptic

	// Middle Eastern Scripts
	RangeArabic = UnicodeRange{0x0600, 0x06FF} // Arabic
	RangeHebrew = UnicodeRange{0x0590, 0x05FF} // Hebrew

	// CJK Scripts
	RangeCJKUnified = UnicodeRange{0x4E00, 0x9FFF} // CJK Unified Ideographs
	RangeHiragana   = UnicodeRange{0x3040, 0x309F} // Hiragana
	RangeKatakana   = UnicodeRange{0x30A0, 0x30FF} // Katakana
	RangeHangul     = UnicodeRange{0xAC00, 0xD7AF} // Hangul Syllables

	// Emoji
	RangeEmoji        = UnicodeRange{0x1F600, 0x1F64F} // Emoticons
	RangeEmojiMisc    = UnicodeRange{0x1F300, 0x1F5FF} // Miscellaneous Symbols and Pictographs
	RangeEmojiSymbols = UnicodeRange{0x1F680, 0x1F6FF} // Transport and Map Symbols
	RangeEmojiFlags   = UnicodeRange{0x1F1E0, 0x1F1FF} // Regional Indicator Symbols (Flags)
)

Common Unicode ranges for filtering faces.

Functions

func Draw

func Draw(dst draw.Image, text string, face Face, x, y float64, col color.Color)

Draw renders text to a destination image. Position (x, y) is the baseline origin. The face must be a *sourceFace from this package.

func IsPunctuation added in v0.10.0

func IsPunctuation(r rune) bool

func IsWhitespace added in v0.10.0

func IsWhitespace(r rune) bool

func Measure

func Measure(text string, face Face) (width, height float64)

Measure returns the dimensions of text. Width is the horizontal advance, height is the font's line height.

func RegisterParser

func RegisterParser(name string, parser FontParser)

RegisterParser registers a custom font parser. This allows users to provide their own parsing implementation.

func SetShaper added in v0.10.0

func SetShaper(s Shaper)

SetShaper sets the global shaper used by Shape(). Pass nil to reset to the default BuiltinShaper.

Example usage with a custom shaper:

text.SetShaper(myHarfBuzzShaper)
defer text.SetShaper(nil) // Reset to default

Types

type Alignment added in v0.10.0

type Alignment int

Alignment specifies text horizontal alignment within the layout width.

const (
	// AlignLeft aligns text to the left edge (default).
	AlignLeft Alignment = iota
	// AlignCenter centers text horizontally.
	AlignCenter
	// AlignRight aligns text to the right edge.
	AlignRight
	// AlignJustify distributes text evenly (future implementation).
	AlignJustify
)

func (Alignment) String added in v0.10.0

func (a Alignment) String() string

String returns the string representation of the alignment.

type BuiltinSegmenter added in v0.10.0

type BuiltinSegmenter struct {
	BaseDirection Direction
}

func NewBuiltinSegmenter added in v0.10.0

func NewBuiltinSegmenter() *BuiltinSegmenter

func NewBuiltinSegmenterWithDirection added in v0.10.0

func NewBuiltinSegmenterWithDirection(dir Direction) *BuiltinSegmenter

func (*BuiltinSegmenter) Segment added in v0.10.0

func (s *BuiltinSegmenter) Segment(text string) []Segment

type BuiltinShaper added in v0.10.0

type BuiltinShaper struct{}

BuiltinShaper provides text shaping using golang.org/x/image/font. It supports Latin, Cyrillic, Greek, CJK, and other scripts that don't require complex text shaping (ligatures, contextual forms, etc.).

For complex scripts like Arabic, Hebrew, or Indic languages that require advanced shaping features (GSUB/GPOS tables), use SetShaper() with a HarfBuzz-compatible implementation such as go-text/typesetting.

BuiltinShaper is stateless and safe for concurrent use.

func (*BuiltinShaper) Shape added in v0.10.0

func (s *BuiltinShaper) Shape(text string, face Face, size float64) []ShapedGlyph

Shape implements the Shaper interface. It converts text to positioned glyphs using the font's glyph metrics.

The shaping is simple left-to-right positioning without:

  • Ligature substitution (fi, fl, etc.)
  • Kerning pairs
  • Contextual alternates
  • Right-to-left reordering

For these features, use a full shaper like go-text/typesetting.

type Cache

type Cache[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Cache is a generic thread-safe LRU cache with soft limit. When the cache exceeds softLimit, oldest entries are evicted.

Cache is safe for concurrent use. Cache must not be copied after creation (has mutex).

func NewCache

func NewCache[K comparable, V any](softLimit int) *Cache[K, V]

NewCache creates a new cache with the given soft limit. A softLimit of 0 means unlimited.

func (*Cache[K, V]) Clear

func (c *Cache[K, V]) Clear()

Clear removes all entries from the cache.

func (*Cache[K, V]) Get

func (c *Cache[K, V]) Get(key K) (V, bool)

Get retrieves a value from the cache. Returns (value, true) if found, (zero, false) otherwise.

func (*Cache[K, V]) GetOrCreate

func (c *Cache[K, V]) GetOrCreate(key K, create func() V) V

GetOrCreate returns cached value or creates it. Thread-safe: create is called under lock to prevent duplicate creation.

func (*Cache[K, V]) Len

func (c *Cache[K, V]) Len() int

Len returns the number of entries in the cache.

func (*Cache[K, V]) Set

func (c *Cache[K, V]) Set(key K, value V)

Set stores a value in the cache. If the cache exceeds softLimit after insertion, oldest entries are evicted.

type Direction

type Direction int

Direction specifies text direction.

const (
	// DirectionLTR is left-to-right text (English, French, etc.)
	DirectionLTR Direction = iota
	// DirectionRTL is right-to-left text (Arabic, Hebrew)
	DirectionRTL
	// DirectionTTB is top-to-bottom text (traditional Chinese, Japanese)
	DirectionTTB
	// DirectionBTT is bottom-to-top text (rare)
	DirectionBTT
)

func (Direction) IsHorizontal added in v0.10.0

func (d Direction) IsHorizontal() bool

IsHorizontal returns true if the direction is horizontal (LTR or RTL).

func (Direction) IsVertical added in v0.10.0

func (d Direction) IsVertical() bool

IsVertical returns true if the direction is vertical (TTB or BTT).

func (Direction) String

func (d Direction) String() string

String returns the string representation of the direction.

type DrawOptions

type DrawOptions struct {
	// Color for the text (default: black)
	Color color.Color
}

DrawOptions provides advanced options for text drawing. Reserved for future enhancements.

type Face

type Face interface {
	// Metrics returns the font metrics at this face's size.
	Metrics() Metrics

	// Advance returns the total advance width of the text in pixels.
	// This is the sum of all glyph advances.
	Advance(text string) float64

	// HasGlyph reports whether the font has a glyph for the given rune.
	HasGlyph(r rune) bool

	// Glyphs returns an iterator over all glyphs in the text.
	// The glyphs are positioned relative to the origin (0, 0).
	// Uses Go 1.25+ iter.Seq for zero-allocation iteration.
	Glyphs(text string) iter.Seq[Glyph]

	// AppendGlyphs appends glyphs for the text to dst and returns the extended slice.
	// This is useful for building glyph slices without allocation.
	AppendGlyphs(dst []Glyph, text string) []Glyph

	// Direction returns the text direction for this face.
	Direction() Direction

	// Source returns the FontSource this face was created from.
	Source() *FontSource

	// Size returns the size of this face in points.
	Size() float64
	// contains filtered or unexported methods
}

Face represents a font face at a specific size. This is a lightweight object that can be created from a FontSource. Face is safe for concurrent use.

type FaceOption

type FaceOption func(*faceConfig)

FaceOption configures Face creation.

func WithDirection

func WithDirection(d Direction) FaceOption

WithDirection sets the text direction for the face.

func WithHinting

func WithHinting(h Hinting) FaceOption

WithHinting sets the hinting mode for the face.

func WithLanguage

func WithLanguage(lang string) FaceOption

WithLanguage sets the language tag for the face (e.g., "en", "ja", "ar").

type FilteredFace

type FilteredFace struct {
	// contains filtered or unexported fields
}

FilteredFace wraps a face and restricts it to specific Unicode ranges. Only glyphs in the specified ranges are considered available. FilteredFace is safe for concurrent use.

func NewFilteredFace

func NewFilteredFace(face Face, ranges ...UnicodeRange) *FilteredFace

NewFilteredFace creates a FilteredFace. Only glyphs in the specified ranges are considered available. If no ranges are specified, all glyphs are available (no filtering).

func (*FilteredFace) Advance

func (f *FilteredFace) Advance(text string) float64

Advance implements Face.Advance. Only includes runes that are in the allowed ranges.

func (*FilteredFace) AppendGlyphs

func (f *FilteredFace) AppendGlyphs(dst []Glyph, text string) []Glyph

AppendGlyphs implements Face.AppendGlyphs. Only appends glyphs for runes in the allowed ranges.

func (*FilteredFace) Direction

func (f *FilteredFace) Direction() Direction

Direction implements Face.Direction.

func (*FilteredFace) Glyphs

func (f *FilteredFace) Glyphs(text string) iter.Seq[Glyph]

Glyphs implements Face.Glyphs. Only yields glyphs for runes in the allowed ranges.

func (*FilteredFace) HasGlyph

func (f *FilteredFace) HasGlyph(r rune) bool

HasGlyph implements Face.HasGlyph. Returns true only if the rune is in the allowed ranges and the wrapped face has it.

func (*FilteredFace) Metrics

func (f *FilteredFace) Metrics() Metrics

Metrics implements Face.Metrics.

func (*FilteredFace) Size

func (f *FilteredFace) Size() float64

Size implements Face.Size.

func (*FilteredFace) Source

func (f *FilteredFace) Source() *FontSource

Source implements Face.Source.

type FontMetrics

type FontMetrics struct {
	// Ascent is the distance from the baseline to the top of the font (positive).
	Ascent float64

	// Descent is the distance from the baseline to the bottom of the font (negative).
	Descent float64

	// LineGap is the recommended line gap between lines.
	LineGap float64

	// XHeight is the height of lowercase letters (like 'x').
	XHeight float64

	// CapHeight is the height of uppercase letters.
	CapHeight float64
}

FontMetrics holds font-level metrics at a specific size.

func (FontMetrics) Height

func (m FontMetrics) Height() float64

Height returns the total line height (ascent - descent + line gap).

type FontParser

type FontParser interface {
	// Parse parses font data (TTF or OTF) and returns a ParsedFont.
	Parse(data []byte) (ParsedFont, error)
}

FontParser is an interface for font parsing backends. This abstraction allows swapping the font parsing library (e.g., golang.org/x/image/font/opentype vs a pure Go implementation).

The default implementation uses golang.org/x/image/font/opentype.

type FontSource

type FontSource struct {
	// contains filtered or unexported fields
}

FontSource represents a loaded font file. One FontSource can create multiple Face instances at different sizes. FontSource is heavyweight and should be shared across the application.

FontSource is safe for concurrent use. FontSource must not be copied after creation (enforced by copyCheck).

func NewFontSource

func NewFontSource(data []byte, opts ...SourceOption) (*FontSource, error)

NewFontSource creates a FontSource from font data (TTF or OTF). The data slice is copied internally and can be reused after this call.

Options can be used to configure caching and parser backend.

func NewFontSourceFromFile

func NewFontSourceFromFile(path string, opts ...SourceOption) (*FontSource, error)

NewFontSourceFromFile loads a FontSource from a font file path.

func (*FontSource) Close

func (s *FontSource) Close() error

Close releases resources associated with the FontSource. All faces created from this source become invalid after Close.

func (*FontSource) Face

func (s *FontSource) Face(size float64, opts ...FaceOption) Face

Face creates a Face at the specified size (in points). Multiple faces can be created from the same FontSource.

Face is a lightweight object that shares caches with the FontSource.

func (*FontSource) Name

func (s *FontSource) Name() string

Name returns the font name.

func (*FontSource) Parsed

func (s *FontSource) Parsed() ParsedFont

Parsed returns the parsed font for advanced operations. This is primarily used by Face implementations.

type Glyph

type Glyph struct {
	// Rune is the Unicode character this glyph represents.
	// For ligatures, this may be the first character of the ligature.
	Rune rune

	// GID is the glyph index in the font.
	GID GlyphID

	// X, Y are the position of the glyph relative to the text origin.
	// The origin is at the baseline of the first character.
	X, Y float64

	// OriginX, OriginY are the absolute position of the glyph's origin point.
	// This is where the glyph should be drawn from.
	OriginX float64
	OriginY float64

	// Advance is the horizontal advance width of the glyph.
	// This is how much the cursor moves after drawing this glyph.
	Advance float64

	// Bounds is the bounding box of the glyph.
	// This defines the area the glyph occupies.
	Bounds Rect

	// Index is the byte position in the original string where this glyph starts.
	Index int

	// Cluster is the character cluster index.
	// Multiple glyphs can belong to the same cluster (e.g., ligatures).
	Cluster int
}

Glyph represents a single shaped glyph with its position and metrics. This is the output of text shaping and is ready for rendering.

type GlyphFlags added in v0.10.0

type GlyphFlags uint8

GlyphFlags provides additional glyph information for rendering.

const (
	// GlyphFlagLigature indicates this glyph is the first in a ligature.
	// The following glyphs with zero advance are part of the same ligature.
	GlyphFlagLigature GlyphFlags = 1 << iota

	// GlyphFlagMark indicates this glyph is a combining mark.
	// Marks are positioned relative to their base glyph.
	GlyphFlagMark

	// GlyphFlagSafeToBreak indicates this is a safe line break point.
	// Used by the layout engine for word wrapping.
	GlyphFlagSafeToBreak

	// GlyphFlagClusterStart indicates this glyph starts a new cluster.
	// Clusters are groups of glyphs that map to one or more characters.
	GlyphFlagClusterStart
)

func (GlyphFlags) Has added in v0.10.0

func (f GlyphFlags) Has(flag GlyphFlags) bool

Has returns true if the flags contain the specified flag.

func (GlyphFlags) String added in v0.10.0

func (f GlyphFlags) String() string

String returns a human-readable representation of the flags.

type GlyphID

type GlyphID uint16

GlyphID is a unique identifier for a glyph within a font. The glyph ID is assigned by the font file and is font-specific.

type GlyphImage

type GlyphImage struct {
	// Mask is the alpha mask (grayscale image).
	// This represents the glyph's shape.
	Mask *image.Alpha

	// Bounds relative to glyph origin.
	// The origin is typically on the baseline at the left edge.
	Bounds image.Rectangle

	// Advance width in pixels.
	// This is how far the cursor should move after drawing this glyph.
	Advance float64
}

GlyphImage represents a rasterized glyph. This contains the alpha mask and positioning information.

func RasterizeGlyph

func RasterizeGlyph(parsed ParsedFont, glyphID GlyphID, ppem float64) *GlyphImage

RasterizeGlyph renders a glyph to an alpha mask. Uses golang.org/x/image/font for rasterization.

This function is primarily intended for future caching implementations and advanced use cases. For normal text drawing, use the Draw function instead.

Parameters:

  • parsed: The parsed font (must be *ximageParsedFont)
  • glyphID: The glyph index to rasterize
  • ppem: Pixels per em (font size)

Returns:

  • *GlyphImage with the rasterized glyph, or nil if rasterization fails

type GlyphKey

type GlyphKey struct {
	GID  GlyphID
	Size float64
}

GlyphKey identifies a rasterized glyph in the glyph cache.

type GlyphType added in v0.10.0

type GlyphType uint8

GlyphType indicates how to render a glyph.

const (
	// GlyphTypeOutline is a vector path glyph (default).
	// Rendered via sparse strips or MSDF.
	GlyphTypeOutline GlyphType = iota

	// GlyphTypeBitmap is an embedded bitmap glyph.
	// Found in sbix (Apple) or CBDT/CBLC (Google) tables.
	// Used for color emoji.
	GlyphTypeBitmap

	// GlyphTypeCOLR is a color layers glyph.
	// Uses COLRv0 or COLRv1 tables for layered color glyphs.
	GlyphTypeCOLR

	// GlyphTypeSVG is an SVG document glyph.
	// Found in SVG table, used for complex color glyphs.
	GlyphTypeSVG
)

func (GlyphType) String added in v0.10.0

func (t GlyphType) String() string

String returns the string representation of the glyph type.

type Hinting

type Hinting int

Hinting specifies font hinting mode.

const (
	// HintingNone disables hinting.
	HintingNone Hinting = iota
	// HintingVertical applies vertical hinting only.
	HintingVertical
	// HintingFull applies full hinting.
	HintingFull
)

func (Hinting) String

func (h Hinting) String() string

String returns the string representation of the hinting.

type Layout added in v0.10.0

type Layout struct {
	// Lines contains all lines of laid out text.
	Lines []Line

	// Width is the maximum width among all lines.
	Width float64

	// Height is the total height of all lines.
	Height float64
}

Layout represents the result of text layout.

func LayoutText added in v0.10.0

func LayoutText(text string, face Face, size float64, opts LayoutOptions) *Layout

LayoutText performs text layout with the given options. It segments text by direction/script, shapes each segment, wraps lines if MaxWidth > 0, and positions lines with alignment.

func LayoutTextSimple added in v0.10.0

func LayoutTextSimple(text string, face Face, size float64) *Layout

LayoutTextSimple is a convenience wrapper with default options.

type LayoutOptions added in v0.10.0

type LayoutOptions struct {
	// MaxWidth is the maximum line width in pixels.
	// If 0, no line wrapping is performed (single-line paragraphs).
	MaxWidth float64

	// LineSpacing is a multiplier for line height.
	// 1.0 uses the font's natural line height; 1.5 adds 50% extra space.
	LineSpacing float64

	// Alignment specifies horizontal text alignment.
	Alignment Alignment

	// Direction is the base text direction (LTR or RTL).
	// Used for paragraph-level direction when no strong directional text is present.
	Direction Direction
}

LayoutOptions configures text layout behavior.

func DefaultLayoutOptions added in v0.10.0

func DefaultLayoutOptions() LayoutOptions

DefaultLayoutOptions returns sensible default layout options.

type Line added in v0.10.0

type Line struct {
	// Runs contains the shaped runs that make up this line.
	// Multiple runs occur with mixed scripts or directions.
	Runs []ShapedRun

	// Glyphs contains all glyphs from Runs, positioned for rendering.
	// Glyph X positions are absolute within the layout.
	Glyphs []ShapedGlyph

	// Width is the total advance width of all glyphs in this line.
	Width float64

	// Ascent is the maximum ascent of all runs (distance above baseline).
	Ascent float64

	// Descent is the maximum descent of all runs (distance below baseline).
	Descent float64

	// Y is the baseline Y position of this line within the layout.
	Y float64
}

Line represents a positioned line of text ready for rendering.

func (*Line) Height added in v0.10.0

func (l *Line) Height() float64

Height returns the total height of the line (ascent + descent).

type Metrics

type Metrics struct {
	// Ascent is the distance from the baseline to the top of the font (positive).
	// This is the maximum height a glyph can reach above the baseline.
	Ascent float64

	// Descent is the distance from the baseline to the bottom of the font (positive, below baseline).
	// This is the maximum depth a glyph can reach below the baseline.
	// Note: Unlike FontMetrics.Descent, this is stored as a positive value.
	Descent float64

	// LineGap is the recommended gap between lines.
	LineGap float64

	// XHeight is the height of lowercase letters (like 'x').
	XHeight float64

	// CapHeight is the height of uppercase letters.
	CapHeight float64
}

Metrics holds font metrics at a specific size. These metrics are derived from the font file and scaled to the face size.

func (Metrics) LineHeight

func (m Metrics) LineHeight() float64

LineHeight returns the total line height (ascent + descent + line gap). This is the recommended vertical distance between baselines of consecutive lines.

type MultiFace

type MultiFace struct {
	// contains filtered or unexported fields
}

MultiFace combines multiple faces with fallback. When rendering, it uses the first face that has the glyph. MultiFace is safe for concurrent use.

func NewMultiFace

func NewMultiFace(faces ...Face) (*MultiFace, error)

NewMultiFace creates a MultiFace from faces. All faces must have the same direction. Returns error if faces is empty or directions don't match.

func (*MultiFace) Advance

func (m *MultiFace) Advance(text string) float64

Advance implements Face.Advance. Calculates total advance using the appropriate face for each rune.

func (*MultiFace) AppendGlyphs

func (m *MultiFace) AppendGlyphs(dst []Glyph, text string) []Glyph

AppendGlyphs implements Face.AppendGlyphs. Appends glyphs using the appropriate face for each rune.

func (*MultiFace) Direction

func (m *MultiFace) Direction() Direction

Direction implements Face.Direction.

func (*MultiFace) Glyphs

func (m *MultiFace) Glyphs(text string) iter.Seq[Glyph]

Glyphs implements Face.Glyphs. Returns an iterator over all glyphs, using the appropriate face for each rune.

func (*MultiFace) HasGlyph

func (m *MultiFace) HasGlyph(r rune) bool

HasGlyph implements Face.HasGlyph. Returns true if any face has the glyph.

func (*MultiFace) Metrics

func (m *MultiFace) Metrics() Metrics

Metrics implements Face.Metrics. Returns metrics from the first face.

func (*MultiFace) Size

func (m *MultiFace) Size() float64

Size implements Face.Size. Returns the size from the first face.

func (*MultiFace) Source

func (m *MultiFace) Source() *FontSource

Source implements Face.Source. Returns nil since MultiFace is a composite face.

type ParsedFont

type ParsedFont interface {
	// Name returns the font family name.
	// Returns empty string if not available.
	Name() string

	// FullName returns the full font name.
	// Returns empty string if not available.
	FullName() string

	// NumGlyphs returns the number of glyphs in the font.
	NumGlyphs() int

	// UnitsPerEm returns the units per em for the font.
	UnitsPerEm() int

	// GlyphIndex returns the glyph index for a rune.
	// Returns 0 if the glyph is not found.
	GlyphIndex(r rune) uint16

	// GlyphAdvance returns the advance width for a glyph at the given size (in points).
	// The ppem (pixels per em) is derived from size and DPI.
	GlyphAdvance(glyphIndex uint16, ppem float64) float64

	// GlyphBounds returns the bounding box for a glyph at the given size.
	GlyphBounds(glyphIndex uint16, ppem float64) Rect

	// Metrics returns the font metrics at the given size.
	Metrics(ppem float64) FontMetrics
}

ParsedFont represents a parsed font file. This interface abstracts the underlying font representation.

type Rect

type Rect struct {
	// Min is the top-left corner
	MinX, MinY float64
	// Max is the bottom-right corner
	MaxX, MaxY float64
}

Rect represents a rectangle for glyph bounds.

func (Rect) Empty

func (r Rect) Empty() bool

Empty reports whether the rectangle is empty.

func (Rect) Height

func (r Rect) Height() float64

Height returns the height of the rectangle.

func (Rect) Width

func (r Rect) Width() float64

Width returns the width of the rectangle.

type RuneToBoolMap

type RuneToBoolMap struct {
	// contains filtered or unexported fields
}

RuneToBoolMap is a memory-efficient map from rune to bool. Uses 2 bits per rune: (checked, hasGlyph). Optimized for sparse access patterns in Unicode space.

Each block covers 256 runes (512 bits = 64 bytes). Blocks are allocated on-demand only when a rune in that range is accessed.

RuneToBoolMap is safe for concurrent use. RuneToBoolMap must not be copied after creation (has mutex).

func NewRuneToBoolMap

func NewRuneToBoolMap() *RuneToBoolMap

NewRuneToBoolMap creates a new rune-to-bool map.

func (*RuneToBoolMap) Clear

func (m *RuneToBoolMap) Clear()

Clear removes all entries from the map.

func (*RuneToBoolMap) Get

func (m *RuneToBoolMap) Get(r rune) (hasGlyph, checked bool)

Get returns (hasGlyph, checked). If checked is false, the rune hasn't been queried yet.

func (*RuneToBoolMap) Set

func (m *RuneToBoolMap) Set(r rune, hasGlyph bool)

Set stores the hasGlyph value for a rune. Marks the rune as checked.

type Script added in v0.10.0

type Script uint32

Script represents a Unicode script for text segmentation. Scripts are used to identify runs of text that should be shaped together.

const (
	// ScriptCommon is used for punctuation, numbers, and symbols shared across scripts.
	ScriptCommon Script = iota
	// ScriptInherited is used for combining marks that inherit the script of the base character.
	ScriptInherited
	// ScriptLatin is used for Latin-based scripts (English, French, German, etc.)
	ScriptLatin
	// ScriptCyrillic is used for Cyrillic script (Russian, Ukrainian, Bulgarian, etc.)
	ScriptCyrillic
	// ScriptGreek is used for Greek script.
	ScriptGreek
	// ScriptArabic is used for Arabic script (Arabic, Persian, Urdu, etc.)
	ScriptArabic
	// ScriptHebrew is used for Hebrew script.
	ScriptHebrew
	// ScriptHan is used for Chinese/Japanese Kanji characters.
	ScriptHan
	// ScriptHiragana is used for Japanese Hiragana.
	ScriptHiragana
	// ScriptKatakana is used for Japanese Katakana.
	ScriptKatakana
	// ScriptHangul is used for Korean script.
	ScriptHangul
	// ScriptDevanagari is used for Devanagari script (Hindi, Sanskrit, etc.)
	ScriptDevanagari
	// ScriptThai is used for Thai script.
	ScriptThai
	// ScriptGeorgian is used for Georgian script.
	ScriptGeorgian
	// ScriptArmenian is used for Armenian script.
	ScriptArmenian
	// ScriptBengali is used for Bengali script.
	ScriptBengali
	// ScriptTamil is used for Tamil script.
	ScriptTamil
	// ScriptTelugu is used for Telugu script.
	ScriptTelugu
	// ScriptKannada is used for Kannada script.
	ScriptKannada
	// ScriptMalayalam is used for Malayalam script.
	ScriptMalayalam
	// ScriptGujarati is used for Gujarati script.
	ScriptGujarati
	// ScriptOriya is used for Oriya script.
	ScriptOriya
	// ScriptGurmukhi is used for Gurmukhi script (Punjabi).
	ScriptGurmukhi
	// ScriptSinhala is used for Sinhala script.
	ScriptSinhala
	// ScriptKhmer is used for Khmer script (Cambodian).
	ScriptKhmer
	// ScriptLao is used for Lao script.
	ScriptLao
	// ScriptMyanmar is used for Myanmar (Burmese) script.
	ScriptMyanmar
	// ScriptTibetan is used for Tibetan script.
	ScriptTibetan
	// ScriptEthiopic is used for Ethiopic script.
	ScriptEthiopic
	// ScriptUnknown is used for unrecognized scripts.
	ScriptUnknown
)

Script constants for common Unicode scripts. The values are based on Unicode script codes but simplified for our use case.

func DetectScript added in v0.10.0

func DetectScript(r rune) Script

DetectScript returns the Unicode script for a given rune. This uses hardcoded Unicode ranges for common scripts to avoid external dependencies.

For characters that appear in multiple scripts or are shared (like punctuation and numbers), ScriptCommon is returned. For combining marks, ScriptInherited is returned.

func (Script) IsRTL added in v0.10.0

func (s Script) IsRTL() bool

IsRTL returns true if the script is typically written right-to-left.

func (Script) RequiresComplexShaping added in v0.10.0

func (s Script) RequiresComplexShaping() bool

RequiresComplexShaping returns true if the script typically needs advanced shaping features (ligatures, contextual forms, etc.) that are not supported by BuiltinShaper.

func (Script) String added in v0.10.0

func (s Script) String() string

String returns the name of the script.

type Segment added in v0.10.0

type Segment struct {
	Text      string
	Start     int
	End       int
	Direction Direction
	Script    Script
	Level     int
}

Segment represents a contiguous run of text with the same direction and script.

func SegmentText added in v0.10.0

func SegmentText(text string) []Segment

func SegmentTextRTL added in v0.10.0

func SegmentTextRTL(text string) []Segment

func (Segment) RuneCount added in v0.10.0

func (s Segment) RuneCount() int

type Segmenter added in v0.10.0

type Segmenter interface {
	Segment(text string) []Segment
}

type ShapedGlyph added in v0.10.0

type ShapedGlyph struct {
	// GID is the glyph index in the font.
	GID GlyphID

	// Cluster is the source character index in the original text.
	// Used for hit testing and cursor positioning.
	Cluster int

	// X is the horizontal position relative to the text origin.
	X float64

	// Y is the vertical position relative to the baseline.
	Y float64

	// XAdvance is the horizontal advance to the next glyph.
	XAdvance float64

	// YAdvance is the vertical advance (for vertical text).
	YAdvance float64
}

ShapedGlyph represents a positioned glyph ready for GPU rendering. Unlike Glyph which contains CPU rasterization data (Mask), ShapedGlyph is minimal and designed for efficient GPU text rendering pipelines.

func Shape added in v0.10.0

func Shape(text string, face Face, size float64) []ShapedGlyph

Shape is a convenience function that uses the global shaper. It converts text to positioned glyphs using the given face and size.

type ShapedRun added in v0.10.0

type ShapedRun struct {
	// Glyphs is the sequence of positioned glyphs.
	Glyphs []ShapedGlyph

	// Advance is the total advance of all glyphs.
	// For horizontal text, this is width; for vertical, height.
	Advance float64

	// Ascent is the maximum ascent above the baseline.
	Ascent float64

	// Descent is the maximum descent below the baseline (positive value).
	Descent float64

	// Direction is the text direction for this run.
	Direction Direction

	// Face is the font face used for this run.
	Face Face

	// Size is the font size in pixels.
	Size float64
}

ShapedRun is a sequence of shaped glyphs with uniform style. Used by the Layout Engine for multi-line and multi-style text rendering.

func (*ShapedRun) Bounds added in v0.10.0

func (r *ShapedRun) Bounds() (x, y, width, height float64)

Bounds returns the bounding rectangle of the run. The origin is at the baseline start.

func (*ShapedRun) Height added in v0.10.0

func (r *ShapedRun) Height() float64

Height returns the total height of the run. For horizontal text, this is Ascent + Descent. For vertical text, this equals Advance.

func (*ShapedRun) LineHeight added in v0.10.0

func (r *ShapedRun) LineHeight() float64

LineHeight returns the recommended line height for this run.

func (*ShapedRun) Width added in v0.10.0

func (r *ShapedRun) Width() float64

Width returns the total width of the run. For horizontal text, this equals Advance. For vertical text, this is based on glyph widths.

type Shaper added in v0.10.0

type Shaper interface {
	// Shape converts text into positioned glyphs using the given face and size.
	// The returned ShapedGlyph slice is ready for GPU rendering.
	Shape(text string, face Face, size float64) []ShapedGlyph
}

Shaper converts text to positioned glyphs. Implementations provide different levels of text shaping support:

  • BuiltinShaper: Uses golang.org/x/image/font for Latin, Cyrillic, Greek, CJK
  • HarfBuzz-compatible: Use SetShaper() with a go-text/typesetting implementation

func GetShaper added in v0.10.0

func GetShaper() Shaper

GetShaper returns the current global shaper.

type ShapingKey

type ShapingKey struct {
	Text      string
	Size      float64
	Direction Direction
}

ShapingKey identifies shaped text in the shaping cache.

type SourceOption

type SourceOption func(*sourceConfig)

SourceOption configures FontSource creation.

func WithCacheLimit

func WithCacheLimit(n int) SourceOption

WithCacheLimit sets the maximum number of cached glyphs. A value of 0 disables the cache limit.

func WithParser

func WithParser(name string) SourceOption

WithParser specifies the font parser backend. The default is "ximage" which uses golang.org/x/image/font/opentype.

Custom parsers can be registered with RegisterParser. This allows using alternative font parsing libraries or a pure Go implementation in the future.

type UnicodeRange

type UnicodeRange struct {
	Start rune
	End   rune
}

UnicodeRange represents a contiguous range of code points.

func (UnicodeRange) Contains

func (ur UnicodeRange) Contains(r rune) bool

Contains reports whether the rune is in the range.

Directories

Path Synopsis
Package cache provides high-performance caching for text shaping and rendering.
Package cache provides high-performance caching for text shaping and rendering.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL