postext 0.3.6 → 0.3.8

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 (137) hide show
  1. package/dist/__tests__/exports.test.js +3 -0
  2. package/dist/__tests__/exports.test.js.map +1 -1
  3. package/dist/canvas-backend/blockRender.d.ts +3 -0
  4. package/dist/canvas-backend/blockRender.d.ts.map +1 -0
  5. package/dist/canvas-backend/blockRender.js +176 -0
  6. package/dist/canvas-backend/blockRender.js.map +1 -0
  7. package/dist/canvas-backend/decorations.d.ts +6 -0
  8. package/dist/canvas-backend/decorations.d.ts.map +1 -0
  9. package/dist/canvas-backend/decorations.js +106 -0
  10. package/dist/canvas-backend/decorations.js.map +1 -0
  11. package/dist/{canvas-backend.d.ts → canvas-backend/index.d.ts} +2 -2
  12. package/dist/canvas-backend/index.d.ts.map +1 -0
  13. package/dist/canvas-backend/index.js +66 -0
  14. package/dist/canvas-backend/index.js.map +1 -0
  15. package/dist/defaults/index.d.ts +1 -0
  16. package/dist/defaults/index.d.ts.map +1 -1
  17. package/dist/defaults/index.js +9 -0
  18. package/dist/defaults/index.js.map +1 -1
  19. package/dist/defaults/pdfGeneration.d.ts +5 -0
  20. package/dist/defaults/pdfGeneration.d.ts.map +1 -0
  21. package/dist/defaults/pdfGeneration.js +37 -0
  22. package/dist/defaults/pdfGeneration.js.map +1 -0
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/knuthPlass/breakpoints.d.ts +6 -0
  28. package/dist/knuthPlass/breakpoints.d.ts.map +1 -0
  29. package/dist/knuthPlass/breakpoints.js +284 -0
  30. package/dist/knuthPlass/breakpoints.js.map +1 -0
  31. package/dist/knuthPlass/constants.d.ts +8 -0
  32. package/dist/knuthPlass/constants.d.ts.map +1 -0
  33. package/dist/knuthPlass/constants.js +8 -0
  34. package/dist/knuthPlass/constants.js.map +1 -0
  35. package/dist/knuthPlass/index.d.ts +12 -0
  36. package/dist/knuthPlass/index.d.ts.map +1 -0
  37. package/dist/knuthPlass/index.js +11 -0
  38. package/dist/knuthPlass/index.js.map +1 -0
  39. package/dist/knuthPlass/pretextAdapter.d.ts +12 -0
  40. package/dist/knuthPlass/pretextAdapter.d.ts.map +1 -0
  41. package/dist/knuthPlass/pretextAdapter.js +178 -0
  42. package/dist/knuthPlass/pretextAdapter.js.map +1 -0
  43. package/dist/knuthPlass/richAdapter.d.ts +26 -0
  44. package/dist/knuthPlass/richAdapter.d.ts.map +1 -0
  45. package/dist/knuthPlass/richAdapter.js +189 -0
  46. package/dist/knuthPlass/richAdapter.js.map +1 -0
  47. package/dist/{knuthPlass.d.ts → knuthPlass/types.d.ts} +1 -31
  48. package/dist/knuthPlass/types.d.ts.map +1 -0
  49. package/dist/knuthPlass/types.js +5 -0
  50. package/dist/knuthPlass/types.js.map +1 -0
  51. package/dist/knuthPlass/utils.d.ts +2 -0
  52. package/dist/knuthPlass/utils.d.ts.map +1 -0
  53. package/dist/knuthPlass/utils.js +4 -0
  54. package/dist/knuthPlass/utils.js.map +1 -0
  55. package/dist/measure/cache.d.ts +5 -0
  56. package/dist/measure/cache.d.ts.map +1 -0
  57. package/dist/measure/cache.js +38 -0
  58. package/dist/measure/cache.js.map +1 -0
  59. package/dist/measure/canvas.d.ts +8 -0
  60. package/dist/measure/canvas.d.ts.map +1 -0
  61. package/dist/measure/canvas.js +30 -0
  62. package/dist/measure/canvas.js.map +1 -0
  63. package/dist/measure/font.d.ts +19 -0
  64. package/dist/measure/font.d.ts.map +1 -0
  65. package/dist/measure/font.js +34 -0
  66. package/dist/measure/font.js.map +1 -0
  67. package/dist/measure/index.d.ts +7 -0
  68. package/dist/measure/index.d.ts.map +1 -0
  69. package/dist/measure/index.js +6 -0
  70. package/dist/measure/index.js.map +1 -0
  71. package/dist/measure/plain.d.ts +13 -0
  72. package/dist/measure/plain.d.ts.map +1 -0
  73. package/dist/measure/plain.js +167 -0
  74. package/dist/measure/plain.js.map +1 -0
  75. package/dist/measure/rich.d.ts +25 -0
  76. package/dist/measure/rich.d.ts.map +1 -0
  77. package/dist/measure/rich.js +246 -0
  78. package/dist/measure/rich.js.map +1 -0
  79. package/dist/measure/types.d.ts +28 -0
  80. package/dist/measure/types.d.ts.map +1 -0
  81. package/dist/measure/types.js +2 -0
  82. package/dist/measure/types.js.map +1 -0
  83. package/dist/parse/blockParser.d.ts +28 -0
  84. package/dist/parse/blockParser.d.ts.map +1 -0
  85. package/dist/parse/blockParser.js +302 -0
  86. package/dist/parse/blockParser.js.map +1 -0
  87. package/dist/parse/index.d.ts +4 -0
  88. package/dist/parse/index.d.ts.map +1 -0
  89. package/dist/parse/index.js +3 -0
  90. package/dist/parse/index.js.map +1 -0
  91. package/dist/parse/inlineFormatting.d.ts +12 -0
  92. package/dist/parse/inlineFormatting.d.ts.map +1 -0
  93. package/dist/parse/inlineFormatting.js +90 -0
  94. package/dist/parse/inlineFormatting.js.map +1 -0
  95. package/dist/parse/inlineMath.d.ts +29 -0
  96. package/dist/parse/inlineMath.d.ts.map +1 -0
  97. package/dist/parse/inlineMath.js +141 -0
  98. package/dist/parse/inlineMath.js.map +1 -0
  99. package/dist/parse/sourceMapping.d.ts +12 -0
  100. package/dist/parse/sourceMapping.d.ts.map +1 -0
  101. package/dist/parse/sourceMapping.js +130 -0
  102. package/dist/parse/sourceMapping.js.map +1 -0
  103. package/dist/{parse.d.ts → parse/types.d.ts} +2 -25
  104. package/dist/parse/types.d.ts.map +1 -0
  105. package/dist/parse/types.js +2 -0
  106. package/dist/parse/types.js.map +1 -0
  107. package/dist/pipeline/build.d.ts.map +1 -1
  108. package/dist/pipeline/build.js +34 -276
  109. package/dist/pipeline/build.js.map +1 -1
  110. package/dist/pipeline/buildBlockKind.d.ts +33 -0
  111. package/dist/pipeline/buildBlockKind.d.ts.map +1 -0
  112. package/dist/pipeline/buildBlockKind.js +82 -0
  113. package/dist/pipeline/buildBlockKind.js.map +1 -0
  114. package/dist/pipeline/buildHelpers.d.ts +47 -0
  115. package/dist/pipeline/buildHelpers.d.ts.map +1 -0
  116. package/dist/pipeline/buildHelpers.js +169 -0
  117. package/dist/pipeline/buildHelpers.js.map +1 -0
  118. package/dist/pipeline/buildMeasurement.d.ts +27 -0
  119. package/dist/pipeline/buildMeasurement.d.ts.map +1 -0
  120. package/dist/pipeline/buildMeasurement.js +49 -0
  121. package/dist/pipeline/buildMeasurement.js.map +1 -0
  122. package/dist/types.d.ts +15 -0
  123. package/dist/types.d.ts.map +1 -1
  124. package/package.json +1 -1
  125. package/dist/canvas-backend.d.ts.map +0 -1
  126. package/dist/canvas-backend.js +0 -370
  127. package/dist/canvas-backend.js.map +0 -1
  128. package/dist/knuthPlass.d.ts.map +0 -1
  129. package/dist/knuthPlass.js +0 -665
  130. package/dist/knuthPlass.js.map +0 -1
  131. package/dist/measure.d.ts +0 -61
  132. package/dist/measure.d.ts.map +0 -1
  133. package/dist/measure.js +0 -512
  134. package/dist/measure.js.map +0 -1
  135. package/dist/parse.d.ts.map +0 -1
  136. package/dist/parse.js +0 -653
  137. package/dist/parse.js.map +0 -1
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Adapter between the bold/italic/math-aware "rich token" stream produced
3
+ * by the measure pipeline and the Knuth-Plass item stream, plus
4
+ * reconstruction of VDT lines from the optimal breakpoint sequence.
5
+ */
6
+ import { createBoundingBox } from '../vdt';
7
+ import { HYPHEN_PENALTY, KP_INFINITY, MAX_STRETCH } from './constants';
8
+ import { cleanSoftHyphens } from './utils';
9
+ export function richTokensToItems(tokens, normalSpaceWidth, maxStretchRatio, minShrinkRatio) {
10
+ const items = [];
11
+ const stretchPerSpace = normalSpaceWidth * (maxStretchRatio - 1);
12
+ const shrinkPerSpace = normalSpaceWidth * (1 - minShrinkRatio);
13
+ for (let t = 0; t < tokens.length; t++) {
14
+ const token = tokens[t];
15
+ const meta = {
16
+ bold: token.bold,
17
+ italic: token.italic,
18
+ originalTokenIndex: t,
19
+ };
20
+ if (token.kind === 'space') {
21
+ items.push({
22
+ type: 'glue',
23
+ width: token.width,
24
+ stretch: stretchPerSpace,
25
+ shrink: shrinkPerSpace,
26
+ sourceIndex: t,
27
+ meta: { ...meta },
28
+ });
29
+ continue;
30
+ }
31
+ // Text token — may have soft-hyphen break points
32
+ if (token.breakPoints && token.breakPoints.length > 0) {
33
+ const hyphenW = token.hyphenWidth ?? 0;
34
+ let prevCharIndex = 0;
35
+ let prevWidth = 0;
36
+ for (let bp = 0; bp < token.breakPoints.length; bp++) {
37
+ const breakPoint = token.breakPoints[bp];
38
+ const fragmentWidth = breakPoint.widthBefore - prevWidth;
39
+ // Box for the fragment before this break point
40
+ items.push({
41
+ type: 'box',
42
+ width: fragmentWidth,
43
+ sourceIndex: t,
44
+ meta: { ...meta, subStart: prevCharIndex, subEnd: breakPoint.charIndex },
45
+ });
46
+ // Penalty at the soft hyphen
47
+ items.push({
48
+ type: 'penalty',
49
+ width: hyphenW,
50
+ penalty: HYPHEN_PENALTY,
51
+ flagged: true,
52
+ sourceIndex: t,
53
+ meta: { ...meta },
54
+ });
55
+ prevCharIndex = breakPoint.charIndex;
56
+ prevWidth = breakPoint.widthBefore;
57
+ }
58
+ // Final fragment after last break point
59
+ items.push({
60
+ type: 'box',
61
+ width: token.width - prevWidth,
62
+ sourceIndex: t,
63
+ meta: { ...meta, subStart: prevCharIndex, subEnd: token.text.length },
64
+ });
65
+ }
66
+ else {
67
+ // Simple text token without break points
68
+ items.push({
69
+ type: 'box',
70
+ width: token.width,
71
+ sourceIndex: t,
72
+ meta: { ...meta, subStart: 0, subEnd: token.text.length },
73
+ });
74
+ }
75
+ }
76
+ // Final-line glue + forced break
77
+ items.push({
78
+ type: 'glue',
79
+ width: 0,
80
+ stretch: MAX_STRETCH,
81
+ shrink: 0,
82
+ sourceIndex: -1,
83
+ });
84
+ items.push({
85
+ type: 'penalty',
86
+ width: 0,
87
+ penalty: -KP_INFINITY,
88
+ flagged: false,
89
+ sourceIndex: -1,
90
+ });
91
+ return items;
92
+ }
93
+ export function reconstructRichLines(items, breaks, tokens, lineHeightPx, lineWidthFn, lineIndentFn, normalSpaceWidth, textAlign) {
94
+ const lines = [];
95
+ let lineStart = 0;
96
+ for (let li = 0; li < breaks.length; li++) {
97
+ const breakAt = breaks[li];
98
+ const isLastLine = li === breaks.length - 1;
99
+ const lineIndent = lineIndentFn(li);
100
+ const lineMaxWidth = lineWidthFn(li);
101
+ const breakItem = items[breakAt];
102
+ const hyphenated = breakItem.type === 'penalty' && breakItem.flagged;
103
+ const lineSegments = [];
104
+ const textParts = [];
105
+ for (let j = lineStart; j < breakAt; j++) {
106
+ const it = items[j];
107
+ if (it.sourceIndex < 0)
108
+ continue;
109
+ const meta = it.meta;
110
+ if (it.type === 'box' && meta) {
111
+ const token = tokens[meta.originalTokenIndex];
112
+ const subText = meta.subStart !== undefined && meta.subEnd !== undefined
113
+ ? token.text.slice(meta.subStart, meta.subEnd)
114
+ : token.text;
115
+ const cleanText = cleanSoftHyphens(subText);
116
+ lineSegments.push({
117
+ kind: token.mathRender ? 'math' : 'text',
118
+ text: cleanText,
119
+ width: it.width,
120
+ bold: meta.bold || undefined,
121
+ italic: meta.italic || undefined,
122
+ ...(token.mathRender ? { mathRender: token.mathRender } : {}),
123
+ });
124
+ textParts.push(cleanText);
125
+ }
126
+ else if (it.type === 'glue' && meta) {
127
+ const token = tokens[meta.originalTokenIndex];
128
+ lineSegments.push({
129
+ kind: 'space',
130
+ text: token.text,
131
+ width: it.width,
132
+ });
133
+ textParts.push(token.text);
134
+ }
135
+ }
136
+ // Trim trailing spaces
137
+ while (lineSegments.length > 0 && lineSegments[lineSegments.length - 1].kind === 'space') {
138
+ lineSegments.pop();
139
+ textParts.pop();
140
+ }
141
+ // If hyphenated, append '-' to the last text segment
142
+ if (hyphenated && lineSegments.length > 0) {
143
+ const breakMeta = breakItem.meta;
144
+ const hyphenW = breakMeta
145
+ ? (tokens[breakMeta.originalTokenIndex]?.hyphenWidth ?? 0)
146
+ : 0;
147
+ const lastIdx = lineSegments.length - 1;
148
+ const last = lineSegments[lastIdx];
149
+ if (last.kind === 'text') {
150
+ lineSegments[lastIdx] = {
151
+ ...last,
152
+ text: last.text + '-',
153
+ width: last.width + hyphenW,
154
+ };
155
+ textParts[textParts.length - 1] = last.text + '-';
156
+ }
157
+ }
158
+ const lineText = textParts.join('');
159
+ const contentWidth = lineSegments.reduce((s, seg) => s + seg.width, 0);
160
+ // Compute justifiedSpaceRatio
161
+ let justifiedSpaceRatio;
162
+ if (textAlign === 'justify' && !isLastLine && normalSpaceWidth > 0) {
163
+ let wordWidth = 0;
164
+ let spaceCount = 0;
165
+ for (const seg of lineSegments) {
166
+ if (seg.kind === 'space')
167
+ spaceCount++;
168
+ else
169
+ wordWidth += seg.width;
170
+ }
171
+ if (spaceCount > 0) {
172
+ const justifiedSpaceWidth = (lineMaxWidth - wordWidth) / spaceCount;
173
+ justifiedSpaceRatio = justifiedSpaceWidth / normalSpaceWidth;
174
+ }
175
+ }
176
+ lines.push({
177
+ text: lineText,
178
+ bbox: createBoundingBox(lineIndent, li * lineHeightPx, contentWidth, lineHeightPx),
179
+ baseline: li * lineHeightPx + lineHeightPx * 0.8,
180
+ hyphenated,
181
+ segments: lineSegments,
182
+ isLastLine,
183
+ ...(justifiedSpaceRatio !== undefined ? { justifiedSpaceRatio } : {}),
184
+ });
185
+ lineStart = breakAt + 1;
186
+ }
187
+ return lines;
188
+ }
189
+ //# sourceMappingURL=richAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"richAdapter.js","sourceRoot":"","sources":["../../src/knuthPlass/richAdapter.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,3 @@
1
- /**
2
- * Knuth-Plass optimal paragraph line-breaking algorithm.
3
- *
4
- * Replaces the greedy first-fit line breaker with a dynamic-programming
5
- * approach that minimizes total demerits across all lines of a paragraph,
6
- * producing more even word-spacing and fewer "loose" lines.
7
- */
8
- import type { PreparedTextWithSegments } from '@chenglou/pretext';
9
- import type { VDTLine } from './vdt';
10
- import type { TextAlign } from './types';
11
1
  export interface KPBox {
12
2
  type: 'box';
13
3
  width: number;
@@ -54,22 +44,6 @@ export interface KPOptions {
54
44
  * penalty. Typically `runtMinCharacters * normalSpaceWidth`. */
55
45
  runtMinWidth?: number;
56
46
  }
57
- export declare function computeBreakpoints(items: KPItem[], options: KPOptions): number[];
58
- export declare function pretextSegmentsToItems(prepared: PreparedTextWithSegments, normalSpaceWidth: number, maxStretchRatio: number, minShrinkRatio: number): KPItem[];
59
- interface RichBreakPoint {
60
- charIndex: number;
61
- widthBefore: number;
62
- }
63
- interface RichToken {
64
- text: string;
65
- bold: boolean;
66
- italic: boolean;
67
- kind: 'text' | 'space';
68
- width: number;
69
- breakPoints?: RichBreakPoint[];
70
- hyphenWidth?: number;
71
- mathRender?: import('./math/types').MathRender;
72
- }
73
47
  export interface RichTokenMeta {
74
48
  bold: boolean;
75
49
  italic: boolean;
@@ -79,8 +53,4 @@ export interface RichTokenMeta {
79
53
  /** Character index within the original token where this sub-box ends. */
80
54
  subEnd?: number;
81
55
  }
82
- export declare function richTokensToItems(tokens: RichToken[], normalSpaceWidth: number, maxStretchRatio: number, minShrinkRatio: number): KPItem[];
83
- export declare function reconstructPretextLines(items: KPItem[], breaks: number[], prepared: PreparedTextWithSegments, lineHeightPx: number, lineWidthFn: (lineIndex: number) => number, lineIndentFn: (lineIndex: number) => number, normalSpaceWidth: number, textAlign: TextAlign): VDTLine[];
84
- export declare function reconstructRichLines(items: KPItem[], breaks: number[], tokens: RichToken[], lineHeightPx: number, lineWidthFn: (lineIndex: number) => number, lineIndentFn: (lineIndex: number) => number, normalSpaceWidth: number, textAlign: TextAlign): VDTLine[];
85
- export {};
86
- //# sourceMappingURL=knuthPlass.d.ts.map
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/knuthPlass/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAMhD,MAAM,WAAW,SAAS;IACxB,0DAA0D;IAC1D,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,uCAAuC;IACvC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,eAAe,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;uEAImE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;qEACiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,5 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Data model: Box / Glue / Penalty
3
+ // ---------------------------------------------------------------------------
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/knuthPlass/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mCAAmC;AACnC,8EAA8E"}
@@ -0,0 +1,2 @@
1
+ export declare function cleanSoftHyphens(text: string): string;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/knuthPlass/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,4 @@
1
+ export function cleanSoftHyphens(text) {
2
+ return text.replace(/\u00AD/g, '');
3
+ }
4
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/knuthPlass/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { InlineSpan } from '../parse';
2
+ import type { MeasuredBlock, MeasurementCache, MeasureBlockOptions } from './types';
3
+ export declare function cachedMeasureBlock(text: string, font: string, maxWidthPx: number, lineHeightPx: number, options: MeasureBlockOptions | undefined, cache: MeasurementCache): MeasuredBlock;
4
+ export declare function cachedMeasureRichBlock(spans: InlineSpan[], normalFont: string, boldFont: string, italicFont: string, boldItalicFont: string, maxWidthPx: number, lineHeightPx: number, options: MeasureBlockOptions | undefined, cache: MeasurementCache): MeasuredBlock;
5
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/measure/cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAoCpF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,KAAK,EAAE,gBAAgB,GACtB,aAAa,CAOf;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,UAAU,EAAE,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,KAAK,EAAE,gBAAgB,GACtB,aAAa,CAOf"}
@@ -0,0 +1,38 @@
1
+ import { measureBlock } from './plain';
2
+ import { measureRichBlock } from './rich';
3
+ function buildPlainCacheKey(text, font, maxWidthPx, lineHeightPx, options) {
4
+ return `${text}\x00${font}\x00${maxWidthPx}\x00${lineHeightPx}\x00${options?.textAlign ?? ''}\x00${options?.hyphenate ?? ''}\x00${options?.firstLineIndentPx ?? ''}\x00${options?.hangingIndent ?? ''}\x00${options?.optimal ?? ''}\x00${options?.maxStretchRatio ?? ''}\x00${options?.minShrinkRatio ?? ''}\x00${options?.runtPenalty ?? ''}\x00${options?.runtMinCharacters ?? ''}`;
5
+ }
6
+ function buildRichCacheKey(spans, fonts, maxWidthPx, lineHeightPx, options) {
7
+ const spanKey = spans.map((s) => `${s.text}|${s.bold}|${s.italic}`).join('\x01');
8
+ return `R\x00${spanKey}\x00${fonts[0]}\x00${fonts[1]}\x00${fonts[2]}\x00${fonts[3]}\x00${maxWidthPx}\x00${lineHeightPx}\x00${options?.textAlign ?? ''}\x00${options?.hyphenate ?? ''}\x00${options?.firstLineIndentPx ?? ''}\x00${options?.hangingIndent ?? ''}\x00${options?.optimal ?? ''}\x00${options?.maxStretchRatio ?? ''}\x00${options?.minShrinkRatio ?? ''}\x00${options?.runtPenalty ?? ''}\x00${options?.runtMinCharacters ?? ''}`;
9
+ }
10
+ function cloneMeasuredBlock(block) {
11
+ return {
12
+ lines: block.lines.map((l) => ({
13
+ ...l,
14
+ bbox: { ...l.bbox },
15
+ segments: l.segments ? l.segments.map((s) => ({ ...s })) : undefined,
16
+ })),
17
+ totalHeight: block.totalHeight,
18
+ };
19
+ }
20
+ export function cachedMeasureBlock(text, font, maxWidthPx, lineHeightPx, options, cache) {
21
+ const key = buildPlainCacheKey(text, font, maxWidthPx, lineHeightPx, options);
22
+ const cached = cache._blocks.get(key);
23
+ if (cached)
24
+ return cloneMeasuredBlock(cached);
25
+ const result = measureBlock(text, font, maxWidthPx, lineHeightPx, options);
26
+ cache._blocks.set(key, result);
27
+ return cloneMeasuredBlock(result);
28
+ }
29
+ export function cachedMeasureRichBlock(spans, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options, cache) {
30
+ const key = buildRichCacheKey(spans, [normalFont, boldFont, italicFont, boldItalicFont], maxWidthPx, lineHeightPx, options);
31
+ const cached = cache._blocks.get(key);
32
+ if (cached)
33
+ return cloneMeasuredBlock(cached);
34
+ const result = measureRichBlock(spans, normalFont, boldFont, italicFont, boldItalicFont, maxWidthPx, lineHeightPx, options);
35
+ cache._blocks.set(key, result);
36
+ return cloneMeasuredBlock(result);
37
+ }
38
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/measure/cache.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAE1C,SAAS,kBAAkB,CACzB,IAAY,EACZ,IAAY,EACZ,UAAkB,EAClB,YAAoB,EACpB,OAAwC;IAExC,OAAO,GAAG,IAAI,OAAO,IAAI,OAAO,UAAU,OAAO,YAAY,OAAO,OAAO,EAAE,SAAS,IAAI,EAAE,OAAO,OAAO,EAAE,SAAS,IAAI,EAAE,OAAO,OAAO,EAAE,iBAAiB,IAAI,EAAE,OAAO,OAAO,EAAE,aAAa,IAAI,EAAE,OAAO,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,OAAO,EAAE,eAAe,IAAI,EAAE,OAAO,OAAO,EAAE,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,WAAW,IAAI,EAAE,OAAO,OAAO,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;AACxX,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAmB,EACnB,KAAuC,EACvC,UAAkB,EAClB,YAAoB,EACpB,OAAwC;IAExC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjF,OAAO,QAAQ,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,UAAU,OAAO,YAAY,OAAO,OAAO,EAAE,SAAS,IAAI,EAAE,OAAO,OAAO,EAAE,SAAS,IAAI,EAAE,OAAO,OAAO,EAAE,iBAAiB,IAAI,EAAE,OAAO,OAAO,EAAE,aAAa,IAAI,EAAE,OAAO,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,OAAO,EAAE,eAAe,IAAI,EAAE,OAAO,OAAO,EAAE,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,WAAW,IAAI,EAAE,OAAO,OAAO,EAAE,iBAAiB,IAAI,EAAE,EAAE,CAAC;AACjb,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAoB;IAC9C,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,GAAG,CAAC;YACJ,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;YACnB,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SACrE,CAAC,CAAC;QACH,WAAW,EAAE,KAAK,CAAC,WAAW;KAC/B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,IAAY,EACZ,UAAkB,EAClB,YAAoB,EACpB,OAAwC,EACxC,KAAuB;IAEvB,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC3E,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC/B,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAmB,EACnB,UAAkB,EAClB,QAAgB,EAChB,UAAkB,EAClB,cAAsB,EACtB,UAAkB,EAClB,YAAoB,EACpB,OAAwC,EACxC,KAAuB;IAEvB,MAAM,GAAG,GAAG,iBAAiB,CAAC,KAAK,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC5H,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAC5H,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC/B,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function measureTextWidth(text: string, font: string): number;
2
+ /** Measure a short glyph (e.g. a list bullet) in the given font. */
3
+ export declare function measureGlyphWidth(text: string, font: string): number;
4
+ /** Compute the normal space width for a given font, used to express justified
5
+ * spacing as a multiplier of the natural space. */
6
+ export declare function normalSpaceWidthFor(font: string): number;
7
+ export declare function cleanSoftHyphens(text: string): string;
8
+ //# sourceMappingURL=canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/measure/canvas.ts"],"names":[],"mappings":"AAaA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED;oDACoD;AACpD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -0,0 +1,30 @@
1
+ let _measureCtx = null;
2
+ function getMeasureCtx() {
3
+ if (!_measureCtx) {
4
+ if (typeof OffscreenCanvas !== 'undefined') {
5
+ _measureCtx = new OffscreenCanvas(1, 1).getContext('2d');
6
+ }
7
+ else {
8
+ _measureCtx = document.createElement('canvas').getContext('2d');
9
+ }
10
+ }
11
+ return _measureCtx;
12
+ }
13
+ export function measureTextWidth(text, font) {
14
+ const ctx = getMeasureCtx();
15
+ ctx.font = font;
16
+ return ctx.measureText(text).width;
17
+ }
18
+ /** Measure a short glyph (e.g. a list bullet) in the given font. */
19
+ export function measureGlyphWidth(text, font) {
20
+ return measureTextWidth(text, font);
21
+ }
22
+ /** Compute the normal space width for a given font, used to express justified
23
+ * spacing as a multiplier of the natural space. */
24
+ export function normalSpaceWidthFor(font) {
25
+ return measureTextWidth(' ', font);
26
+ }
27
+ export function cleanSoftHyphens(text) {
28
+ return text.replace(/\u00AD/g, '');
29
+ }
30
+ //# sourceMappingURL=canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../src/measure/canvas.ts"],"names":[],"mappings":"AAAA,IAAI,WAAW,GAAwE,IAAI,CAAC;AAE5F,SAAS,aAAa;IACpB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,OAAO,eAAe,KAAK,WAAW,EAAE,CAAC;YAC3C,WAAW,GAAG,IAAI,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAE,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,IAAI,CAAE,CAAC;QACnE,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,IAAY;IACzD,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC;IAC5B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAChB,OAAO,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AACrC,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,IAAY;IAC1D,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;oDACoD;AACpD,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { HyphenationLocale } from '../types';
2
+ import type { MeasurementCache } from './types';
3
+ /**
4
+ * Build a CSS font shorthand string for canvas / pretext.
5
+ * Example: "75px EB Garamond"
6
+ */
7
+ export declare function buildFontString(fontFamily: string, fontSizePx: number, weight?: string, style?: string): string;
8
+ /**
9
+ * Initializes the hyphenator for a given locale.
10
+ * Must be called before measureBlock is used with hyphenation.
11
+ */
12
+ export declare function initHyphenator(locale: HyphenationLocale): void;
13
+ /**
14
+ * Clear pretext's internal measurement caches.
15
+ * Call this after fonts finish loading to ensure accurate measurements.
16
+ */
17
+ export declare function clearMeasurementCache(): void;
18
+ export declare function createMeasurementCache(): MeasurementCache;
19
+ //# sourceMappingURL=font.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../../src/measure/font.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAiB,EACzB,KAAK,GAAE,MAAiB,GACvB,MAAM,CAOR;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAE9D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD"}
@@ -0,0 +1,34 @@
1
+ import { clearCache } from '@chenglou/pretext';
2
+ import { setHyphenationLocale } from '../hyphenate';
3
+ /**
4
+ * Build a CSS font shorthand string for canvas / pretext.
5
+ * Example: "75px EB Garamond"
6
+ */
7
+ export function buildFontString(fontFamily, fontSizePx, weight = 'normal', style = 'normal') {
8
+ const parts = [];
9
+ if (style !== 'normal')
10
+ parts.push(style);
11
+ if (weight !== 'normal')
12
+ parts.push(weight);
13
+ parts.push(`${fontSizePx}px`);
14
+ parts.push(fontFamily);
15
+ return parts.join(' ');
16
+ }
17
+ /**
18
+ * Initializes the hyphenator for a given locale.
19
+ * Must be called before measureBlock is used with hyphenation.
20
+ */
21
+ export function initHyphenator(locale) {
22
+ setHyphenationLocale(locale);
23
+ }
24
+ /**
25
+ * Clear pretext's internal measurement caches.
26
+ * Call this after fonts finish loading to ensure accurate measurements.
27
+ */
28
+ export function clearMeasurementCache() {
29
+ clearCache();
30
+ }
31
+ export function createMeasurementCache() {
32
+ return { _blocks: new Map() };
33
+ }
34
+ //# sourceMappingURL=font.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font.js","sourceRoot":"","sources":["../../src/measure/font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGpD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAkB,EAClB,UAAkB,EAClB,SAAiB,QAAQ,EACzB,QAAgB,QAAQ;IAExB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,MAAM,KAAK,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,IAAI,CAAC,CAAC;IAC9B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB;IACtD,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,UAAU,EAAE,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export type { MeasuredBlock, MeasurementCache, MeasureBlockOptions } from './types';
2
+ export { buildFontString, initHyphenator, clearMeasurementCache, createMeasurementCache } from './font';
3
+ export { measureGlyphWidth } from './canvas';
4
+ export { measureBlock } from './plain';
5
+ export { measureRichBlock } from './rich';
6
+ export { cachedMeasureBlock, cachedMeasureRichBlock } from './cache';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/measure/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { buildFontString, initHyphenator, clearMeasurementCache, createMeasurementCache } from './font';
2
+ export { measureGlyphWidth } from './canvas';
3
+ export { measureBlock } from './plain';
4
+ export { measureRichBlock } from './rich';
5
+ export { cachedMeasureBlock, cachedMeasureRichBlock } from './cache';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/measure/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { VDTLineSegment } from '../vdt';
2
+ import type { TextAlign } from '../types';
3
+ import type { MeasuredBlock, MeasureBlockOptions } from './types';
4
+ export declare function computeJustifiedSpaceRatio(segments: VDTLineSegment[], lineMaxWidth: number, normalSpaceWidth: number, textAlign: TextAlign, isLastLine: boolean): number | undefined;
5
+ /**
6
+ * Measure a text block: break it into lines within maxWidthPx
7
+ * and return VDTLine data with bounding boxes.
8
+ *
9
+ * The returned lines have bbox positions relative to the block origin (0,0).
10
+ * The pipeline will offset them to absolute page coordinates later.
11
+ */
12
+ export declare function measureBlock(text: string, font: string, maxWidthPx: number, lineHeightPx: number, options?: MeasureBlockOptions): MeasuredBlock;
13
+ //# sourceMappingURL=plain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain.d.ts","sourceRoot":"","sources":["../../src/measure/plain.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAW,cAAc,EAAE,MAAM,QAAQ,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAQ1C,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AA2DlE,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,cAAc,EAAE,EAC1B,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,MAAM,EACxB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,OAAO,GAClB,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,aAAa,CA+Gf"}