text/glyph_mask_rasterizer.go
Functions
func IsEmpty
func (p *glyphPath) IsEmpty() bool { return len(p.verbs) == 0 }
func NewGlyphMaskRasterizer
func NewGlyphMaskRasterizer() *GlyphMaskRasterizer {
return &GlyphMaskRasterizer{
extractor: NewOutlineExtractor(),
pathVerbs: make([]raster.PathVerb, 0, 64),
pathPoints: make([]float32, 0, 256),
}
}
func Points
func (p *glyphPath) Points() []float32 { return p.points }
func Rasterize
Rasterize renders a single glyph into an R8 alpha mask.
Parameters:
- font: parsed font to extract outlines from
- gid: glyph index in the font
- size: font size in pixels (ppem)
- subpixelX: fractional X offset in pixels [0, 1) for subpixel positioning
- subpixelY: fractional Y offset in pixels [0, 1) for subpixel positioning
Returns nil result for empty glyphs (e.g., space character).
func (r *GlyphMaskRasterizer) Rasterize(
font ParsedFont,
gid GlyphID,
size float64,
subpixelX, subpixelY float64,
) (*GlyphMaskResult, error) {
return r.RasterizeHinted(font, gid, size, subpixelX, subpixelY, HintingNone)
}
func RasterizeAliased
RasterizeAliased renders a single glyph into an R8 alpha mask with binary
coverage (0 or 255 only). No anti-aliasing, no sub-pixel coverage.
This matches Skia's SkFont::Edging::kAlias — the glyph outline is filled
with integer scanline walking (NoAAFiller) instead of the AnalyticFiller.
The result is a crisp, staircase-edged mask suitable for pixel-art
aesthetics, terminal emulators, or bitmap font emulation.
Unlike RasterizeHinted (which uses aaMargin=1 for AA fringe), aliased
rasterization uses aaMargin=0 because there is no sub-pixel fringe.
Parameters:
- font: parsed font to extract outlines from
- gid: glyph index in the font
- size: font size in pixels (ppem)
- subpixelX: fractional X offset in pixels [0, 1) for subpixel positioning
- subpixelY: fractional Y offset in pixels [0, 1) for subpixel positioning
- hinting: hinting mode (HintingNone, HintingVertical, HintingFull)
Returns nil result for empty glyphs (e.g., space character).
func (r *GlyphMaskRasterizer) RasterizeAliased(
font ParsedFont,
gid GlyphID,
size float64,
subpixelX, subpixelY float64,
hinting Hinting,
) (*GlyphMaskResult, error) {
// Extract outline at the target size with hinting.
outline, err := r.extractor.ExtractOutlineHinted(font, gid, size, hinting)
if err != nil {
return nil, err
}
if outline == nil || outline.IsEmpty() {
return nil, nil //nolint:nilnil // nil result = empty glyph, not an error
}
return r.rasterizeOutlineAliased(outline, subpixelX, subpixelY)
}
func RasterizeHinted
RasterizeHinted renders a single glyph into an R8 alpha mask with hinting.
When hinting is HintingVertical or HintingFull, the outline is grid-fitted
before rasterization, producing crisper horizontal stems and consistent
stem widths at small sizes (12-16px).
Parameters:
- font: parsed font to extract outlines from
- gid: glyph index in the font
- size: font size in pixels (ppem)
- subpixelX: fractional X offset in pixels [0, 1) for subpixel positioning
- subpixelY: fractional Y offset in pixels [0, 1) for subpixel positioning
- hinting: hinting mode (HintingNone, HintingVertical, HintingFull)
Returns nil result for empty glyphs (e.g., space character).
func (r *GlyphMaskRasterizer) RasterizeHinted(
font ParsedFont,
gid GlyphID,
size float64,
subpixelX, subpixelY float64,
hinting Hinting,
) (*GlyphMaskResult, error) {
// Extract outline at the target size with hinting.
outline, err := r.extractor.ExtractOutlineHinted(font, gid, size, hinting)
if err != nil {
return nil, err
}
if outline == nil || outline.IsEmpty() {
return nil, nil //nolint:nilnil // nil result = empty glyph, not an error
}
return r.rasterizeOutline(outline, subpixelX, subpixelY)
}
func RasterizeLCD
RasterizeLCD renders a glyph with 3x horizontal oversampling for LCD
subpixel (ClearType) rendering. The glyph outline is rasterized at 3x
horizontal width, then the LCD filter is applied row-by-row to produce
per-channel RGB coverage. The result is stored in the R8 atlas at 3x width
(3 atlas texels per logical pixel: R, G, B coverage).
For BGR layout, the R and B channels are swapped after filtering.
Parameters:
- font: parsed font to extract outlines from
- gid: glyph index in the font
- size: font size in pixels (ppem)
- subpixelX: fractional X offset in pixels [0, 1) for subpixel positioning
- subpixelY: fractional Y offset in pixels [0, 1) for subpixel positioning
- hinting: hinting mode (HintingNone, HintingVertical, HintingFull)
- filter: LCD FIR filter for fringe reduction
- layout: physical subpixel arrangement (RGB or BGR)
Returns nil result for empty glyphs (e.g., space character).
func (r *GlyphMaskRasterizer) RasterizeLCD(
font ParsedFont,
gid GlyphID,
size float64,
subpixelX, subpixelY float64,
hinting Hinting,
filter LCDFilter,
layout LCDLayout,
) (*LCDMaskResult, error) {
// Extract outline at the target size with hinting.
outline, err := r.extractor.ExtractOutlineHinted(font, gid, size, hinting)
if err != nil {
return nil, err
}
if outline == nil || outline.IsEmpty() {
return nil, nil //nolint:nilnil // nil result = empty glyph, not an error
}
return r.rasterizeLCDOutline(outline, subpixelX, subpixelY, filter, layout)
}
func RasterizeLCDOutline
RasterizeLCDOutline renders a pre-extracted glyph outline with 3x horizontal
oversampling for LCD subpixel rendering. This is useful when the outline has
already been extracted (e.g., from cache).
func (r *GlyphMaskRasterizer) RasterizeLCDOutline(
outline *GlyphOutline,
subpixelX, subpixelY float64,
filter LCDFilter,
layout LCDLayout,
) (*LCDMaskResult, error) {
if outline == nil || outline.IsEmpty() {
return nil, nil //nolint:nilnil // nil result = empty glyph, not an error
}
return r.rasterizeLCDOutline(outline, subpixelX, subpixelY, filter, layout)
}
func RasterizeOutline
RasterizeOutline renders a pre-extracted glyph outline into an R8 alpha mask.
This is useful when the outline has already been extracted (e.g., from cache).
func (r *GlyphMaskRasterizer) RasterizeOutline(
outline *GlyphOutline,
subpixelX, subpixelY float64,
) (*GlyphMaskResult, error) {
if outline == nil || outline.IsEmpty() {
return nil, nil //nolint:nilnil // nil result = empty glyph, not an error
}
return r.rasterizeOutline(outline, subpixelX, subpixelY)
}
func Verbs
func (p *glyphPath) Verbs() []raster.PathVerb { return p.verbs }
Structs
type GlyphMaskRasterizer struct
GlyphMaskRasterizer renders glyph outlines into R8 alpha masks using the
AnalyticFiller (256-level analytic anti-aliasing). This is the CPU side of
the Tier 6 glyph mask cache pipeline.
The rasterizer extracts glyph outlines from the font at the exact device
pixel size, builds edges via EdgeBuilder, and fills to an alpha buffer.
The result is a tight-bbox alpha mask suitable for packing into the
GlyphMaskAtlas R8 texture.
This follows the Skia/Chrome pattern:
- CPU rasterizes at exact pixel size (no scaling artifacts)
- 256-level coverage (vs MSDF's distance-based approximation)
- Hinting-ready (future TEXT-012)
- Subpixel positioning via fractional offset in outline coordinates
GlyphMaskRasterizer is NOT safe for concurrent use. Each goroutine should
use its own instance, or protect access with a mutex.
type GlyphMaskRasterizer struct {
extractor *OutlineExtractor
// Reusable path buffer to avoid allocations per glyph.
pathVerbs []raster.PathVerb
pathPoints []float32
}
type GlyphMaskResult struct
GlyphMaskResult holds the output of rasterizing a single glyph.
type GlyphMaskResult struct {
// Mask is the R8 alpha buffer (1 byte per pixel, row-major).
Mask []byte
// Width and Height of the mask in pixels.
Width, Height int
// BearingX is the horizontal offset from the glyph origin to the left
// edge of the mask bounding box, in pixels.
BearingX float32
// BearingY is the vertical offset from the baseline to the top edge
// of the mask bounding box, in pixels. Positive = above baseline.
BearingY float32
}
NewGlyphMaskRasterizer creates a new glyph mask rasterizer.