@flighthq/textlayout 0.1.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/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/richTextContent.d.ts +6 -0
- package/dist/richTextContent.d.ts.map +1 -0
- package/dist/richTextContent.js +435 -0
- package/dist/richTextContent.js.map +1 -0
- package/dist/richTextMetrics.d.ts +9 -0
- package/dist/richTextMetrics.d.ts.map +1 -0
- package/dist/richTextMetrics.js +44 -0
- package/dist/richTextMetrics.js.map +1 -0
- package/dist/richTextQuery.d.ts +14 -0
- package/dist/richTextQuery.d.ts.map +1 -0
- package/dist/richTextQuery.js +205 -0
- package/dist/richTextQuery.js.map +1 -0
- package/dist/textBounds.d.ts +13 -0
- package/dist/textBounds.d.ts.map +1 -0
- package/dist/textBounds.js +42 -0
- package/dist/textBounds.js.map +1 -0
- package/dist/textFormat.d.ts +7 -0
- package/dist/textFormat.d.ts.map +1 -0
- package/dist/textFormat.js +24 -0
- package/dist/textFormat.js.map +1 -0
- package/dist/textFormatRange.d.ts +3 -0
- package/dist/textFormatRange.d.ts.map +1 -0
- package/dist/textFormatRange.js +4 -0
- package/dist/textFormatRange.js.map +1 -0
- package/dist/textLayout.d.ts +8 -0
- package/dist/textLayout.d.ts.map +1 -0
- package/dist/textLayout.js +632 -0
- package/dist/textLayout.js.map +1 -0
- package/dist/textLayoutGroup.d.ts +3 -0
- package/dist/textLayoutGroup.d.ts.map +1 -0
- package/dist/textLayoutGroup.js +17 -0
- package/dist/textLayoutGroup.js.map +1 -0
- package/dist/textLayoutMeasure.d.ts +4 -0
- package/dist/textLayoutMeasure.d.ts.map +1 -0
- package/dist/textLayoutMeasure.js +23 -0
- package/dist/textLayoutMeasure.js.map +1 -0
- package/dist/textLayoutRuntime.d.ts +4 -0
- package/dist/textLayoutRuntime.d.ts.map +1 -0
- package/dist/textLayoutRuntime.js +11 -0
- package/dist/textLayoutRuntime.js.map +1 -0
- package/dist/textLineBreaks.d.ts +8 -0
- package/dist/textLineBreaks.d.ts.map +1 -0
- package/dist/textLineBreaks.js +36 -0
- package/dist/textLineBreaks.js.map +1 -0
- package/dist/textMetrics.d.ts +4 -0
- package/dist/textMetrics.d.ts.map +1 -0
- package/dist/textMetrics.js +12 -0
- package/dist/textMetrics.js.map +1 -0
- package/package.json +38 -0
- package/src/richTextContent.test.ts +201 -0
- package/src/richTextMetrics.test.ts +124 -0
- package/src/richTextQuery.test.ts +196 -0
- package/src/textBounds.test.ts +110 -0
- package/src/textFormat.test.ts +66 -0
- package/src/textFormatRange.test.ts +9 -0
- package/src/textLayout.test.ts +661 -0
- package/src/textLayoutGroup.test.ts +30 -0
- package/src/textLayoutMeasure.test.ts +36 -0
- package/src/textLayoutRuntime.test.ts +30 -0
- package/src/textLineBreaks.test.ts +73 -0
- package/src/textMetrics.test.ts +19 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import { getTextFormatAscent, getTextFormatDescent, getTextFormatLeading, mergeTextFormat } from './textFormat';
|
|
2
|
+
import { createTextLayoutGroup } from './textLayoutGroup';
|
|
3
|
+
import { getTextLineBreaks } from './textLineBreaks';
|
|
4
|
+
/** Inner padding (px) between a text box edge and its content, applied on every side. */
|
|
5
|
+
export const TEXT_LAYOUT_GUTTER = 2;
|
|
6
|
+
const _lineBreaks = [];
|
|
7
|
+
const _charAdvances = [];
|
|
8
|
+
// Paragraph-final line indices collected by buildGroups, consumed by justifyLines.
|
|
9
|
+
// Lines at these indices must not be justified (CSS standard: last line of a paragraph is left).
|
|
10
|
+
const _paragraphLastLines = new Set();
|
|
11
|
+
export function computeTextLayout(out, params) {
|
|
12
|
+
const { text, formatRanges, width, measure, wordWrap = false, multiline = false, autoSize = 'none', border = false, direction = 'LeftToRight', justification = 'interWord', maxLines = -1, truncationCharacter = '…', } = params;
|
|
13
|
+
if (!text || formatRanges.length === 0) {
|
|
14
|
+
out.groups.length = 0;
|
|
15
|
+
out.lineAscents.length = 0;
|
|
16
|
+
out.lineDescents.length = 0;
|
|
17
|
+
out.lineHeights.length = 0;
|
|
18
|
+
out.lineLeadings.length = 0;
|
|
19
|
+
out.lineWidths.length = 0;
|
|
20
|
+
out.numLines = 1;
|
|
21
|
+
out.textHeight = 0;
|
|
22
|
+
out.textWidth = 0;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
getTextLineBreaks(_lineBreaks, text);
|
|
26
|
+
_paragraphLastLines.clear();
|
|
27
|
+
buildGroups(out.groups, _paragraphLastLines, text, formatRanges, _lineBreaks, width, measure, wordWrap, multiline, maxLines, truncationCharacter);
|
|
28
|
+
writeLineMetrics(out, out.groups);
|
|
29
|
+
// Alignment shifts require knowing per-line widths first.
|
|
30
|
+
applyAlignment(out.groups, width, out.lineWidths, direction, justification, _paragraphLastLines, text);
|
|
31
|
+
// autoSize is intentionally not applied here — callers (scene graph /
|
|
32
|
+
// renderer) own the node's width/height and apply the result themselves.
|
|
33
|
+
void autoSize;
|
|
34
|
+
void border;
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Internal helpers
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
function charAdvances(out, text, format, start, end, measure, startX = 0) {
|
|
40
|
+
out.length = 0;
|
|
41
|
+
const letterSpacing = format.letterSpacing ?? 0;
|
|
42
|
+
const tabStops = format.tabStops;
|
|
43
|
+
const kerningEnabled = format.kerning !== false;
|
|
44
|
+
let currentX = startX;
|
|
45
|
+
// Iterate codepoints so surrogate pairs (emoji, astral scripts) are not split.
|
|
46
|
+
let i = start;
|
|
47
|
+
while (i < end) {
|
|
48
|
+
const cp = text.codePointAt(i) ?? 0;
|
|
49
|
+
const charLen = cp > 0xffff ? 2 : 1;
|
|
50
|
+
const char = text.slice(i, i + charLen);
|
|
51
|
+
let advance;
|
|
52
|
+
if (char === '\t') {
|
|
53
|
+
advance = getTabAdvance(currentX, tabStops, measure, format);
|
|
54
|
+
out.push(advance);
|
|
55
|
+
currentX += advance;
|
|
56
|
+
i += charLen;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Look ahead for the next codepoint to compute a kerned pair advance.
|
|
60
|
+
const nextStart = i + charLen;
|
|
61
|
+
if (kerningEnabled && nextStart < end && text.charCodeAt(nextStart) !== 9 /* \t */) {
|
|
62
|
+
const nextCp = text.codePointAt(nextStart) ?? 0;
|
|
63
|
+
const nextLen = nextCp > 0xffff ? 2 : 1;
|
|
64
|
+
const nextChar = text.slice(nextStart, nextStart + nextLen);
|
|
65
|
+
const nextW = measure(nextChar, format);
|
|
66
|
+
const pairW = measure(char + nextChar, format);
|
|
67
|
+
advance = pairW - nextW;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
advance = measure(char, format);
|
|
71
|
+
}
|
|
72
|
+
out.push(advance + letterSpacing);
|
|
73
|
+
currentX += advance + letterSpacing;
|
|
74
|
+
i += charLen;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function sumAdvances(positions) {
|
|
78
|
+
let total = 0;
|
|
79
|
+
for (const p of positions)
|
|
80
|
+
total += p;
|
|
81
|
+
return total;
|
|
82
|
+
}
|
|
83
|
+
function getTabAdvance(currentX, tabStops, measure, format) {
|
|
84
|
+
if (tabStops != null && tabStops.length > 0) {
|
|
85
|
+
for (const stop of tabStops) {
|
|
86
|
+
if (stop > currentX)
|
|
87
|
+
return stop - currentX;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Default: advance to next multiple of 4 spaces
|
|
91
|
+
const spaceW = measure(' ', format) / 4;
|
|
92
|
+
const tabW = Math.max(spaceW, 1) * 4;
|
|
93
|
+
return tabW - (currentX % tabW);
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Layout group construction
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
function buildGroups(out, paragraphLastLines, text, formatRanges, lineBreaks, containerWidth, measure, wordWrap, multiline, maxLines, truncationCharacter) {
|
|
99
|
+
out.length = 0;
|
|
100
|
+
const groups = out;
|
|
101
|
+
let rangeIndex = 0;
|
|
102
|
+
let formatRange = formatRanges[0];
|
|
103
|
+
let currentFormat = { ...formatRange.format };
|
|
104
|
+
// Paragraph-level properties — taken from the first character of each paragraph.
|
|
105
|
+
let leftMargin = currentFormat.leftMargin ?? 0;
|
|
106
|
+
let rightMargin = currentFormat.rightMargin ?? 0;
|
|
107
|
+
let blockIndent = currentFormat.blockIndent ?? 0;
|
|
108
|
+
let indent = currentFormat.indent ?? 0;
|
|
109
|
+
let firstLineOfParagraph = true;
|
|
110
|
+
// Bullet: hanging-indent prefix for list items. Set when bullet format starts a paragraph.
|
|
111
|
+
let bulletPending = false;
|
|
112
|
+
const bulletChar = '•'; // •
|
|
113
|
+
// Line-level metrics.
|
|
114
|
+
let ascent = getTextFormatAscent(currentFormat);
|
|
115
|
+
let descent = getTextFormatDescent(currentFormat);
|
|
116
|
+
let leading = getTextFormatLeading(currentFormat);
|
|
117
|
+
let lineHeight = Math.ceil(ascent + descent + leading);
|
|
118
|
+
let maxAscent = ascent;
|
|
119
|
+
let maxLineHeight = lineHeight;
|
|
120
|
+
let textIndex = 0;
|
|
121
|
+
let lineIndex = 0;
|
|
122
|
+
let offsetX = 0;
|
|
123
|
+
let offsetY = 0;
|
|
124
|
+
// Track whether truncation has been applied to stop further placement.
|
|
125
|
+
let truncated = false;
|
|
126
|
+
let breakCount = 0;
|
|
127
|
+
let breakIndex = lineBreaks.length > 0 ? lineBreaks[0] : -1;
|
|
128
|
+
let spaceIndex = text.indexOf(' ');
|
|
129
|
+
let prevSpaceIndex = -2;
|
|
130
|
+
let activeGroup = null;
|
|
131
|
+
// --- Local helpers that close over the mutable state above ---
|
|
132
|
+
function baseX() {
|
|
133
|
+
return TEXT_LAYOUT_GUTTER + leftMargin + blockIndent + (firstLineOfParagraph ? indent : 0);
|
|
134
|
+
}
|
|
135
|
+
function wrapWidth() {
|
|
136
|
+
return containerWidth - TEXT_LAYOUT_GUTTER - rightMargin - baseX();
|
|
137
|
+
}
|
|
138
|
+
function updateLineMetrics() {
|
|
139
|
+
ascent = getTextFormatAscent(currentFormat);
|
|
140
|
+
descent = getTextFormatDescent(currentFormat);
|
|
141
|
+
leading = getTextFormatLeading(currentFormat);
|
|
142
|
+
lineHeight = Math.ceil(ascent + descent + leading);
|
|
143
|
+
if (lineHeight > maxLineHeight)
|
|
144
|
+
maxLineHeight = lineHeight;
|
|
145
|
+
if (ascent > maxAscent)
|
|
146
|
+
maxAscent = ascent;
|
|
147
|
+
}
|
|
148
|
+
function updateParagraphMetrics() {
|
|
149
|
+
firstLineOfParagraph = true;
|
|
150
|
+
leftMargin = currentFormat.leftMargin ?? 0;
|
|
151
|
+
rightMargin = currentFormat.rightMargin ?? 0;
|
|
152
|
+
blockIndent = currentFormat.blockIndent ?? 0;
|
|
153
|
+
indent = currentFormat.indent ?? 0;
|
|
154
|
+
// Detect bullet format at paragraph start.
|
|
155
|
+
bulletPending = currentFormat.bullet === true;
|
|
156
|
+
}
|
|
157
|
+
function advanceFormatRange() {
|
|
158
|
+
if (rangeIndex < formatRanges.length - 1) {
|
|
159
|
+
rangeIndex++;
|
|
160
|
+
formatRange = formatRanges[rangeIndex];
|
|
161
|
+
currentFormat = mergeTextFormat(currentFormat, formatRange.format);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
// Finalise the current line: set max ascent/height on all groups in it,
|
|
167
|
+
// then advance the pen to the next line.
|
|
168
|
+
function commitLine() {
|
|
169
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
170
|
+
const g = groups[i];
|
|
171
|
+
if (g.lineIndex < lineIndex)
|
|
172
|
+
break;
|
|
173
|
+
g.ascent = maxAscent;
|
|
174
|
+
g.height = maxLineHeight;
|
|
175
|
+
}
|
|
176
|
+
offsetY += maxLineHeight;
|
|
177
|
+
maxAscent = 0;
|
|
178
|
+
maxLineHeight = 0;
|
|
179
|
+
lineIndex++;
|
|
180
|
+
offsetX = 0;
|
|
181
|
+
firstLineOfParagraph = false;
|
|
182
|
+
activeGroup = null;
|
|
183
|
+
updateLineMetrics();
|
|
184
|
+
}
|
|
185
|
+
// Check whether maxLines has been reached. If so, append the truncation
|
|
186
|
+
// character to the last visible line and mark truncated.
|
|
187
|
+
// Must be called after commitLine(), so lineIndex points one past the last committed line.
|
|
188
|
+
function checkTruncation() {
|
|
189
|
+
if (maxLines < 0 || lineIndex < maxLines)
|
|
190
|
+
return false;
|
|
191
|
+
// The last committed line index is lineIndex - 1.
|
|
192
|
+
const lastLineIndex = lineIndex - 1;
|
|
193
|
+
// Append truncation character to last visible group on that line if it fits.
|
|
194
|
+
if (truncationCharacter.length > 0 && groups.length > 0) {
|
|
195
|
+
// Find the last group on the last committed line.
|
|
196
|
+
let lastGroup = null;
|
|
197
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
198
|
+
if (groups[i].lineIndex === lastLineIndex) {
|
|
199
|
+
lastGroup = groups[i];
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (lastGroup !== null) {
|
|
204
|
+
const ellipsisW = measure(truncationCharacter, lastGroup.format);
|
|
205
|
+
const available = containerWidth - TEXT_LAYOUT_GUTTER - rightMargin - lastGroup.offsetX;
|
|
206
|
+
// Trim characters from the end of the last group until the ellipsis fits.
|
|
207
|
+
while (lastGroup.positions.length > 0) {
|
|
208
|
+
const usedW = sumAdvances(lastGroup.positions);
|
|
209
|
+
if (usedW + ellipsisW <= available)
|
|
210
|
+
break;
|
|
211
|
+
const trimmed = lastGroup.positions.pop() ?? 0;
|
|
212
|
+
lastGroup.width -= trimmed;
|
|
213
|
+
lastGroup.endIndex--;
|
|
214
|
+
if (lastGroup.endIndex <= lastGroup.startIndex)
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
// Build a synthetic group for the ellipsis using the last group's format.
|
|
218
|
+
const ellipsisGroup = createTextLayoutGroup(lastGroup.format, lastGroup.endIndex, lastGroup.endIndex);
|
|
219
|
+
const ellipsisOffsetX = lastGroup.offsetX + lastGroup.width;
|
|
220
|
+
ellipsisGroup.positions = [ellipsisW];
|
|
221
|
+
ellipsisGroup.width = ellipsisW;
|
|
222
|
+
ellipsisGroup.offsetX = ellipsisOffsetX;
|
|
223
|
+
ellipsisGroup.ascent = lastGroup.ascent;
|
|
224
|
+
ellipsisGroup.descent = lastGroup.descent;
|
|
225
|
+
ellipsisGroup.leading = lastGroup.leading;
|
|
226
|
+
ellipsisGroup.lineIndex = lastLineIndex;
|
|
227
|
+
ellipsisGroup.offsetY = lastGroup.offsetY;
|
|
228
|
+
ellipsisGroup.height = lastGroup.height;
|
|
229
|
+
groups.push(ellipsisGroup);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
truncated = true;
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
// Emit a bullet glyph at the start of a list-item paragraph.
|
|
236
|
+
function emitBullet() {
|
|
237
|
+
if (!bulletPending)
|
|
238
|
+
return;
|
|
239
|
+
bulletPending = false;
|
|
240
|
+
// Respect listMarker: 'none' suppresses the glyph while keeping paragraph indent.
|
|
241
|
+
if (currentFormat.listMarker === 'none') {
|
|
242
|
+
if (indent <= 0)
|
|
243
|
+
indent = Math.ceil(measure(bulletChar, currentFormat)) + 2;
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const bulletW = measure(bulletChar, currentFormat);
|
|
247
|
+
// Hanging-indent: the bullet occupies the indent area before the text margin.
|
|
248
|
+
const bulletGroup = createTextLayoutGroup(currentFormat, textIndex, textIndex);
|
|
249
|
+
bulletGroup.positions = [bulletW];
|
|
250
|
+
bulletGroup.width = bulletW;
|
|
251
|
+
// Position bullet in the indent area to the left of baseX.
|
|
252
|
+
bulletGroup.offsetX = TEXT_LAYOUT_GUTTER + leftMargin + blockIndent;
|
|
253
|
+
bulletGroup.ascent = ascent;
|
|
254
|
+
bulletGroup.descent = descent;
|
|
255
|
+
bulletGroup.leading = leading;
|
|
256
|
+
bulletGroup.lineIndex = lineIndex;
|
|
257
|
+
bulletGroup.offsetY = offsetY + TEXT_LAYOUT_GUTTER;
|
|
258
|
+
bulletGroup.height = lineHeight;
|
|
259
|
+
groups.push(bulletGroup);
|
|
260
|
+
// An explicit positive indent set by the user always wins, even if it is
|
|
261
|
+
// narrower than the bullet glyph (the text may then overlap the bullet) —
|
|
262
|
+
// the user owns the hanging-indent width. Only when no indent is supplied
|
|
263
|
+
// (indent <= 0) do we auto-compute one wide enough to clear the bullet.
|
|
264
|
+
if (indent <= 0) {
|
|
265
|
+
indent = Math.ceil(bulletW) + 2;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Place a contiguous span [start, end) of text, respecting format range
|
|
269
|
+
// boundaries (may emit multiple groups if the span crosses a format change).
|
|
270
|
+
function placeSpan(start, end) {
|
|
271
|
+
let idx = start;
|
|
272
|
+
while (idx < end) {
|
|
273
|
+
const rangeEnd = Math.min(end, formatRange.end);
|
|
274
|
+
if (idx < rangeEnd) {
|
|
275
|
+
if (activeGroup === null || activeGroup.startIndex !== activeGroup.endIndex) {
|
|
276
|
+
activeGroup = createTextLayoutGroup(formatRange.format, idx, rangeEnd);
|
|
277
|
+
groups.push(activeGroup);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
activeGroup.format = formatRange.format;
|
|
281
|
+
activeGroup.startIndex = idx;
|
|
282
|
+
activeGroup.endIndex = rangeEnd;
|
|
283
|
+
}
|
|
284
|
+
charAdvances(activeGroup.positions, text, currentFormat, idx, rangeEnd, measure, offsetX + baseX());
|
|
285
|
+
const spanWidth = sumAdvances(activeGroup.positions);
|
|
286
|
+
activeGroup.offsetX = offsetX + baseX();
|
|
287
|
+
activeGroup.ascent = ascent;
|
|
288
|
+
activeGroup.descent = descent;
|
|
289
|
+
activeGroup.leading = leading;
|
|
290
|
+
activeGroup.lineIndex = lineIndex;
|
|
291
|
+
activeGroup.offsetY = offsetY + TEXT_LAYOUT_GUTTER;
|
|
292
|
+
activeGroup.width = spanWidth;
|
|
293
|
+
activeGroup.height = lineHeight;
|
|
294
|
+
offsetX += spanWidth;
|
|
295
|
+
idx = rangeEnd;
|
|
296
|
+
}
|
|
297
|
+
if (idx >= end)
|
|
298
|
+
break;
|
|
299
|
+
if (!advanceFormatRange())
|
|
300
|
+
break;
|
|
301
|
+
updateLineMetrics();
|
|
302
|
+
}
|
|
303
|
+
textIndex = end;
|
|
304
|
+
// Step past exhausted format ranges so the next placeSpan call starts
|
|
305
|
+
// in the right range.
|
|
306
|
+
while (textIndex >= formatRange.end && rangeIndex < formatRanges.length - 1) {
|
|
307
|
+
advanceFormatRange();
|
|
308
|
+
updateLineMetrics();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// Measure a span without placing it (saves/restores rangeIndex state).
|
|
312
|
+
function measureSpan(start, end) {
|
|
313
|
+
if (start >= end)
|
|
314
|
+
return { positions: [], width: 0 };
|
|
315
|
+
const savedRangeIndex = rangeIndex;
|
|
316
|
+
const savedFormat = { ...currentFormat };
|
|
317
|
+
const savedFormatRange = formatRange;
|
|
318
|
+
let idx = start;
|
|
319
|
+
const allPositions = [];
|
|
320
|
+
while (idx < end) {
|
|
321
|
+
const rangeEnd = Math.min(end, formatRange.end);
|
|
322
|
+
if (idx < rangeEnd) {
|
|
323
|
+
charAdvances(_charAdvances, text, currentFormat, idx, rangeEnd, measure, offsetX + baseX() + sumAdvances(allPositions));
|
|
324
|
+
for (const p of _charAdvances)
|
|
325
|
+
allPositions.push(p);
|
|
326
|
+
idx = rangeEnd;
|
|
327
|
+
}
|
|
328
|
+
if (idx >= end)
|
|
329
|
+
break;
|
|
330
|
+
if (!advanceFormatRange())
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
// Restore
|
|
334
|
+
rangeIndex = savedRangeIndex;
|
|
335
|
+
formatRange = savedFormatRange;
|
|
336
|
+
currentFormat = savedFormat;
|
|
337
|
+
return { positions: allPositions, width: sumAdvances(allPositions) };
|
|
338
|
+
}
|
|
339
|
+
// Break a run [textIndex, end) across lines when word-wrap is active and the
|
|
340
|
+
// run is a single long word that exceeds the wrap width.
|
|
341
|
+
function breakLongWord(end) {
|
|
342
|
+
let remaining = textIndex;
|
|
343
|
+
while (remaining < end) {
|
|
344
|
+
if (truncated)
|
|
345
|
+
return;
|
|
346
|
+
charAdvances(_charAdvances, text, currentFormat, remaining, end, measure, offsetX + baseX());
|
|
347
|
+
const totalW = sumAdvances(_charAdvances);
|
|
348
|
+
if (offsetX + totalW <= wrapWidth()) {
|
|
349
|
+
placeSpan(remaining, end);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
// Find the largest prefix that fits, stepping by codepoint.
|
|
353
|
+
let count = 0;
|
|
354
|
+
let charCount = 0;
|
|
355
|
+
let w = 0;
|
|
356
|
+
let i = remaining;
|
|
357
|
+
while (i < end && count < _charAdvances.length) {
|
|
358
|
+
const cp = text.codePointAt(i) ?? 0;
|
|
359
|
+
const cpLen = cp > 0xffff ? 2 : 1;
|
|
360
|
+
if (offsetX + w + (_charAdvances[count] ?? 0) > wrapWidth())
|
|
361
|
+
break;
|
|
362
|
+
w += _charAdvances[count] ?? 0;
|
|
363
|
+
count++;
|
|
364
|
+
charCount += cpLen;
|
|
365
|
+
i += cpLen;
|
|
366
|
+
}
|
|
367
|
+
if (charCount === 0) {
|
|
368
|
+
// Always place at least one codepoint.
|
|
369
|
+
const cp = text.codePointAt(remaining) ?? 0;
|
|
370
|
+
charCount = cp > 0xffff ? 2 : 1;
|
|
371
|
+
}
|
|
372
|
+
placeSpan(remaining, remaining + charCount);
|
|
373
|
+
commitLine();
|
|
374
|
+
if (checkTruncation())
|
|
375
|
+
return;
|
|
376
|
+
remaining += charCount;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
// ---------------------------------------------------------------------------
|
|
380
|
+
// Main loop
|
|
381
|
+
// ---------------------------------------------------------------------------
|
|
382
|
+
updateLineMetrics();
|
|
383
|
+
updateParagraphMetrics();
|
|
384
|
+
while (textIndex <= text.length) {
|
|
385
|
+
if (truncated)
|
|
386
|
+
break;
|
|
387
|
+
// Emit pending bullet at the start of each list-item paragraph.
|
|
388
|
+
emitBullet();
|
|
389
|
+
const hasBreak = breakIndex !== -1;
|
|
390
|
+
const breakBeforeSpace = hasBreak && (spaceIndex === -1 || breakIndex <= spaceIndex);
|
|
391
|
+
if (breakBeforeSpace) {
|
|
392
|
+
// Place text up to the line break character.
|
|
393
|
+
if (textIndex <= breakIndex) {
|
|
394
|
+
placeSpan(textIndex, breakIndex);
|
|
395
|
+
activeGroup = null;
|
|
396
|
+
}
|
|
397
|
+
commitLine();
|
|
398
|
+
// The just-committed line (lineIndex - 1) ends a paragraph — do not justify it.
|
|
399
|
+
paragraphLastLines.add(lineIndex - 1);
|
|
400
|
+
if (checkTruncation())
|
|
401
|
+
break;
|
|
402
|
+
if (!multiline)
|
|
403
|
+
break;
|
|
404
|
+
textIndex = breakIndex + 1;
|
|
405
|
+
breakCount++;
|
|
406
|
+
breakIndex = breakCount < lineBreaks.length ? lineBreaks[breakCount] : -1;
|
|
407
|
+
spaceIndex = text.indexOf(' ', textIndex);
|
|
408
|
+
prevSpaceIndex = -2;
|
|
409
|
+
updateParagraphMetrics();
|
|
410
|
+
updateLineMetrics();
|
|
411
|
+
}
|
|
412
|
+
else if (spaceIndex !== -1) {
|
|
413
|
+
// Determine the segment to try placing: from textIndex to end of the
|
|
414
|
+
// word that follows this space (i.e. including the space itself).
|
|
415
|
+
const wordEnd = spaceIndex + 1;
|
|
416
|
+
const segEnd = hasBreak && breakIndex < wordEnd ? breakIndex : wordEnd;
|
|
417
|
+
const { positions: segPos, width: segWidth } = measureSpan(textIndex, segEnd);
|
|
418
|
+
let shouldWrap = wordWrap && containerWidth >= TEXT_LAYOUT_GUTTER * 2 && offsetX + segWidth > wrapWidth();
|
|
419
|
+
// If the overrun is only due to the trailing space, don't wrap.
|
|
420
|
+
if (shouldWrap && segEnd === wordEnd && segPos.length > 0) {
|
|
421
|
+
const trailingSpace = segPos[segPos.length - 1];
|
|
422
|
+
if (offsetX + segWidth - trailingSpace <= wrapWidth())
|
|
423
|
+
shouldWrap = false;
|
|
424
|
+
}
|
|
425
|
+
if (shouldWrap) {
|
|
426
|
+
// Trim trailing space from the last group on the current line.
|
|
427
|
+
const trimTarget = activeGroup ?? (groups.length > 0 ? groups[groups.length - 1] : null);
|
|
428
|
+
if (trimTarget && trimTarget.positions.length > 0 && trimTarget.lineIndex === lineIndex) {
|
|
429
|
+
const trailingW = trimTarget.positions[trimTarget.positions.length - 1];
|
|
430
|
+
trimTarget.width -= trailingW;
|
|
431
|
+
trimTarget.endIndex--;
|
|
432
|
+
}
|
|
433
|
+
commitLine();
|
|
434
|
+
if (checkTruncation())
|
|
435
|
+
break;
|
|
436
|
+
// Skip leading space of the newly wrapped line.
|
|
437
|
+
if (textIndex === prevSpaceIndex + 1)
|
|
438
|
+
textIndex++;
|
|
439
|
+
}
|
|
440
|
+
placeSpan(textIndex, segEnd);
|
|
441
|
+
prevSpaceIndex = spaceIndex;
|
|
442
|
+
spaceIndex = text.indexOf(' ', wordEnd);
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// No more spaces or breaks — place the remainder of the text.
|
|
446
|
+
if (textIndex >= text.length)
|
|
447
|
+
break;
|
|
448
|
+
if (wordWrap && containerWidth >= TEXT_LAYOUT_GUTTER * 2) {
|
|
449
|
+
breakLongWord(text.length);
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
placeSpan(textIndex, text.length);
|
|
453
|
+
}
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// Commit the final line.
|
|
458
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
459
|
+
const g = groups[i];
|
|
460
|
+
if (g.lineIndex < lineIndex)
|
|
461
|
+
break;
|
|
462
|
+
g.ascent = maxAscent || g.ascent;
|
|
463
|
+
g.height = maxLineHeight || g.height;
|
|
464
|
+
}
|
|
465
|
+
// The current lineIndex is always the last paragraph's final line (never justified).
|
|
466
|
+
paragraphLastLines.add(lineIndex);
|
|
467
|
+
}
|
|
468
|
+
// ---------------------------------------------------------------------------
|
|
469
|
+
// Alignment pass
|
|
470
|
+
// ---------------------------------------------------------------------------
|
|
471
|
+
function applyAlignment(groups, containerWidth, lineWidths, direction, justification, paragraphLastLines, text) {
|
|
472
|
+
for (const g of groups) {
|
|
473
|
+
const lineW = lineWidths[g.lineIndex];
|
|
474
|
+
const align = g.format.align ?? 'left';
|
|
475
|
+
let shift = 0;
|
|
476
|
+
// Resolve direction-relative aliases.
|
|
477
|
+
const resolved = align === 'start'
|
|
478
|
+
? direction === 'RightToLeft'
|
|
479
|
+
? 'right'
|
|
480
|
+
: 'left'
|
|
481
|
+
: align === 'end'
|
|
482
|
+
? direction === 'RightToLeft'
|
|
483
|
+
? 'left'
|
|
484
|
+
: 'right'
|
|
485
|
+
: align;
|
|
486
|
+
if (resolved === 'right') {
|
|
487
|
+
shift = containerWidth - lineW - TEXT_LAYOUT_GUTTER * 2;
|
|
488
|
+
}
|
|
489
|
+
else if (resolved === 'center') {
|
|
490
|
+
shift = (containerWidth - lineW - TEXT_LAYOUT_GUTTER * 2) / 2;
|
|
491
|
+
}
|
|
492
|
+
else if (resolved === 'justify' && justification !== 'none') {
|
|
493
|
+
// Justify is applied per-line across groups on the same line; handled below.
|
|
494
|
+
}
|
|
495
|
+
if (shift !== 0)
|
|
496
|
+
g.offsetX += shift;
|
|
497
|
+
}
|
|
498
|
+
// Inter-word justification pass: for each line where align === 'justify',
|
|
499
|
+
// distribute residual width across inter-word spaces. The last line of each
|
|
500
|
+
// paragraph (tracked in paragraphLastLines) is left-aligned per CSS standard.
|
|
501
|
+
justifyLines(groups, containerWidth, lineWidths, justification, paragraphLastLines, text);
|
|
502
|
+
}
|
|
503
|
+
function justifyLines(groups, containerWidth, lineWidths, justification, paragraphLastLines, text) {
|
|
504
|
+
if (justification === 'none')
|
|
505
|
+
return;
|
|
506
|
+
const lineCount = lineWidths.length;
|
|
507
|
+
for (let li = 0; li < lineCount; li++) {
|
|
508
|
+
if (paragraphLastLines.has(li))
|
|
509
|
+
continue;
|
|
510
|
+
const lineGroups = [];
|
|
511
|
+
for (const g of groups) {
|
|
512
|
+
if (g.lineIndex === li && g.format.align === 'justify')
|
|
513
|
+
lineGroups.push(g);
|
|
514
|
+
}
|
|
515
|
+
if (lineGroups.length === 0)
|
|
516
|
+
continue;
|
|
517
|
+
const lineW = lineWidths[li];
|
|
518
|
+
const available = containerWidth - TEXT_LAYOUT_GUTTER * 2;
|
|
519
|
+
const residual = available - lineW;
|
|
520
|
+
if (residual <= 0)
|
|
521
|
+
continue;
|
|
522
|
+
if (justification === 'interCharacter') {
|
|
523
|
+
let charCount = 0;
|
|
524
|
+
for (const g of lineGroups)
|
|
525
|
+
charCount += g.positions.length;
|
|
526
|
+
const gapCount = Math.max(0, charCount - 1);
|
|
527
|
+
if (gapCount === 0)
|
|
528
|
+
continue;
|
|
529
|
+
const extraPerGap = residual / gapCount;
|
|
530
|
+
let accumulated = 0;
|
|
531
|
+
const lastGroup = lineGroups[lineGroups.length - 1];
|
|
532
|
+
for (const g of lineGroups) {
|
|
533
|
+
g.offsetX += accumulated;
|
|
534
|
+
let groupExtra = 0;
|
|
535
|
+
const lastPos = g === lastGroup ? g.positions.length - 1 : g.positions.length;
|
|
536
|
+
for (let ci = 0; ci < lastPos; ci++) {
|
|
537
|
+
g.positions[ci] += extraPerGap;
|
|
538
|
+
accumulated += extraPerGap;
|
|
539
|
+
groupExtra += extraPerGap;
|
|
540
|
+
}
|
|
541
|
+
g.width += groupExtra;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
// interWord: count actual space characters across all groups on the line.
|
|
546
|
+
let spaceCount = 0;
|
|
547
|
+
for (const g of lineGroups) {
|
|
548
|
+
for (let ci = 0; ci < g.positions.length; ci++) {
|
|
549
|
+
if (text.charCodeAt(g.startIndex + ci) === 0x20)
|
|
550
|
+
spaceCount++;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (spaceCount === 0)
|
|
554
|
+
continue;
|
|
555
|
+
const extraPerSpace = residual / spaceCount;
|
|
556
|
+
let accumulated = 0;
|
|
557
|
+
for (const g of lineGroups) {
|
|
558
|
+
g.offsetX += accumulated;
|
|
559
|
+
let groupExtra = 0;
|
|
560
|
+
for (let ci = 0; ci < g.positions.length; ci++) {
|
|
561
|
+
if (text.charCodeAt(g.startIndex + ci) === 0x20) {
|
|
562
|
+
g.positions[ci] += extraPerSpace;
|
|
563
|
+
accumulated += extraPerSpace;
|
|
564
|
+
groupExtra += extraPerSpace;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
g.width += groupExtra;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// ---------------------------------------------------------------------------
|
|
573
|
+
// Line metrics pass
|
|
574
|
+
// ---------------------------------------------------------------------------
|
|
575
|
+
function writeLineMetrics(out, groups) {
|
|
576
|
+
out.lineAscents.length = 0;
|
|
577
|
+
out.lineDescents.length = 0;
|
|
578
|
+
out.lineHeights.length = 0;
|
|
579
|
+
out.lineLeadings.length = 0;
|
|
580
|
+
out.lineWidths.length = 0;
|
|
581
|
+
out.textWidth = 0;
|
|
582
|
+
out.textHeight = 0;
|
|
583
|
+
out.numLines = 0;
|
|
584
|
+
for (const g of groups) {
|
|
585
|
+
while (g.lineIndex >= out.numLines) {
|
|
586
|
+
out.lineAscents.push(0);
|
|
587
|
+
out.lineDescents.push(0);
|
|
588
|
+
out.lineHeights.push(0);
|
|
589
|
+
out.lineLeadings.push(0);
|
|
590
|
+
out.lineWidths.push(0);
|
|
591
|
+
out.numLines++;
|
|
592
|
+
}
|
|
593
|
+
const li = g.lineIndex;
|
|
594
|
+
out.lineAscents[li] = Math.max(out.lineAscents[li], g.ascent);
|
|
595
|
+
out.lineDescents[li] = Math.max(out.lineDescents[li], g.descent);
|
|
596
|
+
out.lineHeights[li] = Math.max(out.lineHeights[li], g.height);
|
|
597
|
+
if (g.leading > out.lineLeadings[li])
|
|
598
|
+
out.lineLeadings[li] = g.leading;
|
|
599
|
+
const rightEdge = g.offsetX - TEXT_LAYOUT_GUTTER + g.width;
|
|
600
|
+
if (rightEdge > out.lineWidths[li])
|
|
601
|
+
out.lineWidths[li] = rightEdge;
|
|
602
|
+
if (rightEdge > out.textWidth)
|
|
603
|
+
out.textWidth = rightEdge;
|
|
604
|
+
const bottom = Math.ceil(g.offsetY - TEXT_LAYOUT_GUTTER + g.ascent + g.descent);
|
|
605
|
+
if (bottom > out.textHeight)
|
|
606
|
+
out.textHeight = bottom;
|
|
607
|
+
}
|
|
608
|
+
if (out.numLines === 0)
|
|
609
|
+
out.numLines = 1;
|
|
610
|
+
}
|
|
611
|
+
// ---------------------------------------------------------------------------
|
|
612
|
+
// Public helpers
|
|
613
|
+
// ---------------------------------------------------------------------------
|
|
614
|
+
export function createTextLayoutResult() {
|
|
615
|
+
return {
|
|
616
|
+
groups: [],
|
|
617
|
+
lineAscents: [],
|
|
618
|
+
lineDescents: [],
|
|
619
|
+
lineHeights: [],
|
|
620
|
+
lineLeadings: [],
|
|
621
|
+
lineWidths: [],
|
|
622
|
+
numLines: 0,
|
|
623
|
+
textHeight: 0,
|
|
624
|
+
textWidth: 0,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
export function getTextLayoutIsTruncated(layout, params) {
|
|
628
|
+
if (params.maxLines === undefined || params.maxLines < 0)
|
|
629
|
+
return false;
|
|
630
|
+
return layout.numLines >= params.maxLines && layout.groups.length > 0;
|
|
631
|
+
}
|
|
632
|
+
//# sourceMappingURL=textLayout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textLayout.js","sourceRoot":"","sources":["../src/textLayout.ts"],"names":[],"mappings":"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"}
|