text-shaper 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +6 -1
  2. package/README.md +27 -1
  3. package/dist/font/brotli/context.d.ts +6 -0
  4. package/dist/font/brotli/decode.d.ts +9 -0
  5. package/dist/font/brotli/dictionary.d.ts +11 -0
  6. package/dist/font/brotli/transform.d.ts +12 -0
  7. package/dist/font/font.d.ts +19 -5
  8. package/dist/font/tables/cff.d.ts +4 -0
  9. package/dist/font/tables/gasp.d.ts +54 -0
  10. package/dist/font/tables/gdef.d.ts +3 -0
  11. package/dist/font/tables/glyf.d.ts +2 -0
  12. package/dist/font/tables/hinting.d.ts +38 -0
  13. package/dist/font/woff2.d.ts +8 -0
  14. package/dist/hinting/index.d.ts +9 -0
  15. package/dist/hinting/instructions/arithmetic.d.ts +46 -0
  16. package/dist/hinting/instructions/control-flow.d.ts +26 -0
  17. package/dist/hinting/instructions/delta.d.ts +32 -0
  18. package/dist/hinting/instructions/graphics-state.d.ts +94 -0
  19. package/dist/hinting/instructions/interpolate.d.ts +16 -0
  20. package/dist/hinting/instructions/points.d.ts +76 -0
  21. package/dist/hinting/instructions/stack.d.ts +28 -0
  22. package/dist/hinting/interpreter.d.ts +30 -0
  23. package/dist/hinting/programs.d.ts +88 -0
  24. package/dist/hinting/rounding.d.ts +51 -0
  25. package/dist/hinting/types.d.ts +369 -0
  26. package/dist/index.d.ts +21 -11
  27. package/dist/index.js +10 -8
  28. package/dist/index.js.map +60 -29
  29. package/dist/raster/atlas.d.ts +37 -0
  30. package/dist/raster/bbox.d.ts +91 -0
  31. package/dist/raster/bitmap-utils.d.ts +25 -0
  32. package/dist/raster/blur.d.ts +27 -0
  33. package/dist/raster/cell.d.ts +140 -0
  34. package/dist/raster/fixed-point.d.ts +100 -0
  35. package/dist/raster/gradient.d.ts +61 -0
  36. package/dist/raster/gray-raster.d.ts +132 -0
  37. package/dist/raster/lcd-filter.d.ts +44 -0
  38. package/dist/raster/outline-decompose.d.ts +61 -0
  39. package/dist/raster/rasterize.d.ts +43 -0
  40. package/dist/raster/sdf.d.ts +37 -0
  41. package/dist/raster/stroker.d.ts +29 -0
  42. package/dist/raster/synth.d.ts +50 -0
  43. package/dist/raster/types.d.ts +176 -0
  44. package/dist/render/path.d.ts +50 -2
  45. package/dist/shaper/complex/indic.d.ts +4 -0
  46. package/dist/types.d.ts +4 -0
  47. package/dist/unicode/bidi/brackets.gen.d.ts +5 -0
  48. package/dist/unicode/bidi/char-types.gen.d.ts +25 -0
  49. package/dist/unicode/bidi/mirroring.gen.d.ts +2 -0
  50. package/package.json +41 -14
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Texture atlas generator for GPU font rendering
3
+ *
4
+ * Packs multiple glyph bitmaps into a single texture atlas
5
+ * using shelf/skyline bin packing algorithm.
6
+ */
7
+ import type { Font } from "../font/font.ts";
8
+ import { type AtlasOptions, type GlyphAtlas } from "./types.ts";
9
+ /**
10
+ * Build a texture atlas from a set of glyphs
11
+ */
12
+ export declare function buildAtlas(font: Font, glyphIds: number[], options: AtlasOptions): GlyphAtlas;
13
+ /**
14
+ * Build atlas for ASCII printable characters (32-126)
15
+ */
16
+ export declare function buildAsciiAtlas(font: Font, options: AtlasOptions): GlyphAtlas;
17
+ /**
18
+ * Build atlas for a specific string (including all unique glyphs)
19
+ */
20
+ export declare function buildStringAtlas(font: Font, text: string, options: AtlasOptions): GlyphAtlas;
21
+ /**
22
+ * Export atlas to formats suitable for GPU upload
23
+ */
24
+ export declare function atlasToRGBA(atlas: GlyphAtlas): Uint8Array;
25
+ /**
26
+ * Export atlas as single-channel alpha texture
27
+ */
28
+ export declare function atlasToAlpha(atlas: GlyphAtlas): Uint8Array;
29
+ /**
30
+ * Get UV coordinates for a glyph in the atlas
31
+ */
32
+ export declare function getGlyphUV(atlas: GlyphAtlas, glyphId: number): {
33
+ u0: number;
34
+ v0: number;
35
+ u1: number;
36
+ v1: number;
37
+ } | null;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Exact bounding box calculation for paths with bezier curves
3
+ *
4
+ * Bezier curves can extend beyond their control points, so we need to find
5
+ * the actual extrema by solving for where the derivative equals zero.
6
+ */
7
+ import type { GlyphPath } from "../render/path.ts";
8
+ /**
9
+ * Bounding box in 2D space
10
+ */
11
+ export interface BBox {
12
+ xMin: number;
13
+ yMin: number;
14
+ xMax: number;
15
+ yMax: number;
16
+ }
17
+ /**
18
+ * Calculate exact bounding box for a path
19
+ *
20
+ * For line segments: min/max of endpoints
21
+ * For quadratic bezier: find t where derivative = 0, evaluate curve at those t values
22
+ * For cubic bezier: solve quadratic for extrema, evaluate curve at those t values
23
+ *
24
+ * @param path - Path to calculate bounds for
25
+ * @returns Bounding box or null for empty path
26
+ */
27
+ export declare function getExactBounds(path: GlyphPath): BBox | null;
28
+ /**
29
+ * Find t values where a quadratic bezier has extrema
30
+ *
31
+ * For quadratic bezier B(t) = (1-t)²p0 + 2(1-t)t*p1 + t²p2
32
+ * Derivative: B'(t) = 2(1-t)(p1-p0) + 2t(p2-p1)
33
+ * = 2(p1-p0) + 2t(p0-2p1+p2)
34
+ * = 2[(p1-p0) + t(p0-2p1+p2)]
35
+ *
36
+ * Set B'(t) = 0:
37
+ * (p1-p0) + t(p0-2p1+p2) = 0
38
+ * t = -(p1-p0)/(p0-2p1+p2)
39
+ * = (p0-p1)/(p0-2p1+p2)
40
+ *
41
+ * @param p0 - Start point
42
+ * @param p1 - Control point
43
+ * @param p2 - End point
44
+ * @returns Array of t values in [0,1] where extrema occur
45
+ */
46
+ export declare function getQuadraticExtrema(p0: number, p1: number, p2: number): number[];
47
+ /**
48
+ * Find t values where a cubic bezier has extrema
49
+ *
50
+ * For cubic bezier B(t) = (1-t)³p0 + 3(1-t)²t*p1 + 3(1-t)t²p2 + t³p3
51
+ * Derivative: B'(t) = 3(1-t)²(p1-p0) + 6(1-t)t(p2-p1) + 3t²(p3-p2)
52
+ *
53
+ * Simplified: B'(t) = at² + bt + c where:
54
+ * a = 3(p3 - 3p2 + 3p1 - p0)
55
+ * b = 6(p2 - 2p1 + p0)
56
+ * c = 3(p1 - p0)
57
+ *
58
+ * Solve using quadratic formula: t = (-b ± √(b²-4ac)) / 2a
59
+ *
60
+ * @param p0 - Start point
61
+ * @param p1 - First control point
62
+ * @param p2 - Second control point
63
+ * @param p3 - End point
64
+ * @returns Array of t values in [0,1] where extrema occur
65
+ */
66
+ export declare function getCubicExtrema(p0: number, p1: number, p2: number, p3: number): number[];
67
+ /**
68
+ * Evaluate quadratic bezier at parameter t
69
+ *
70
+ * B(t) = (1-t)²p0 + 2(1-t)t*p1 + t²p2
71
+ *
72
+ * @param p0 - Start point
73
+ * @param p1 - Control point
74
+ * @param p2 - End point
75
+ * @param t - Parameter in [0,1]
76
+ * @returns Value at t
77
+ */
78
+ export declare function evaluateQuadratic(p0: number, p1: number, p2: number, t: number): number;
79
+ /**
80
+ * Evaluate cubic bezier at parameter t
81
+ *
82
+ * B(t) = (1-t)³p0 + 3(1-t)²t*p1 + 3(1-t)t²p2 + t³p3
83
+ *
84
+ * @param p0 - Start point
85
+ * @param p1 - First control point
86
+ * @param p2 - Second control point
87
+ * @param p3 - End point
88
+ * @param t - Parameter in [0,1]
89
+ * @returns Value at t
90
+ */
91
+ export declare function evaluateCubic(p0: number, p1: number, p2: number, p3: number, t: number): number;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Bitmap manipulation utilities
3
+ */
4
+ import { type Bitmap, PixelMode } from "./types.ts";
5
+ /**
6
+ * Embolden a bitmap by dilating pixel values
7
+ * Makes text bolder by spreading coverage in x and y directions
8
+ */
9
+ export declare function emboldenBitmap(bitmap: Bitmap, xStrength: number, yStrength: number): Bitmap;
10
+ /**
11
+ * Convert bitmap between pixel modes
12
+ */
13
+ export declare function convertBitmap(bitmap: Bitmap, targetMode: PixelMode): Bitmap;
14
+ /**
15
+ * Alpha blend src bitmap onto dst bitmap at position (x, y)
16
+ */
17
+ export declare function blendBitmap(dst: Bitmap, src: Bitmap, x: number, y: number, opacity: number): void;
18
+ /**
19
+ * Create a deep copy of a bitmap
20
+ */
21
+ export declare function copyBitmap(bitmap: Bitmap): Bitmap;
22
+ /**
23
+ * Resize bitmap using nearest-neighbor interpolation
24
+ */
25
+ export declare function resizeBitmap(bitmap: Bitmap, newWidth: number, newHeight: number): Bitmap;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Bitmap blur filters - Gaussian and Box blur
3
+ */
4
+ import { type Bitmap } from "./types.ts";
5
+ /**
6
+ * Generate 1D Gaussian kernel
7
+ * Uses Gaussian function: exp(-x²/(2σ²))
8
+ */
9
+ export declare function createGaussianKernel(radius: number): Float32Array;
10
+ /**
11
+ * Gaussian blur implementation using separable 2-pass algorithm
12
+ * Modifies bitmap in-place and returns it
13
+ */
14
+ export declare function gaussianBlur(bitmap: Bitmap, radius: number): Bitmap;
15
+ /**
16
+ * Box blur using running sum for O(1) per pixel
17
+ * Modifies bitmap in-place and returns it
18
+ */
19
+ export declare function boxBlur(bitmap: Bitmap, radius: number): Bitmap;
20
+ /**
21
+ * Apply blur filter to a bitmap in-place
22
+ * @param bitmap - Bitmap to blur (modified in-place)
23
+ * @param radius - Blur radius in pixels (can be fractional)
24
+ * @param type - Blur type: 'gaussian' (default) or 'box'
25
+ * @returns The modified bitmap
26
+ */
27
+ export declare function blurBitmap(bitmap: Bitmap, radius: number, type?: "gaussian" | "box"): Bitmap;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Cell management for scanline rasterization
3
+ *
4
+ * Based on FreeType's ftgrays.c cell accumulation approach.
5
+ * Each cell tracks coverage and area for anti-aliased rendering.
6
+ *
7
+ * Uses pool-based allocation with overflow detection for bounded memory.
8
+ */
9
+ /**
10
+ * Pool overflow error - thrown when cell pool is exhausted
11
+ */
12
+ export declare class PoolOverflowError extends Error {
13
+ constructor();
14
+ }
15
+ /**
16
+ * A cell accumulates coverage information for one pixel
17
+ */
18
+ export interface Cell {
19
+ /** X coordinate in pixels */
20
+ x: number;
21
+ /** Accumulated signed area */
22
+ area: number;
23
+ /** Accumulated coverage (winding number contribution) */
24
+ cover: number;
25
+ /** Next cell in linked list (index into pool, -1 for end) */
26
+ next: number;
27
+ }
28
+ /**
29
+ * Cell storage with pool-based allocation and linked lists per scanline.
30
+ * Matches FreeType's approach for bounded memory usage.
31
+ */
32
+ export declare class CellBuffer {
33
+ /** Fixed-size cell pool */
34
+ private pool;
35
+ /** Pool size */
36
+ private poolSize;
37
+ /** Next free cell index */
38
+ private freeIndex;
39
+ /** Per-scanline linked list heads (index into pool, -1 for empty) */
40
+ private ycells;
41
+ /** Band bounds (Y range for current render pass) */
42
+ private bandMinY;
43
+ private bandMaxY;
44
+ /** Bounding box of active cells */
45
+ minY: number;
46
+ maxY: number;
47
+ minX: number;
48
+ maxX: number;
49
+ /** Current position for incremental cell updates */
50
+ private currentX;
51
+ private currentY;
52
+ private currentCellIndex;
53
+ /** Clip bounds in pixels */
54
+ private clipMinX;
55
+ private clipMinY;
56
+ private clipMaxX;
57
+ private clipMaxY;
58
+ /** Null cell index (sentinel at end of pool) */
59
+ private nullCellIndex;
60
+ /** Whether band bounds have been set */
61
+ private bandSet;
62
+ constructor(poolSize?: number);
63
+ /**
64
+ * Set clipping bounds
65
+ */
66
+ setClip(minX: number, minY: number, maxX: number, maxY: number): void;
67
+ /**
68
+ * Set band bounds for current render pass
69
+ */
70
+ setBandBounds(minY: number, maxY: number): void;
71
+ /**
72
+ * Clear all cells for new band
73
+ */
74
+ reset(): void;
75
+ /**
76
+ * Set current position (in subpixel coordinates)
77
+ * @throws PoolOverflowError if pool is exhausted
78
+ */
79
+ setCurrentCell(x: number, y: number): void;
80
+ /**
81
+ * Find or create a cell at the given pixel position
82
+ * @throws PoolOverflowError if pool is exhausted
83
+ */
84
+ private findOrCreateCell;
85
+ /**
86
+ * Ensure ycells array can accommodate the given Y coordinate
87
+ * Used for backward compatibility when setBandBounds is not called
88
+ */
89
+ private ensureYCellsCapacity;
90
+ /**
91
+ * Add area and cover to current cell
92
+ */
93
+ addArea(area: number, cover: number): void;
94
+ /**
95
+ * Get current cell area (for accumulation)
96
+ */
97
+ getArea(): number;
98
+ /**
99
+ * Get current cell cover
100
+ */
101
+ getCover(): number;
102
+ /**
103
+ * Get all cells for a given Y coordinate, sorted by X
104
+ */
105
+ getCellsForRow(y: number): Cell[];
106
+ /**
107
+ * Iterate over all cells in scanline order within band
108
+ */
109
+ iterateCells(): Generator<{
110
+ y: number;
111
+ cells: Cell[];
112
+ }>;
113
+ /**
114
+ * Iterate cells for a single row (for band sweep)
115
+ */
116
+ iterateRowCells(y: number): Generator<Cell>;
117
+ /**
118
+ * Get number of cells currently allocated
119
+ */
120
+ getCellCount(): number;
121
+ /**
122
+ * Check if pool is near capacity
123
+ */
124
+ isNearCapacity(): boolean;
125
+ }
126
+ /**
127
+ * Convert cell coverage to 8-bit grayscale value
128
+ *
129
+ * The area is accumulated in 2*PIXEL_BITS precision.
130
+ * We need to shift down to get 0-255 coverage.
131
+ */
132
+ export declare function coverageToGray(area: number): number;
133
+ /**
134
+ * Apply non-zero winding fill rule
135
+ */
136
+ export declare function applyNonZeroRule(cover: number): number;
137
+ /**
138
+ * Apply even-odd fill rule
139
+ */
140
+ export declare function applyEvenOddRule(cover: number): number;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Fixed-point arithmetic utilities for rasterization
3
+ *
4
+ * FreeType uses several fixed-point formats:
5
+ * - F26Dot6: 26.6 format (64 units per pixel) for coordinates
6
+ * - F16Dot16: 16.16 format for high-precision calculations
7
+ * - F2Dot14: 2.14 format for normalized vectors
8
+ */
9
+ export declare const PIXEL_BITS = 8;
10
+ export declare const ONE_PIXEL: number;
11
+ export declare const PIXEL_MASK: number;
12
+ export declare const F26DOT6_SHIFT = 6;
13
+ export declare const F26DOT6_ONE: number;
14
+ export declare const F16DOT16_SHIFT = 16;
15
+ export declare const F16DOT16_ONE: number;
16
+ /**
17
+ * Convert float to 26.6 fixed-point
18
+ */
19
+ export declare function floatToF26Dot6(x: number): number;
20
+ /**
21
+ * Convert 26.6 fixed-point to float
22
+ */
23
+ export declare function f26Dot6ToFloat(x: number): number;
24
+ /**
25
+ * Convert float to internal raster coordinates (PIXEL_BITS precision)
26
+ * Input is in font units, output has 256 subpixel levels per pixel
27
+ */
28
+ export declare function floatToPixel(x: number, scale: number): number;
29
+ /**
30
+ * Truncate to pixel (floor for positive, ceil for negative)
31
+ */
32
+ export declare function truncPixel(x: number): number;
33
+ /**
34
+ * Get fractional part (0 to ONE_PIXEL-1)
35
+ */
36
+ export declare function fracPixel(x: number): number;
37
+ /**
38
+ * Round to nearest pixel
39
+ */
40
+ export declare function roundPixel(x: number): number;
41
+ /**
42
+ * Floor to pixel boundary
43
+ */
44
+ export declare function floorPixel(x: number): number;
45
+ /**
46
+ * Ceiling to pixel boundary
47
+ */
48
+ export declare function ceilPixel(x: number): number;
49
+ /**
50
+ * Upscale from 26.6 to internal PIXEL_BITS format
51
+ * PIXEL_BITS=8 means 2 extra bits of precision vs 26.6
52
+ */
53
+ export declare function upscale(x: number): number;
54
+ /**
55
+ * Downscale from internal format to 26.6
56
+ */
57
+ export declare function downscale(x: number): number;
58
+ /**
59
+ * Multiply two fixed-point numbers and divide, avoiding overflow
60
+ * Computes (a * b) / c with 64-bit intermediate precision
61
+ */
62
+ export declare function mulDiv(a: number, b: number, c: number): number;
63
+ /**
64
+ * Multiply two 16.16 fixed-point numbers
65
+ */
66
+ export declare function mulFix(a: number, b: number): number;
67
+ /**
68
+ * Divide two numbers and return 16.16 fixed-point result
69
+ */
70
+ export declare function divFix(a: number, b: number): number;
71
+ /**
72
+ * Fast approximation of sqrt(x*x + y*y) using "alpha max plus beta min" algorithm.
73
+ * Uses alpha = 1, beta = 3/8 for max error < 7% vs exact value.
74
+ * From FreeType's FT_HYPOT macro.
75
+ */
76
+ export declare function hypot(x: number, y: number): number;
77
+ /**
78
+ * Calculate the length of a 2D vector (integer math)
79
+ * Uses FreeType's "alpha max plus beta min" approximation
80
+ */
81
+ export declare function vectorLength(dx: number, dy: number): number;
82
+ /**
83
+ * Normalize a 2D vector to unit length (16.16 fixed-point output)
84
+ */
85
+ export declare function normalizeVector(dx: number, dy: number): {
86
+ x: number;
87
+ y: number;
88
+ };
89
+ /**
90
+ * Clamp value to range
91
+ */
92
+ export declare function clamp(x: number, min: number, max: number): number;
93
+ /**
94
+ * Absolute value
95
+ */
96
+ export declare function abs(x: number): number;
97
+ /**
98
+ * Sign of value (-1, 0, or 1)
99
+ */
100
+ export declare function sign(x: number): number;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Gradient fill rendering for paths
3
+ */
4
+ import type { GlyphPath } from "../render/path.ts";
5
+ import { type Bitmap, type RasterizeOptions } from "./types.ts";
6
+ /**
7
+ * Color stop in a gradient (RGBA, 0-255 each)
8
+ */
9
+ export interface ColorStop {
10
+ /** Position along gradient, 0.0 to 1.0 */
11
+ offset: number;
12
+ /** RGBA color values, 0-255 each */
13
+ color: [number, number, number, number];
14
+ }
15
+ /**
16
+ * Linear gradient from point (x0,y0) to (x1,y1)
17
+ */
18
+ export interface LinearGradient {
19
+ type: "linear";
20
+ /** Start X coordinate */
21
+ x0: number;
22
+ /** Start Y coordinate */
23
+ y0: number;
24
+ /** End X coordinate */
25
+ x1: number;
26
+ /** End Y coordinate */
27
+ y1: number;
28
+ /** Color stops */
29
+ stops: ColorStop[];
30
+ }
31
+ /**
32
+ * Radial gradient from center point with radius
33
+ */
34
+ export interface RadialGradient {
35
+ type: "radial";
36
+ /** Center X coordinate */
37
+ cx: number;
38
+ /** Center Y coordinate */
39
+ cy: number;
40
+ /** Gradient radius */
41
+ radius: number;
42
+ /** Color stops */
43
+ stops: ColorStop[];
44
+ }
45
+ /**
46
+ * Gradient type union
47
+ */
48
+ export type Gradient = LinearGradient | RadialGradient;
49
+ /**
50
+ * Get color at position in gradient
51
+ */
52
+ export declare function interpolateGradient(gradient: Gradient, x: number, y: number): [number, number, number, number];
53
+ /**
54
+ * Create a bitmap filled with gradient (no path)
55
+ */
56
+ export declare function createGradientBitmap(width: number, height: number, gradient: Gradient): Bitmap;
57
+ /**
58
+ * Rasterize path with gradient fill
59
+ * First rasterizes path to get coverage mask, then fills with gradient
60
+ */
61
+ export declare function rasterizePathWithGradient(path: GlyphPath, gradient: Gradient, options: RasterizeOptions): Bitmap;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Gray-scale anti-aliased rasterizer
3
+ *
4
+ * Based on FreeType's ftgrays.c - a coverage-based scanline rasterizer
5
+ * that produces high-quality anti-aliased output.
6
+ *
7
+ * Algorithm overview:
8
+ * 1. Convert outline to line segments (flatten curves)
9
+ * 2. For each line segment, compute coverage contribution to cells
10
+ * 3. Sweep scanlines, accumulating coverage
11
+ * 4. Convert coverage to grayscale pixels
12
+ *
13
+ * Key concepts:
14
+ * - cover: accumulated vertical change (winding contribution)
15
+ * - area: accumulated (y-delta * x-position) for edge anti-aliasing
16
+ *
17
+ * Band processing:
18
+ * - Large glyphs are divided into vertical bands
19
+ * - Each band is rendered with bounded memory pool
20
+ * - On overflow, band is bisected and retried
21
+ */
22
+ import type { Bitmap, FillRule, Span } from "./types.ts";
23
+ /**
24
+ * Rasterizer state
25
+ */
26
+ export declare class GrayRaster {
27
+ private cells;
28
+ private x;
29
+ private y;
30
+ private minX;
31
+ private minY;
32
+ private maxX;
33
+ private maxY;
34
+ constructor();
35
+ /**
36
+ * Set clip rectangle (in pixels)
37
+ */
38
+ setClip(minX: number, minY: number, maxX: number, maxY: number): void;
39
+ /**
40
+ * Set band bounds for current render pass
41
+ */
42
+ setBandBounds(minY: number, maxY: number): void;
43
+ /**
44
+ * Reset rasterizer state
45
+ */
46
+ reset(): void;
47
+ /**
48
+ * Move to a new position (start new contour)
49
+ * Coordinates are in subpixel units (ONE_PIXEL per pixel)
50
+ */
51
+ moveTo(x: number, y: number): void;
52
+ /**
53
+ * Draw line to position
54
+ */
55
+ lineTo(toX: number, toY: number): void;
56
+ /**
57
+ * Render a line from current position to (toX, toY)
58
+ * This is the core rasterization algorithm.
59
+ */
60
+ private renderLine;
61
+ /**
62
+ * Render a line segment within a single scanline
63
+ */
64
+ private renderScanline;
65
+ /**
66
+ * Multiply and divide with 64-bit precision
67
+ */
68
+ private mulDiv;
69
+ /**
70
+ * Draw a quadratic Bezier curve using simple parametric sampling
71
+ */
72
+ conicTo(cx: number, cy: number, toX: number, toY: number): void;
73
+ /**
74
+ * Draw a cubic Bezier curve
75
+ */
76
+ cubicTo(cx1: number, cy1: number, cx2: number, cy2: number, x: number, y: number): void;
77
+ private subdivCubic;
78
+ /**
79
+ * Sweep all cells and render to bitmap
80
+ *
81
+ * Supports both top-down (positive pitch) and bottom-up (negative pitch) bitmaps.
82
+ * For positive pitch: y=0 is at top of image (first row in buffer)
83
+ * For negative pitch: y=0 is at bottom of image (last row in buffer)
84
+ */
85
+ sweep(bitmap: Bitmap, fillRule?: FillRule): void;
86
+ private applyFillRule;
87
+ private fillSpan;
88
+ private setPixel;
89
+ /**
90
+ * Sweep and call span callback (unbuffered)
91
+ * @param callback Span callback function
92
+ * @param fillRule Fill rule to apply
93
+ * @param userData User data passed to callback (like FreeType's render_span_data)
94
+ */
95
+ sweepSpans<T = void>(callback: (y: number, spans: Span[], userData: T) => void, fillRule?: FillRule, userData?: T): void;
96
+ /**
97
+ * Sweep with span buffering (like FreeType's gray_sweep_direct)
98
+ * Buffers up to 16 spans before flushing for better performance
99
+ * @param callback Span callback function
100
+ * @param fillRule Fill rule to apply
101
+ * @param minX Minimum X clip bound
102
+ * @param maxX Maximum X clip bound
103
+ * @param userData User data passed to callback (like FreeType's render_span_data)
104
+ */
105
+ sweepDirect<T = void>(callback: (y: number, spans: Span[], userData: T) => void, fillRule?: FillRule, minX?: number, maxX?: number, userData?: T): void;
106
+ /**
107
+ * Render with band processing for bounded memory.
108
+ * Divides large glyphs into bands, retries with bisection on overflow.
109
+ * Supports both Y-dimension (vertical) and X-dimension (horizontal) bisection
110
+ * like FreeType's ftgrays.c gray_convert_glyph.
111
+ *
112
+ * @param bitmap Target bitmap
113
+ * @param decomposeFn Function that decomposes outline to rasterizer commands
114
+ * @param bounds Glyph bounds (minY, maxY, optionally minX, maxX)
115
+ * @param fillRule Fill rule to apply
116
+ */
117
+ renderWithBands(bitmap: Bitmap, decomposeFn: () => void, bounds: {
118
+ minY: number;
119
+ maxY: number;
120
+ minX?: number;
121
+ maxX?: number;
122
+ }, fillRule?: FillRule): void;
123
+ /**
124
+ * Render a single band with X clipping
125
+ * @returns true on success, false on pool overflow
126
+ */
127
+ private renderBandWithXClip;
128
+ /**
129
+ * Sweep a band with X clipping and render to bitmap
130
+ */
131
+ private sweepBandWithXClip;
132
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * LCD subpixel rendering support
3
+ *
4
+ * LCD displays have RGB subpixels that can be individually addressed
5
+ * to achieve higher effective resolution. This module provides:
6
+ * 1. Subpixel rendering (3x horizontal resolution)
7
+ * 2. FIR filtering to reduce color fringing
8
+ */
9
+ import type { GlyphPath } from "../render/path.ts";
10
+ import type { Bitmap } from "./types.ts";
11
+ /**
12
+ * LCD filter weights for reducing color fringing
13
+ * These are based on FreeType's default LCD filter
14
+ */
15
+ export declare const LCD_FILTER_LIGHT: number[];
16
+ export declare const LCD_FILTER_DEFAULT: number[];
17
+ export declare const LCD_FILTER_LEGACY: number[];
18
+ /**
19
+ * LCD rendering mode
20
+ */
21
+ export declare enum LcdMode {
22
+ /** Horizontal RGB subpixels (most common) */
23
+ RGB = 0,
24
+ /** Horizontal BGR subpixels */
25
+ BGR = 1,
26
+ /** Vertical RGB subpixels */
27
+ RGB_V = 2,
28
+ /** Vertical BGR subpixels */
29
+ BGR_V = 3
30
+ }
31
+ /**
32
+ * Rasterize a glyph with LCD subpixel rendering
33
+ *
34
+ * The algorithm:
35
+ * 1. Render at 3x horizontal resolution
36
+ * 2. Apply FIR filter to reduce color fringing
37
+ * 3. Output RGB values per pixel
38
+ */
39
+ export declare function rasterizeLcd(path: GlyphPath, width: number, height: number, scale: number, offsetX: number, offsetY: number, mode?: LcdMode, filterWeights?: number[]): Bitmap;
40
+ /**
41
+ * Convert LCD bitmap to RGBA for display
42
+ * Uses gamma-corrected blending against a background color
43
+ */
44
+ export declare function lcdToRGBA(lcd: Bitmap, bgColor?: [number, number, number], fgColor?: [number, number, number]): Uint8Array;