text/lcd_filter.go

Functions Structs

Functions

func Apply

Apply runs the 5-tap horizontal FIR filter on a 3x-oversampled R8 buffer,

producing per-channel RGB coverage values.

 

Parameters:

- dst: output buffer, must be at least width*3 bytes (RGB triplets)

- src: input buffer of 3*width alpha samples (3x horizontal oversampling)

- width: number of output pixels (dst has width*3 bytes, src has 3*width bytes)

 

For each output pixel at position i, the three subpixel columns are at

src indices i*3+0 (red), i*3+1 (green), i*3+2 (blue). The 5-tap filter

is centered on each subpixel column independently. Out-of-bounds samples

are treated as zero.

func (f *LCDFilter) Apply(dst []byte, src []byte, width int) {
	srcLen := 3 * width
	if len(dst) < width*3 || len(src) < srcLen {
		return
	}

	for i := range width {
		// For each output pixel, filter 3 subpixel columns independently.
		for ch := range 3 {
			center := i*3 + ch	// index in the 3x-wide source buffer

			var acc float32
			for tap := range 5 {
				srcIdx := center + tap - 2	// 5-tap centered: -2, -1, 0, +1, +2
				if srcIdx >= 0 && srcIdx < srcLen {
					acc += f.Weights[tap] * float32(src[srcIdx])
				}
			}

			// Clamp to [0, 255]
			v := int(acc + 0.5)
			if v < 0 {
				v = 0
			}
			if v > 255 {
				v = 255
			}
			dst[i*3+ch] = byte(v)	//nolint:gosec // v is clamped to [0,255]
		}
	}
}

func DefaultLCDFilter

DefaultLCDFilter returns the FreeType-compatible "light" LCD filter.

Weights: [0.08, 0.24, 0.36, 0.24, 0.08] (sum = 1.0).

This provides good fringe reduction without excessive blurring.

func DefaultLCDFilter() LCDFilter {
	return LCDFilter{Weights: [5]float32{0.08, 0.24, 0.36, 0.24, 0.08}}
}

func String

String returns the string representation of the LCD layout.

func (l LCDLayout) String() string {
	switch l {
	case LCDLayoutNone:
		return noneStr
	case LCDLayoutRGB:
		return "RGB"
	case LCDLayoutBGR:
		return "BGR"
	default:
		return unknownStr
	}
}

Structs

type LCDFilter struct

LCDFilter applies a 5-tap FIR (Finite Impulse Response) filter to a

3x-oversampled coverage buffer to reduce color fringing in ClearType

subpixel rendering.

 

The filter convolves each subpixel column with 5 weights, distributing

energy from adjacent subpixels to reduce chromatic artifacts at glyph

edges. This is the same approach used by FreeType's LCD filtering.

 

The default weights [0.08, 0.24, 0.36, 0.24, 0.08] (sum = 1.0) provide

a good balance between sharpness and fringe reduction ("light" filter).

type LCDFilter struct {
	// Weights are the 5-tap FIR filter coefficients, centered on the
	// current subpixel column. Weights[2] is the center tap.
	Weights [5]float32
}

type LCDMaskResult struct

LCDMaskResult holds the output of LCD subpixel rasterization.

type LCDMaskResult struct {
	// Mask is the RGB coverage buffer (3 bytes per pixel: R, G, B).
	// Row-major, width x height pixels, 3*width bytes per row.
	Mask	[]byte

	// Width and Height of the mask in pixels (NOT the 3x oversampled width).
	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
}