text/glyph_renderer.go
Functions
func Cache
func (r *GlyphRenderer) Cache() *GlyphCache {
r.mu.RLock()
defer r.mu.RUnlock()
return r.cache
}
func DefaultRenderParams
DefaultRenderParams returns default rendering parameters.
func DefaultRenderParams() RenderParams {
return RenderParams{
Transform: nil,
Color: color.RGBA{R: 0, G: 0, B: 0, A: 255},
Opacity: 1.0,
}
}
func GetGlobalTextRenderer
GetGlobalTextRenderer returns the global shared text renderer.
func GetGlobalTextRenderer() *TextRenderer {
return globalTextRenderer
}
func GlyphRenderer
GlyphRenderer returns the underlying glyph renderer.
func (tr *TextRenderer) GlyphRenderer() *GlyphRenderer {
return tr.glyphRenderer
}
func NewGlyphRenderer
NewGlyphRenderer creates a new glyph renderer with the global cache.
func NewGlyphRenderer() *GlyphRenderer {
return &GlyphRenderer{
cache: GetGlobalGlyphCache(),
extractor: NewOutlineExtractor(),
}
}
func NewGlyphRendererWithCache
NewGlyphRendererWithCache creates a new glyph renderer with a custom cache.
func NewGlyphRendererWithCache(cache *GlyphCache) *GlyphRenderer {
if cache == nil {
cache = GetGlobalGlyphCache()
}
return &GlyphRenderer{
cache: cache,
extractor: NewOutlineExtractor(),
}
}
func NewTextRenderer
NewTextRenderer creates a new text renderer.
func NewTextRenderer() *TextRenderer {
return &TextRenderer{
glyphRenderer: NewGlyphRenderer(),
defaultSize: 16.0,
defaultColor: color.RGBA{R: 0, G: 0, B: 0, A: 255},
}
}
func RenderGlyph
RenderGlyph renders a single glyph to an outline.
Returns the glyph outline with positioning applied.
Parameters:
- glyph: The shaped glyph to render
- font: The parsed font to use for outline extraction
- size: Font size in pixels (ppem)
- params: Rendering parameters
Returns the transformed outline, or nil if the glyph has no outline.
func (r *GlyphRenderer) RenderGlyph(
glyph *ShapedGlyph,
font ParsedFont,
size float64,
params RenderParams,
) *GlyphOutline {
if glyph == nil || font == nil {
return nil
}
// Get font ID for cache key
fontID := computeFontID(font)
// Build cache key
key := OutlineCacheKey{
FontID: fontID,
GID: glyph.GID,
Size: sizeToInt16(size),
Hinting: HintingNone,
}
// Get or create outline
outline := r.cache.GetOrCreate(key, func() *GlyphOutline {
o, err := r.extractor.ExtractOutline(font, glyph.GID, size)
if err != nil {
return nil
}
return o
})
// No outline means nothing to draw (e.g., space character)
if outline == nil || outline.IsEmpty() {
return nil
}
// Apply transformation if needed
return r.transformOutline(outline, glyph, params)
}
func RenderGlyphs
RenderGlyphs renders multiple glyphs to outlines.
Returns a slice of outlines corresponding to each input glyph.
Glyphs with no outline (e.g., spaces) will have nil entries.
func (r *GlyphRenderer) RenderGlyphs(
glyphs []ShapedGlyph,
font ParsedFont,
size float64,
params RenderParams,
) []*GlyphOutline {
if len(glyphs) == 0 || font == nil {
return nil
}
outlines := make([]*GlyphOutline, len(glyphs))
for i := range glyphs {
outlines[i] = r.RenderGlyph(&glyphs[i], font, size, params)
}
return outlines
}
func RenderLayout
RenderLayout renders a complete layout to outlines.
Returns a 2D slice where [line][glyph] contains the outlines.
func (r *GlyphRenderer) RenderLayout(layout *Layout, params RenderParams) [][]*GlyphOutline {
if layout == nil || len(layout.Lines) == 0 {
return nil
}
result := make([][]*GlyphOutline, len(layout.Lines))
for i := range layout.Lines {
line := &layout.Lines[i]
lineOutlines := make([]*GlyphOutline, 0, len(line.Glyphs))
// Apply line Y offset to transform
lineParams := params
if params.Transform != nil {
lineTranslate := TranslateTransform(0, float32(line.Y))
lineParams.Transform = params.Transform.Multiply(lineTranslate)
} else {
lineParams.Transform = TranslateTransform(0, float32(line.Y))
}
// Render runs in this line
for j := range line.Runs {
run := &line.Runs[j]
runOutlines := r.RenderRun(run, lineParams)
lineOutlines = append(lineOutlines, runOutlines...)
}
result[i] = lineOutlines
}
return result
}
func RenderRun
RenderRun renders a shaped run to outlines.
func (r *GlyphRenderer) RenderRun(run *ShapedRun, params RenderParams) []*GlyphOutline {
if run == nil || len(run.Glyphs) == 0 || run.Face == nil {
return nil
}
font := run.Face.Source().Parsed()
if font == nil {
return nil
}
return r.RenderGlyphs(run.Glyphs, font, run.Size, params)
}
func RotateTransform
RotateTransform creates a rotation transformation (angle in radians).
func RotateTransform(angle float32) *AffineTransform {
sin := float32(sinf64(float64(angle)))
cos := float32(cosf64(float64(angle)))
return &AffineTransform{
A: cos, B: -sin,
C: sin, D: cos,
Tx: 0, Ty: 0,
}
}
func ScaleTransformXY
ScaleTransformXY creates a non-uniform scaling transformation.
func ScaleTransformXY(sx, sy float32) *AffineTransform {
return &AffineTransform{A: sx, D: sy}
}
func SetCache
SetCache sets the glyph cache used by this renderer.
func (r *GlyphRenderer) SetCache(cache *GlyphCache) {
r.mu.Lock()
defer r.mu.Unlock()
if cache == nil {
cache = GetGlobalGlyphCache()
}
r.cache = cache
}
func SetDefaultColor
SetDefaultColor sets the default text color.
func (tr *TextRenderer) SetDefaultColor(c color.RGBA) {
tr.defaultColor = c
}
func SetDefaultFace
SetDefaultFace sets the default font face for rendering.
func (tr *TextRenderer) SetDefaultFace(face Face) {
tr.defaultFace = face
}
func SetDefaultSize
SetDefaultSize sets the default font size.
func (tr *TextRenderer) SetDefaultSize(size float64) {
if size > 0 {
tr.defaultSize = size
}
}
func ShapeAndRender
ShapeAndRender shapes text and returns the glyph outlines.
func (tr *TextRenderer) ShapeAndRender(text string) ([]*GlyphOutline, error) {
if tr.defaultFace == nil {
return nil, ErrUnsupportedFontType
}
// Shape the text
glyphs := Shape(text, tr.defaultFace)
if len(glyphs) == 0 {
return nil, nil
}
// Get the parsed font
font := tr.defaultFace.Source().Parsed()
if font == nil {
return nil, ErrUnsupportedFontType
}
params := RenderParams{
Color: tr.defaultColor,
Opacity: 1.0,
}
return tr.glyphRenderer.RenderGlyphs(glyphs, font, tr.defaultSize, params), nil
}
func ShapeAndRenderAt
ShapeAndRenderAt shapes text and returns outlines at the specified position.
func (tr *TextRenderer) ShapeAndRenderAt(text string, x, y float64) ([]*GlyphOutline, error) {
if tr.defaultFace == nil {
return nil, ErrUnsupportedFontType
}
// Shape the text
glyphs := Shape(text, tr.defaultFace)
if len(glyphs) == 0 {
return nil, nil
}
// Get the parsed font
font := tr.defaultFace.Source().Parsed()
if font == nil {
return nil, ErrUnsupportedFontType
}
params := RenderParams{
Transform: TranslateTransform(float32(x), float32(y)),
Color: tr.defaultColor,
Opacity: 1.0,
}
return tr.glyphRenderer.RenderGlyphs(glyphs, font, tr.defaultSize, params), nil
}
func WithColor
WithColor returns a copy of params with the given color.
func (p RenderParams) WithColor(c color.RGBA) RenderParams {
p.Color = c
return p
}
func WithOpacity
WithOpacity returns a copy of params with the given opacity.
func (p RenderParams) WithOpacity(opacity float64) RenderParams {
p.Opacity = clampOpacity(opacity)
return p
}
func WithTransform
WithTransform returns a copy of params with the given transform.
func (p RenderParams) WithTransform(t *AffineTransform) RenderParams {
p.Transform = t
return p
}
Structs
type RenderParams struct
RenderParams holds parameters for glyph rendering.
type RenderParams struct {
// Transform is an optional affine transformation to apply to all glyphs.
// If nil, identity transform is used.
Transform *AffineTransform
// Color is the fill color for glyphs.
Color color.RGBA
// Opacity is the overall opacity [0, 1].
// 1.0 means fully opaque, 0.0 means fully transparent.
Opacity float64
}
type GlyphRenderer struct
GlyphRenderer converts shaped glyphs to outline paths.
It uses the GlyphCache for efficient outline caching and
OutlineExtractor for extracting glyph outlines from fonts.
GlyphRenderer is safe for concurrent use.
type GlyphRenderer struct {
cache *GlyphCache
extractor *OutlineExtractor
mu sync.RWMutex
}
type TextRenderer struct
TextRenderer provides a high-level API for text rendering.
It combines shaping and glyph outline extraction.
Note: For rendering to a scene.Scene, use scene.TextRenderer instead,
which provides direct scene integration.
type TextRenderer struct {
glyphRenderer *GlyphRenderer
defaultFace Face
defaultSize float64
defaultColor color.RGBA
}
Cache returns the glyph cache used by this renderer.