@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,59 @@
|
|
|
1
|
+
import { BaselineConfig, BaselineType, BoxDimensions, VerticalTextAlignmentValues } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Normalise a baseline option (string shorthand or object) into a BaselineConfig.
|
|
4
|
+
*/
|
|
5
|
+
export declare const normaliseBaselineOption: (baseline: BaselineType | BaselineConfig | undefined) => BaselineConfig;
|
|
6
|
+
/**
|
|
7
|
+
* Validate a custom baseline SVG path string.
|
|
8
|
+
*/
|
|
9
|
+
export declare const validateCustomBaselinePath: (path: string) => void;
|
|
10
|
+
export interface GenerateFlatBaselineOptions {
|
|
11
|
+
boxDimensions: BoxDimensions;
|
|
12
|
+
totalTextHeight: number;
|
|
13
|
+
baseline: number;
|
|
14
|
+
lineHeight: number;
|
|
15
|
+
verticalAlignment?: VerticalTextAlignmentValues;
|
|
16
|
+
lineNumber?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate a path as a baseline for straight text
|
|
20
|
+
* This can be called multiple times for multiline text by incrementing the lineNumber parameter
|
|
21
|
+
*
|
|
22
|
+
* @returns an SVG path command to draw the baseline
|
|
23
|
+
*/
|
|
24
|
+
export declare const generateFlatBaseline: ({ boxDimensions, totalTextHeight, baseline, lineHeight, verticalAlignment, lineNumber, }: GenerateFlatBaselineOptions) => string;
|
|
25
|
+
export interface GenerateCurvedBaselineOptions {
|
|
26
|
+
boxDimensions: BoxDimensions;
|
|
27
|
+
baseline: number;
|
|
28
|
+
textHeight: number;
|
|
29
|
+
verticalAlignment: VerticalTextAlignmentValues;
|
|
30
|
+
}
|
|
31
|
+
/** Where the arch sits vertically: its peak, and the baseline at its ends. */
|
|
32
|
+
export interface CurvedBaselineGeometry {
|
|
33
|
+
/** y of the peak — the highest point of the baseline. */
|
|
34
|
+
curveTop: number;
|
|
35
|
+
/** y of the two ends — the lowest points of the baseline. */
|
|
36
|
+
curveBottom: number;
|
|
37
|
+
/** Horizontal gap left at each end so the outer glyphs are not clipped. */
|
|
38
|
+
curveXInset: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The arch's placement, on its own so that the path and anything reasoning
|
|
42
|
+
* about where the text will land come from one calculation.
|
|
43
|
+
*
|
|
44
|
+
* Sizing needs this: it has to know where the renderer will actually put the
|
|
45
|
+
* baseline before it can say whether the text riding it clears the box. Working
|
|
46
|
+
* that out separately is what let the fit engine believe a size fitted while
|
|
47
|
+
* the render clipped.
|
|
48
|
+
*/
|
|
49
|
+
export declare const curvedBaselineGeometry: ({ boxDimensions, baseline, textHeight, verticalAlignment, }: GenerateCurvedBaselineOptions) => CurvedBaselineGeometry;
|
|
50
|
+
/**
|
|
51
|
+
* Generate a path command to curve text and align that text to the top of the box.
|
|
52
|
+
* Uses two quadratic bezier curves — one from the bottom left to the peak, and a
|
|
53
|
+
* second mirrored from the peak to the end.
|
|
54
|
+
*
|
|
55
|
+
* Curved text is not currently supported for multiline text.
|
|
56
|
+
*
|
|
57
|
+
* @returns an SVG path command to draw the curve
|
|
58
|
+
*/
|
|
59
|
+
export declare const generateCurvedBaseline: ({ boxDimensions, baseline, textHeight, verticalAlignment, }: GenerateCurvedBaselineOptions) => string;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for @unmade/configuration-engine
|
|
3
|
+
*
|
|
4
|
+
* CE doesn't ship .d.ts files. These types cover the subset of the
|
|
5
|
+
* factory API and editor shape that the CE adapter needs.
|
|
6
|
+
*/
|
|
7
|
+
export interface EditorPaletteColour {
|
|
8
|
+
id: number;
|
|
9
|
+
hex: string;
|
|
10
|
+
name: string;
|
|
11
|
+
display_name?: string;
|
|
12
|
+
reference?: string | null;
|
|
13
|
+
extra?: object | null;
|
|
14
|
+
categories?: string[];
|
|
15
|
+
lab?: [number, number, number];
|
|
16
|
+
}
|
|
17
|
+
export interface EditorPalette {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
colours: EditorPaletteColour[];
|
|
22
|
+
extended_palette_id?: number;
|
|
23
|
+
extendedPalette?: EditorPalette;
|
|
24
|
+
categories?: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface EditorGarment {
|
|
27
|
+
slug: string;
|
|
28
|
+
size: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
panels_svg?: string;
|
|
31
|
+
embellishment_positions?: EmbellishmentPosition[];
|
|
32
|
+
}
|
|
33
|
+
export interface EmbellishmentPosition {
|
|
34
|
+
placement: string;
|
|
35
|
+
width: number;
|
|
36
|
+
height: number;
|
|
37
|
+
physical_width?: number;
|
|
38
|
+
physical_height?: number;
|
|
39
|
+
physical_width_decimal: number;
|
|
40
|
+
physical_height_decimal: number;
|
|
41
|
+
physical_size_units: string;
|
|
42
|
+
baseline_path?: string;
|
|
43
|
+
rotation: number;
|
|
44
|
+
variant?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface TextLibraryItemFont {
|
|
47
|
+
id: number;
|
|
48
|
+
font_url: string;
|
|
49
|
+
font_family: string;
|
|
50
|
+
letter_spacing?: number;
|
|
51
|
+
letter_spacing_outline?: number;
|
|
52
|
+
outline_width?: number;
|
|
53
|
+
fixed_colours?: Record<string, {
|
|
54
|
+
reference: string;
|
|
55
|
+
hex: string;
|
|
56
|
+
id: string;
|
|
57
|
+
text: string;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
export interface TextLibraryItem {
|
|
61
|
+
id: string;
|
|
62
|
+
type: 'text';
|
|
63
|
+
fonts: TextLibraryItemFont[];
|
|
64
|
+
palette?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface PlacementLibraryItem {
|
|
67
|
+
id: string;
|
|
68
|
+
type: string;
|
|
69
|
+
palette?: number;
|
|
70
|
+
}
|
|
71
|
+
export interface BasePlacementSettings {
|
|
72
|
+
manufacturing_methods?: {
|
|
73
|
+
name: string;
|
|
74
|
+
}[];
|
|
75
|
+
vertical_alignment?: string;
|
|
76
|
+
horizontal_alignment?: string;
|
|
77
|
+
}
|
|
78
|
+
export interface PlacementsSettings {
|
|
79
|
+
byId: Record<string, BasePlacementSettings>;
|
|
80
|
+
library: Record<string, PlacementLibraryItem | TextLibraryItem>;
|
|
81
|
+
}
|
|
82
|
+
export interface CombinedEditorSettings {
|
|
83
|
+
editor: string;
|
|
84
|
+
mixins: string[];
|
|
85
|
+
garments: EditorGarment[];
|
|
86
|
+
palettes: number[];
|
|
87
|
+
allPalettes: Record<number, EditorPalette>;
|
|
88
|
+
endpoints: {
|
|
89
|
+
palettes: string;
|
|
90
|
+
[key: string]: string | undefined;
|
|
91
|
+
};
|
|
92
|
+
placements?: PlacementsSettings;
|
|
93
|
+
embellishments?: PlacementsSettings;
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
export interface BasePlacementState {
|
|
97
|
+
type: string;
|
|
98
|
+
libraryItemID: string;
|
|
99
|
+
meta?: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
export interface EditorStateVals {
|
|
102
|
+
placements?: Record<string, BasePlacementState>;
|
|
103
|
+
embellishments?: Record<string, BasePlacementState>;
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
}
|
|
106
|
+
export interface EditorState {
|
|
107
|
+
garment?: string;
|
|
108
|
+
vals?: EditorStateVals;
|
|
109
|
+
[key: string]: unknown;
|
|
110
|
+
}
|
|
111
|
+
export interface Palettes {
|
|
112
|
+
byId: Record<string, unknown>;
|
|
113
|
+
getColours(paletteId: number): EditorPaletteColour[];
|
|
114
|
+
getUsedColours(paletteId: number, ids: (number | null)[]): (EditorPaletteColour | null)[];
|
|
115
|
+
getExtendedColours(paletteId: number): EditorPaletteColour[];
|
|
116
|
+
}
|
|
117
|
+
export interface PlacementPositionResult {
|
|
118
|
+
placement: string;
|
|
119
|
+
x: number;
|
|
120
|
+
y: number;
|
|
121
|
+
width: number;
|
|
122
|
+
height: number;
|
|
123
|
+
dimensionsForCanvas: {
|
|
124
|
+
width: number;
|
|
125
|
+
height: number;
|
|
126
|
+
x: number;
|
|
127
|
+
y: number;
|
|
128
|
+
};
|
|
129
|
+
variant: string;
|
|
130
|
+
panel: string;
|
|
131
|
+
rotation: boolean;
|
|
132
|
+
physical_width: number;
|
|
133
|
+
physical_height: number;
|
|
134
|
+
physical_width_decimal: string;
|
|
135
|
+
physical_height_decimal: string;
|
|
136
|
+
physical_size_units: string;
|
|
137
|
+
}
|
|
138
|
+
export interface EditorVariant {
|
|
139
|
+
name: string;
|
|
140
|
+
placements: string[];
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Editor instance returned by CE's factory.
|
|
144
|
+
*
|
|
145
|
+
* The exact shape depends on which mixins are applied at runtime.
|
|
146
|
+
* We type the parts the CE adapter needs and treat the rest as opaque.
|
|
147
|
+
* Uses Element rather than SVGElement for cross-environment compatibility.
|
|
148
|
+
*/
|
|
149
|
+
export interface ConfigEditor {
|
|
150
|
+
getState(): EditorState & {
|
|
151
|
+
vals: NonNullable<EditorState['vals']>;
|
|
152
|
+
};
|
|
153
|
+
palettes: Palettes;
|
|
154
|
+
settings: CombinedEditorSettings;
|
|
155
|
+
placements?: {
|
|
156
|
+
initialise(): Promise<void>;
|
|
157
|
+
getAssetsAsSVGElements(state: EditorState, manufacturingMethod: string): Promise<Record<string, {
|
|
158
|
+
asset: Element;
|
|
159
|
+
position: PlacementPositionResult;
|
|
160
|
+
}>>;
|
|
161
|
+
};
|
|
162
|
+
embellishments?: {
|
|
163
|
+
initialise(): Promise<void>;
|
|
164
|
+
getAssetsAsSVGElements(state: EditorState, manufacturingMethod: string): Promise<Record<string, {
|
|
165
|
+
asset: Element;
|
|
166
|
+
position: PlacementPositionResult;
|
|
167
|
+
}>>;
|
|
168
|
+
};
|
|
169
|
+
getVariants?(): EditorVariant[];
|
|
170
|
+
getCurrentVariant?(): string;
|
|
171
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConfigEditor } from './ce-types';
|
|
2
|
+
import { LoadedTextPlacement } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Extract text placements from a loaded config editor instance.
|
|
5
|
+
*
|
|
6
|
+
* Reads the editor state, resolves fonts and colours from settings and
|
|
7
|
+
* palettes, and returns a structured array of text placements ready for
|
|
8
|
+
* rendering or comparison. Processes both the placements and embellishments
|
|
9
|
+
* buckets.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractTextPlacements(editor: ConfigEditor): LoadedTextPlacement[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CE Adapter for @unmade/text-renderer
|
|
3
|
+
*
|
|
4
|
+
* Utilities for extracting text placement state from a loaded
|
|
5
|
+
* @unmade/configuration-engine editor instance and mapping it to
|
|
6
|
+
* renderer options. Intended for use in server-side comparison pipelines
|
|
7
|
+
* and any environment that bridges CE state to the text-renderer.
|
|
8
|
+
*/
|
|
9
|
+
export { extractTextPlacements } from './extractTextPlacements';
|
|
10
|
+
export { mapStateToRendererOptions } from './mapStateToRendererOptions';
|
|
11
|
+
export type { BasePlacementSettings, BasePlacementState, CombinedEditorSettings, ConfigEditor, EditorGarment, EditorPalette, EditorPaletteColour, EditorState, EditorStateVals, EditorVariant, EmbellishmentPosition, Palettes, PlacementLibraryItem, PlacementPositionResult, PlacementsSettings, TextLibraryItem, TextLibraryItemFont, } from './ce-types';
|
|
12
|
+
export type { LoadedTextPlacement, TextPlacementFont, TextPlacementPosition, TextPlacementSpacing, } from './types';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { GetRenderedTextOptions } from '../types';
|
|
2
|
+
import { LoadedTextPlacement } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Map a LoadedTextPlacement to GetRenderedTextOptions for the text-renderer.
|
|
5
|
+
*
|
|
6
|
+
* Handles the key differences between config-engine and text-renderer:
|
|
7
|
+
* - American to British English ('center' -> 'centre')
|
|
8
|
+
* - isDistributed flag -> horizontalAlignment: 'distributed'
|
|
9
|
+
* - isCurved flag -> baseline: 'curved'
|
|
10
|
+
* - baselinePath -> baseline: { type: 'custom', path }
|
|
11
|
+
* - snake_case spacing -> camelCase spacing
|
|
12
|
+
*/
|
|
13
|
+
export declare function mapStateToRendererOptions(placement: LoadedTextPlacement): GetRenderedTextOptions;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { EditorPaletteColour } from './ce-types';
|
|
2
|
+
export interface TextPlacementPosition {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
physicalWidth: number;
|
|
6
|
+
physicalHeight: number;
|
|
7
|
+
physicalUnits: string;
|
|
8
|
+
baselinePath?: string;
|
|
9
|
+
rotation: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TextPlacementFont {
|
|
12
|
+
id: number;
|
|
13
|
+
fontUrl: string;
|
|
14
|
+
fontFamily: string;
|
|
15
|
+
letterSpacing: number;
|
|
16
|
+
letterSpacingOutline: number;
|
|
17
|
+
outlineWidth: number;
|
|
18
|
+
fixedColours?: Record<string, {
|
|
19
|
+
reference: string;
|
|
20
|
+
hex: string;
|
|
21
|
+
id: string;
|
|
22
|
+
text: string;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export interface TextPlacementSpacing {
|
|
26
|
+
letter_spacing: number;
|
|
27
|
+
letter_spacing_outline: number;
|
|
28
|
+
line_height?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface LoadedTextPlacement {
|
|
31
|
+
placementId: string;
|
|
32
|
+
displayName: string;
|
|
33
|
+
source: 'placements' | 'embellishments';
|
|
34
|
+
text: string;
|
|
35
|
+
font: TextPlacementFont;
|
|
36
|
+
isCurved: boolean;
|
|
37
|
+
isDistributed: boolean;
|
|
38
|
+
verticalAlignment: string;
|
|
39
|
+
horizontalAlignment: string;
|
|
40
|
+
rotation: number;
|
|
41
|
+
spacing: TextPlacementSpacing | null;
|
|
42
|
+
fillColour: EditorPaletteColour | null;
|
|
43
|
+
outlineColour: EditorPaletteColour | null;
|
|
44
|
+
position: TextPlacementPosition;
|
|
45
|
+
userSetPhysicalSize: [number, string] | null;
|
|
46
|
+
fontMetrics: {
|
|
47
|
+
size: number;
|
|
48
|
+
height: number;
|
|
49
|
+
baseline: number;
|
|
50
|
+
width: number;
|
|
51
|
+
physicalHeight?: number;
|
|
52
|
+
physicalUnits?: string;
|
|
53
|
+
physicalFontSize?: [number, 'mm' | 'in'];
|
|
54
|
+
};
|
|
55
|
+
manufacturingMethod: string;
|
|
56
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { LoadedFont } from '../loading';
|
|
2
|
+
import { BaselineConfig, BaselineType, BoxDimensions, PhysicalSize, TextSpacing, VerticalTextAlignmentValues } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* How the font size is arrived at.
|
|
5
|
+
*
|
|
6
|
+
* `fitToBox` solves for the largest size the box allows. The other two pin the
|
|
7
|
+
* size and leave the text length as the free variable instead — which is what a
|
|
8
|
+
* fixed size preset is: hold 60mm, and fit as many characters as will go. All
|
|
9
|
+
* three then behave identically downstream, so a pinned size is an ordinary mode
|
|
10
|
+
* rather than a special path.
|
|
11
|
+
*/
|
|
12
|
+
export type FitSize = {
|
|
13
|
+
mode: 'fitToBox';
|
|
14
|
+
minFontSize: number;
|
|
15
|
+
maxFontSize: number;
|
|
16
|
+
} | {
|
|
17
|
+
mode: 'fontSize';
|
|
18
|
+
fontSize: number;
|
|
19
|
+
} | {
|
|
20
|
+
mode: 'physicalSize';
|
|
21
|
+
physicalSize: PhysicalSize;
|
|
22
|
+
};
|
|
23
|
+
export interface FitTextToBoxOptions {
|
|
24
|
+
font: LoadedFont;
|
|
25
|
+
text: string;
|
|
26
|
+
boxDimensions: BoxDimensions;
|
|
27
|
+
size: FitSize;
|
|
28
|
+
spacing?: TextSpacing;
|
|
29
|
+
baseline?: BaselineType | BaselineConfig;
|
|
30
|
+
verticalAlignment?: VerticalTextAlignmentValues;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Which limit decided the outcome.
|
|
34
|
+
*
|
|
35
|
+
* - `width` — the box width, or the arc/custom path length for a non-flat baseline
|
|
36
|
+
* - `height` — the box height
|
|
37
|
+
* - `requestedSize` — the size the caller asked for, reached before the box
|
|
38
|
+
* mattered. Covers both hitting `maxFontSize` when solving and simply getting
|
|
39
|
+
* the pinned size that was requested.
|
|
40
|
+
*/
|
|
41
|
+
export type FitConstraint = 'width' | 'height' | 'requestedSize';
|
|
42
|
+
export interface FitTextToBoxResult {
|
|
43
|
+
fontSize: number;
|
|
44
|
+
/** False when the text cannot fit within the box even at minFontSize. */
|
|
45
|
+
fits: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* When `fits`, the limit that capped the size. When not, the limit that could
|
|
48
|
+
* not be satisfied.
|
|
49
|
+
*
|
|
50
|
+
* Callers need this to tell one failure from another: overflowing the width
|
|
51
|
+
* and overflowing the height call for different responses, and in the
|
|
52
|
+
* configuration engine they surface as different messages to the user.
|
|
53
|
+
*/
|
|
54
|
+
boundBy: FitConstraint;
|
|
55
|
+
}
|
|
56
|
+
export interface FitAndTruncateTextToBoxResult extends FitTextToBoxResult {
|
|
57
|
+
text: string;
|
|
58
|
+
truncated: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* How the text was shortened. Reported separately because dropping a line and
|
|
61
|
+
* trimming characters are different outcomes with different messages, and a
|
|
62
|
+
* single pass can do both — drop a line, then still need to trim.
|
|
63
|
+
*/
|
|
64
|
+
linesDropped: number;
|
|
65
|
+
charactersRemoved: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Calculate the font size at which `text` fills `boxDimensions` as closely
|
|
69
|
+
* as possible without overflowing, for any baseline shape. This replaces
|
|
70
|
+
* binary-searching for a fitting font size: for flat and custom baselines
|
|
71
|
+
* it's a direct O(1) calculation; for curved baselines it's a bounded
|
|
72
|
+
* numeric solve (see solveCurvedFit).
|
|
73
|
+
*
|
|
74
|
+
* `fits: false` means the text doesn't fit even at minFontSize — the caller
|
|
75
|
+
* (e.g. fitAndTruncateTextToBox) should either shorten the text or accept
|
|
76
|
+
* the overflow at minFontSize.
|
|
77
|
+
*/
|
|
78
|
+
export declare const getFontSizeToFitBox: (options: FitTextToBoxOptions) => FitTextToBoxResult;
|
|
79
|
+
/**
|
|
80
|
+
* Like getFontSizeToFitBox, but when text doesn't fit even at minFontSize,
|
|
81
|
+
* shortens it (dropping the last whole line first if there is more than
|
|
82
|
+
* one, otherwise trimming trailing characters) and retries until it fits
|
|
83
|
+
* or there's nothing left to remove. Mirrors CE's existing truncation UX —
|
|
84
|
+
* text lost this way is a caller/product concern, not a rendering one.
|
|
85
|
+
*/
|
|
86
|
+
export declare const fitAndTruncateTextToBox: (options: FitTextToBoxOptions) => FitAndTruncateTextToBoxResult;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LoadedFont } from '../loading';
|
|
2
|
+
import { ColourInfo, ColourMap, GlyphFill } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Get the unique colours used by a font's SVG glyphs.
|
|
5
|
+
*
|
|
6
|
+
* @param font - A loaded font with svgGlyphs populated
|
|
7
|
+
* @returns Array of unique hex colour strings found in the font's SVG glyphs
|
|
8
|
+
*/
|
|
9
|
+
export declare function getFontColours(font: LoadedFont): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Extract fill paths from SVG content with optional colour remapping.
|
|
12
|
+
*
|
|
13
|
+
* @param svgContent - Raw SVG string from the font's SVG table
|
|
14
|
+
* @param colourMap - Optional mapping of original colours to replacements
|
|
15
|
+
* @returns Array of GlyphFill objects
|
|
16
|
+
*/
|
|
17
|
+
export declare function extractFillsFromSVG(svgContent: string, colourMap?: ColourMap): GlyphFill[];
|
|
18
|
+
/**
|
|
19
|
+
* Apply colour map to remap a colour value.
|
|
20
|
+
*
|
|
21
|
+
* @param colour - Original colour hex string
|
|
22
|
+
* @param colourMap - Optional colour replacement mapping
|
|
23
|
+
* @returns ColourInfo with hex and optional reference
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyColourMap(colour: string, colourMap?: ColourMap): ColourInfo;
|
|
26
|
+
/**
|
|
27
|
+
* Extract the inner content from a raw SVG glyph string.
|
|
28
|
+
* Strips the XML declaration and outer <svg> wrapper, returning the inner elements.
|
|
29
|
+
*/
|
|
30
|
+
export declare function extractSvgGlyphContent(rawSvg: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Namespace all IDs in SVG content to prevent collisions when multiple
|
|
33
|
+
* glyphs are embedded in the same document. Prefixes all id attributes
|
|
34
|
+
* and updates all references (href, url(), clip-path, mask, filter).
|
|
35
|
+
*/
|
|
36
|
+
export declare function namespaceSvgIds(svgContent: string, prefix: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Remap colour values in raw SVG content. Replaces fill, stroke,
|
|
39
|
+
* and stop-color attribute values according to the colour map.
|
|
40
|
+
* Also handles elements without explicit fill that default to black.
|
|
41
|
+
*/
|
|
42
|
+
export declare function remapSvgColours(svgContent: string, colourMap: ColourMap): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { PlatformMatrix } from '../types';
|
|
2
|
+
export declare class Box {
|
|
3
|
+
corners: DOMPoint[];
|
|
4
|
+
x1: number;
|
|
5
|
+
y1: number;
|
|
6
|
+
x2: number;
|
|
7
|
+
y2: number;
|
|
8
|
+
_x3: number | undefined;
|
|
9
|
+
_y3: number | undefined;
|
|
10
|
+
_x4: number | undefined;
|
|
11
|
+
_y4: number | undefined;
|
|
12
|
+
get x3(): number;
|
|
13
|
+
get y3(): number;
|
|
14
|
+
get x4(): number;
|
|
15
|
+
get y4(): number;
|
|
16
|
+
constructor(x1: number, y1: number, x2: number, y2: number, x3?: number, y3?: number, x4?: number, y4?: number);
|
|
17
|
+
transform(matrix: PlatformMatrix): void;
|
|
18
|
+
toPointsArray(): number[][];
|
|
19
|
+
getBBox(): BBox;
|
|
20
|
+
}
|
|
21
|
+
export declare class BBox extends Box {
|
|
22
|
+
get x(): number;
|
|
23
|
+
get y(): number;
|
|
24
|
+
get width(): number;
|
|
25
|
+
get height(): number;
|
|
26
|
+
add(box: Box): void;
|
|
27
|
+
addPoint(x: number, y: number): void;
|
|
28
|
+
serialize(): {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class Point {
|
|
2
|
+
private x;
|
|
3
|
+
private y;
|
|
4
|
+
constructor(x: number, y: number);
|
|
5
|
+
get X(): number;
|
|
6
|
+
get Y(): number;
|
|
7
|
+
toSVGString(): string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Rotate a point about a pivot point
|
|
11
|
+
*
|
|
12
|
+
* @param point - the point to rotate
|
|
13
|
+
* @param rotate - the amount in degrees
|
|
14
|
+
* @param pivotPoint - the point around which to rotate
|
|
15
|
+
* @returns the new point
|
|
16
|
+
*/
|
|
17
|
+
export declare function rotatePoint(point: Point, rotate: number, pivotPoint?: Point): Point;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function escapeXML(str: string): string;
|