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 ¶
- Variables
- func Draw(dst draw.Image, text string, face Face, x, y float64, col color.Color)
- func Measure(text string, face Face) (width, height float64)
- func RegisterParser(name string, parser FontParser)
- type Cache
- type Direction
- type DrawOptions
- type Face
- type FaceOption
- type FilteredFace
- func (f *FilteredFace) Advance(text string) float64
- func (f *FilteredFace) AppendGlyphs(dst []Glyph, text string) []Glyph
- func (f *FilteredFace) Direction() Direction
- func (f *FilteredFace) Glyphs(text string) iter.Seq[Glyph]
- func (f *FilteredFace) HasGlyph(r rune) bool
- func (f *FilteredFace) Metrics() Metrics
- func (f *FilteredFace) Size() float64
- func (f *FilteredFace) Source() *FontSource
- type FontMetrics
- type FontParser
- type FontSource
- type Glyph
- type GlyphID
- type GlyphImage
- type GlyphKey
- type Hinting
- type Metrics
- type MultiFace
- func (m *MultiFace) Advance(text string) float64
- func (m *MultiFace) AppendGlyphs(dst []Glyph, text string) []Glyph
- func (m *MultiFace) Direction() Direction
- func (m *MultiFace) Glyphs(text string) iter.Seq[Glyph]
- func (m *MultiFace) HasGlyph(r rune) bool
- func (m *MultiFace) Metrics() Metrics
- func (m *MultiFace) Size() float64
- func (m *MultiFace) Source() *FontSource
- type ParsedFont
- type Rect
- type RuneToBoolMap
- type ShapingKey
- type SourceOption
- type UnicodeRange
Constants ¶
This section is empty.
Variables ¶
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 ¶
Draw renders text to a destination image. Position (x, y) is the baseline origin. The face must be a *sourceFace from this package.
func Measure ¶
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.
Types ¶
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]) Get ¶
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.
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 )
type DrawOptions ¶
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) 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) 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 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 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 ¶
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 ¶
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 ¶
Advance implements Face.Advance. Calculates total advance using the appropriate face for each rune.
func (*MultiFace) AppendGlyphs ¶
AppendGlyphs implements Face.AppendGlyphs. Appends glyphs using the appropriate face for each rune.
func (*MultiFace) Glyphs ¶
Glyphs implements Face.Glyphs. Returns an iterator over all glyphs, using the appropriate face for each rune.
func (*MultiFace) HasGlyph ¶
HasGlyph implements Face.HasGlyph. Returns true if any face has the glyph.
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.
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 ShapingKey ¶
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 ¶
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.