text/glyph_mask_rasterizer.go

Functions Structs

Functions

func IsEmpty

func (p *glyphPath) IsEmpty() bool	{ return len(p.verbs) == 0 }

func NewGlyphMaskRasterizer

NewGlyphMaskRasterizer creates a new glyph mask rasterizer.

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
}