@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.
Files changed (53) hide show
  1. package/README.md +35 -0
  2. package/bin/vyaz.js +27 -0
  3. package/dist/cli/check.d.ts +12 -0
  4. package/dist/cli/check.d.ts.map +1 -0
  5. package/dist/cli/check.js +4077 -0
  6. package/dist/compile/ParagraphCompiler.d.ts +84 -0
  7. package/dist/compile/ParagraphCompiler.d.ts.map +1 -0
  8. package/dist/debug/lines-to-yaml.d.ts +14 -0
  9. package/dist/debug/lines-to-yaml.d.ts.map +1 -0
  10. package/dist/debug.d.ts +11 -0
  11. package/dist/debug.d.ts.map +1 -0
  12. package/dist/debug.js +4 -0
  13. package/dist/index.browser.d.ts +11 -4
  14. package/dist/index.browser.d.ts.map +1 -1
  15. package/dist/index.browser.js +3244 -4669
  16. package/dist/index.d.ts +15 -11
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +5133 -811
  19. package/dist/layout/AutoFitEngine.d.ts.map +1 -1
  20. package/dist/layout/LineBoxValidator.d.ts +5 -10
  21. package/dist/layout/LineBoxValidator.d.ts.map +1 -1
  22. package/dist/layout/ParagraphLayoutEngine.d.ts +13 -8
  23. package/dist/layout/ParagraphLayoutEngine.d.ts.map +1 -1
  24. package/dist/layout/PositioningEngine.d.ts +1 -1
  25. package/dist/layout/PositioningEngine.d.ts.map +1 -1
  26. package/dist/layout/TableLayoutEngine.d.ts +174 -0
  27. package/dist/layout/TableLayoutEngine.d.ts.map +1 -0
  28. package/dist/layout/TextFrameLayoutEngine.d.ts +115 -16
  29. package/dist/layout/TextFrameLayoutEngine.d.ts.map +1 -1
  30. package/dist/layout/create-engine.d.ts +32 -0
  31. package/dist/layout/create-engine.d.ts.map +1 -0
  32. package/dist/layout/resolve-font.d.ts +25 -0
  33. package/dist/layout/resolve-font.d.ts.map +1 -0
  34. package/dist/measure/FontEngine.d.ts +44 -1
  35. package/dist/measure/FontEngine.d.ts.map +1 -1
  36. package/dist/measure/FontMetricsProvider.d.ts +3 -10
  37. package/dist/measure/FontMetricsProvider.d.ts.map +1 -1
  38. package/dist/measure/FontkitMeasureContext.d.ts +109 -0
  39. package/dist/measure/FontkitMeasureContext.d.ts.map +1 -0
  40. package/dist/measure/canvas-polyfill.d.ts.map +1 -1
  41. package/dist/types/Document.d.ts +73 -28
  42. package/dist/types/Document.d.ts.map +1 -1
  43. package/dist/types/FontTypes.d.ts +1 -1
  44. package/dist/types/FontTypes.d.ts.map +1 -1
  45. package/dist/types/LayoutTypes.d.ts +19 -2
  46. package/dist/types/LayoutTypes.d.ts.map +1 -1
  47. package/dist/types/TableTypes.d.ts +198 -0
  48. package/dist/types/TableTypes.d.ts.map +1 -0
  49. package/dist/utils/sides.d.ts +26 -0
  50. package/dist/utils/sides.d.ts.map +1 -0
  51. package/dist/utils/widths.d.ts +16 -0
  52. package/dist/utils/widths.d.ts.map +1 -0
  53. 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,CAcX;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
+ {"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 and YAML serialization.
2
+ * LineBoxValidator.ts — Parley-inspired line-box invariant checks.
3
3
  *
4
- * Parley-inspired invariant checks:
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 snapshots: semantic data only (no metric noise).
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;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,IAAI,EAA2B,MAAM,yBAAyB,CAAC;AAM7E,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;AAYD;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,MAAM,CAwBR"}
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 (DocumentCompiler)
6
+ * → compile (ParagraphCompiler)
7
7
  * → prepareRichInline (pretext)
8
8
  * → walkRichInlineLineRanges + materializeRichInlineLineRange (pretext)
9
9
  * → positionLines (PositioningEngine)
10
- * → assertLineInvariants (LineInvariants)
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 (for SVG glyph mode).
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;;;;;;;;;;;;;GAaG;AAGH,OAAO,+BAA+B,CAAC;AAEvC,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;AAqCrE,qBAAa,qBAAqB;IAChC,OAAO,CAAC,aAAa,CAAyC;IAE9D;;;;;;;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,GACvB,qBAAqB;IA+HxB;;;;;OAKG;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"}
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/DocumentCompiler.js';
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,gCAAgC,CAAC;AAO7E,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;AA8CD;;;;;;;;;;;;;;;;;;;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,CA8ezC"}
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
- /** Frame width (set when TextFrame.width was provided). */
35
- frameWidth?: number;
36
- /** Frame height (set when TextFrame.height was provided). */
37
- frameHeight?: number;
38
- /** Actual content width (may exceed frameWidth when wrap=false). */
39
- contentWidth: number;
40
- /** Actual content height (may exceed frameHeight). */
41
- contentHeight: number;
42
- /** Whether horizontal dimension should use frame or content size. */
43
- fitHorizontal: 'frame' | 'content';
44
- /** Whether vertical dimension should use frame or content size. */
45
- fitVertical: 'frame' | 'content';
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
- * Layout a full TextFrame by stacking paragraphs with Y offset accumulation.
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 declare function layoutTextFrame(frame: TextFrame): TextFrameLayoutResult;
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;AAC/F,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAKpD;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,aAAa,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC,mEAAmE;IACnE,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC;AAmED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,qBAAqB,CAoRvE"}
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): Promise<FontFace>;
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;AAKzD,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;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAQxF;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"}
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;AAMhD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAyExC;;;;;;;;;;;;;;;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;IAWzC,oCAAoC;IACpC,OAAO,IAAI,SAAS,GAAG,QAAQ;IAI/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAYrB;;;;;;;;;OASG;IACG,YAAY,CAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAC5C,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,GACf,WAAW;CA6Ef;AAED,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,EAAE,mBAA+C,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"}