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.
- package/LICENSE +6 -1
- package/README.md +27 -1
- package/dist/font/brotli/context.d.ts +6 -0
- package/dist/font/brotli/decode.d.ts +9 -0
- package/dist/font/brotli/dictionary.d.ts +11 -0
- package/dist/font/brotli/transform.d.ts +12 -0
- package/dist/font/font.d.ts +19 -5
- package/dist/font/tables/cff.d.ts +4 -0
- package/dist/font/tables/gasp.d.ts +54 -0
- package/dist/font/tables/gdef.d.ts +3 -0
- package/dist/font/tables/glyf.d.ts +2 -0
- package/dist/font/tables/hinting.d.ts +38 -0
- package/dist/font/woff2.d.ts +8 -0
- package/dist/hinting/index.d.ts +9 -0
- package/dist/hinting/instructions/arithmetic.d.ts +46 -0
- package/dist/hinting/instructions/control-flow.d.ts +26 -0
- package/dist/hinting/instructions/delta.d.ts +32 -0
- package/dist/hinting/instructions/graphics-state.d.ts +94 -0
- package/dist/hinting/instructions/interpolate.d.ts +16 -0
- package/dist/hinting/instructions/points.d.ts +76 -0
- package/dist/hinting/instructions/stack.d.ts +28 -0
- package/dist/hinting/interpreter.d.ts +30 -0
- package/dist/hinting/programs.d.ts +88 -0
- package/dist/hinting/rounding.d.ts +51 -0
- package/dist/hinting/types.d.ts +369 -0
- package/dist/index.d.ts +21 -11
- package/dist/index.js +10 -8
- package/dist/index.js.map +60 -29
- package/dist/raster/atlas.d.ts +37 -0
- package/dist/raster/bbox.d.ts +91 -0
- package/dist/raster/bitmap-utils.d.ts +25 -0
- package/dist/raster/blur.d.ts +27 -0
- package/dist/raster/cell.d.ts +140 -0
- package/dist/raster/fixed-point.d.ts +100 -0
- package/dist/raster/gradient.d.ts +61 -0
- package/dist/raster/gray-raster.d.ts +132 -0
- package/dist/raster/lcd-filter.d.ts +44 -0
- package/dist/raster/outline-decompose.d.ts +61 -0
- package/dist/raster/rasterize.d.ts +43 -0
- package/dist/raster/sdf.d.ts +37 -0
- package/dist/raster/stroker.d.ts +29 -0
- package/dist/raster/synth.d.ts +50 -0
- package/dist/raster/types.d.ts +176 -0
- package/dist/render/path.d.ts +50 -2
- package/dist/shaper/complex/indic.d.ts +4 -0
- package/dist/types.d.ts +4 -0
- package/dist/unicode/bidi/brackets.gen.d.ts +5 -0
- package/dist/unicode/bidi/char-types.gen.d.ts +25 -0
- package/dist/unicode/bidi/mirroring.gen.d.ts +2 -0
- 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;
|