@vyaz/core 0.0.16 → 0.3.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 +35 -0
- package/bin/vyaz.js +27 -0
- package/dist/cli/check.d.ts +12 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +4077 -0
- package/dist/compile/ParagraphCompiler.d.ts +84 -0
- package/dist/compile/ParagraphCompiler.d.ts.map +1 -0
- package/dist/debug/lines-to-yaml.d.ts +14 -0
- package/dist/debug/lines-to-yaml.d.ts.map +1 -0
- package/dist/debug.d.ts +11 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +4 -0
- package/dist/index.browser.d.ts +11 -4
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +3244 -4669
- package/dist/index.d.ts +15 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5133 -811
- package/dist/layout/AutoFitEngine.d.ts.map +1 -1
- package/dist/layout/LineBoxValidator.d.ts +5 -10
- package/dist/layout/LineBoxValidator.d.ts.map +1 -1
- package/dist/layout/ParagraphLayoutEngine.d.ts +13 -8
- package/dist/layout/ParagraphLayoutEngine.d.ts.map +1 -1
- package/dist/layout/PositioningEngine.d.ts +1 -1
- package/dist/layout/PositioningEngine.d.ts.map +1 -1
- package/dist/layout/TableLayoutEngine.d.ts +174 -0
- package/dist/layout/TableLayoutEngine.d.ts.map +1 -0
- package/dist/layout/TextFrameLayoutEngine.d.ts +115 -16
- package/dist/layout/TextFrameLayoutEngine.d.ts.map +1 -1
- package/dist/layout/create-engine.d.ts +32 -0
- package/dist/layout/create-engine.d.ts.map +1 -0
- package/dist/layout/resolve-font.d.ts +25 -0
- package/dist/layout/resolve-font.d.ts.map +1 -0
- package/dist/measure/FontEngine.d.ts +44 -1
- package/dist/measure/FontEngine.d.ts.map +1 -1
- package/dist/measure/FontMetricsProvider.d.ts +3 -10
- package/dist/measure/FontMetricsProvider.d.ts.map +1 -1
- package/dist/measure/FontkitMeasureContext.d.ts +109 -0
- package/dist/measure/FontkitMeasureContext.d.ts.map +1 -0
- package/dist/measure/canvas-polyfill.d.ts.map +1 -1
- package/dist/types/Document.d.ts +73 -28
- package/dist/types/Document.d.ts.map +1 -1
- package/dist/types/FontTypes.d.ts +1 -1
- package/dist/types/FontTypes.d.ts.map +1 -1
- package/dist/types/LayoutTypes.d.ts +19 -2
- package/dist/types/LayoutTypes.d.ts.map +1 -1
- package/dist/types/TableTypes.d.ts +198 -0
- package/dist/types/TableTypes.d.ts.map +1 -0
- package/dist/utils/sides.d.ts +26 -0
- package/dist/utils/sides.d.ts.map +1 -0
- package/dist/utils/widths.d.ts +16 -0
- package/dist/utils/widths.d.ts.map +1 -0
- package/package.json +25 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoFitEngine.d.ts","sourceRoot":"","sources":["../../src/layout/AutoFitEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,GACZ,SAAS,
|
|
1
|
+
{"version":3,"file":"AutoFitEngine.d.ts","sourceRoot":"","sources":["../../src/layout/AutoFitEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,sBAAsB;AACtB,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAqB;AACrB,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,GACZ,SAAS,CAgBX;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACrE,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EAC/C,OAAO,CAAC,EAAE,cAAc,GACvB,aAAa,CAoCf"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LineBoxValidator.ts — invariant checks
|
|
2
|
+
* LineBoxValidator.ts — Parley-inspired line-box invariant checks.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* NO_OVERLAP, MONOTONIC_Y, INDEX_CONSIST, WIDTH_FIT, BASELINE_EQ
|
|
4
|
+
* Invariants: NO_OVERLAP, MONOTONIC_Y, INDEX_CONSIST, WIDTH_FIT, BASELINE_EQ.
|
|
6
5
|
*
|
|
7
|
-
* YAML
|
|
6
|
+
* YAML snapshot serialization lives in `../debug/lines-to-yaml.ts` (pulled in
|
|
7
|
+
* only through the `@vyaz/core/debug` entry, so `js-yaml` stays out of the
|
|
8
|
+
* production bundle).
|
|
8
9
|
*/
|
|
9
10
|
import type { Line } from '../types/LayoutTypes.js';
|
|
10
11
|
export interface InvariantError {
|
|
@@ -17,10 +18,4 @@ export interface InvariantError {
|
|
|
17
18
|
* Throws on first violation.
|
|
18
19
|
*/
|
|
19
20
|
export declare function assertLineInvariants(lines: Line[], originalText: string, maxWidth: number): void;
|
|
20
|
-
/**
|
|
21
|
-
* Convert Line[] to YAML string for snapshots.
|
|
22
|
-
* Only semantic data: text, x, width, style.
|
|
23
|
-
* No glyphAdvances, fontMetrics (noise), inlineWidget.
|
|
24
|
-
*/
|
|
25
|
-
export declare function linesToYAML(lines: Line[], paragraphWidth: number, paragraphHeight: number): string;
|
|
26
21
|
//# sourceMappingURL=LineBoxValidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineBoxValidator.d.ts","sourceRoot":"","sources":["../../src/layout/LineBoxValidator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"LineBoxValidator.d.ts","sourceRoot":"","sources":["../../src/layout/LineBoxValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAMpD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GACf,IAAI,CAqFN"}
|
|
@@ -3,21 +3,28 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Pipeline:
|
|
5
5
|
* Paragraph
|
|
6
|
-
* → compile (
|
|
6
|
+
* → compile (ParagraphCompiler)
|
|
7
7
|
* → prepareRichInline (pretext)
|
|
8
8
|
* → walkRichInlineLineRanges + materializeRichInlineLineRange (pretext)
|
|
9
9
|
* → positionLines (PositioningEngine)
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
|
+
* Line-box invariant checks live in `@vyaz/core/debug` (assertLineInvariants);
|
|
12
|
+
* they are not run on the layout hot path.
|
|
11
13
|
*
|
|
12
14
|
* Supports autofit via AutoFitEngine.findScale.
|
|
13
15
|
* Caches PreparedRichInline per paragraph key (Parley LayoutContext pattern).
|
|
14
16
|
*/
|
|
15
|
-
import '../measure/canvas-polyfill.js';
|
|
16
17
|
import type { Paragraph, ListStyle } from '../types/Document.js';
|
|
17
18
|
import type { IFontMetricsProvider } from '../types/FontTypes.js';
|
|
18
19
|
import type { ParagraphLayoutResult } from '../types/LayoutTypes.js';
|
|
20
|
+
import { type OnMissingFont } from './resolve-font.js';
|
|
19
21
|
export declare class ParagraphLayoutEngine {
|
|
22
|
+
/** LRU (Map insertion order) of PreparedRichInline keyed by {@link preparedCacheKey}. */
|
|
20
23
|
private preparedCache;
|
|
24
|
+
private readonly cacheMax;
|
|
25
|
+
constructor(cacheMax?: number);
|
|
26
|
+
/** Drop all cached prepared-line data (e.g. on document close). */
|
|
27
|
+
clearCache(): void;
|
|
21
28
|
/**
|
|
22
29
|
* Layout a single paragraph — basic variant.
|
|
23
30
|
*
|
|
@@ -26,12 +33,10 @@ export declare class ParagraphLayoutEngine {
|
|
|
26
33
|
* @param fontProvider — optional metrics provider (default: fontMetricsProvider)
|
|
27
34
|
* @returns ParagraphLayoutResult with Line[]
|
|
28
35
|
*/
|
|
29
|
-
layout(paragraph: Paragraph, maxWidth: number, yOffset?: number, fontProvider?: IFontMetricsProvider, listStyle?: ListStyle, listIndex?: number, listMarkerWidth?: number): ParagraphLayoutResult;
|
|
36
|
+
layout(paragraph: Paragraph, maxWidth: number, yOffset?: number, fontProvider?: IFontMetricsProvider, listStyle?: ListStyle, listIndex?: number, listMarkerWidth?: number, wantGlyphAdvances?: boolean, mode?: 'browser' | 'office', onMissingFont?: OnMissingFont): ParagraphLayoutResult;
|
|
30
37
|
/**
|
|
31
|
-
* Layout with per-glyph advance widths
|
|
32
|
-
*
|
|
33
|
-
* glyphAdvances are now filled by layout() automatically, so
|
|
34
|
-
* this method is equivalent to layout(). Kept for API compatibility.
|
|
38
|
+
* Layout with per-glyph advance widths filled on every text span
|
|
39
|
+
* (SVG "glyph" preset, caret hit-testing).
|
|
35
40
|
*/
|
|
36
41
|
layoutGlyph(paragraph: Paragraph, maxWidth: number, yOffset?: number): ParagraphLayoutResult;
|
|
37
42
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParagraphLayoutEngine.d.ts","sourceRoot":"","sources":["../../src/layout/ParagraphLayoutEngine.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ParagraphLayoutEngine.d.ts","sourceRoot":"","sources":["../../src/layout/ParagraphLayoutEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAQrE,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAyG1E,qBAAa,qBAAqB;IAChC,yFAAyF;IACzF,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,QAAQ,GAAE,MAAmC;IAIzD,mEAAmE;IACnE,UAAU,IAAI,IAAI;IAIlB;;;;;;;OAOG;IACH,MAAM,CACJ,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAU,EACnB,YAAY,CAAC,EAAE,oBAAoB,EACnC,SAAS,CAAC,EAAE,SAAS,EACrB,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,EACxB,iBAAiB,GAAE,OAAe,EAClC,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,EAC3B,aAAa,GAAE,aAAuB,GACrC,qBAAqB;IAmLxB;;;OAGG;IACH,WAAW,CACT,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAU,GAClB,qBAAqB;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;CAoC7B;AAED,gBAAgB;AAChB,eAAO,MAAM,qBAAqB,EAAE,qBAAmD,CAAC"}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import type { ParagraphStyle, ListStyle } from '../types/Document.js';
|
|
19
19
|
import type { FontMetrics } from '../types/FontTypes.js';
|
|
20
20
|
import type { Line } from '../types/LayoutTypes.js';
|
|
21
|
-
import type { PreparedRichInlineItem } from '../compile/
|
|
21
|
+
import type { PreparedRichInlineItem } from '../compile/ParagraphCompiler.js';
|
|
22
22
|
interface PretextFragment {
|
|
23
23
|
itemIndex: number;
|
|
24
24
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PositioningEngine.d.ts","sourceRoot":"","sources":["../../src/layout/PositioningEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAyB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"PositioningEngine.d.ts","sourceRoot":"","sources":["../../src/layout/PositioningEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAyB,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAK9E,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,GAAG,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAED,UAAU,WAAW;IACnB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAmDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,WAAW,EAAE,EAC3B,KAAK,EAAE,sBAAsB,EAAE,EAC/B,aAAa,EAAE,CAAC,IAAI,EAAE,sBAAsB,KAAK,WAAW,EAC5D,KAAK,EAAE,cAAc,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,YAAI,EAClB,IAAI,EAAE,SAAS,GAAG,QAAQ,YAAY,EACtC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,MAAM,EACrH,GAAG,CAAC,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,SAAS,EACrB,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB;IAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAohBzC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TableLayoutEngine.ts — TableFrame → positioned grid.
|
|
3
|
+
*
|
|
4
|
+
* Column widths and row heights are *measured*, not required from the caller
|
|
5
|
+
* (unlike svg-table-core, whose `calculateRows` takes them as input — see
|
|
6
|
+
* TableTypes.ts header): each cell's `TextFrame` content is laid out twice —
|
|
7
|
+
* once unconstrained to get its natural width, once at the final column width
|
|
8
|
+
* to get its wrapped height.
|
|
9
|
+
*
|
|
10
|
+
* Pipeline:
|
|
11
|
+
* 1. placeCells — colSpan/rowSpan → each cell's (startRow, startCol),
|
|
12
|
+
* borrowing svg-table-core's "occupied slot" idea
|
|
13
|
+
* (calculateRows' insertIgnoredCell), done natively.
|
|
14
|
+
* 2. column widths — span-1 cells set the per-column max; span>N cells only
|
|
15
|
+
* *widen* their spanned columns, evenly, if their own
|
|
16
|
+
* natural width doesn't already fit (never shrink).
|
|
17
|
+
* 3. per-cell content — laid out once at its final (possibly multi-column)
|
|
18
|
+
* width, inset by padding *and* border width (border-box
|
|
19
|
+
* model — a border never overlaps the text); same
|
|
20
|
+
* deficit-widen rule for row heights and rowSpan cells.
|
|
21
|
+
* 4. position — column/row offsets accumulated from final sizes.
|
|
22
|
+
*
|
|
23
|
+
* `table.width`/`table.height` (both optional) scale the *final* colWidths/
|
|
24
|
+
* rowHeights arrays proportionally to fit, applied after whichever source
|
|
25
|
+
* produced them (measured or an explicit `columnWidths`/`rowHeights`
|
|
26
|
+
* override) — symmetric, but width-shrink reflows text via wrapping while
|
|
27
|
+
* height-shrink has no equivalent and simply overflows the row.
|
|
28
|
+
*
|
|
29
|
+
* Border dash patterns (`borderPatterns`) and per-side `stroke-linecap`
|
|
30
|
+
* (`borderShapes`) resolve here (`resolveBorder`) but paint in
|
|
31
|
+
* `@vyaz/renderer`'s `TableRenderer.ts` (`borderMarkup`) — this engine only
|
|
32
|
+
* produces the resolved per-side values. Asymmetric corner radii (only a
|
|
33
|
+
* uniform `rx`/`ry` today) remain a possible future addition.
|
|
34
|
+
*
|
|
35
|
+
* Nested tables: `TableCell.content` can be a `TableFrame` instead of a
|
|
36
|
+
* `TextFrame` (`isNestedTable`). Both the natural-width pass and the final
|
|
37
|
+
* layout pass then call `layoutTableFrame` recursively instead of
|
|
38
|
+
* `layoutTextFrame` — meaning a nested cell's own two-pass layout happens
|
|
39
|
+
* *twice* (once per outer pass), so cost roughly doubles per nesting depth.
|
|
40
|
+
* The nested `TableLayoutResult` is exposed as `TableCellLayoutResult.
|
|
41
|
+
* nestedTable`; `content` still gets a placeholder `TextFrameLayoutResult`
|
|
42
|
+
* (zero lines, sized to the nested table) so every existing consumer that
|
|
43
|
+
* reads cell dimensions off `content.content.{width,height}` keeps working
|
|
44
|
+
* unchanged — `TableRenderer.ts` checks `nestedTable` first and renders that
|
|
45
|
+
* instead of `content` when present. `_depth` is an internal recursion
|
|
46
|
+
* counter (not meant to be set by callers) — past 50 levels this throws
|
|
47
|
+
* instead of hanging, on the assumption that's a cyclic/pathological input,
|
|
48
|
+
* not a real document.
|
|
49
|
+
*/
|
|
50
|
+
import type { TableFrame, BorderLineCap } from '../types/TableTypes.js';
|
|
51
|
+
import type { TextFrameLayoutResult } from './TextFrameLayoutEngine.js';
|
|
52
|
+
import { type Side } from '../utils/sides.js';
|
|
53
|
+
/** A resolved, ready-to-paint border. Absent when every side's width is `0`. */
|
|
54
|
+
export interface ResolvedBorder {
|
|
55
|
+
widths: Record<Side, number>;
|
|
56
|
+
colors: Record<Side, string>;
|
|
57
|
+
/** Present only when at least one side has a non-empty dash pattern. */
|
|
58
|
+
patterns?: Record<Side, number[] | undefined>;
|
|
59
|
+
/** Present only when `borderShapes` was set anywhere in the style cascade. */
|
|
60
|
+
shapes?: Record<Side, BorderLineCap>;
|
|
61
|
+
/** Present only when `rx`/`ry` was set anywhere in the style cascade. */
|
|
62
|
+
rx?: number;
|
|
63
|
+
ry?: number;
|
|
64
|
+
}
|
|
65
|
+
export interface TableCellLayoutResult {
|
|
66
|
+
/** Absolute X of the cell box (border-box) within the table. */
|
|
67
|
+
x: number;
|
|
68
|
+
/** Absolute Y of the cell box within the table. */
|
|
69
|
+
y: number;
|
|
70
|
+
/** Full box width — sums every spanned column + the gaps between them. */
|
|
71
|
+
width: number;
|
|
72
|
+
/** Full box height — sums every spanned row + the gaps between them. */
|
|
73
|
+
height: number;
|
|
74
|
+
/** Resolved padding box (inside the border, if any). */
|
|
75
|
+
padding: {
|
|
76
|
+
top: number;
|
|
77
|
+
right: number;
|
|
78
|
+
bottom: number;
|
|
79
|
+
left: number;
|
|
80
|
+
};
|
|
81
|
+
/** Extra Y offset inside the padding box from `verticalAlign` (0 for `'top'`). */
|
|
82
|
+
verticalOffset: number;
|
|
83
|
+
/** `TableCellStyle.cx`/`cy` — an additional px nudge on top of padding/alignment. Default `0`. */
|
|
84
|
+
cx: number;
|
|
85
|
+
/** @see cx */
|
|
86
|
+
cy: number;
|
|
87
|
+
/** `TableCellStyle.allowOverflow` — let content paint past the cell's padding box. Default `false`. */
|
|
88
|
+
allowOverflow: boolean;
|
|
89
|
+
bgColor?: string;
|
|
90
|
+
border?: ResolvedBorder;
|
|
91
|
+
/**
|
|
92
|
+
* The cell's laid-out content — same shape a lone `TextFrame` produces.
|
|
93
|
+
* When `TableCell.content` was a `TableFrame` (see `nestedTable`), this is
|
|
94
|
+
* a zero-line placeholder sized to match it — a renderer should check
|
|
95
|
+
* `nestedTable` first and use that instead of painting `content` as text.
|
|
96
|
+
*/
|
|
97
|
+
content: TextFrameLayoutResult;
|
|
98
|
+
/**
|
|
99
|
+
* Present when `TableCell.content` was a `TableFrame` — a table nested
|
|
100
|
+
* inside this cell, already laid out at the cell's own content width.
|
|
101
|
+
* `content` (above) is a same-sized placeholder in this case, not real
|
|
102
|
+
* text — paint this instead.
|
|
103
|
+
*/
|
|
104
|
+
nestedTable?: TableLayoutResult;
|
|
105
|
+
/**
|
|
106
|
+
* `TableCell.before`, laid out unwrapped at its own natural size and
|
|
107
|
+
* positioned absolute-within-the-table, already vertically centered.
|
|
108
|
+
* Absent when the cell has no `before`.
|
|
109
|
+
*/
|
|
110
|
+
before?: {
|
|
111
|
+
content: TextFrameLayoutResult;
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
};
|
|
115
|
+
/** @see before — from `TableCell.after`, right-anchored instead. */
|
|
116
|
+
after?: {
|
|
117
|
+
content: TextFrameLayoutResult;
|
|
118
|
+
x: number;
|
|
119
|
+
y: number;
|
|
120
|
+
};
|
|
121
|
+
/** Columns this cell occupies (>1 for `colSpan`). */
|
|
122
|
+
colSpan: number;
|
|
123
|
+
/** Rows this cell occupies (>1 for `rowSpan`). */
|
|
124
|
+
rowSpan: number;
|
|
125
|
+
}
|
|
126
|
+
export interface TableRowLayoutResult {
|
|
127
|
+
y: number;
|
|
128
|
+
height: number;
|
|
129
|
+
bgColor?: string;
|
|
130
|
+
border?: ResolvedBorder;
|
|
131
|
+
/** Only cells that *start* in this row (a rowSpan cell from above is not repeated here). */
|
|
132
|
+
cells: TableCellLayoutResult[];
|
|
133
|
+
}
|
|
134
|
+
export interface TableLayoutResult {
|
|
135
|
+
/** Full outer box width, margins included. */
|
|
136
|
+
width: number;
|
|
137
|
+
/** Full outer box height, margins included. */
|
|
138
|
+
height: number;
|
|
139
|
+
bgColor?: string;
|
|
140
|
+
/** The table's own outer border (`TableStyle`), distinct from row/cell borders. */
|
|
141
|
+
border?: ResolvedBorder;
|
|
142
|
+
/**
|
|
143
|
+
* The border-box — the outer box with `TableStyle.margins` excluded. Rows
|
|
144
|
+
* span its full width; `border` (above) is drawn at this box. A renderer
|
|
145
|
+
* uses it directly instead of re-deriving margins from row/cell positions.
|
|
146
|
+
*/
|
|
147
|
+
contentBox: {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
width: number;
|
|
151
|
+
height: number;
|
|
152
|
+
};
|
|
153
|
+
rows: TableRowLayoutResult[];
|
|
154
|
+
}
|
|
155
|
+
export interface TableLayoutOptions {
|
|
156
|
+
mode?: 'browser' | 'office';
|
|
157
|
+
/**
|
|
158
|
+
* What to do when a cell's `fontFamily` isn't registered — forwarded to
|
|
159
|
+
* every cell's own `layoutTextFrame` call. `'throw'` (default) raises
|
|
160
|
+
* `FontNotFoundError`; `'substitute'` uses any registered family and folds
|
|
161
|
+
* the cell's own warnings into the table's (none surfaced directly here —
|
|
162
|
+
* a caller wanting them should lay out a cell's `TextFrame` itself).
|
|
163
|
+
*/
|
|
164
|
+
onMissingFont?: 'throw' | 'substitute';
|
|
165
|
+
/**
|
|
166
|
+
* Internal nested-table recursion counter — do not set this yourself.
|
|
167
|
+
* `layoutTableFrame` increments it on every recursive call (a `TableCell`
|
|
168
|
+
* whose `content` is itself a `TableFrame`) and throws past 50 levels.
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
_depth?: number;
|
|
172
|
+
}
|
|
173
|
+
export declare function layoutTableFrame(table: TableFrame, options?: TableLayoutOptions): TableLayoutResult;
|
|
174
|
+
//# sourceMappingURL=TableLayoutEngine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableLayoutEngine.d.ts","sourceRoot":"","sources":["../../src/layout/TableLayoutEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* 4. If frame.height is set, lines overflow to next column when colHeight exceeded
|
|
21
21
|
* 5. If no frame.height, columns are infinite (all lines stay in column 0)
|
|
22
22
|
*/
|
|
23
|
-
import type { TextFrame } from '../types/Document.js';
|
|
24
|
-
import type { Line } from '../types/LayoutTypes.js';
|
|
23
|
+
import type { TextFrame, WritingMode } from '../types/Document.js';
|
|
24
|
+
import type { Line, LayoutWarning } from '../types/LayoutTypes.js';
|
|
25
|
+
import { ParagraphLayoutEngine } from './ParagraphLayoutEngine.js';
|
|
25
26
|
/**
|
|
26
27
|
* Result of laying out a full TextFrame.
|
|
27
28
|
*
|
|
@@ -31,21 +32,119 @@ import type { Line } from '../types/LayoutTypes.js';
|
|
|
31
32
|
*/
|
|
32
33
|
export interface TextFrameLayoutResult {
|
|
33
34
|
lines: Line[];
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
|
|
35
|
+
/** Intrinsic content box — the text bounding box. */
|
|
36
|
+
content: {
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
};
|
|
40
|
+
/** Frame box as given on the input; an axis is omitted when its size was not set. */
|
|
41
|
+
frame: {
|
|
42
|
+
width?: number;
|
|
43
|
+
height?: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Whether content spills past the frame on each axis. `false` for an axis
|
|
47
|
+
* with no frame size. Use it to decide auto-grow vs clip vs autofit.
|
|
48
|
+
*/
|
|
49
|
+
overflow: {
|
|
50
|
+
horizontal: boolean;
|
|
51
|
+
vertical: boolean;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Which size a renderer should use per axis: `'frame'` when a frame size was
|
|
55
|
+
* provided, otherwise `'content'`.
|
|
56
|
+
*/
|
|
57
|
+
fit: {
|
|
58
|
+
horizontal: 'frame' | 'content';
|
|
59
|
+
vertical: 'frame' | 'content';
|
|
60
|
+
};
|
|
61
|
+
/** Present when autofit ran — the scale applied and whether it bottomed out. */
|
|
62
|
+
autofit?: AutofitOutcome;
|
|
63
|
+
/**
|
|
64
|
+
* Block flow direction this layout was produced for — echoes
|
|
65
|
+
* `TextFrame.writingMode`, defaulting to `'horizontal-tb'`.
|
|
66
|
+
*/
|
|
67
|
+
writingMode: WritingMode;
|
|
68
|
+
/**
|
|
69
|
+
* Post-layout rigid transform to realise `writingMode: 'sideways-*'` and/or
|
|
70
|
+
* `TextFrame.rotation`. Omitted when the net rotation is a multiple of 360°
|
|
71
|
+
* (nothing to apply). `lines`, `content` bbox aside, live in pre-rotation
|
|
72
|
+
* layout space; `content` / `overflow` are reported in **visual** space.
|
|
73
|
+
*/
|
|
74
|
+
transform?: FrameTransform;
|
|
75
|
+
/** Non-fatal issues (font fallback / substitution). Omitted when empty. */
|
|
76
|
+
warnings?: LayoutWarning[];
|
|
46
77
|
}
|
|
47
78
|
/**
|
|
48
|
-
*
|
|
79
|
+
* Rigid transform a renderer applies to {@link TextFrameLayoutResult.lines} so a
|
|
80
|
+
* `sideways-*` writing mode or an explicit `rotation` takes visual effect. The
|
|
81
|
+
* layout math itself (line breaking, measuring, positioning) is unchanged.
|
|
49
82
|
*/
|
|
50
|
-
export
|
|
83
|
+
export interface FrameTransform {
|
|
84
|
+
/** Net clockwise rotation in degrees, normalised to `[0, 360)`. */
|
|
85
|
+
rotate: number;
|
|
86
|
+
/**
|
|
87
|
+
* The box `lines` occupy in their own pre-rotation coordinate space. The
|
|
88
|
+
* renderer rotates this box about its centre; for `rotate` of 90 / 270 the
|
|
89
|
+
* visible canvas is this box with width and height swapped.
|
|
90
|
+
*/
|
|
91
|
+
layoutBox: {
|
|
92
|
+
width: number;
|
|
93
|
+
height: number;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Options for {@link layoutTextFrame}. */
|
|
97
|
+
export interface LayoutOptions {
|
|
98
|
+
/**
|
|
99
|
+
* Fill `Span.glyphAdvances` on every text span. Needed only by the SVG
|
|
100
|
+
* `glyph` preset and by caret hit-testing; off by default because it costs
|
|
101
|
+
* O(chars) font lookups + allocation on every layout.
|
|
102
|
+
*/
|
|
103
|
+
glyphAdvances?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Metric mode for this layout, overriding the provider's global mode:
|
|
106
|
+
* - `'browser'` (default) — CSS/Chrome line-box, hhea ascent/descent
|
|
107
|
+
* - `'office'` — PowerPoint/DrawingML line-box, OS/2 winAscent/winDescent
|
|
108
|
+
*/
|
|
109
|
+
mode?: 'browser' | 'office';
|
|
110
|
+
/**
|
|
111
|
+
* Shrink every run's `fontSize` proportionally until the content fits the
|
|
112
|
+
* frame box. `true` uses defaults; an object bounds the minimum size.
|
|
113
|
+
* The chosen scale is reported on `result.autofit`.
|
|
114
|
+
*/
|
|
115
|
+
autofit?: boolean | {
|
|
116
|
+
minFontSize?: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* What to do when none of a run's `fontFamily` entries are registered:
|
|
120
|
+
* - `'throw'` (default) — raise `FontNotFoundError`
|
|
121
|
+
* - `'substitute'` — use any registered family and add a `result.warnings`
|
|
122
|
+
* entry instead of failing
|
|
123
|
+
*/
|
|
124
|
+
onMissingFont?: 'throw' | 'substitute';
|
|
125
|
+
/**
|
|
126
|
+
* Measure widths through fontkit's `layout()` — GPOS kerning + GSUB ligatures,
|
|
127
|
+
* i.e. what a browser paints — instead of the default per-code-point advance
|
|
128
|
+
* sum. Applies to line breaking and positioning for this call only. Leave off
|
|
129
|
+
* unless the output is consumed by a browser (SVG `browser` preset).
|
|
130
|
+
*/
|
|
131
|
+
shaping?: boolean;
|
|
132
|
+
}
|
|
133
|
+
/** Autofit outcome, present on the result when {@link LayoutOptions.autofit} was set. */
|
|
134
|
+
export interface AutofitOutcome {
|
|
135
|
+
/** Proportional font-size scale applied (1 = no shrink). */
|
|
136
|
+
scale: number;
|
|
137
|
+
/** True when the min-size floor was hit and content still overflows. */
|
|
138
|
+
clampedToMin: boolean;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Layout a full TextFrame (paragraphs stacked with Y-offset accumulation).
|
|
142
|
+
*
|
|
143
|
+
* Uses a shared default engine with its own bounded prepared-line cache. For
|
|
144
|
+
* isolation, an explicit cache bound, or `clearCache()`, make your own via
|
|
145
|
+
* {@link createLayoutEngine}.
|
|
146
|
+
*/
|
|
147
|
+
export declare function layoutTextFrame(frame: TextFrame, options?: LayoutOptions): TextFrameLayoutResult;
|
|
148
|
+
/** @internal Shared implementation, parameterised by the engine instance. */
|
|
149
|
+
export declare function runFlow(frame: TextFrame, options: LayoutOptions, engine: ParagraphLayoutEngine): TextFrameLayoutResult;
|
|
51
150
|
//# sourceMappingURL=TextFrameLayoutEngine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextFrameLayoutEngine.d.ts","sourceRoot":"","sources":["../../src/layout/TextFrameLayoutEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,SAAS,EAA2C,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"TextFrameLayoutEngine.d.ts","sourceRoot":"","sources":["../../src/layout/TextFrameLayoutEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,SAAS,EAA2C,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC5G,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAyB,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAM1F;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,qDAAqD;IACrD,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,qFAAqF;IACrF,KAAK,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C;;;OAGG;IACH,QAAQ,EAAE;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACrD;;;OAGG;IACH,GAAG,EAAE;QAAE,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;QAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;KAAE,CAAC;IACxE,gFAAgF;IAChF,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB;;;OAGG;IACH,WAAW,EAAE,WAAW,CAAC;IACzB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAyED,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IACvC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,yFAAyF;AACzF,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,aAAkB,GAAG,qBAAqB,CAEpG;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CACrB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,qBAAqB,GAC5B,qBAAqB,CAoVvB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* create-engine.ts — a layout engine you own.
|
|
3
|
+
*
|
|
4
|
+
* `layoutTextFrame` is a convenience wrapper over a shared default engine. When
|
|
5
|
+
* you need isolation (a per-document or per-request cache), an explicit cache
|
|
6
|
+
* bound, or the ability to drop the cache, create your own:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const engine = createLayoutEngine({ cache: { max: 1024 } });
|
|
10
|
+
* const result = engine.layout(frame);
|
|
11
|
+
* engine.clearCache(); // e.g. on document close
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
import type { TextFrame } from '../types/Document.js';
|
|
15
|
+
import type { LayoutOptions, TextFrameLayoutResult } from './TextFrameLayoutEngine.js';
|
|
16
|
+
/** Configuration for {@link createLayoutEngine}. */
|
|
17
|
+
export interface LayoutEngineOptions {
|
|
18
|
+
/** Prepared-line cache bound (LRU entries). Default 4096. */
|
|
19
|
+
cache?: {
|
|
20
|
+
max?: number;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** A layout engine with its own prepared-line cache. */
|
|
24
|
+
export interface LayoutEngine {
|
|
25
|
+
/** Lay out a full text frame. Same result shape as {@link layoutTextFrame}. */
|
|
26
|
+
layout(frame: TextFrame, options?: LayoutOptions): TextFrameLayoutResult;
|
|
27
|
+
/** Drop all cached prepared-line data. */
|
|
28
|
+
clearCache(): void;
|
|
29
|
+
}
|
|
30
|
+
/** Create a layout engine with an isolated, bounded prepared-line cache. */
|
|
31
|
+
export declare function createLayoutEngine(options?: LayoutEngineOptions): LayoutEngine;
|
|
32
|
+
//# sourceMappingURL=create-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-engine.d.ts","sourceRoot":"","sources":["../../src/layout/create-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEvF,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,KAAK,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,qBAAqB,CAAC;IACzE,0CAA0C;IAC1C,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY,CAMlF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* resolve-font.ts — turn a `fontFamily` (single name or CSS-style fallback
|
|
3
|
+
* list) into one concrete registered family, per the `onMissingFont` policy.
|
|
4
|
+
*
|
|
5
|
+
* Everything downstream (positioning, rendering) sees a plain string.
|
|
6
|
+
*/
|
|
7
|
+
import type { FontFace } from '../measure/FontEngine.js';
|
|
8
|
+
import type { LayoutWarning } from '../types/LayoutTypes.js';
|
|
9
|
+
/** How to react when none of a run's requested families are registered. */
|
|
10
|
+
export type OnMissingFont = 'throw' | 'substitute';
|
|
11
|
+
/** Minimal provider surface this module needs. */
|
|
12
|
+
export interface FontResolverLike {
|
|
13
|
+
getFont(family: string, weight?: string, style?: string): FontFace | undefined;
|
|
14
|
+
getRegisteredFamilies(): string[];
|
|
15
|
+
}
|
|
16
|
+
export interface ResolvedFamily {
|
|
17
|
+
family: string;
|
|
18
|
+
warning: Omit<LayoutWarning, 'runIndex'> | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @param family run's `fontFamily`: a name, or a fallback list
|
|
22
|
+
* @param onMissing policy when nothing matches (default `'throw'`)
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveFontFamily(provider: FontResolverLike, family: string | string[], weight: string, style: string, onMissing?: OnMissingFont): ResolvedFamily;
|
|
25
|
+
//# sourceMappingURL=resolve-font.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-font.d.ts","sourceRoot":"","sources":["../../src/layout/resolve-font.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,YAAY,CAAC;AAEnD,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC/E,qBAAqB,IAAI,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,aAAuB,GACjC,cAAc,CAqBhB"}
|
|
@@ -11,6 +11,15 @@
|
|
|
11
11
|
* is removed (or when the import is not blocked by stubs).
|
|
12
12
|
*/
|
|
13
13
|
import type { FontMetrics } from '../types/FontTypes.js';
|
|
14
|
+
/**
|
|
15
|
+
* Factor used when a glyph is not present in the font.
|
|
16
|
+
* Multiplied by fontSize to estimate the missing glyph's advance.
|
|
17
|
+
*
|
|
18
|
+
* Lives here, in the fontkit facade, so every measurement path can share one
|
|
19
|
+
* definition without importing FontMetricsProvider (which installs globals as
|
|
20
|
+
* an import side effect).
|
|
21
|
+
*/
|
|
22
|
+
export declare const MISSING_GLYPH_FACTOR = 0.5;
|
|
14
23
|
/** Opaque font face handle returned by FontEngine.create() */
|
|
15
24
|
export interface FontFace {
|
|
16
25
|
/** fontkit font object (private — not meant for direct access) */
|
|
@@ -27,9 +36,43 @@ export interface FontFace {
|
|
|
27
36
|
* Create a font face from a binary buffer.
|
|
28
37
|
*
|
|
29
38
|
* @param buffer Font file bytes (ArrayBuffer in browser, Uint8Array/Buffer in Node.js)
|
|
39
|
+
* @param opts.variation For a variable font, axis values to instance before use
|
|
40
|
+
* (e.g. `{ wght: 700, wdth: 100 }`). Ignored when the font has no axes. Every
|
|
41
|
+
* downstream call — `glyphForCodePoint`, `layout`, metric extraction — then
|
|
42
|
+
* sees the instanced master, matching what a browser renders for that weight.
|
|
30
43
|
* @returns Opaque FontFace handle
|
|
31
44
|
*/
|
|
32
|
-
export declare function createFontFace(buffer: ArrayBuffer | Uint8Array
|
|
45
|
+
export declare function createFontFace(buffer: ArrayBuffer | Uint8Array, opts?: {
|
|
46
|
+
variation?: Record<string, number>;
|
|
47
|
+
}): Promise<FontFace>;
|
|
48
|
+
/** One shaped glyph: its id and its post-GPOS advance / offset, in font units. */
|
|
49
|
+
export interface ShapedGlyph {
|
|
50
|
+
glyphId: number;
|
|
51
|
+
xAdvance: number;
|
|
52
|
+
xOffset: number;
|
|
53
|
+
}
|
|
54
|
+
/** Result of {@link shapeRun}: total advance + per-glyph detail, in font units. */
|
|
55
|
+
export interface ShapedRun {
|
|
56
|
+
/** Sum of every glyph's xAdvance after kerning / ligature substitution. */
|
|
57
|
+
advanceWidth: number;
|
|
58
|
+
glyphs: ShapedGlyph[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Shape `text` through fontkit's OpenType layout engine — the same GPOS kerning
|
|
62
|
+
* and GSUB substitutions (`liga`, `clig`, `calt`, `ccmp`) a browser applies by
|
|
63
|
+
* default. Use this instead of summing {@link getGlyphAdvance} when the measured
|
|
64
|
+
* width has to line up with what the browser will actually paint.
|
|
65
|
+
*
|
|
66
|
+
* Widths are in font units; multiply by `fontSize / unitsPerEm`.
|
|
67
|
+
*
|
|
68
|
+
* @param opts.features OpenType feature overrides, e.g. `{ liga: false }` to
|
|
69
|
+
* emulate `text-rendering: optimizeSpeed`. Omit for browser-default behaviour.
|
|
70
|
+
*/
|
|
71
|
+
export declare function shapeRun(font: FontFace, text: string, opts?: {
|
|
72
|
+
features?: Record<string, boolean>;
|
|
73
|
+
script?: string;
|
|
74
|
+
language?: string;
|
|
75
|
+
}): ShapedRun;
|
|
33
76
|
/**
|
|
34
77
|
* Get the advance width (in font units) for a single code point.
|
|
35
78
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontEngine.d.ts","sourceRoot":"","sources":["../../src/measure/FontEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"FontEngine.d.ts","sourceRoot":"","sources":["../../src/measure/FontEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAKxC,8DAA8D;AAC9D,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;IACnB,kDAAkD;IAClD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAkDD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,GAAG,UAAU,EAChC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC5C,OAAO,CAAC,QAAQ,CAAC,CAWnB;AAID,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,mFAAmF;AACnF,MAAM,WAAW,SAAS;IACxB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAChF,SAAS,CAYX;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,WAAW,CAqB7G;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO9D"}
|
|
@@ -14,11 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { FontMetrics, IFontMetricsProvider } from '../types/FontTypes.js';
|
|
16
16
|
import type { FontFace } from './FontEngine.js';
|
|
17
|
-
|
|
18
|
-
* Factor used when a glyph is not found in the font.
|
|
19
|
-
* Multiplied by fontSize to estimate the missing glyph width.
|
|
20
|
-
*/
|
|
21
|
-
export declare const MISSING_GLYPH_FACTOR = 0.5;
|
|
17
|
+
export { MISSING_GLYPH_FACTOR } from './FontEngine.js';
|
|
22
18
|
/**
|
|
23
19
|
* Font metrics provider — registers, resolves, and measures fonts.
|
|
24
20
|
*
|
|
@@ -58,10 +54,6 @@ export declare class FontMetricsProvider implements IFontMetricsProvider {
|
|
|
58
54
|
setMode(mode: 'browser' | 'office'): void;
|
|
59
55
|
/** Get current measurement mode. */
|
|
60
56
|
getMode(): 'browser' | 'office';
|
|
61
|
-
/**
|
|
62
|
-
* @internal Flatten the nested registry for office mode.
|
|
63
|
-
*/
|
|
64
|
-
private _flattenCache;
|
|
65
57
|
/**
|
|
66
58
|
* Register a binary font for use with fontkit.
|
|
67
59
|
*
|
|
@@ -75,6 +67,7 @@ export declare class FontMetricsProvider implements IFontMetricsProvider {
|
|
|
75
67
|
registerFont(family: string, options: {
|
|
76
68
|
weight?: string;
|
|
77
69
|
style?: string;
|
|
70
|
+
variation?: Record<string, number>;
|
|
78
71
|
}, source: string | ArrayBuffer | Uint8Array, sourcePath?: string): Promise<void>;
|
|
79
72
|
/** @internal Internal registration logic */
|
|
80
73
|
private _registerFontInternal;
|
|
@@ -117,7 +110,7 @@ export declare class FontMetricsProvider implements IFontMetricsProvider {
|
|
|
117
110
|
*
|
|
118
111
|
* @throws FontNotFoundError when font is neither registered nor available via Canvas
|
|
119
112
|
*/
|
|
120
|
-
getMetrics(fontFamily: string, fontSize: number, weight?: string, style?: string): FontMetrics;
|
|
113
|
+
getMetrics(fontFamily: string, fontSize: number, weight?: string, style?: string, mode?: 'browser' | 'office'): FontMetrics;
|
|
121
114
|
}
|
|
122
115
|
/** Singleton */
|
|
123
116
|
export declare const fontMetricsProvider: FontMetricsProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontMetricsProvider.d.ts","sourceRoot":"","sources":["../../src/measure/FontMetricsProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"FontMetricsProvider.d.ts","sourceRoot":"","sources":["../../src/measure/FontMetricsProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAQhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAyEvD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,YAAW,oBAAoB;IAC9D,gEAAgE;IAChE,OAAO,CAAC,QAAQ,CAA4C;IAE5D,gEAAgE;IAChE,OAAO,CAAC,YAAY,CAAkC;IAEtD,gBAAgB;IAChB,OAAO,CAAC,IAAI,CAAmC;IAE/C,qFAAqF;IACrF,OAAO,CAAC,oBAAoB,CAA4B;IAExD,2EAA2E;IAC3E,OAAO,CAAC,cAAc,CAAoD;IAC1E,gBAAgB;IAChB,OAAO,CAAC,WAAW,CAA6E;IAEhG,wDAAwD;IACxD,OAAO,CAAC,kBAAkB;IAe1B;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,GAAG,IAAI;IASzC,oCAAoC;IACpC,OAAO,IAAI,SAAS,GAAG,QAAQ;IAM/B;;;;;;;;;OASG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,EAChF,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,EACzC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAUhB,4CAA4C;YAC9B,qBAAqB;IAmCnC;;;;;OAKG;IACG,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlD;;;;OAIG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAIjC;;;;;OAKG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAO3C;;;OAGG;IACH,OAAO,CACL,MAAM,EAAE,MAAM,EACd,MAAM,SAAW,EACjB,KAAK,SAAW,GACf,QAAQ,GAAG,SAAS;IAMvB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAsEpB;;;;;;;;OAQG;IACH,UAAU,CACR,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,SAAW,EACjB,KAAK,SAAW,EAChB,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,GAC1B,WAAW;CAgFf;AAED,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,EAAE,mBAA+C,CAAC"}
|