@unmade/text-renderer 1.1.0 → 1.2.0
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/README.md +184 -0
- package/dist/__vite-browser-external-oLchLuMx.js +7 -0
- package/dist/baselines/index.d.ts +59 -0
- package/dist/ce-adapter/index.cjs +1 -1
- package/dist/ce-adapter/index.js +154 -152
- package/dist/constants.d.ts +5 -0
- package/dist/fitting/index.d.ts +86 -0
- package/dist/glyph/svg-glyph-converter.d.ts +42 -0
- package/dist/helpers/bbox.d.ts +34 -0
- package/dist/helpers/point.d.ts +17 -0
- package/dist/helpers/xml.d.ts +1 -0
- package/dist/index.d.ts +17 -249
- package/dist/index.js +2221 -2005
- package/dist/loading/createLoadedFont.d.ts +53 -0
- package/dist/loading/index.d.ts +4 -0
- package/dist/measuring/conversion.d.ts +2 -0
- package/dist/measuring/index.d.ts +28 -0
- package/dist/node/baselines/index.d.ts +59 -0
- package/dist/node/ce-adapter/ce-types.d.ts +171 -0
- package/dist/node/ce-adapter/extractTextPlacements.d.ts +11 -0
- package/dist/node/ce-adapter/index.d.ts +12 -0
- package/dist/node/ce-adapter/mapStateToRendererOptions.d.ts +13 -0
- package/dist/node/ce-adapter/types.d.ts +56 -0
- package/dist/node/constants.d.ts +5 -0
- package/dist/node/fitting/index.d.ts +86 -0
- package/dist/node/glyph/svg-glyph-converter.d.ts +42 -0
- package/dist/node/helpers/bbox.d.ts +34 -0
- package/dist/node/helpers/point.d.ts +17 -0
- package/dist/node/helpers/xml.d.ts +1 -0
- package/dist/node/index.d.ts +17 -249
- package/dist/node/index.js +940 -948
- package/dist/node/loading/createLoadedFont.d.ts +53 -0
- package/dist/node/loading/index.d.ts +4 -0
- package/dist/node/measuring/conversion.d.ts +2 -0
- package/dist/node/measuring/index.d.ts +28 -0
- package/dist/node/renderText.d.ts +5 -0
- package/dist/node/rendering/index.d.ts +42 -0
- package/dist/node/svg/index.d.ts +11 -0
- package/dist/node/types.d.ts +75 -0
- package/dist/renderText.d.ts +5 -0
- package/dist/rendering/index.d.ts +42 -0
- package/dist/rolldown-runtime-DtPi1Y-2.js +13 -0
- package/dist/svg/index.d.ts +11 -0
- package/dist/types.d.ts +75 -0
- package/dist/worker/baselines/index.d.ts +59 -0
- package/dist/worker/ce-adapter/ce-types.d.ts +171 -0
- package/dist/worker/ce-adapter/extractTextPlacements.d.ts +11 -0
- package/dist/worker/ce-adapter/index.d.ts +12 -0
- package/dist/worker/ce-adapter/mapStateToRendererOptions.d.ts +13 -0
- package/dist/worker/ce-adapter/types.d.ts +56 -0
- package/dist/worker/constants.d.ts +5 -0
- package/dist/worker/fitting/index.d.ts +86 -0
- package/dist/worker/glyph/svg-glyph-converter.d.ts +42 -0
- package/dist/worker/helpers/bbox.d.ts +34 -0
- package/dist/worker/helpers/point.d.ts +17 -0
- package/dist/worker/helpers/xml.d.ts +1 -0
- package/dist/worker/index.d.ts +17 -249
- package/dist/worker/index.js +8346 -9728
- package/dist/worker/loading/createLoadedFont.d.ts +53 -0
- package/dist/worker/loading/index.d.ts +4 -0
- package/dist/worker/measuring/conversion.d.ts +2 -0
- package/dist/worker/measuring/index.d.ts +28 -0
- package/dist/worker/renderText.d.ts +5 -0
- package/dist/worker/rendering/index.d.ts +42 -0
- package/dist/worker/svg/index.d.ts +11 -0
- package/dist/worker/types.d.ts +75 -0
- package/package.json +19 -11
- package/dist/__vite-browser-external-l0sNRNKZ.js +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Face, Font } from 'harfbuzzjs';
|
|
2
|
+
export interface SVGGlyphData {
|
|
3
|
+
svg: string;
|
|
4
|
+
viewbox: string;
|
|
5
|
+
}
|
|
6
|
+
export interface LoadedFont {
|
|
7
|
+
unitsPerEm: number;
|
|
8
|
+
names: {
|
|
9
|
+
fontFamily: string;
|
|
10
|
+
};
|
|
11
|
+
svgGlyphs?: Map<number, SVGGlyphData>;
|
|
12
|
+
charToGlyph(char: string): {
|
|
13
|
+
index: number;
|
|
14
|
+
advanceWidth: number;
|
|
15
|
+
name: string;
|
|
16
|
+
getBoundingBox(): {
|
|
17
|
+
x1: number;
|
|
18
|
+
y1: number;
|
|
19
|
+
x2: number;
|
|
20
|
+
y2: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
getPath(text: string, x: number, y: number, fontSize: number, options?: {
|
|
24
|
+
drawSVG?: boolean;
|
|
25
|
+
}): {
|
|
26
|
+
getBoundingBox(): {
|
|
27
|
+
x1: number;
|
|
28
|
+
y1: number;
|
|
29
|
+
x2: number;
|
|
30
|
+
y2: number;
|
|
31
|
+
};
|
|
32
|
+
toPathData(decimals?: number): string;
|
|
33
|
+
};
|
|
34
|
+
getPaths(text: string, x: number, y: number, fontSize: number, options?: {
|
|
35
|
+
drawSVG?: boolean;
|
|
36
|
+
}): Array<{
|
|
37
|
+
getBoundingBox(): {
|
|
38
|
+
x1: number;
|
|
39
|
+
y1: number;
|
|
40
|
+
x2: number;
|
|
41
|
+
y2: number;
|
|
42
|
+
};
|
|
43
|
+
toPathData(decimals?: number): string;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
export declare function boundsFromPath(pathData: string): {
|
|
47
|
+
x1: number;
|
|
48
|
+
y1: number;
|
|
49
|
+
x2: number;
|
|
50
|
+
y2: number;
|
|
51
|
+
} | null;
|
|
52
|
+
export declare function transformPath(pathData: string, scaleX: number, scaleY: number, dx: number): string;
|
|
53
|
+
export declare function createLoadedFont(face: Face, font: Font, familyName: string, svgGlyphs?: Map<number, SVGGlyphData>): LoadedFont;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { createLoadedFont, LoadedFont } from './createLoadedFont';
|
|
2
|
+
export { createLoadedFont, type LoadedFont };
|
|
3
|
+
export declare const getFontCache: () => Map<string, LoadedFont>;
|
|
4
|
+
export declare const loadFont: (fontUrl: string, fetchSVGGlyphs?: boolean) => Promise<LoadedFont>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LoadedFont } from '../loading';
|
|
2
|
+
import { BoxDimensions, PhysicalSize, TextSpacing } from '../types';
|
|
3
|
+
export interface GetFontSizeFromPhysicalSizeOptions {
|
|
4
|
+
font: LoadedFont;
|
|
5
|
+
boxDimensions: BoxDimensions;
|
|
6
|
+
physicalSize: PhysicalSize;
|
|
7
|
+
spacing?: TextSpacing;
|
|
8
|
+
}
|
|
9
|
+
export interface GetTextMetricsAtFontSizeOptions {
|
|
10
|
+
font: LoadedFont;
|
|
11
|
+
text: string;
|
|
12
|
+
fontSize: number;
|
|
13
|
+
spacing?: TextSpacing;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* This is the character we use to calculate font sizes
|
|
17
|
+
* when fixed physical text height is set for a placement.
|
|
18
|
+
*
|
|
19
|
+
* The 'I' character is used because of its flat top and bottom.
|
|
20
|
+
* https://en.wikipedia.org/wiki/Cap_height
|
|
21
|
+
*/
|
|
22
|
+
export declare const getStandardCharacter: (font: LoadedFont) => string;
|
|
23
|
+
export declare const getFontSizeFromPhysicalSize: ({ font, boxDimensions, physicalSize, spacing, }: GetFontSizeFromPhysicalSizeOptions) => number;
|
|
24
|
+
export declare const getTextMetricsAtFontSize: ({ font, text, fontSize, spacing, }: GetTextMetricsAtFontSizeOptions) => {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
baseline: number;
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LoadedFont } from '../loading';
|
|
2
|
+
import { ColourMap, GlyphFill, HorizontalTextAlignmentValues, PlatformMatrix, TextSpacing } from '../types';
|
|
3
|
+
export interface SvgGlyphEntry {
|
|
4
|
+
content: string;
|
|
5
|
+
viewBox: string;
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
glyphIndex: number;
|
|
11
|
+
}
|
|
12
|
+
export interface PathEntry {
|
|
13
|
+
attributes: {
|
|
14
|
+
d: string;
|
|
15
|
+
'data-character': string;
|
|
16
|
+
transform: string;
|
|
17
|
+
};
|
|
18
|
+
path: unknown;
|
|
19
|
+
matrix: PlatformMatrix;
|
|
20
|
+
glyphData: {
|
|
21
|
+
index: number;
|
|
22
|
+
bbox: {
|
|
23
|
+
x1: number;
|
|
24
|
+
y1: number;
|
|
25
|
+
x2: number;
|
|
26
|
+
y2: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
svgGlyph?: SvgGlyphEntry;
|
|
30
|
+
fills?: GlyphFill[];
|
|
31
|
+
}
|
|
32
|
+
export declare const fontUnitsToPixels: (value: number, fontSize: number, unitsPerEm: number) => number;
|
|
33
|
+
export interface GetTextAsPathDataOptions {
|
|
34
|
+
font: LoadedFont;
|
|
35
|
+
baselinePath: string;
|
|
36
|
+
text: string;
|
|
37
|
+
fontSize: number;
|
|
38
|
+
spacing?: TextSpacing;
|
|
39
|
+
horizontalAlignment?: HorizontalTextAlignmentValues;
|
|
40
|
+
colourMap?: ColourMap;
|
|
41
|
+
}
|
|
42
|
+
export declare const getTextAsPathData: ({ font, baselinePath, text, fontSize, spacing, horizontalAlignment, colourMap, }: GetTextAsPathDataOptions) => PathEntry[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PathEntry } from '../rendering';
|
|
2
|
+
import { BoxDimensions, ColourInfo, TextSpacing } from '../types';
|
|
3
|
+
export interface AssembleSvgOptions {
|
|
4
|
+
boxDimensions: BoxDimensions;
|
|
5
|
+
paths: PathEntry[];
|
|
6
|
+
spacing?: TextSpacing;
|
|
7
|
+
fontSize?: number;
|
|
8
|
+
fillColour?: ColourInfo;
|
|
9
|
+
strokeColour?: ColourInfo;
|
|
10
|
+
}
|
|
11
|
+
export declare const assembleSvg: ({ boxDimensions, paths, spacing, fontSize, fillColour, strokeColour, }: AssembleSvgOptions) => string;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DOMMatrix } from '@unmade/platform';
|
|
2
|
+
import { LoadedFont } from './loading';
|
|
3
|
+
/** The platform's matrix, which is not the same shape as the DOM's DOMMatrix. */
|
|
4
|
+
export type PlatformMatrix = InstanceType<typeof DOMMatrix>;
|
|
5
|
+
export type MeasurementUnits = 'mm' | 'in';
|
|
6
|
+
export type BoxDimensions = {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
physicalWidth: number;
|
|
10
|
+
physicalHeight: number;
|
|
11
|
+
physicalUnits: MeasurementUnits;
|
|
12
|
+
};
|
|
13
|
+
export type VerticalTextAlignmentValues = 'centre' | 'top' | 'bottom';
|
|
14
|
+
export type HorizontalTextAlignmentValues = 'left' | 'centre' | 'right' | 'distributed';
|
|
15
|
+
export type PhysicalSize = [height: number, units: MeasurementUnits];
|
|
16
|
+
export type BaselineType = 'flat' | 'curved';
|
|
17
|
+
export type BaselineConfig = {
|
|
18
|
+
type: 'flat';
|
|
19
|
+
} | {
|
|
20
|
+
type: 'curved';
|
|
21
|
+
} | {
|
|
22
|
+
type: 'custom';
|
|
23
|
+
path: string;
|
|
24
|
+
};
|
|
25
|
+
export interface ColourInfo {
|
|
26
|
+
readonly hex: string;
|
|
27
|
+
readonly reference?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface GlyphFill {
|
|
30
|
+
readonly pathData: string;
|
|
31
|
+
readonly colour: ColourInfo;
|
|
32
|
+
}
|
|
33
|
+
/** Maps original hex colour → replacement ColourInfo. */
|
|
34
|
+
export type ColourMap = Readonly<Record<string, ColourInfo>>;
|
|
35
|
+
export interface TextSpacing {
|
|
36
|
+
readonly outlineWidth: number;
|
|
37
|
+
readonly letterSpacing: number;
|
|
38
|
+
readonly letterSpacingOutline: number;
|
|
39
|
+
}
|
|
40
|
+
/** Options for synchronous renderText (font already loaded). */
|
|
41
|
+
export interface RenderTextOptions {
|
|
42
|
+
text: string;
|
|
43
|
+
font: LoadedFont;
|
|
44
|
+
physicalSize: PhysicalSize;
|
|
45
|
+
/** When provided, bypasses the physicalSize → font size calculation. */
|
|
46
|
+
fontSize?: number;
|
|
47
|
+
boxDimensions: BoxDimensions;
|
|
48
|
+
spacing?: TextSpacing;
|
|
49
|
+
verticalAlignment?: VerticalTextAlignmentValues;
|
|
50
|
+
baseline?: BaselineType | BaselineConfig;
|
|
51
|
+
horizontalAlignment?: HorizontalTextAlignmentValues;
|
|
52
|
+
fillColour?: ColourInfo;
|
|
53
|
+
strokeColour?: ColourInfo;
|
|
54
|
+
colourMap?: ColourMap;
|
|
55
|
+
}
|
|
56
|
+
/** Options for async getRenderedText (loads font from URL). */
|
|
57
|
+
export interface GetRenderedTextOptions {
|
|
58
|
+
text: string;
|
|
59
|
+
fontUrl: string;
|
|
60
|
+
physicalSize: PhysicalSize;
|
|
61
|
+
/**
|
|
62
|
+
* Fallback font size (in pixels) to use if the calculated size causes a
|
|
63
|
+
* TOO_WIDE error. Useful when the caller has an authoritative size (e.g.
|
|
64
|
+
* from the CE) that avoids floating-point rounding issues.
|
|
65
|
+
*/
|
|
66
|
+
fontSizeFallback?: number;
|
|
67
|
+
boxDimensions: BoxDimensions;
|
|
68
|
+
spacing?: TextSpacing;
|
|
69
|
+
verticalAlignment?: VerticalTextAlignmentValues;
|
|
70
|
+
baseline?: BaselineType | BaselineConfig;
|
|
71
|
+
horizontalAlignment?: HorizontalTextAlignmentValues;
|
|
72
|
+
fillColour?: ColourInfo;
|
|
73
|
+
strokeColour?: ColourInfo;
|
|
74
|
+
colourMap?: ColourMap;
|
|
75
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unmade/text-renderer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Pure function text renderer for SVG output",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/unmadeworks/config-engine-packages.git",
|
|
8
|
+
"directory": "packages/text-renderer"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"main": "./dist/index.js",
|
|
7
12
|
"module": "./dist/index.js",
|
|
@@ -63,30 +68,33 @@
|
|
|
63
68
|
"build:ce-adapter": "vite build --config vite.config.ce-adapter.ts",
|
|
64
69
|
"build:types": "cp dist/index.d.ts dist/node/index.d.ts && cp dist/index.d.ts dist/worker/index.d.ts",
|
|
65
70
|
"test": "vitest run",
|
|
66
|
-
"test:unit": "vitest run --exclude '**/__tests__/regression.test.ts'",
|
|
71
|
+
"test:unit": "vitest run --exclude '**/__tests__/regression.test.ts' --exclude '**/__tests__/platform/**'",
|
|
67
72
|
"test:regression": "vitest run __tests__/regression.test.ts",
|
|
73
|
+
"test:platform": "npm run build && vitest run --config vitest.config.platform.ts",
|
|
68
74
|
"test:watch": "vitest",
|
|
69
75
|
"benchmark": "vitest bench __tests__/benchmark.bench.ts",
|
|
70
76
|
"typecheck": "tsc --noEmit"
|
|
71
77
|
},
|
|
72
78
|
"dependencies": {
|
|
73
|
-
"@unmade/platform": "^0.1.
|
|
74
|
-
"@unmade/svg-helpers": "^0.1.
|
|
75
|
-
"harfbuzzjs": "^1.
|
|
79
|
+
"@unmade/platform": "^0.1.5",
|
|
80
|
+
"@unmade/svg-helpers": "^0.1.3",
|
|
81
|
+
"harfbuzzjs": "^1.6.0"
|
|
76
82
|
},
|
|
77
83
|
"peerDependencies": {
|
|
78
|
-
"svg-path-properties": "^
|
|
84
|
+
"svg-path-properties": "^2.0.2"
|
|
79
85
|
},
|
|
80
86
|
"devDependencies": {
|
|
81
87
|
"@resvg/resvg-js": "^2.6.2",
|
|
82
88
|
"@types/pngjs": "^6.0.5",
|
|
89
|
+
"@typescript/typescript6": "^6.0.2",
|
|
83
90
|
"pixelmatch": "^7.2.0",
|
|
91
|
+
"playwright": "^1.62.1",
|
|
84
92
|
"pngjs": "^7.0.0",
|
|
85
|
-
"svg-path-properties": "^
|
|
86
|
-
"typescript": "^
|
|
87
|
-
"vite": "^
|
|
88
|
-
"vite-plugin-dts": "^
|
|
89
|
-
"vitest": "^4.1.
|
|
93
|
+
"svg-path-properties": "^2.0.2",
|
|
94
|
+
"typescript": "^7.0.2",
|
|
95
|
+
"vite": "^8.2.1",
|
|
96
|
+
"vite-plugin-dts": "^5.0.3",
|
|
97
|
+
"vitest": "^4.1.10"
|
|
90
98
|
},
|
|
91
99
|
"keywords": [
|
|
92
100
|
"text",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|