@weasel-js/text 1.13.0-rc.0 → 1.14.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/chunk-FODNMBHI.js +2256 -0
- package/dist/chunk-FODNMBHI.js.map +1 -0
- package/dist/index.d.ts +93 -17
- package/dist/index.js +162 -348
- package/dist/index.js.map +1 -1
- package/dist/{test-seams-B0BDm36M.d.ts → test-seams-DHGfE_6p.d.ts} +180 -22
- package/dist/test-seams.d.ts +1 -1
- package/dist/test-seams.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-ADRQIIHS.js +0 -1043
- package/dist/chunk-ADRQIIHS.js.map +0 -1
|
@@ -0,0 +1,2256 @@
|
|
|
1
|
+
import { isSolidPaint, resolveFill, resolveScreenLength, fillHasInk, strokeHasInk, paintKey, strokeKey } from '@weasel-js/paint';
|
|
2
|
+
import { cssFamilyName, resolveFontVariant, syntheticBoldGrowth, glyphOutline, faceMetricsOf, glyphGeneration, faceGeneration, metricsOf, warnNoMetrics, resolveColorCluster, glyphIn, resolveGlyph } from '@weasel-js/font';
|
|
3
|
+
import { mergeRegion, growRegion, pathToD, pathFromD } from '@weasel-js/geom';
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/layout/tabStops.ts
|
|
12
|
+
var DEFAULT_TAB_SIZE = 8;
|
|
13
|
+
function tabAdvance(x, stop, min) {
|
|
14
|
+
if (!(stop > 0)) return 0;
|
|
15
|
+
const toNext = (Math.floor(x / stop) + 1) * stop - x;
|
|
16
|
+
return toNext < min ? toNext + stop : toNext;
|
|
17
|
+
}
|
|
18
|
+
function widthWithTabs(start, end, tabs2, stopOf2, flatWidth2, piece) {
|
|
19
|
+
let x = 0;
|
|
20
|
+
let from = start;
|
|
21
|
+
const lay = (to) => {
|
|
22
|
+
if (to <= from) return;
|
|
23
|
+
piece?.(from, to, x);
|
|
24
|
+
x += flatWidth2(from, to);
|
|
25
|
+
};
|
|
26
|
+
for (const t of tabs2) {
|
|
27
|
+
if (t < start) continue;
|
|
28
|
+
if (t >= end) break;
|
|
29
|
+
lay(t);
|
|
30
|
+
const { stop, min } = stopOf2(t);
|
|
31
|
+
x += tabAdvance(x, stop, min);
|
|
32
|
+
from = t + 1;
|
|
33
|
+
}
|
|
34
|
+
lay(end);
|
|
35
|
+
return x;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/textStyle.ts
|
|
39
|
+
function resolveAlign(align, direction) {
|
|
40
|
+
if (align === "start" || align === "justify") return direction === "rtl" ? "right" : "left";
|
|
41
|
+
if (align === "end") return direction === "rtl" ? "left" : "right";
|
|
42
|
+
return align;
|
|
43
|
+
}
|
|
44
|
+
var DEFAULT_FILL = { kind: "solid", color: "#000" };
|
|
45
|
+
var DEFAULT_TEXT_FILL = { paint: DEFAULT_FILL };
|
|
46
|
+
function paintColor(p) {
|
|
47
|
+
return isSolidPaint(p) ? p.color : "#000";
|
|
48
|
+
}
|
|
49
|
+
var mixedColor = "";
|
|
50
|
+
var mixed = "";
|
|
51
|
+
function defaultSelectionBackground(textColor) {
|
|
52
|
+
if (textColor !== mixedColor) {
|
|
53
|
+
mixed = `color-mix(in srgb, ${textColor} 25%, transparent)`;
|
|
54
|
+
mixedColor = textColor;
|
|
55
|
+
}
|
|
56
|
+
return mixed;
|
|
57
|
+
}
|
|
58
|
+
var DEFAULT_TEXT_STYLE = {
|
|
59
|
+
fontSize: 16,
|
|
60
|
+
fontFamily: "sans-serif",
|
|
61
|
+
fontWeight: 400,
|
|
62
|
+
fontStyle: "normal",
|
|
63
|
+
align: "left",
|
|
64
|
+
direction: "auto",
|
|
65
|
+
lineHeight: 1.2,
|
|
66
|
+
tabSize: DEFAULT_TAB_SIZE,
|
|
67
|
+
wrap: false,
|
|
68
|
+
fill: null,
|
|
69
|
+
caretColor: paintColor(DEFAULT_FILL),
|
|
70
|
+
selectionBackground: defaultSelectionBackground(paintColor(DEFAULT_FILL)),
|
|
71
|
+
selectionColor: null,
|
|
72
|
+
letterSpacing: 0,
|
|
73
|
+
underline: false,
|
|
74
|
+
strikethrough: false,
|
|
75
|
+
overline: false,
|
|
76
|
+
textTransform: "none",
|
|
77
|
+
fontVariantCaps: "normal"
|
|
78
|
+
};
|
|
79
|
+
var NOTHING = Object.freeze({});
|
|
80
|
+
function resolveTextStyle(style, paint, scale = 1) {
|
|
81
|
+
const fill2 = resolveFill(paint?.fill);
|
|
82
|
+
const stroke = paint?.stroke ?? void 0;
|
|
83
|
+
if (!style) {
|
|
84
|
+
return fill2 === null && stroke === void 0 ? DEFAULT_TEXT_STYLE : {
|
|
85
|
+
...DEFAULT_TEXT_STYLE,
|
|
86
|
+
fill: fill2,
|
|
87
|
+
caretColor: paintColor(fill2?.paint ?? null),
|
|
88
|
+
selectionBackground: defaultSelectionBackground(paintColor(fill2?.paint ?? null)),
|
|
89
|
+
...stroke !== void 0 ? { stroke } : NOTHING
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const caretColor = style.caretColor ?? paintColor(fill2?.paint ?? null);
|
|
93
|
+
let selectionBackground;
|
|
94
|
+
if (style.selectionBackground === "none") {
|
|
95
|
+
selectionBackground = null;
|
|
96
|
+
} else if (style.selectionBackground != null) {
|
|
97
|
+
selectionBackground = style.selectionBackground;
|
|
98
|
+
} else {
|
|
99
|
+
selectionBackground = defaultSelectionBackground(caretColor);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
fontSize: resolveScreenLength(style.fontSize ?? DEFAULT_TEXT_STYLE.fontSize, scale),
|
|
103
|
+
fontFamily: style.fontFamily ?? DEFAULT_TEXT_STYLE.fontFamily,
|
|
104
|
+
fontWeight: style.fontWeight ?? DEFAULT_TEXT_STYLE.fontWeight,
|
|
105
|
+
fontStyle: style.fontStyle ?? DEFAULT_TEXT_STYLE.fontStyle,
|
|
106
|
+
align: style.align ?? DEFAULT_TEXT_STYLE.align,
|
|
107
|
+
direction: style.direction ?? DEFAULT_TEXT_STYLE.direction,
|
|
108
|
+
lineHeight: style.lineHeight ?? DEFAULT_TEXT_STYLE.lineHeight,
|
|
109
|
+
tabSize: style.tabSize ?? DEFAULT_TEXT_STYLE.tabSize,
|
|
110
|
+
wrap: style.wrap ?? DEFAULT_TEXT_STYLE.wrap,
|
|
111
|
+
fill: fill2,
|
|
112
|
+
caretColor,
|
|
113
|
+
selectionBackground,
|
|
114
|
+
selectionColor: style.selectionColor ?? null,
|
|
115
|
+
letterSpacing: resolveScreenLength(style.letterSpacing ?? DEFAULT_TEXT_STYLE.letterSpacing, scale),
|
|
116
|
+
underline: style.underline ?? DEFAULT_TEXT_STYLE.underline,
|
|
117
|
+
strikethrough: style.strikethrough ?? DEFAULT_TEXT_STYLE.strikethrough,
|
|
118
|
+
overline: style.overline ?? DEFAULT_TEXT_STYLE.overline,
|
|
119
|
+
textTransform: style.textTransform ?? DEFAULT_TEXT_STYLE.textTransform,
|
|
120
|
+
fontVariantCaps: style.fontVariantCaps ?? DEFAULT_TEXT_STYLE.fontVariantCaps,
|
|
121
|
+
...style.script !== void 0 ? { script: style.script } : NOTHING,
|
|
122
|
+
...style.lang ? { lang: style.lang } : NOTHING,
|
|
123
|
+
...stroke !== void 0 ? { stroke } : NOTHING
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function fontString(s) {
|
|
127
|
+
return `${s.fontStyle} ${s.fontWeight} ${s.fontSize}px ${cssFamilyName(s.fontFamily)}`;
|
|
128
|
+
}
|
|
129
|
+
var registered = null;
|
|
130
|
+
function registerShaper(shaper) {
|
|
131
|
+
registered = shaper;
|
|
132
|
+
return () => {
|
|
133
|
+
if (registered === shaper) registered = null;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function registeredShaper() {
|
|
137
|
+
return registered;
|
|
138
|
+
}
|
|
139
|
+
var bytesOf = /* @__PURE__ */ new WeakMap();
|
|
140
|
+
function shapeableBytes(resolved2) {
|
|
141
|
+
const face = resolved2.outlineFace;
|
|
142
|
+
if (!face) return null;
|
|
143
|
+
let bytes = bytesOf.get(face);
|
|
144
|
+
if (bytes === void 0) {
|
|
145
|
+
bytes = face.embedding?.().sfnt ?? null;
|
|
146
|
+
bytesOf.set(face, bytes);
|
|
147
|
+
}
|
|
148
|
+
return bytes;
|
|
149
|
+
}
|
|
150
|
+
function shapesWithFeature(family, weight, style, tag, shaper = registered) {
|
|
151
|
+
if (shaper === null) return false;
|
|
152
|
+
const bytes = shapeableBytes(resolveFontVariant(family, weight, style));
|
|
153
|
+
return bytes !== null && shaper.hasFeature(bytes, tag);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// src/layout/decorationMetrics.ts
|
|
157
|
+
var DECORATION_KINDS = ["underline", "strikethrough", "overline"];
|
|
158
|
+
var DEFAULT_DECORATION_METRICS = Object.freeze({
|
|
159
|
+
underline: Object.freeze({ offset: 0.1, thickness: 0.05 }),
|
|
160
|
+
strikethrough: Object.freeze({ offset: -0.3, thickness: 0.05 }),
|
|
161
|
+
overline: Object.freeze({ offset: -0.9, thickness: 0.05 })
|
|
162
|
+
});
|
|
163
|
+
var resolved = /* @__PURE__ */ new WeakMap();
|
|
164
|
+
function decorationMetrics(face) {
|
|
165
|
+
if (!face) return DEFAULT_DECORATION_METRICS;
|
|
166
|
+
let out = resolved.get(face);
|
|
167
|
+
if (!out) {
|
|
168
|
+
const underline = face.underline ?? DEFAULT_DECORATION_METRICS.underline;
|
|
169
|
+
out = Object.freeze({
|
|
170
|
+
underline,
|
|
171
|
+
strikethrough: face.strikethrough ?? DEFAULT_DECORATION_METRICS.strikethrough,
|
|
172
|
+
overline: Object.freeze({ offset: DEFAULT_DECORATION_METRICS.overline.offset, thickness: underline.thickness })
|
|
173
|
+
});
|
|
174
|
+
resolved.set(face, out);
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
function decorationRule(kind, baselineY, fontSize, face) {
|
|
179
|
+
const m = decorationMetrics(face)[kind];
|
|
180
|
+
const y0 = baselineY + fontSize * m.offset;
|
|
181
|
+
return { y0, y1: y0 + fontSize * m.thickness };
|
|
182
|
+
}
|
|
183
|
+
function lineDecorations(runs, faceOf, paintOf2) {
|
|
184
|
+
const rules = [];
|
|
185
|
+
let open = null;
|
|
186
|
+
const close = () => {
|
|
187
|
+
const s = open;
|
|
188
|
+
open = null;
|
|
189
|
+
if (!s || s.x1 <= s.x0) return;
|
|
190
|
+
for (const kind of DECORATION_KINDS) {
|
|
191
|
+
if (!s.style[kind]) continue;
|
|
192
|
+
const { y0, y1 } = decorationRule(kind, s.baselineY, s.style.fontSize, s.face);
|
|
193
|
+
rules.push({ kind, x0: s.x0, y0, x1: s.x1, y1, run: s.run });
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
add(g) {
|
|
198
|
+
const style = runs[g.run];
|
|
199
|
+
const paint = style.underline || style.strikethrough || style.overline ? paintOf2(g.run) : null;
|
|
200
|
+
if (paint === null) {
|
|
201
|
+
if (open !== null) close();
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const face = faceOf(g.run);
|
|
205
|
+
const joins = open !== null && DECORATION_KINDS.every((kind) => open.style[kind] === style[kind]) && open.style.fontSize === style.fontSize && open.face === face && open.baselineY === g.baselineY && open.paint === paint;
|
|
206
|
+
if (joins) {
|
|
207
|
+
open.x1 = g.x + g.step;
|
|
208
|
+
} else {
|
|
209
|
+
close();
|
|
210
|
+
open = { run: g.run, style, face, paint, baselineY: g.baselineY, x0: g.x, x1: g.x + g.step };
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
end() {
|
|
214
|
+
close();
|
|
215
|
+
return rules;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/layout/lineBreak/lineBreakTable.ts
|
|
221
|
+
var lineBreakTable_exports = {};
|
|
222
|
+
__export(lineBreakTable_exports, {
|
|
223
|
+
AK: () => AK,
|
|
224
|
+
AL: () => AL,
|
|
225
|
+
AP: () => AP,
|
|
226
|
+
AS: () => AS,
|
|
227
|
+
B2: () => B2,
|
|
228
|
+
BA: () => BA,
|
|
229
|
+
BB: () => BB,
|
|
230
|
+
BK: () => BK,
|
|
231
|
+
CB: () => CB,
|
|
232
|
+
CL: () => CL,
|
|
233
|
+
CLASS_MASK: () => CLASS_MASK,
|
|
234
|
+
CM: () => CM,
|
|
235
|
+
CP: () => CP,
|
|
236
|
+
CR: () => CR,
|
|
237
|
+
EAST_ASIAN: () => EAST_ASIAN,
|
|
238
|
+
EB: () => EB,
|
|
239
|
+
EM: () => EM,
|
|
240
|
+
EX: () => EX,
|
|
241
|
+
GL: () => GL,
|
|
242
|
+
H2: () => H2,
|
|
243
|
+
H3: () => H3,
|
|
244
|
+
HL: () => HL,
|
|
245
|
+
HY: () => HY,
|
|
246
|
+
ID: () => ID,
|
|
247
|
+
IN: () => IN,
|
|
248
|
+
IS: () => IS,
|
|
249
|
+
JL: () => JL,
|
|
250
|
+
JT: () => JT,
|
|
251
|
+
JV: () => JV,
|
|
252
|
+
LF: () => LF,
|
|
253
|
+
NL: () => NL,
|
|
254
|
+
NS: () => NS,
|
|
255
|
+
NU: () => NU,
|
|
256
|
+
OP: () => OP,
|
|
257
|
+
PICTOGRAPHIC_CN: () => PICTOGRAPHIC_CN,
|
|
258
|
+
PO: () => PO,
|
|
259
|
+
PR: () => PR,
|
|
260
|
+
QU: () => QU,
|
|
261
|
+
QU_PF: () => QU_PF,
|
|
262
|
+
QU_PI: () => QU_PI,
|
|
263
|
+
RI: () => RI,
|
|
264
|
+
SP: () => SP,
|
|
265
|
+
SY: () => SY,
|
|
266
|
+
UNICODE_VERSION: () => UNICODE_VERSION,
|
|
267
|
+
VF: () => VF,
|
|
268
|
+
VI: () => VI,
|
|
269
|
+
WJ: () => WJ,
|
|
270
|
+
ZW: () => ZW,
|
|
271
|
+
ZWJ: () => ZWJ,
|
|
272
|
+
lineBreakPropsOf: () => lineBreakPropsOf
|
|
273
|
+
});
|
|
274
|
+
var UNICODE_VERSION = "16.0.0";
|
|
275
|
+
var BK = 0;
|
|
276
|
+
var CR = 1;
|
|
277
|
+
var LF = 2;
|
|
278
|
+
var NL = 3;
|
|
279
|
+
var SP = 4;
|
|
280
|
+
var ZW = 5;
|
|
281
|
+
var ZWJ = 6;
|
|
282
|
+
var CM = 7;
|
|
283
|
+
var WJ = 8;
|
|
284
|
+
var GL = 9;
|
|
285
|
+
var BA = 10;
|
|
286
|
+
var BB = 11;
|
|
287
|
+
var B2 = 12;
|
|
288
|
+
var HY = 13;
|
|
289
|
+
var CB = 14;
|
|
290
|
+
var CL = 15;
|
|
291
|
+
var CP = 16;
|
|
292
|
+
var EX = 17;
|
|
293
|
+
var IN = 18;
|
|
294
|
+
var NS = 19;
|
|
295
|
+
var OP = 20;
|
|
296
|
+
var QU = 21;
|
|
297
|
+
var IS = 22;
|
|
298
|
+
var NU = 23;
|
|
299
|
+
var PO = 24;
|
|
300
|
+
var PR = 25;
|
|
301
|
+
var SY = 26;
|
|
302
|
+
var AL = 27;
|
|
303
|
+
var HL = 28;
|
|
304
|
+
var ID = 29;
|
|
305
|
+
var EB = 30;
|
|
306
|
+
var EM = 31;
|
|
307
|
+
var H2 = 32;
|
|
308
|
+
var H3 = 33;
|
|
309
|
+
var JL = 34;
|
|
310
|
+
var JV = 35;
|
|
311
|
+
var JT = 36;
|
|
312
|
+
var RI = 37;
|
|
313
|
+
var AK = 38;
|
|
314
|
+
var AP = 39;
|
|
315
|
+
var AS = 40;
|
|
316
|
+
var VF = 41;
|
|
317
|
+
var VI = 42;
|
|
318
|
+
var QU_PI = 43;
|
|
319
|
+
var QU_PF = 44;
|
|
320
|
+
var CLASS_MASK = 63;
|
|
321
|
+
var EAST_ASIAN = 64;
|
|
322
|
+
var PICTOGRAPHIC_CN = 128;
|
|
323
|
+
var ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+,-./:;<=>?@[]^_{|}~";
|
|
324
|
+
var PALETTE = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 71, 73, 74, 79, 81, 82, 83, 84, 88, 89, 91, 93, 94, 95, 96, 97, 98, 155, 157];
|
|
325
|
+
var RUNS = 2787;
|
|
326
|
+
var PACKED = "9H1K1C2A1B18H1E1R1V1b1Z1Y1b1V1U1Q1b1Z1W1N1W1a10X2W3b1R27b1U1Z1Q29b1U1K1P1b6H1D26H1J1U1Y3Z5b1n1b1K2b1Y1Z2b1L6b1o3b1U520b1L3b1L18b1L32b79H1J12H7J13H14b1W260b7H255b1W1K4b1Z1b45H1K1H1b2H1b2H1R1H8b27c4b4c13b6X3b3Y2W2b11H1R1H3R43b21H10X1Y2X3b1H99b1R1b7H1X1b6H2b2H1b4H2b10X23b1H30b27H91b11H15b10X33b9H4b1W1R3b1H2Z22b4H1b9H1b3H1b5H43b3H52b2X5b9H42b24H1X33H54b3H1b18H1b7H10b2H2K10X17b3H56b1H1b7H2b2H2b3H9b1H10b2H2b10X2b2Y5b1Y1b1Z2b1H2b3H56b1H1b5H4b2H2b3H3b1H20b10X2H3b1H11b3H56b1H1b8H1b3H1b3H20b2H2b10X1b1Z8b6H1b3H56b1H1b7H2b2H2b3H7b3H10b2H2b10X18b1H59b5H3b3H1b4H9b1H14b10X9b1Z6b5H55b1H1b7H1b3H1b4H7b2H11b2H2b10X7b1L9b3H1L55b1H1b7H1b3H1b4H7b2H11b2H2b10X3b1H12b4H55b2H1b7H1b3H1b4H9b1H10b2H2b10X9b1Y7b3H70b1H4b6H1b1H1b8H6b10X2b2H61b1H2b7H4b1Z7b8H1b10X2K85b1H2b9H11b7H1b10X39b4L1b2L1J2L1K1J5R1J1b1R3b2H6b10X10b1K1H1b1H1b1H1U1P1U1P2H49b14H1K5H1K2H5b11H1b36H1b2K6b1H9b2L1K1L5b2J80b20H1b10X2K10b4H4b3H1b3H2b7H3b4H13b12H1b1H10X4H98b96(72f88g349b3H1b1K158b1K639b1K26b1U1P78b3K36b4H28b3H2K27b2H30b2H64b32H2K1T1b1K1b1K1Z1b1H2b10X24b2R2K1L1b2R1b3H1J1H10X107b2H34b1H118b12H4b12H8b2R10X128b11X60b5H57b10H1b29H2b1H10X6b10X22b31H49b5H47i16H1m8i1b2K10k2K1d4K10d9H9d3K3H30b13H2b10X6b38k12H2l48b20H3b5K10X6b10X36b2K80b3H1b21H4b1H6b1H2b3H198b13H1J46H1J3H509b1L2b7K1J3K1F1H1G2H1K1J2K1M3b1n1o1U2n1o1U1n4b3S1K2A5H1J8Y1b1n1o1b2T6b1W1U1P3T12b1K1Y4K1b3K1I5b10H13b1U1P14b1U1P17b7Z1Y1Z1y12Z1Y4Z1Y2Z1Y1Z1Y15Z33H18b1Y5b1Y12b1Z251b2Z219b1S24b1U1P1U1P14b2!13b1w1s190b4z3b1!2d1!521b2z1b4d16b2!2b1d1b3d1e2d16b8z1b3d12b12z20b1d22b1!10b6z3b1z13b1z8b2z17b2!5d2!3d4b1d1z3d1b1d1!3b2d2b1d2b3d8b1!6b1d2!1d1!1b2d1e1!2b1!7d1z2b2d2#2e26b1z35b1z1b1z4b3z1b1z3b6V1b2R1d3b1U1P1U1P1U1P1U1P1U1P1U1P1U1P31b3z24b1z14b1z5b1U1P31b1U1P1U1P1U1P1U1P1U1P403b1U1P1U1P1U1P1U1P1U1P1U1P1U1P1U1P1U1P1U1P1U1P63b1U1P1U1P32b1U1P285b2z51b1z4b1z409b3H7b1R3K1b1R1K112b1K14b1H96b32H2V1n1o1n1o3V1n1o1V1n1o8K1b1K1U1K2b1n1o2b1n1o1U1P1U1P1U1P1U1P4K1R1b2K1b2K5b2M3K1b2K1U8K1b1K1b2K3b2R1U1Q1U1Q1U1Q1U1Q1K34b26!1b89!12b214!26b16!1r2s2!1v2!1w1s1w1s1w1s1w1s1w1s2!1w1s1w1s1w1s1w1s1v1w2s10!6p5!1p5!2v2!1d1b1v1!1v1!1v1!1v1!1v25!1v31!1v1!1v1!1v6!1v6!2v2b2p4v1!2v1!1v1!1v1!1v1!1v25!1v31!1v1!1v1!1v6!1v6!2v4!4v1!5b43!1b94!1b86!9b1!16v31!1b40!8b7024!64z21013!1v1143!3b55!55b2K269b1K1R1K16b10X69b4H1b10H32b2H80b2H1b5K266b1H3b1H4b1H23b5H4b1H11b1Y59b2L2R8b2H50b18H8b2K10X6b18H10b1L2b1H10X28b8H2K23b13H12b29(3b4H47i13H1m6d3K4d1b1K10k4b2d5b1H10b10X6b41k14H9b3K1H8K2H2b10k2b1d3K27b3H50b1H1b3H2b2H5b2H1b1H41b5H2K3b2H236b8H1K2H2b10X6b1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&1%27&12b23f4b49g8452b512!29b1c1H10c1b13c1b5c1b1c1b2c1b2c1b10c494b1P1U188b1Y3b16H3s2v2t1w1s1u6b1J1H1J1H1J1H2J1H1J1H1J1H2J1H5!1w1s1w1s1w1s1w1s1w1s1w1s1w1s1w1s2!1w1s7!1s1!1s1b2v2t1!1w1s1w1s1w1s8!1b1!1y1x1!147b1I1b1t2!1y1x2!1w1s2!1s1!1s11!2v3!1t27!1w1!1s29!1w1!1s1!1w2s1w2s1v1!10v45!2v31!3b6!2b6!2b6!2b3!3b1x1y3!2y1b7z10b3H1O259b3K250b1H226b1H149b5H36b1K48b1K207b10X941b1K199b1K225b3H1b2H5b4H40b3H4b1H16b8K141b2H9b6K1S66b7K484b4H8b10X6b10X31b5H1K316b2H1K78b4H70b11H49b4H122b3H2j51i14H1m2K5d4b20d10k1H2i2H1i9b1J3H45b11H2b1X4K1H10b1X34b10X6b3H36b14H1b10X4K1b2H44b1H1b1L10b3H48b14H4b2K1b1K4H1b2H10X1b1L1b3K76b12H2K1b2K1b1H2b1H103b1K53b12H5b10X6b4H1b8i2b2i2b22i1b7i1b2i1b5i1b2H1K7H2b2H2b2H1m2b1k6b1H5b1K2k2i2H2b7H3b5H11b10k1b1k2b1k1b2k36i1b1d9H1b1H2b1H1b4H1b4H1m1j1H3d1b2d8b2H82b18H4b4K1b10X2K2b1H81b20H12b10X213b7H2b9H1L2K2R3b15K4b2H82b17H2K13b10X6b13L62b13H8b10X6b20X57b15H4b10X2b3K237b15H165b10X22b7i2b1i2b8i1b2i1b24i6H1b2H2b3H1m1j1H1j2H3K9b10k119b7H2b7H1b1L1b1H28b10H40b7H1b4H1L1b4K1L1b1H9b11H46b16H3K1b3L2K93b10L230b10X53b8H1b8H1b5K10b10X22b1L1R32b22H1b14H122b6H3b1H1b2H1b7H1b1H8b10X48b5H1b2H1b5H8b10X310b18k1K4H2K7b2H1j1H13i1b34i7H3b4H1m2K11d10k1H130b4Y30b1K1136b5K3555b3U3P36b1P3b1U1P1U1P239b1U2P179b1U7J1U1P3J1U1P1U1P1H6b15H4472b1U1P6960b30k18H10k2342b10X4b2K80b10X38b5H1K58b7H3K10b1K11b10X532b2K10X285b2K182b1H1b55H7b4H77b4v1q11b2p14b6136!8b768!470z41b1z9!8935b4z1b7z1b2z1b291!15b1v29b3v2b1v14b4v8b396!2465b2H1K4H4172b10X518b46H2b23H542b5H3b22H2b7H30b4H148b3H187b87z9b23z1111b50X512b55H4b50H8b1H14b1H2b4K16b5H1b15H1360b7H1b17H2b7H1b2H1b5H100b1H160b7H9b10X356b1H61b4H10X5b1Z492b4H10X244b2H1b10X725b7H109b7H5b10X4b2U844b1Y3b1Y847b4d1!39d4*100d12*15d2*15d1*14d1!1*37d10*142b1z2b10z19b56*26h3!13*44!4*9!7*2!14*6!154*33!12d9!1d70!1d7!1#14!8d2b2d21!2z5!1z5!3#2!1#2!1#2e2d5!12d17!3d1!3d3!5$63!1d1!1d2#2!11#21!19#3!1#4!3#1!3#7!1#1!1#14!1z1!1z1!1z5!1#4!1z1!2z74!2d1!7z16!14z13!12z12b1d4!1d24!12d2e4d1#21d1e4d2#13d1!47d8b24d6b1d74!3#3!5#38b3V3T4b35!1#16!3#9!1#5!6d1#3d3!2d3!4*4!11d2!3*4d9!3*116b3d4*5d85b5d6*12!4*1!15*12b4)56b8)10b6)40b8)30b2)12b4)2b62)12b1#2!1#8!8#6!1#9!10#1!1d3#7!1d48!1#61!2#1!2#1!1#17!3#1!13#34!84b12*14d2*13!3*10!5*52!3#1!7*15!2*11!6*9#7*240b10X6b1022*2b65534!2b65534!655363b1H30b96H128b240H196112b";
|
|
327
|
+
var bmp = null;
|
|
328
|
+
var astralStarts = null;
|
|
329
|
+
var astralValues = null;
|
|
330
|
+
function decode() {
|
|
331
|
+
const direct = new Uint8Array(65536);
|
|
332
|
+
const starts = new Int32Array(RUNS);
|
|
333
|
+
const values = new Uint8Array(RUNS);
|
|
334
|
+
const slot = new Uint8Array(128);
|
|
335
|
+
for (let i = 0; i < ALPHABET.length; i++) slot[ALPHABET.charCodeAt(i)] = PALETTE[i];
|
|
336
|
+
let cp = 0;
|
|
337
|
+
let run = 0;
|
|
338
|
+
let len = 0;
|
|
339
|
+
for (let i = 0; i < PACKED.length; i++) {
|
|
340
|
+
const code = PACKED.charCodeAt(i);
|
|
341
|
+
if (code <= 57 && code >= 48) len = len * 10 + code - 48;
|
|
342
|
+
else {
|
|
343
|
+
const v = slot[code];
|
|
344
|
+
starts[run] = cp;
|
|
345
|
+
values[run] = v;
|
|
346
|
+
if (cp < 65536) direct.fill(v, cp, Math.min(cp + len, 65536));
|
|
347
|
+
run++;
|
|
348
|
+
cp += len;
|
|
349
|
+
len = 0;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
bmp = direct;
|
|
353
|
+
astralStarts = starts;
|
|
354
|
+
astralValues = values;
|
|
355
|
+
}
|
|
356
|
+
function lineBreakPropsOf(cp) {
|
|
357
|
+
if (bmp === null) decode();
|
|
358
|
+
if (cp < 65536) return bmp[cp];
|
|
359
|
+
if (cp > 1114111) return AL;
|
|
360
|
+
const starts = astralStarts;
|
|
361
|
+
let lo = 0;
|
|
362
|
+
let hi = starts.length - 1;
|
|
363
|
+
while (lo < hi) {
|
|
364
|
+
const mid = lo + hi + 1 >> 1;
|
|
365
|
+
if (starts[mid] <= cp) lo = mid;
|
|
366
|
+
else hi = mid - 1;
|
|
367
|
+
}
|
|
368
|
+
return astralValues[lo];
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/layout/lineBreak/lineBreaks.ts
|
|
372
|
+
var {
|
|
373
|
+
lineBreakPropsOf: lineBreakPropsOf2,
|
|
374
|
+
CLASS_MASK: CLASS_MASK2,
|
|
375
|
+
EAST_ASIAN: EAST_ASIAN2,
|
|
376
|
+
PICTOGRAPHIC_CN: PICTOGRAPHIC_CN2,
|
|
377
|
+
BK: BK2,
|
|
378
|
+
CR: CR2,
|
|
379
|
+
LF: LF2,
|
|
380
|
+
NL: NL2,
|
|
381
|
+
SP: SP2,
|
|
382
|
+
ZW: ZW2,
|
|
383
|
+
ZWJ: ZWJ2,
|
|
384
|
+
CM: CM2,
|
|
385
|
+
WJ: WJ2,
|
|
386
|
+
GL: GL2,
|
|
387
|
+
BA: BA2,
|
|
388
|
+
BB: BB2,
|
|
389
|
+
B2: B22,
|
|
390
|
+
HY: HY2,
|
|
391
|
+
CB: CB2,
|
|
392
|
+
CL: CL2,
|
|
393
|
+
CP: CP2,
|
|
394
|
+
EX: EX2,
|
|
395
|
+
IN: IN2,
|
|
396
|
+
NS: NS2,
|
|
397
|
+
OP: OP2,
|
|
398
|
+
QU: QU2,
|
|
399
|
+
IS: IS2,
|
|
400
|
+
NU: NU2,
|
|
401
|
+
PO: PO2,
|
|
402
|
+
PR: PR2,
|
|
403
|
+
SY: SY2,
|
|
404
|
+
AL: AL2,
|
|
405
|
+
HL: HL2,
|
|
406
|
+
ID: ID2,
|
|
407
|
+
EB: EB2,
|
|
408
|
+
EM: EM2,
|
|
409
|
+
H2: H22,
|
|
410
|
+
H3: H32,
|
|
411
|
+
JL: JL2,
|
|
412
|
+
JV: JV2,
|
|
413
|
+
JT: JT2,
|
|
414
|
+
RI: RI2,
|
|
415
|
+
AK: AK2,
|
|
416
|
+
AP: AP2,
|
|
417
|
+
AS: AS2,
|
|
418
|
+
VF: VF2,
|
|
419
|
+
VI: VI2,
|
|
420
|
+
QU_PI: QU_PI2,
|
|
421
|
+
QU_PF: QU_PF2
|
|
422
|
+
} = lineBreakTable_exports;
|
|
423
|
+
var NO_BREAK = 0;
|
|
424
|
+
var BREAK_ALLOWED = 1;
|
|
425
|
+
var BREAK_MANDATORY = 2;
|
|
426
|
+
var HYPHEN = 8208;
|
|
427
|
+
var DOTTED_CIRCLE = 9676;
|
|
428
|
+
var isQU = (c) => c === QU2 || c === QU_PI2 || c === QU_PF2;
|
|
429
|
+
var isHard = (c) => c === BK2 || c === CR2 || c === LF2 || c === NL2;
|
|
430
|
+
function isHardLineBreak(cp) {
|
|
431
|
+
return isHard(lineBreakPropsOf2(cp) & CLASS_MASK2);
|
|
432
|
+
}
|
|
433
|
+
var isAlpha = (c) => c === AL2 || c === HL2;
|
|
434
|
+
var isKorean = (c) => c === JL2 || c === JV2 || c === JT2 || c === H22 || c === H32;
|
|
435
|
+
var isIdeoLike = (c) => c === ID2 || c === EB2 || c === EM2;
|
|
436
|
+
var newScratch = (n) => ({
|
|
437
|
+
cls: new Uint8Array(n),
|
|
438
|
+
ea: new Uint8Array(n),
|
|
439
|
+
pict: new Uint8Array(n),
|
|
440
|
+
cp: new Int32Array(n),
|
|
441
|
+
start: new Int32Array(n)
|
|
442
|
+
});
|
|
443
|
+
var SCRATCH_MAX = 1 << 16;
|
|
444
|
+
var shared = newScratch(64);
|
|
445
|
+
function growScratch(n) {
|
|
446
|
+
if (shared.cls.length < n) shared = newScratch(Math.min(SCRATCH_MAX, Math.max(n, shared.cls.length * 2)));
|
|
447
|
+
return shared;
|
|
448
|
+
}
|
|
449
|
+
function lineBreakOpportunities(cps) {
|
|
450
|
+
const n = cps.length;
|
|
451
|
+
const out = new Uint8Array(n + 1);
|
|
452
|
+
if (n === 0) return out;
|
|
453
|
+
out[n] = BREAK_MANDATORY;
|
|
454
|
+
const scratch2 = n <= SCRATCH_MAX ? growScratch(n) : newScratch(n);
|
|
455
|
+
const { cls, ea, pict, cp } = scratch2;
|
|
456
|
+
const start = scratch2.start;
|
|
457
|
+
let u = 0;
|
|
458
|
+
for (let i = 0; i < n; i++) {
|
|
459
|
+
const props = lineBreakPropsOf2(cps[i]);
|
|
460
|
+
const c = props & CLASS_MASK2;
|
|
461
|
+
if ((c === CM2 || c === ZWJ2) && u > 0) {
|
|
462
|
+
const base = cls[u - 1];
|
|
463
|
+
if (!isHard(base) && base !== SP2 && base !== ZW2) continue;
|
|
464
|
+
}
|
|
465
|
+
if (c === CM2 || c === ZWJ2) {
|
|
466
|
+
cls[u] = AL2;
|
|
467
|
+
ea[u] = 0;
|
|
468
|
+
pict[u] = 0;
|
|
469
|
+
} else {
|
|
470
|
+
cls[u] = c;
|
|
471
|
+
ea[u] = props & EAST_ASIAN2 ? 1 : 0;
|
|
472
|
+
pict[u] = props & PICTOGRAPHIC_CN2 ? 1 : 0;
|
|
473
|
+
}
|
|
474
|
+
cp[u] = cps[i];
|
|
475
|
+
start[u] = i;
|
|
476
|
+
u++;
|
|
477
|
+
}
|
|
478
|
+
const units = u;
|
|
479
|
+
const prevIsZWJ = (b) => (lineBreakPropsOf2(cps[start[b] - 1]) & CLASS_MASK2) === ZWJ2;
|
|
480
|
+
const beforeSpaces = (k) => {
|
|
481
|
+
while (k >= 0 && cls[k] === SP2) k--;
|
|
482
|
+
return k;
|
|
483
|
+
};
|
|
484
|
+
for (let b = 1; b < units; b++) {
|
|
485
|
+
out[start[b]] = decide(b);
|
|
486
|
+
}
|
|
487
|
+
return out;
|
|
488
|
+
function decide(b) {
|
|
489
|
+
const a = b - 1;
|
|
490
|
+
const A = cls[a];
|
|
491
|
+
const B = cls[b];
|
|
492
|
+
if (A === CR2 && B === LF2) return NO_BREAK;
|
|
493
|
+
if (isHard(A)) return BREAK_MANDATORY;
|
|
494
|
+
if (isHard(B) || B === SP2 || B === ZW2) return NO_BREAK;
|
|
495
|
+
const s = beforeSpaces(a);
|
|
496
|
+
if (s >= 0 && cls[s] === ZW2) return BREAK_ALLOWED;
|
|
497
|
+
if (prevIsZWJ(b)) return NO_BREAK;
|
|
498
|
+
if (A === WJ2 || B === WJ2 || A === GL2) return NO_BREAK;
|
|
499
|
+
if (B === GL2 && A !== SP2 && A !== BA2 && A !== HY2) return NO_BREAK;
|
|
500
|
+
if (B === CL2 || B === CP2 || B === EX2 || B === SY2) return NO_BREAK;
|
|
501
|
+
const S = s >= 0 ? cls[s] : -1;
|
|
502
|
+
if (S === OP2) return NO_BREAK;
|
|
503
|
+
if (S === QU_PI2) {
|
|
504
|
+
const p = s - 1;
|
|
505
|
+
if (p < 0) return NO_BREAK;
|
|
506
|
+
const P = cls[p];
|
|
507
|
+
if (isHard(P) || P === OP2 || isQU(P) || P === GL2 || P === SP2 || P === ZW2) return NO_BREAK;
|
|
508
|
+
}
|
|
509
|
+
if (B === QU_PF2) {
|
|
510
|
+
if (b + 1 >= units) return NO_BREAK;
|
|
511
|
+
const N = cls[b + 1];
|
|
512
|
+
if (N === SP2 || N === GL2 || N === WJ2 || N === CL2 || isQU(N) || N === CP2 || N === EX2 || N === IS2 || N === SY2 || isHard(N) || N === ZW2) return NO_BREAK;
|
|
513
|
+
}
|
|
514
|
+
if (A === SP2 && B === IS2 && b + 1 < units && cls[b + 1] === NU2) return BREAK_ALLOWED;
|
|
515
|
+
if (B === IS2) return NO_BREAK;
|
|
516
|
+
if ((S === CL2 || S === CP2) && B === NS2) return NO_BREAK;
|
|
517
|
+
if (S === B22 && B === B22) return NO_BREAK;
|
|
518
|
+
if (A === SP2) return BREAK_ALLOWED;
|
|
519
|
+
if (B === QU2 || B === QU_PF2) return NO_BREAK;
|
|
520
|
+
if (A === QU2 || A === QU_PI2) return NO_BREAK;
|
|
521
|
+
if (isQU(B)) {
|
|
522
|
+
if (!ea[a]) return NO_BREAK;
|
|
523
|
+
if (b + 1 >= units || !ea[b + 1]) return NO_BREAK;
|
|
524
|
+
}
|
|
525
|
+
if (isQU(A)) {
|
|
526
|
+
if (!ea[b]) return NO_BREAK;
|
|
527
|
+
if (a === 0 || !ea[a - 1]) return NO_BREAK;
|
|
528
|
+
}
|
|
529
|
+
if (A === CB2 || B === CB2) return BREAK_ALLOWED;
|
|
530
|
+
if ((A === HY2 || cp[a] === HYPHEN) && B === AL2) {
|
|
531
|
+
if (a === 0) return NO_BREAK;
|
|
532
|
+
const P = cls[a - 1];
|
|
533
|
+
if (isHard(P) || P === SP2 || P === ZW2 || P === CB2 || P === GL2) return NO_BREAK;
|
|
534
|
+
}
|
|
535
|
+
if (B === BA2 || B === HY2 || B === NS2 || A === BB2) return NO_BREAK;
|
|
536
|
+
if (a > 0 && cls[a - 1] === HL2 && (A === HY2 || A === BA2 && !ea[a]) && B !== HL2) return NO_BREAK;
|
|
537
|
+
if (A === SY2 && B === HL2) return NO_BREAK;
|
|
538
|
+
if (B === IN2) return NO_BREAK;
|
|
539
|
+
if (isAlpha(A) && B === NU2 || A === NU2 && isAlpha(B)) return NO_BREAK;
|
|
540
|
+
if (A === PR2 && isIdeoLike(B) || isIdeoLike(A) && B === PO2) return NO_BREAK;
|
|
541
|
+
if ((A === PR2 || A === PO2) && isAlpha(B) || isAlpha(A) && (B === PR2 || B === PO2)) return NO_BREAK;
|
|
542
|
+
if (B === PO2 || B === PR2) {
|
|
543
|
+
let k = A === CL2 || A === CP2 ? a - 1 : a;
|
|
544
|
+
while (k >= 0 && (cls[k] === SY2 || cls[k] === IS2)) k--;
|
|
545
|
+
if (k >= 0 && cls[k] === NU2) return NO_BREAK;
|
|
546
|
+
}
|
|
547
|
+
if (A === PO2 || A === PR2) {
|
|
548
|
+
if (B === NU2) return NO_BREAK;
|
|
549
|
+
if (B === OP2 && b + 1 < units) {
|
|
550
|
+
const N = cls[b + 1];
|
|
551
|
+
if (N === NU2) return NO_BREAK;
|
|
552
|
+
if (N === IS2 && b + 2 < units && cls[b + 2] === NU2) return NO_BREAK;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if ((A === HY2 || A === IS2) && B === NU2) return NO_BREAK;
|
|
556
|
+
if (B === NU2) {
|
|
557
|
+
let k = a;
|
|
558
|
+
while (k >= 0 && (cls[k] === SY2 || cls[k] === IS2)) k--;
|
|
559
|
+
if (k >= 0 && cls[k] === NU2) return NO_BREAK;
|
|
560
|
+
}
|
|
561
|
+
if (A === JL2 && (B === JL2 || B === JV2 || B === H22 || B === H32)) return NO_BREAK;
|
|
562
|
+
if ((A === JV2 || A === H22) && (B === JV2 || B === JT2)) return NO_BREAK;
|
|
563
|
+
if ((A === JT2 || A === H32) && B === JT2) return NO_BREAK;
|
|
564
|
+
if (isKorean(A) && B === PO2 || A === PR2 && isKorean(B)) return NO_BREAK;
|
|
565
|
+
if (isAlpha(A) && isAlpha(B)) return NO_BREAK;
|
|
566
|
+
const aksaraA = A === AK2 || A === AS2 || cp[a] === DOTTED_CIRCLE;
|
|
567
|
+
const aksaraB = B === AK2 || B === AS2 || cp[b] === DOTTED_CIRCLE;
|
|
568
|
+
if (A === AP2 && aksaraB) return NO_BREAK;
|
|
569
|
+
if (aksaraA && (B === VF2 || B === VI2)) return NO_BREAK;
|
|
570
|
+
if (A === VI2 && a > 0 && (cls[a - 1] === AK2 || cls[a - 1] === AS2 || cp[a - 1] === DOTTED_CIRCLE) && (B === AK2 || cp[b] === DOTTED_CIRCLE)) return NO_BREAK;
|
|
571
|
+
if (aksaraA && aksaraB && b + 1 < units && cls[b + 1] === VF2) return NO_BREAK;
|
|
572
|
+
if (A === IS2 && isAlpha(B)) return NO_BREAK;
|
|
573
|
+
if ((isAlpha(A) || A === NU2) && B === OP2 && !ea[b]) return NO_BREAK;
|
|
574
|
+
if (A === CP2 && !ea[a] && (isAlpha(B) || B === NU2)) return NO_BREAK;
|
|
575
|
+
if (A === RI2 && B === RI2) {
|
|
576
|
+
let k = a;
|
|
577
|
+
while (k >= 0 && cls[k] === RI2) k--;
|
|
578
|
+
if ((a - k) % 2 === 1) return NO_BREAK;
|
|
579
|
+
}
|
|
580
|
+
if (B === EM2 && (A === EB2 || pict[a])) return NO_BREAK;
|
|
581
|
+
return BREAK_ALLOWED;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/layout/bidiRegistry.ts
|
|
586
|
+
var registered2 = null;
|
|
587
|
+
function registerBidi(engine) {
|
|
588
|
+
registered2 = engine;
|
|
589
|
+
return () => {
|
|
590
|
+
if (registered2 === engine) registered2 = null;
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
function registeredBidi() {
|
|
594
|
+
return registered2;
|
|
595
|
+
}
|
|
596
|
+
function directionOfLevel(level) {
|
|
597
|
+
return level % 2 === 1 ? "rtl" : "ltr";
|
|
598
|
+
}
|
|
599
|
+
function paragraphDirection(text, direction = "auto", engine = registered2) {
|
|
600
|
+
if (direction !== "auto") return direction;
|
|
601
|
+
if (engine === null) return "ltr";
|
|
602
|
+
const cps = [];
|
|
603
|
+
for (const ch of text) {
|
|
604
|
+
const cp = ch.codePointAt(0);
|
|
605
|
+
if (isHardLineBreak(cp)) break;
|
|
606
|
+
cps.push(cp);
|
|
607
|
+
}
|
|
608
|
+
return directionOfLevel(engine.baseLevel(engine.analyze(cps, "auto")));
|
|
609
|
+
}
|
|
610
|
+
var RTL_BLOCKS = [
|
|
611
|
+
[1424, 1535],
|
|
612
|
+
[1536, 1983],
|
|
613
|
+
[2144, 2303],
|
|
614
|
+
[64285, 65023],
|
|
615
|
+
[65136, 65279],
|
|
616
|
+
[67584, 69631],
|
|
617
|
+
[124928, 126975]
|
|
618
|
+
];
|
|
619
|
+
var RTL_BLOCK_NUMBERS = [
|
|
620
|
+
[1536, 1541],
|
|
621
|
+
[1632, 1644],
|
|
622
|
+
[1757, 1757],
|
|
623
|
+
[1776, 1785],
|
|
624
|
+
[2274, 2274],
|
|
625
|
+
[68912, 68921],
|
|
626
|
+
[69216, 69246]
|
|
627
|
+
];
|
|
628
|
+
var RTL_BLOCK_NEUTRALS = [
|
|
629
|
+
[1548, 1548],
|
|
630
|
+
[64830, 64831],
|
|
631
|
+
[65279, 65279]
|
|
632
|
+
];
|
|
633
|
+
function within(ranges, cp) {
|
|
634
|
+
for (let i = 0; i < ranges.length; i++) if (cp >= ranges[i][0] && cp <= ranges[i][1]) return true;
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
var warnedLogicalRtl = false;
|
|
638
|
+
function warnRtlWithoutEngine(codePoints) {
|
|
639
|
+
if (warnedLogicalRtl) return;
|
|
640
|
+
for (let i = 0; i < codePoints.length; i++) {
|
|
641
|
+
const cp = codePoints[i];
|
|
642
|
+
if (!within(RTL_BLOCKS, cp) || within(RTL_BLOCK_NUMBERS, cp) || within(RTL_BLOCK_NEUTRALS, cp)) continue;
|
|
643
|
+
warnedLogicalRtl = true;
|
|
644
|
+
console.warn(
|
|
645
|
+
// Naming the import in `from "<pkg>"` form would trip labkit's
|
|
646
|
+
// consumer smoke test, which greps dist for that exact shape.
|
|
647
|
+
"weasel layoutRuns: this text contains right-to-left characters but no `bidi` engine is registered, so it is being laid out in logical order \u2014 the glyphs will appear reversed. Import `bidi` out of the `@weasel-js/bidi` package and call `registerBidi(bidi)` once at startup."
|
|
648
|
+
);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
function _resetBidiWarningForTests() {
|
|
653
|
+
warnedLogicalRtl = false;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/layout/bidiLines.ts
|
|
657
|
+
function analyzeParagraphs(engine, codePoints, isBreak, direction) {
|
|
658
|
+
const paragraphs = [];
|
|
659
|
+
let start = 0;
|
|
660
|
+
for (let i = 0; i <= codePoints.length; i++) {
|
|
661
|
+
if (i < codePoints.length && !isBreak(i)) continue;
|
|
662
|
+
if (i > start) {
|
|
663
|
+
paragraphs.push({ start, end: i, analysis: engine.analyze(codePoints.slice(start, i), direction) });
|
|
664
|
+
}
|
|
665
|
+
start = i + 1;
|
|
666
|
+
}
|
|
667
|
+
const holding = (at) => {
|
|
668
|
+
let lo = 0;
|
|
669
|
+
let hi = paragraphs.length - 1;
|
|
670
|
+
while (lo < hi) {
|
|
671
|
+
const mid = lo + hi >> 1;
|
|
672
|
+
if (paragraphs[mid].end <= at) lo = mid + 1;
|
|
673
|
+
else hi = mid;
|
|
674
|
+
}
|
|
675
|
+
const p = paragraphs[lo];
|
|
676
|
+
return p !== void 0 && at >= p.start && at < p.end ? p : void 0;
|
|
677
|
+
};
|
|
678
|
+
return {
|
|
679
|
+
reorder(from, to) {
|
|
680
|
+
const p = holding(from);
|
|
681
|
+
if (p === void 0 || to > p.end) return { order: [], levels: [] };
|
|
682
|
+
const r = engine.reorder(p.analysis, from - p.start, to - p.start);
|
|
683
|
+
return { order: r.order.map((i) => i + p.start), levels: r.levels };
|
|
684
|
+
},
|
|
685
|
+
baseLevel(at) {
|
|
686
|
+
const p = holding(at);
|
|
687
|
+
return p === void 0 ? 0 : engine.baseLevel(p.analysis);
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
function restoreRemoved(order, count, rtl) {
|
|
692
|
+
if (order.length === count) return [...order];
|
|
693
|
+
const kept = new Set(order);
|
|
694
|
+
const leading = [];
|
|
695
|
+
const following = /* @__PURE__ */ new Map();
|
|
696
|
+
let anchor = -1;
|
|
697
|
+
let firstKept = -1;
|
|
698
|
+
for (let k = 0; k < count; k++) {
|
|
699
|
+
if (kept.has(k)) {
|
|
700
|
+
anchor = k;
|
|
701
|
+
if (firstKept < 0) firstKept = k;
|
|
702
|
+
} else if (anchor < 0) {
|
|
703
|
+
leading.push(k);
|
|
704
|
+
} else {
|
|
705
|
+
const list = following.get(anchor);
|
|
706
|
+
if (list) list.push(k);
|
|
707
|
+
else following.set(anchor, [k]);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (firstKept < 0) return leading;
|
|
711
|
+
const out = [];
|
|
712
|
+
for (const p of order) {
|
|
713
|
+
const after = following.get(p) ?? [];
|
|
714
|
+
const before = p === firstKept ? leading : [];
|
|
715
|
+
if (rtl(p)) out.push(...[...after].reverse(), p, ...[...before].reverse());
|
|
716
|
+
else out.push(...before, p, ...after);
|
|
717
|
+
}
|
|
718
|
+
return out;
|
|
719
|
+
}
|
|
720
|
+
var SHARED_ORDER_LIMIT = 1024;
|
|
721
|
+
var logicalOrders = [];
|
|
722
|
+
function logicalOrder(count) {
|
|
723
|
+
const known = logicalOrders[count];
|
|
724
|
+
if (known !== void 0) return known;
|
|
725
|
+
const order = {
|
|
726
|
+
visual: Array.from({ length: count }, (_, pos) => pos),
|
|
727
|
+
levels: new Array(count).fill(0)
|
|
728
|
+
};
|
|
729
|
+
if (count <= SHARED_ORDER_LIMIT) logicalOrders[count] = order;
|
|
730
|
+
return order;
|
|
731
|
+
}
|
|
732
|
+
function orderLine(paragraphs, start, count) {
|
|
733
|
+
if (paragraphs === null || count === 0) return logicalOrder(count);
|
|
734
|
+
const levels = new Array(count).fill(0);
|
|
735
|
+
const r = paragraphs.reorder(start, start + count);
|
|
736
|
+
for (let pos = 0; pos < count; pos++) {
|
|
737
|
+
const level = r.levels[pos];
|
|
738
|
+
if (typeof level === "number" && level >= 0) levels[pos] = level;
|
|
739
|
+
}
|
|
740
|
+
const kept = /* @__PURE__ */ new Set();
|
|
741
|
+
for (const at of r.order) {
|
|
742
|
+
const pos = at - start;
|
|
743
|
+
if (Number.isInteger(pos) && pos >= 0 && pos < count) kept.add(pos);
|
|
744
|
+
}
|
|
745
|
+
return { visual: restoreRemoved([...kept], count, (pos) => levels[pos] % 2 === 1), levels };
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/layout/arrayPool.ts
|
|
749
|
+
var TEMPLATE_LIMIT = 1 << 16;
|
|
750
|
+
var template = [0.5];
|
|
751
|
+
function doubles(n) {
|
|
752
|
+
if (n > TEMPLATE_LIMIT) return new Array(n).fill(0.5);
|
|
753
|
+
while (template.length < n) template = template.concat(template);
|
|
754
|
+
return template.slice(0, n);
|
|
755
|
+
}
|
|
756
|
+
var ARRAY_POOL_LIMIT = 1 << 18;
|
|
757
|
+
var nums = /* @__PURE__ */ new Map();
|
|
758
|
+
var refs = /* @__PURE__ */ new Map();
|
|
759
|
+
var held = 0;
|
|
760
|
+
function take(pool, n) {
|
|
761
|
+
const b = pool.get(n);
|
|
762
|
+
if (b === void 0 || b.n === 0) return void 0;
|
|
763
|
+
held -= n;
|
|
764
|
+
const a = b.items[--b.n];
|
|
765
|
+
b.items[b.n] = void 0;
|
|
766
|
+
return a;
|
|
767
|
+
}
|
|
768
|
+
function give(pool, a) {
|
|
769
|
+
const n = a.length;
|
|
770
|
+
if (n === 0 || held + n > ARRAY_POOL_LIMIT) return;
|
|
771
|
+
let b = pool.get(n);
|
|
772
|
+
if (b === void 0) pool.set(n, b = { items: [], n: 0 });
|
|
773
|
+
b.items[b.n++] = a;
|
|
774
|
+
held += n;
|
|
775
|
+
}
|
|
776
|
+
function takeDoubles(n) {
|
|
777
|
+
return take(nums, n) ?? doubles(n);
|
|
778
|
+
}
|
|
779
|
+
function takeRefs(n) {
|
|
780
|
+
return take(refs, n) ?? new Array(n);
|
|
781
|
+
}
|
|
782
|
+
function giveDoubles(a) {
|
|
783
|
+
give(nums, a);
|
|
784
|
+
}
|
|
785
|
+
function giveRefs(a) {
|
|
786
|
+
give(refs, a);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/layout/layoutColumns.ts
|
|
790
|
+
var NUM = 13;
|
|
791
|
+
var X = 0;
|
|
792
|
+
var STEP = 1;
|
|
793
|
+
var ADVANCE = 2;
|
|
794
|
+
var FONT_SIZE = 3;
|
|
795
|
+
var BASELINE = 4;
|
|
796
|
+
var SRC_INDEX = 5;
|
|
797
|
+
var SRC_END = 6;
|
|
798
|
+
var CP3 = 7;
|
|
799
|
+
var LEVEL = 8;
|
|
800
|
+
var FLAGS = 9;
|
|
801
|
+
var RUN = 10;
|
|
802
|
+
var VISUAL = 11;
|
|
803
|
+
var ROTATE = 12;
|
|
804
|
+
var DRAWS_INK = 1;
|
|
805
|
+
var CLUSTER_END = 2;
|
|
806
|
+
var REF = 5;
|
|
807
|
+
var EMPTY_NUM = [];
|
|
808
|
+
var EMPTY_REF = [];
|
|
809
|
+
var spare = [];
|
|
810
|
+
var SPARE_MAX = 1024;
|
|
811
|
+
var LayoutColumns = class _LayoutColumns {
|
|
812
|
+
num;
|
|
813
|
+
ref;
|
|
814
|
+
/** The layout's line boxes, its `lines`. A recycled layout's are refilled
|
|
815
|
+
* by the next layout to take its columns. */
|
|
816
|
+
boxes = [];
|
|
817
|
+
/** The paint cache's paintings of this layout, kept here rather than in a
|
|
818
|
+
* map keyed by the layout, so that recycling one deletes no map entry. */
|
|
819
|
+
paintings = [];
|
|
820
|
+
/** The layout cache's record of who can still reach this layout: runs
|
|
821
|
+
* arrays it is filed under, whether its structural list holds it, and
|
|
822
|
+
* whether any caller was handed it to keep. Only a layout with none of the
|
|
823
|
+
* three gives its arrays back. */
|
|
824
|
+
owners = 0;
|
|
825
|
+
listed = false;
|
|
826
|
+
pinned = false;
|
|
827
|
+
constructor(size) {
|
|
828
|
+
this.num = takeDoubles(size * NUM);
|
|
829
|
+
this.ref = takeRefs(size * REF);
|
|
830
|
+
}
|
|
831
|
+
/** Columns for `size` code points: a recycled layout's, refilled, when the
|
|
832
|
+
* pool holds one. */
|
|
833
|
+
static take(size) {
|
|
834
|
+
const cols = spare.pop();
|
|
835
|
+
if (cols === void 0) return new _LayoutColumns(size);
|
|
836
|
+
cols.num = takeDoubles(size * NUM);
|
|
837
|
+
cols.ref = takeRefs(size * REF);
|
|
838
|
+
return cols;
|
|
839
|
+
}
|
|
840
|
+
/** Give the arrays back to the pool, and these columns with their line
|
|
841
|
+
* boxes to the next layout. A line box still held afterwards reads that
|
|
842
|
+
* layout's code points, so only a layout nobody holds is recycled. */
|
|
843
|
+
recycle() {
|
|
844
|
+
giveDoubles(this.num);
|
|
845
|
+
const { ref } = this;
|
|
846
|
+
for (let i = 0; i < ref.length; i++) ref[i] = void 0;
|
|
847
|
+
giveRefs(ref);
|
|
848
|
+
this.num = EMPTY_NUM;
|
|
849
|
+
this.ref = EMPTY_REF;
|
|
850
|
+
this.paintings.length = 0;
|
|
851
|
+
this.owners = 0;
|
|
852
|
+
this.listed = false;
|
|
853
|
+
this.pinned = false;
|
|
854
|
+
if (spare.length < SPARE_MAX) spare.push(this);
|
|
855
|
+
}
|
|
856
|
+
/** Store code point `i`: entry `e`, set at `x` on a baseline at `baselineY`,
|
|
857
|
+
* moving the pen `step`. */
|
|
858
|
+
set(i, e, level, x, step, baselineY) {
|
|
859
|
+
const n = i * NUM, r = i * REF;
|
|
860
|
+
const { num, ref } = this;
|
|
861
|
+
num[n + X] = x;
|
|
862
|
+
num[n + STEP] = step;
|
|
863
|
+
num[n + ADVANCE] = e.advance;
|
|
864
|
+
num[n + FONT_SIZE] = e.fontSize;
|
|
865
|
+
num[n + BASELINE] = baselineY;
|
|
866
|
+
num[n + SRC_INDEX] = e.srcIndex;
|
|
867
|
+
num[n + SRC_END] = e.srcEnd;
|
|
868
|
+
num[n + CP3] = e.cp;
|
|
869
|
+
num[n + LEVEL] = level;
|
|
870
|
+
num[n + RUN] = e.run;
|
|
871
|
+
num[n + ROTATE] = e.rotate;
|
|
872
|
+
num[n + FLAGS] = (e.drawsInk ? DRAWS_INK : 0) | (e.clusterEnd ? CLUSTER_END : 0);
|
|
873
|
+
ref[r] = e.resolved;
|
|
874
|
+
ref[r + 1] = e.metrics;
|
|
875
|
+
ref[r + 2] = e.font;
|
|
876
|
+
ref[r + 3] = e.glyph;
|
|
877
|
+
ref[r + 4] = e.shaped;
|
|
878
|
+
}
|
|
879
|
+
/** Lengthen code point `i`'s step by `by`: the kerning the pen takes after it. */
|
|
880
|
+
widen(i, by) {
|
|
881
|
+
this.num[i * NUM + STEP] += by;
|
|
882
|
+
}
|
|
883
|
+
/** Record that the `slot`-th code point the pen reaches on the line starting
|
|
884
|
+
* at `start` is the line's `pos`-th in logical order. */
|
|
885
|
+
setVisual(start, slot, pos) {
|
|
886
|
+
this.num[(start + slot) * NUM + VISUAL] = pos;
|
|
887
|
+
}
|
|
888
|
+
/** Logical index, within its line, of the glyph at visual `slot`. */
|
|
889
|
+
visual(start, slot) {
|
|
890
|
+
return this.num[(start + slot) * NUM + VISUAL];
|
|
891
|
+
}
|
|
892
|
+
/** Fill `out` with code point `start + pos`'s placed glyph and return it.
|
|
893
|
+
* Every field is overwritten, so one object can walk a whole layout. */
|
|
894
|
+
glyph(start, pos, out) {
|
|
895
|
+
const i = start + pos;
|
|
896
|
+
const n = i * NUM, r = i * REF;
|
|
897
|
+
const { num, ref } = this;
|
|
898
|
+
out.run = num[n + RUN];
|
|
899
|
+
out.cell = pos;
|
|
900
|
+
out.cp = num[n + CP3];
|
|
901
|
+
out.fontSize = num[n + FONT_SIZE];
|
|
902
|
+
out.resolved = ref[r];
|
|
903
|
+
out.metrics = ref[r + 1];
|
|
904
|
+
out.font = ref[r + 2];
|
|
905
|
+
out.glyph = ref[r + 3];
|
|
906
|
+
out.shaped = ref[r + 4];
|
|
907
|
+
out.x = num[n + X];
|
|
908
|
+
out.baselineY = num[n + BASELINE];
|
|
909
|
+
out.advance = num[n + ADVANCE];
|
|
910
|
+
out.step = num[n + STEP];
|
|
911
|
+
out.rotate = num[n + ROTATE];
|
|
912
|
+
return out;
|
|
913
|
+
}
|
|
914
|
+
/** Code point `start + pos`'s `LaidOutCell.drawsInk`, without building the cell. */
|
|
915
|
+
drawsInk(start, pos) {
|
|
916
|
+
return (this.num[(start + pos) * NUM + FLAGS] & DRAWS_INK) !== 0;
|
|
917
|
+
}
|
|
918
|
+
/** Code point `start + pos`'s cell, as a new object. */
|
|
919
|
+
cell(start, pos) {
|
|
920
|
+
const n = (start + pos) * NUM;
|
|
921
|
+
const { num } = this;
|
|
922
|
+
const flags = num[n + FLAGS];
|
|
923
|
+
return {
|
|
924
|
+
srcIndex: num[n + SRC_INDEX],
|
|
925
|
+
srcEnd: num[n + SRC_END],
|
|
926
|
+
cp: num[n + CP3],
|
|
927
|
+
x: num[n + X],
|
|
928
|
+
advance: num[n + STEP],
|
|
929
|
+
level: num[n + LEVEL],
|
|
930
|
+
drawsInk: (flags & DRAWS_INK) !== 0,
|
|
931
|
+
clusterEnd: (flags & CLUSTER_END) !== 0
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
function blankGlyph() {
|
|
936
|
+
return {
|
|
937
|
+
run: 0,
|
|
938
|
+
cell: 0,
|
|
939
|
+
cp: 0,
|
|
940
|
+
fontSize: 0.5,
|
|
941
|
+
resolved: null,
|
|
942
|
+
metrics: null,
|
|
943
|
+
font: null,
|
|
944
|
+
glyph: null,
|
|
945
|
+
shaped: null,
|
|
946
|
+
x: 0.5,
|
|
947
|
+
baselineY: 0.5,
|
|
948
|
+
advance: 0.5,
|
|
949
|
+
step: 0.5,
|
|
950
|
+
rotate: 0.5
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
var LineBox = class _LineBox {
|
|
954
|
+
x0;
|
|
955
|
+
y0;
|
|
956
|
+
x1;
|
|
957
|
+
y1;
|
|
958
|
+
baselineY;
|
|
959
|
+
srcEnd;
|
|
960
|
+
justified;
|
|
961
|
+
#cols;
|
|
962
|
+
#start;
|
|
963
|
+
#count;
|
|
964
|
+
/** Whether a view was built, replacing its accessor with a value. */
|
|
965
|
+
#viewed = false;
|
|
966
|
+
constructor(x0, y0, x1, y1, baselineY, srcEnd, justified, cols, start, count) {
|
|
967
|
+
this.x0 = x0;
|
|
968
|
+
this.y0 = y0;
|
|
969
|
+
this.x1 = x1;
|
|
970
|
+
this.y1 = y1;
|
|
971
|
+
this.baselineY = baselineY;
|
|
972
|
+
this.srcEnd = srcEnd;
|
|
973
|
+
this.justified = justified;
|
|
974
|
+
this.#cols = cols;
|
|
975
|
+
this.#start = start;
|
|
976
|
+
this.#count = count;
|
|
977
|
+
Object.defineProperties(this, _LineBox.#views);
|
|
978
|
+
}
|
|
979
|
+
/** Set this box to another line of the same columns, as the constructor
|
|
980
|
+
* would, its views unbuilt again. */
|
|
981
|
+
refill(x0, y0, x1, y1, baselineY, srcEnd, justified, start, count) {
|
|
982
|
+
this.x0 = x0;
|
|
983
|
+
this.y0 = y0;
|
|
984
|
+
this.x1 = x1;
|
|
985
|
+
this.y1 = y1;
|
|
986
|
+
this.baselineY = baselineY;
|
|
987
|
+
this.srcEnd = srcEnd;
|
|
988
|
+
this.justified = justified;
|
|
989
|
+
this.#start = start;
|
|
990
|
+
this.#count = count;
|
|
991
|
+
if (this.#viewed) {
|
|
992
|
+
this.#viewed = false;
|
|
993
|
+
Object.defineProperties(this, _LineBox.#views);
|
|
994
|
+
}
|
|
995
|
+
return this;
|
|
996
|
+
}
|
|
997
|
+
/** The columns a line reads; null for a line built by hand. */
|
|
998
|
+
static columns(line) {
|
|
999
|
+
return line instanceof _LineBox ? line.#cols : null;
|
|
1000
|
+
}
|
|
1001
|
+
/** Where a line built by layout starts in its columns; 0 for one built by hand. */
|
|
1002
|
+
static start(line) {
|
|
1003
|
+
return line instanceof _LineBox ? line.#start : 0;
|
|
1004
|
+
}
|
|
1005
|
+
/** How many code points the line holds, without building a view. */
|
|
1006
|
+
static count(line) {
|
|
1007
|
+
return line instanceof _LineBox ? line.#count : line.glyphs.length;
|
|
1008
|
+
}
|
|
1009
|
+
static #views = {
|
|
1010
|
+
cells: lazy("cells", (l) => {
|
|
1011
|
+
l.#viewed = true;
|
|
1012
|
+
const out = new Array(l.#count);
|
|
1013
|
+
for (let pos = 0; pos < l.#count; pos++) out[pos] = l.#cols.cell(l.#start, pos);
|
|
1014
|
+
return out;
|
|
1015
|
+
}),
|
|
1016
|
+
glyphs: lazy("glyphs", (l) => {
|
|
1017
|
+
l.#viewed = true;
|
|
1018
|
+
const out = new Array(l.#count);
|
|
1019
|
+
for (let slot = 0; slot < l.#count; slot++) {
|
|
1020
|
+
out[slot] = l.#cols.glyph(l.#start, l.#cols.visual(l.#start, slot), blankGlyph());
|
|
1021
|
+
}
|
|
1022
|
+
return out;
|
|
1023
|
+
})
|
|
1024
|
+
};
|
|
1025
|
+
};
|
|
1026
|
+
function lazy(key, build) {
|
|
1027
|
+
return {
|
|
1028
|
+
enumerable: true,
|
|
1029
|
+
configurable: true,
|
|
1030
|
+
get() {
|
|
1031
|
+
const value = build(this);
|
|
1032
|
+
Object.defineProperty(this, key, { value, enumerable: true, configurable: true, writable: false });
|
|
1033
|
+
return value;
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// src/measure/graphemes.ts
|
|
1039
|
+
var segmenter;
|
|
1040
|
+
var NEEDS_SEGMENTING = /[\r\u0300-\uffff]/;
|
|
1041
|
+
function graphemeSegmenter() {
|
|
1042
|
+
if (segmenter === void 0) {
|
|
1043
|
+
segmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
1044
|
+
}
|
|
1045
|
+
return segmenter;
|
|
1046
|
+
}
|
|
1047
|
+
function graphemeEnds(text, into) {
|
|
1048
|
+
const out = into ?? [];
|
|
1049
|
+
let n = 0;
|
|
1050
|
+
if (!NEEDS_SEGMENTING.test(text)) {
|
|
1051
|
+
for (let i = 1; i <= text.length; i++) out[n++] = i;
|
|
1052
|
+
} else {
|
|
1053
|
+
const seg = graphemeSegmenter();
|
|
1054
|
+
if (seg) {
|
|
1055
|
+
for (const s of seg.segment(text)) out[n++] = s.index + s.segment.length;
|
|
1056
|
+
} else {
|
|
1057
|
+
let at = 0;
|
|
1058
|
+
for (const ch of text) out[n++] = at += ch.length;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
out.length = n;
|
|
1062
|
+
return out;
|
|
1063
|
+
}
|
|
1064
|
+
function graphemeCount(text) {
|
|
1065
|
+
return graphemeEnds(text).length;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// src/layout/shapedRuns.ts
|
|
1069
|
+
var NOTHING_DRAWN = Object.freeze({ d: null, key: "", glyphs: Object.freeze([]), rtl: false, text: "" });
|
|
1070
|
+
var COVERED = Object.freeze({ cluster: NOTHING_DRAWN, advance: 0 });
|
|
1071
|
+
var slotsOf = /* @__PURE__ */ new WeakMap();
|
|
1072
|
+
var fmt = (v) => String(Math.round(v * 1e5) / 1e5);
|
|
1073
|
+
function shapeRun(run, resolved2, shaper) {
|
|
1074
|
+
if (shaper === null) return null;
|
|
1075
|
+
const face = shapeableBytes(resolved2);
|
|
1076
|
+
if (face === null) return null;
|
|
1077
|
+
const glyphs = shaper.shape(face, run.text, run.fontFeatures, run.lang);
|
|
1078
|
+
let slots2 = slotsOf.get(glyphs);
|
|
1079
|
+
if (slots2) return slots2;
|
|
1080
|
+
slots2 = slotsFor(shaper, face, run.text, glyphs);
|
|
1081
|
+
slotsOf.set(glyphs, slots2);
|
|
1082
|
+
return slots2;
|
|
1083
|
+
}
|
|
1084
|
+
function slotsFor(shaper, face, text, glyphs) {
|
|
1085
|
+
const slots2 = new Array(text.length);
|
|
1086
|
+
const ends = graphemeEnds(text);
|
|
1087
|
+
let g = 0;
|
|
1088
|
+
let i = 0;
|
|
1089
|
+
while (i < glyphs.length) {
|
|
1090
|
+
const start = glyphs[i].cluster;
|
|
1091
|
+
let j = i;
|
|
1092
|
+
while (j < glyphs.length && glyphs[j].cluster === start) j++;
|
|
1093
|
+
const end = j < glyphs.length ? glyphs[j].cluster : text.length;
|
|
1094
|
+
while (g < ends.length && ends[g] <= start) g++;
|
|
1095
|
+
let inner = 0;
|
|
1096
|
+
for (let k = g; k < ends.length && ends[k] < end; k++) inner++;
|
|
1097
|
+
if (!holdsNotdef(glyphs, i, j)) {
|
|
1098
|
+
const total = advanceOf(glyphs, i, j);
|
|
1099
|
+
const share = total / (inner + 1);
|
|
1100
|
+
const shift = glyphs[i].rtl ? share - total : 0;
|
|
1101
|
+
slots2[start] = clusterSlot(shaper, face, glyphs, i, j, text.slice(start, end), shift, share);
|
|
1102
|
+
const opens = share === 0 ? COVERED : { cluster: NOTHING_DRAWN, advance: share };
|
|
1103
|
+
for (let at = start + 1, k = g; at < end; at++) {
|
|
1104
|
+
const opening = k < ends.length && ends[k] === at;
|
|
1105
|
+
if (opening) k++;
|
|
1106
|
+
slots2[at] = opening ? opens : COVERED;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
i = j;
|
|
1110
|
+
}
|
|
1111
|
+
return slots2;
|
|
1112
|
+
}
|
|
1113
|
+
function advanceOf(glyphs, from, to) {
|
|
1114
|
+
let sum2 = 0;
|
|
1115
|
+
for (let k = from; k < to; k++) sum2 += glyphs[k].advance;
|
|
1116
|
+
return sum2;
|
|
1117
|
+
}
|
|
1118
|
+
function holdsNotdef(glyphs, from, to) {
|
|
1119
|
+
for (let k = from; k < to; k++) if (glyphs[k].gid === 0) return true;
|
|
1120
|
+
return false;
|
|
1121
|
+
}
|
|
1122
|
+
function clusterSlot(shaper, face, glyphs, from, to, text, shift, advance) {
|
|
1123
|
+
const placed2 = [];
|
|
1124
|
+
let pen = shift;
|
|
1125
|
+
let d = "";
|
|
1126
|
+
let key = "";
|
|
1127
|
+
for (let k = from; k < to; k++) {
|
|
1128
|
+
const g = glyphs[k];
|
|
1129
|
+
const x = pen + g.dx, y = g.dy;
|
|
1130
|
+
placed2.push({ gid: g.gid, x, y });
|
|
1131
|
+
d += shaper.glyphD(face, g.gid, x, y) ?? "";
|
|
1132
|
+
key += `${k === from ? "" : ";"}${g.gid}${x === 0 && y === 0 ? "" : `@${fmt(x)},${fmt(y)}`}`;
|
|
1133
|
+
pen += g.advance;
|
|
1134
|
+
}
|
|
1135
|
+
return { cluster: { d: d.length > 0 ? d : null, key, glyphs: placed2, rtl: glyphs[from].rtl, text }, advance };
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// src/layout/layoutEntries.ts
|
|
1139
|
+
var NONSPACING_MARK = /^[\p{Mn}\p{Me}]$/u;
|
|
1140
|
+
function measureRuns(runs, tabSize, pool, into, shaper = null) {
|
|
1141
|
+
const entries = into ?? [];
|
|
1142
|
+
let n = 0;
|
|
1143
|
+
let prev;
|
|
1144
|
+
let srcIndex = 0;
|
|
1145
|
+
for (let runIndex = 0; runIndex < runs.length; runIndex++) {
|
|
1146
|
+
const run = runs[runIndex];
|
|
1147
|
+
const resolved2 = resolveFontVariant(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
1148
|
+
const metrics = metricsOf(resolved2);
|
|
1149
|
+
if (!metrics) {
|
|
1150
|
+
warnNoMetrics(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
1151
|
+
srcIndex += run.srcMap?.length ?? run.text.length;
|
|
1152
|
+
prev = void 0;
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
const runBase = srcIndex;
|
|
1156
|
+
const map = run.srcMap;
|
|
1157
|
+
const clusterEnds = graphemeEnds(run.text, CLUSTER_ENDS);
|
|
1158
|
+
const shaped = shapeRun(run, resolved2, shaper);
|
|
1159
|
+
let cluster = 0;
|
|
1160
|
+
let clusterStart = 0;
|
|
1161
|
+
let color = null;
|
|
1162
|
+
let at = 0;
|
|
1163
|
+
const text = run.text;
|
|
1164
|
+
while (at < text.length) {
|
|
1165
|
+
const cp = text.codePointAt(at);
|
|
1166
|
+
const len = cp > 65535 ? 2 : 1;
|
|
1167
|
+
const slot = shaped?.[at];
|
|
1168
|
+
const fontSize = run.sizeMap ? run.sizeMap[at] : run.fontSize;
|
|
1169
|
+
if (at === clusterStart) {
|
|
1170
|
+
color = resolveColorCluster(
|
|
1171
|
+
resolved2,
|
|
1172
|
+
run.fontFamily,
|
|
1173
|
+
run.fontWeight,
|
|
1174
|
+
run.fontStyle,
|
|
1175
|
+
run.text.slice(at, clusterEnds[cluster])
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
const clusterEnd = at + len === clusterEnds[cluster];
|
|
1179
|
+
if (clusterEnd) clusterStart = clusterEnds[cluster++];
|
|
1180
|
+
const tracking = clusterEnd ? run.letterSpacing : 0;
|
|
1181
|
+
const srcStart = map ? runBase + map.starts[at] : runBase + at;
|
|
1182
|
+
const srcEnd = map ? runBase + map.ends[at] : runBase + at + len;
|
|
1183
|
+
at += len;
|
|
1184
|
+
srcIndex = map ? runBase + map.length : srcEnd;
|
|
1185
|
+
const mark = isNonspacingMark(cp);
|
|
1186
|
+
const kerningBefore = prev && !mark ? prev.metrics.kernOf(prev.cp, cp) * (prev.fontSize / prev.metrics.size) : 0;
|
|
1187
|
+
const blank = blankEntry(
|
|
1188
|
+
pool,
|
|
1189
|
+
n,
|
|
1190
|
+
runIndex,
|
|
1191
|
+
cp,
|
|
1192
|
+
fontSize,
|
|
1193
|
+
Math.max(run.fontSize, run.strutSize ?? 0),
|
|
1194
|
+
// Optional on the authored run type; absent, every y would go NaN.
|
|
1195
|
+
run.baselineShift ?? 0,
|
|
1196
|
+
run.rotate ?? 0,
|
|
1197
|
+
srcStart,
|
|
1198
|
+
srcEnd,
|
|
1199
|
+
clusterEnd,
|
|
1200
|
+
resolved2,
|
|
1201
|
+
metrics
|
|
1202
|
+
);
|
|
1203
|
+
if (color) {
|
|
1204
|
+
entries[n++] = clusterEnd ? ink(blank, color, 0, tracking) : blank;
|
|
1205
|
+
prev = void 0;
|
|
1206
|
+
} else if (isHardLineBreak(cp)) {
|
|
1207
|
+
entries[n++] = blank;
|
|
1208
|
+
prev = void 0;
|
|
1209
|
+
} else if (cp === 9 || cp === 32) {
|
|
1210
|
+
const space = metrics.advanceOf(32);
|
|
1211
|
+
const advance = space !== null ? space * (fontSize / metrics.size) : fontSize * 0.25;
|
|
1212
|
+
if (cp === 9) {
|
|
1213
|
+
entries[n++] = { ...blank, tab: { stop: tabSize * (advance + run.letterSpacing), min: advance / 2 } };
|
|
1214
|
+
prev = void 0;
|
|
1215
|
+
} else {
|
|
1216
|
+
const own2 = glyphIn(resolved2, 32, HIT);
|
|
1217
|
+
blank.font = own2?.font ?? null;
|
|
1218
|
+
blank.glyph = own2?.glyph ?? null;
|
|
1219
|
+
blank.advance = advance;
|
|
1220
|
+
blank.tracking = tracking;
|
|
1221
|
+
blank.kerningBefore = kerningBefore;
|
|
1222
|
+
prev = blank;
|
|
1223
|
+
entries[n++] = prev;
|
|
1224
|
+
}
|
|
1225
|
+
} else if (slot !== void 0) {
|
|
1226
|
+
entries[n++] = shape(blank, slot, tracking);
|
|
1227
|
+
prev = void 0;
|
|
1228
|
+
} else {
|
|
1229
|
+
const hit = resolveGlyph(resolved2, run.fontFamily, run.fontWeight, run.fontStyle, cp, true, HIT);
|
|
1230
|
+
const entry = hit ? ink(blank, hit, kerningBefore, tracking) : blank;
|
|
1231
|
+
entries[n++] = entry;
|
|
1232
|
+
if (!mark) prev = entry;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
entries.length = n;
|
|
1237
|
+
return entries;
|
|
1238
|
+
}
|
|
1239
|
+
function isNonspacingMark(cp) {
|
|
1240
|
+
return cp >= 768 && NONSPACING_MARK.test(String.fromCodePoint(cp));
|
|
1241
|
+
}
|
|
1242
|
+
var CLUSTER_ENDS = [];
|
|
1243
|
+
var HIT = { resolved: null, metrics: null, advance: 0, font: null, glyph: null };
|
|
1244
|
+
var POOL_MAX = 4096;
|
|
1245
|
+
function blankEntry(pool, i, run, cp, fontSize, lineSize, baselineShift, rotate, srcIndex, srcEnd, clusterEnd, resolved2, metrics) {
|
|
1246
|
+
const e = pool?.[i];
|
|
1247
|
+
if (!e) {
|
|
1248
|
+
const made = {
|
|
1249
|
+
run,
|
|
1250
|
+
cp,
|
|
1251
|
+
fontSize,
|
|
1252
|
+
lineSize,
|
|
1253
|
+
baselineShift,
|
|
1254
|
+
rotate,
|
|
1255
|
+
srcIndex,
|
|
1256
|
+
srcEnd,
|
|
1257
|
+
clusterEnd,
|
|
1258
|
+
resolved: resolved2,
|
|
1259
|
+
metrics,
|
|
1260
|
+
font: null,
|
|
1261
|
+
glyph: null,
|
|
1262
|
+
advance: 0,
|
|
1263
|
+
tracking: 0,
|
|
1264
|
+
kerningBefore: 0,
|
|
1265
|
+
tab: void 0,
|
|
1266
|
+
shaped: null,
|
|
1267
|
+
drawsInk: false
|
|
1268
|
+
};
|
|
1269
|
+
if (pool && i < POOL_MAX) pool[i] = made;
|
|
1270
|
+
return made;
|
|
1271
|
+
}
|
|
1272
|
+
e.run = run;
|
|
1273
|
+
e.cp = cp;
|
|
1274
|
+
e.fontSize = fontSize;
|
|
1275
|
+
e.lineSize = lineSize;
|
|
1276
|
+
e.baselineShift = baselineShift;
|
|
1277
|
+
e.rotate = rotate;
|
|
1278
|
+
e.srcIndex = srcIndex;
|
|
1279
|
+
e.srcEnd = srcEnd;
|
|
1280
|
+
e.clusterEnd = clusterEnd;
|
|
1281
|
+
e.resolved = resolved2;
|
|
1282
|
+
e.metrics = metrics;
|
|
1283
|
+
e.font = null;
|
|
1284
|
+
e.glyph = null;
|
|
1285
|
+
e.advance = 0;
|
|
1286
|
+
e.tracking = 0;
|
|
1287
|
+
e.kerningBefore = 0;
|
|
1288
|
+
e.tab = void 0;
|
|
1289
|
+
e.shaped = null;
|
|
1290
|
+
e.drawsInk = false;
|
|
1291
|
+
return e;
|
|
1292
|
+
}
|
|
1293
|
+
function ink(e, hit, kerning, tracking) {
|
|
1294
|
+
e.resolved = hit.resolved;
|
|
1295
|
+
e.metrics = hit.metrics;
|
|
1296
|
+
e.font = hit.font;
|
|
1297
|
+
e.glyph = hit.glyph;
|
|
1298
|
+
e.advance = hit.advance * (e.fontSize / hit.metrics.size);
|
|
1299
|
+
e.tracking = tracking;
|
|
1300
|
+
e.kerningBefore = kerning;
|
|
1301
|
+
e.drawsInk = true;
|
|
1302
|
+
return e;
|
|
1303
|
+
}
|
|
1304
|
+
function shape(e, slot, tracking) {
|
|
1305
|
+
e.shaped = slot.cluster;
|
|
1306
|
+
e.advance = slot.advance * e.fontSize;
|
|
1307
|
+
e.tracking = tracking;
|
|
1308
|
+
e.drawsInk = slot.cluster.d !== null;
|
|
1309
|
+
return e;
|
|
1310
|
+
}
|
|
1311
|
+
function mirrorEntries(entries, levels, mirror, runs) {
|
|
1312
|
+
return entries.map((entry, pos) => {
|
|
1313
|
+
const odd = levels[pos] % 2 === 1;
|
|
1314
|
+
if (entry.shaped !== null && entry.shaped.rtl !== odd) {
|
|
1315
|
+
const flipped = mirror(entry.cp);
|
|
1316
|
+
if (flipped !== null && flipped !== entry.cp) entry = { ...entry, shaped: null };
|
|
1317
|
+
}
|
|
1318
|
+
if (!odd) return entry;
|
|
1319
|
+
if (entry.shaped !== null) return entry;
|
|
1320
|
+
const cp = mirror(entry.cp);
|
|
1321
|
+
if (cp === null || cp === entry.cp) return entry;
|
|
1322
|
+
if (entry.font === null) return { ...entry, cp };
|
|
1323
|
+
const run = runs[entry.run];
|
|
1324
|
+
const hit = resolveGlyph(entry.resolved, run.fontFamily, run.fontWeight, run.fontStyle, cp, false);
|
|
1325
|
+
if (!hit) return entry;
|
|
1326
|
+
return { ...entry, cp, resolved: hit.resolved, metrics: hit.metrics, font: hit.font, glyph: hit.glyph };
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// src/layout/lineBreak/wrapLines.ts
|
|
1331
|
+
var hangs = (cp) => cp === 32 || cp === 9;
|
|
1332
|
+
function wrapLines(cps, maxWidth, widthOf) {
|
|
1333
|
+
const lines = [];
|
|
1334
|
+
wrapSpans(cps, maxWidth, widthOf, (start, end, wrapped) => {
|
|
1335
|
+
lines.push({ start, end, wrapped });
|
|
1336
|
+
});
|
|
1337
|
+
return lines;
|
|
1338
|
+
}
|
|
1339
|
+
function wrapSpans(cps, maxWidth, widthOf, emit) {
|
|
1340
|
+
const n = cps.length;
|
|
1341
|
+
const breaks = Number.isFinite(maxWidth) ? lineBreakOpportunities(cps) : null;
|
|
1342
|
+
let start = 0;
|
|
1343
|
+
let i = 0;
|
|
1344
|
+
while (i < n) {
|
|
1345
|
+
const cp = cps[i];
|
|
1346
|
+
if (isHardLineBreak(cp)) {
|
|
1347
|
+
emit(start, i, false);
|
|
1348
|
+
i += cp === 13 && cps[i + 1] === 10 ? 2 : 1;
|
|
1349
|
+
start = i;
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1352
|
+
if (hangs(cp)) {
|
|
1353
|
+
i++;
|
|
1354
|
+
continue;
|
|
1355
|
+
}
|
|
1356
|
+
let j = i + 1;
|
|
1357
|
+
let ink2 = i + 1;
|
|
1358
|
+
while (j < n && !isHardLineBreak(cps[j]) && (!breaks || breaks[j] === NO_BREAK)) {
|
|
1359
|
+
if (!hangs(cps[j])) ink2 = j + 1;
|
|
1360
|
+
j++;
|
|
1361
|
+
}
|
|
1362
|
+
if (breaks && i > start && widthOf(start, ink2) > maxWidth) {
|
|
1363
|
+
emit(start, i, true);
|
|
1364
|
+
start = i;
|
|
1365
|
+
}
|
|
1366
|
+
i = j;
|
|
1367
|
+
}
|
|
1368
|
+
if (start < n) emit(start, n, false);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
// src/layout/layoutLines.ts
|
|
1372
|
+
function aboveBaseline(e, lineHeight) {
|
|
1373
|
+
const k = e.lineSize / e.metrics.size;
|
|
1374
|
+
const ascent = e.metrics.ascent * k;
|
|
1375
|
+
if (e.metrics.descent === void 0) return ascent;
|
|
1376
|
+
return (e.lineSize * lineHeight - ascent - e.metrics.descent * k) / 2 + ascent;
|
|
1377
|
+
}
|
|
1378
|
+
var NONE = [];
|
|
1379
|
+
var cur = NONE;
|
|
1380
|
+
var sum = doubles(64);
|
|
1381
|
+
var tabs = [];
|
|
1382
|
+
var broken = [];
|
|
1383
|
+
var brokenCount = 0;
|
|
1384
|
+
var linePool = [];
|
|
1385
|
+
var LINE_POOL_MAX = 64;
|
|
1386
|
+
function flatWidth(start, end) {
|
|
1387
|
+
return cur[start].advance + cur[start].tracking + sum[end] - sum[start + 1];
|
|
1388
|
+
}
|
|
1389
|
+
var stopOf = (k) => cur[k].tab;
|
|
1390
|
+
function tabbedWidth(start, end) {
|
|
1391
|
+
return widthWithTabs(start, end, tabs, stopOf, flatWidth);
|
|
1392
|
+
}
|
|
1393
|
+
function pushSpan(start, end, wrapped) {
|
|
1394
|
+
const i = brokenCount++;
|
|
1395
|
+
let line = linePool[i];
|
|
1396
|
+
if (line === void 0) {
|
|
1397
|
+
line = { start: 0, entries: [], width: 0.5, height: 0.5, ascent: 0.5, wrapped: false, srcEnd: 0, end: 0 };
|
|
1398
|
+
if (i < LINE_POOL_MAX) linePool[i] = line;
|
|
1399
|
+
}
|
|
1400
|
+
line.start = start;
|
|
1401
|
+
line.end = end;
|
|
1402
|
+
line.wrapped = wrapped;
|
|
1403
|
+
line.width = 0;
|
|
1404
|
+
line.height = 0;
|
|
1405
|
+
line.ascent = 0;
|
|
1406
|
+
line.srcEnd = 0;
|
|
1407
|
+
broken[i] = line;
|
|
1408
|
+
}
|
|
1409
|
+
function breakLines(entries, cps, maxWidth, lineHeight) {
|
|
1410
|
+
if (sum.length < entries.length + 1) sum = doubles(entries.length + 1);
|
|
1411
|
+
sum[0] = 0;
|
|
1412
|
+
let tabCount = 0;
|
|
1413
|
+
brokenCount = 0;
|
|
1414
|
+
for (let k = 0; k < entries.length; k++) {
|
|
1415
|
+
const e = entries[k];
|
|
1416
|
+
sum[k + 1] = sum[k] + e.kerningBefore + e.advance + e.tracking;
|
|
1417
|
+
if (e.tab) tabs[tabCount++] = k;
|
|
1418
|
+
}
|
|
1419
|
+
tabs.length = tabCount;
|
|
1420
|
+
cur = entries;
|
|
1421
|
+
wrapSpans(cps, maxWidth, tabCount === 0 ? flatWidth : tabbedWidth, pushSpan);
|
|
1422
|
+
cur = NONE;
|
|
1423
|
+
broken.length = brokenCount;
|
|
1424
|
+
for (let i = 0; i < broken.length; i++) {
|
|
1425
|
+
const line = broken[i];
|
|
1426
|
+
if (line.start === line.end) {
|
|
1427
|
+
const brk = entries[line.end];
|
|
1428
|
+
line.height = brk.lineSize * lineHeight;
|
|
1429
|
+
line.ascent = aboveBaseline(brk, lineHeight);
|
|
1430
|
+
line.srcEnd = brk.srcIndex;
|
|
1431
|
+
line.entries.length = 0;
|
|
1432
|
+
continue;
|
|
1433
|
+
}
|
|
1434
|
+
const out = line.entries;
|
|
1435
|
+
for (let k = line.start; k < line.end; k++) {
|
|
1436
|
+
const e = entries[k];
|
|
1437
|
+
if (k === line.start) e.kerningBefore = 0;
|
|
1438
|
+
if (e.tab) e.advance = tabAdvance(line.width, e.tab.stop, e.tab.min);
|
|
1439
|
+
out[k - line.start] = e;
|
|
1440
|
+
line.width += e.kerningBefore + e.advance + e.tracking;
|
|
1441
|
+
line.height = Math.max(line.height, e.lineSize * lineHeight);
|
|
1442
|
+
line.ascent = Math.max(line.ascent, aboveBaseline(e, lineHeight));
|
|
1443
|
+
}
|
|
1444
|
+
out.length = line.end - line.start;
|
|
1445
|
+
line.srcEnd = entries[line.end - 1].srcEnd;
|
|
1446
|
+
}
|
|
1447
|
+
return broken;
|
|
1448
|
+
}
|
|
1449
|
+
function hungWidth(entries) {
|
|
1450
|
+
let hung = 0;
|
|
1451
|
+
for (let k = entries.length - 1; k >= 0 && hangs(entries[k].cp); k--) {
|
|
1452
|
+
const e = entries[k];
|
|
1453
|
+
hung += e.kerningBefore + e.advance + e.tracking;
|
|
1454
|
+
}
|
|
1455
|
+
return hung;
|
|
1456
|
+
}
|
|
1457
|
+
function wordGaps(entries) {
|
|
1458
|
+
const gaps = /* @__PURE__ */ new Set();
|
|
1459
|
+
let first = 0;
|
|
1460
|
+
while (first < entries.length && entries[first].cp === 32) first++;
|
|
1461
|
+
let last2 = entries.length - 1;
|
|
1462
|
+
while (last2 > first && entries[last2].cp === 32) last2--;
|
|
1463
|
+
for (let k = first + 1; k < last2; k++) if (entries[k].cp === 32) gaps.add(k);
|
|
1464
|
+
return gaps;
|
|
1465
|
+
}
|
|
1466
|
+
function alignOffset(align, alignWidth, inkWidth) {
|
|
1467
|
+
if (align === "left") return 0;
|
|
1468
|
+
if (!Number.isFinite(alignWidth)) return align === "center" ? -inkWidth / 2 : -inkWidth;
|
|
1469
|
+
const slack = alignWidth - inkWidth;
|
|
1470
|
+
return align === "center" ? slack / 2 : slack;
|
|
1471
|
+
}
|
|
1472
|
+
var NO_GAPS = /* @__PURE__ */ new Set();
|
|
1473
|
+
var placed = { box: null, inkWidth: 0.5 };
|
|
1474
|
+
function placeLine(line, y, order, align, alignWidth, justify, cols, start, at) {
|
|
1475
|
+
const { entries } = line;
|
|
1476
|
+
const hung = hungWidth(entries);
|
|
1477
|
+
const inkWidth = line.width - hung;
|
|
1478
|
+
const slack = alignWidth - inkWidth;
|
|
1479
|
+
const gaps = justify && line.wrapped && Number.isFinite(alignWidth) && slack > 0 ? wordGaps(entries) : NO_GAPS;
|
|
1480
|
+
const gapExtra = gaps.size > 0 ? slack / gaps.size : 0;
|
|
1481
|
+
const spread = gapExtra * gaps.size;
|
|
1482
|
+
const inkLeft = spread > 0 ? 0 : alignOffset(align, alignWidth, inkWidth);
|
|
1483
|
+
const hangsLeft = hung > 0 && order.levels[entries.length - 1] % 2 === 1;
|
|
1484
|
+
const left = hangsLeft ? inkLeft - hung : inkLeft;
|
|
1485
|
+
const lineBaselineY = y + line.ascent;
|
|
1486
|
+
let penX = left;
|
|
1487
|
+
let prevPos = -1;
|
|
1488
|
+
let wide = -1;
|
|
1489
|
+
let slot = 0;
|
|
1490
|
+
const { visual } = order;
|
|
1491
|
+
for (let v = 0; v < visual.length; v++) {
|
|
1492
|
+
const pos = visual[v];
|
|
1493
|
+
const e = entries[pos];
|
|
1494
|
+
const kern = prevPos < 0 ? 0 : pos === prevPos + 1 ? e.kerningBefore : prevPos === pos + 1 ? entries[prevPos].kerningBefore : 0;
|
|
1495
|
+
if (kern !== 0) cols.widen(start + (wide >= 0 ? wide : prevPos), kern);
|
|
1496
|
+
penX += kern;
|
|
1497
|
+
prevPos = pos;
|
|
1498
|
+
const step = e.advance + e.tracking + (gaps.has(pos) ? gapExtra : 0);
|
|
1499
|
+
if (step !== 0) wide = pos;
|
|
1500
|
+
cols.set(start + pos, e, order.levels[pos], penX, step, lineBaselineY - e.baselineShift);
|
|
1501
|
+
cols.setVisual(start, slot++, pos);
|
|
1502
|
+
penX += step;
|
|
1503
|
+
}
|
|
1504
|
+
const x1 = left + line.width + spread;
|
|
1505
|
+
const y1 = y + line.height;
|
|
1506
|
+
const prior = cols.boxes[at];
|
|
1507
|
+
placed.box = prior !== void 0 ? prior.refill(left, y, x1, y1, lineBaselineY, line.srcEnd, spread > 0, start, entries.length) : cols.boxes[at] = new LineBox(left, y, x1, y1, lineBaselineY, line.srcEnd, spread > 0, cols, start, entries.length);
|
|
1508
|
+
placed.inkWidth = inkWidth + spread;
|
|
1509
|
+
return placed;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// src/layout/layoutOpts.ts
|
|
1513
|
+
function resolveLayoutOpts(opts, out = {
|
|
1514
|
+
maxWidth: 0,
|
|
1515
|
+
alignWidth: 0,
|
|
1516
|
+
lineHeight: 0,
|
|
1517
|
+
align: "left",
|
|
1518
|
+
justify: false,
|
|
1519
|
+
bidi: null,
|
|
1520
|
+
shaper: null,
|
|
1521
|
+
direction: "auto",
|
|
1522
|
+
tabSize: 0
|
|
1523
|
+
}) {
|
|
1524
|
+
out.maxWidth = opts.maxWidth;
|
|
1525
|
+
out.alignWidth = opts.alignWidth ?? opts.maxWidth;
|
|
1526
|
+
out.lineHeight = opts.lineHeight;
|
|
1527
|
+
out.align = opts.align;
|
|
1528
|
+
out.justify = opts.justify === true || opts.align === "justify";
|
|
1529
|
+
out.bidi = layoutBidi(opts);
|
|
1530
|
+
out.shaper = layoutShaper(opts);
|
|
1531
|
+
out.direction = opts.direction ?? "auto";
|
|
1532
|
+
out.tabSize = opts.tabSize ?? DEFAULT_TAB_SIZE;
|
|
1533
|
+
return out;
|
|
1534
|
+
}
|
|
1535
|
+
function layoutBidi(opts) {
|
|
1536
|
+
return opts.bidi ?? registeredBidi();
|
|
1537
|
+
}
|
|
1538
|
+
function layoutShaper(opts) {
|
|
1539
|
+
return opts.shaper ?? registeredShaper();
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
// src/layout/layoutRuns.ts
|
|
1543
|
+
var ENTRY_POOL = [];
|
|
1544
|
+
var ENTRIES = [];
|
|
1545
|
+
var CPS = [];
|
|
1546
|
+
var OPTS = resolveLayoutOpts({ maxWidth: 0, lineHeight: 0, align: "left" });
|
|
1547
|
+
function layoutRuns(runs, opts) {
|
|
1548
|
+
const {
|
|
1549
|
+
maxWidth,
|
|
1550
|
+
alignWidth,
|
|
1551
|
+
lineHeight,
|
|
1552
|
+
align,
|
|
1553
|
+
justify,
|
|
1554
|
+
bidi,
|
|
1555
|
+
shaper,
|
|
1556
|
+
direction,
|
|
1557
|
+
tabSize
|
|
1558
|
+
} = resolveLayoutOpts(opts, OPTS);
|
|
1559
|
+
const entries = measureRuns(runs, tabSize, ENTRY_POOL, ENTRIES, shaper);
|
|
1560
|
+
const cps = CPS;
|
|
1561
|
+
cps.length = entries.length;
|
|
1562
|
+
for (let k = 0; k < entries.length; k++) cps[k] = entries[k].cp;
|
|
1563
|
+
const paragraphs = bidi ? analyzeParagraphs(bidi, cps, (i) => isHardLineBreak(cps[i]), direction) : null;
|
|
1564
|
+
if (!bidi) warnRtlWithoutEngine(cps);
|
|
1565
|
+
const broken2 = breakLines(entries, cps, maxWidth, lineHeight);
|
|
1566
|
+
let size = 0;
|
|
1567
|
+
for (let i = 0; i < broken2.length; i++) size += broken2[i].entries.length;
|
|
1568
|
+
const cols = broken2.length > 0 ? LayoutColumns.take(size) : null;
|
|
1569
|
+
const lines = cols !== null ? cols.boxes : [];
|
|
1570
|
+
let y = 0;
|
|
1571
|
+
let width = 0;
|
|
1572
|
+
let start = 0;
|
|
1573
|
+
for (let i = 0; i < broken2.length; i++) {
|
|
1574
|
+
const line = broken2[i];
|
|
1575
|
+
const order = orderLine(paragraphs, line.start, line.entries.length);
|
|
1576
|
+
if (bidi) line.entries = mirrorEntries(line.entries, order.levels, (cp) => bidi.mirror(cp), runs);
|
|
1577
|
+
const reads = direction !== "auto" ? direction : directionOfLevel(line.entries.length > 0 ? paragraphs?.baseLevel(line.start) ?? 0 : 0);
|
|
1578
|
+
const placed2 = placeLine(
|
|
1579
|
+
line,
|
|
1580
|
+
y,
|
|
1581
|
+
order,
|
|
1582
|
+
resolveAlign(align, reads),
|
|
1583
|
+
alignWidth,
|
|
1584
|
+
justify,
|
|
1585
|
+
cols,
|
|
1586
|
+
start,
|
|
1587
|
+
i
|
|
1588
|
+
);
|
|
1589
|
+
start += line.entries.length;
|
|
1590
|
+
width = Math.max(width, placed2.inkWidth);
|
|
1591
|
+
y += line.height;
|
|
1592
|
+
}
|
|
1593
|
+
lines.length = broken2.length;
|
|
1594
|
+
return { lines, bounds: { width, height: y } };
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
// src/layout/glyphQuads.ts
|
|
1598
|
+
var QUAD_STRIDE = 11;
|
|
1599
|
+
function hasGlyphQuad(g) {
|
|
1600
|
+
const { font, glyph } = g;
|
|
1601
|
+
return font !== null && glyph !== null && glyph.width !== 0 && glyph.page >= 0;
|
|
1602
|
+
}
|
|
1603
|
+
function writeGlyphQuad(g, out, at) {
|
|
1604
|
+
const font = g.font, glyph = g.glyph;
|
|
1605
|
+
const scale = g.fontSize / g.metrics.size;
|
|
1606
|
+
const x0 = g.x + glyph.xoffset * scale;
|
|
1607
|
+
const y0 = g.baselineY + (glyph.yoffset - g.metrics.base) * scale;
|
|
1608
|
+
out[at] = x0;
|
|
1609
|
+
out[at + 1] = y0;
|
|
1610
|
+
out[at + 2] = x0 + glyph.width * scale;
|
|
1611
|
+
out[at + 3] = y0 + glyph.height * scale;
|
|
1612
|
+
out[at + 4] = glyph.x / font.common.scaleW;
|
|
1613
|
+
out[at + 5] = glyph.y / font.common.scaleH;
|
|
1614
|
+
out[at + 6] = (glyph.x + glyph.width) / font.common.scaleW;
|
|
1615
|
+
out[at + 7] = (glyph.y + glyph.height) / font.common.scaleH;
|
|
1616
|
+
out[at + 8] = g.baselineY;
|
|
1617
|
+
out[at + 9] = g.x;
|
|
1618
|
+
out[at + 10] = g.rotate ?? 0;
|
|
1619
|
+
}
|
|
1620
|
+
var quadsViewed = /* @__PURE__ */ new WeakSet();
|
|
1621
|
+
var quadViews = {
|
|
1622
|
+
quads: lazy("quads", (group) => {
|
|
1623
|
+
quadsViewed.add(group);
|
|
1624
|
+
const d = group.quadData;
|
|
1625
|
+
const out = [];
|
|
1626
|
+
for (let at = 0, k = 0; at < d.length; at += QUAD_STRIDE, k++) {
|
|
1627
|
+
const q = {
|
|
1628
|
+
x0: d[at],
|
|
1629
|
+
y0: d[at + 1],
|
|
1630
|
+
x1: d[at + 2],
|
|
1631
|
+
y1: d[at + 3],
|
|
1632
|
+
u0: d[at + 4],
|
|
1633
|
+
v0: d[at + 5],
|
|
1634
|
+
u1: d[at + 6],
|
|
1635
|
+
v1: d[at + 7],
|
|
1636
|
+
baselineY: d[at + 8],
|
|
1637
|
+
penX: d[at + 9],
|
|
1638
|
+
rotate: d[at + 10]
|
|
1639
|
+
};
|
|
1640
|
+
if (group.colorGlyphs) q.colorGlyph = group.colorGlyphs[k];
|
|
1641
|
+
out.push(q);
|
|
1642
|
+
}
|
|
1643
|
+
return out;
|
|
1644
|
+
})
|
|
1645
|
+
};
|
|
1646
|
+
var SYNTHETIC_BOLD_TOLERANCE = 5e-4;
|
|
1647
|
+
var CACHE_LIMIT = 4096;
|
|
1648
|
+
var cache = /* @__PURE__ */ new Map();
|
|
1649
|
+
var dCache = /* @__PURE__ */ new Map();
|
|
1650
|
+
function syntheticBoldOffset(resolved2) {
|
|
1651
|
+
if (!resolved2.synthetic.bold) return null;
|
|
1652
|
+
const { source } = resolved2;
|
|
1653
|
+
if (source !== "atlas" && source !== "canvas") return null;
|
|
1654
|
+
const { family, weight, style } = resolved2.resolved;
|
|
1655
|
+
const growth = syntheticBoldGrowth(source, family, weight, style);
|
|
1656
|
+
if (growth === void 0 || !(growth > 0)) return null;
|
|
1657
|
+
return { growth, join: source === "atlas" ? "miter" : "round" };
|
|
1658
|
+
}
|
|
1659
|
+
function emboldenGlyph(em, d, resolved2) {
|
|
1660
|
+
const offset = syntheticBoldOffset(resolved2);
|
|
1661
|
+
if (offset === null) return em;
|
|
1662
|
+
const key = `${offset.growth}|${offset.join}|${d}`;
|
|
1663
|
+
let grown = cache.get(key);
|
|
1664
|
+
if (grown) return grown;
|
|
1665
|
+
grown = mergeRegion(
|
|
1666
|
+
growRegion(em, offset.growth, { join: offset.join, tolerance: SYNTHETIC_BOLD_TOLERANCE }),
|
|
1667
|
+
{ tolerance: SYNTHETIC_BOLD_TOLERANCE }
|
|
1668
|
+
);
|
|
1669
|
+
if (cache.size >= CACHE_LIMIT) cache.clear();
|
|
1670
|
+
cache.set(key, grown);
|
|
1671
|
+
return grown;
|
|
1672
|
+
}
|
|
1673
|
+
function emboldenGlyphD(d, resolved2) {
|
|
1674
|
+
const offset = syntheticBoldOffset(resolved2);
|
|
1675
|
+
if (offset === null) return null;
|
|
1676
|
+
const tag = `bold:${offset.growth}:${offset.join}`;
|
|
1677
|
+
const key = `${tag}|${d}`;
|
|
1678
|
+
let grown = dCache.get(key);
|
|
1679
|
+
if (grown === void 0) {
|
|
1680
|
+
grown = pathToD(emboldenGlyph(pathFromD(d), d, resolved2));
|
|
1681
|
+
if (dCache.size >= CACHE_LIMIT) dCache.clear();
|
|
1682
|
+
dCache.set(key, grown);
|
|
1683
|
+
}
|
|
1684
|
+
return { d: grown, tag };
|
|
1685
|
+
}
|
|
1686
|
+
function strokeOn(run, source) {
|
|
1687
|
+
return source === "outline" && strokeHasInk(run.stroke) ? run.stroke : void 0;
|
|
1688
|
+
}
|
|
1689
|
+
function paintOf(run, source) {
|
|
1690
|
+
return `${paintKey(run.fill?.paint)}|${strokeKey(strokeOn(run, source))}`;
|
|
1691
|
+
}
|
|
1692
|
+
function groupFor(runs, g, source) {
|
|
1693
|
+
const { family, weight, style } = g.resolved.resolved;
|
|
1694
|
+
const { synthetic } = g.resolved;
|
|
1695
|
+
const page = source === "outline" ? 0 : g.glyph.page;
|
|
1696
|
+
if (last.group !== null && last.run === g.run && last.source === source && last.page === page && last.family === family && last.weight === weight && last.style === style && last.bold === synthetic.bold && last.italic === synthetic.italic) {
|
|
1697
|
+
return last.group;
|
|
1698
|
+
}
|
|
1699
|
+
const run = runs[g.run];
|
|
1700
|
+
let group = null;
|
|
1701
|
+
let paint = null;
|
|
1702
|
+
for (let k = 0; k < slots.length; k++) {
|
|
1703
|
+
const slot = slots[k];
|
|
1704
|
+
const c = slot.group;
|
|
1705
|
+
if (c.source !== source || c.page !== page || c.family !== family || c.weight !== weight || c.style !== style || c.synthetic.bold !== synthetic.bold || c.synthetic.italic !== synthetic.italic) continue;
|
|
1706
|
+
if (slot.run !== g.run) {
|
|
1707
|
+
paint ??= paintOf(run, source);
|
|
1708
|
+
slot.paint ??= paintOf(runs[slot.run], source);
|
|
1709
|
+
if (slot.paint !== paint) continue;
|
|
1710
|
+
}
|
|
1711
|
+
group = c;
|
|
1712
|
+
break;
|
|
1713
|
+
}
|
|
1714
|
+
if (group === null) {
|
|
1715
|
+
const stroke = strokeOn(run, source);
|
|
1716
|
+
group = stroke === void 0 && source !== "color" ? spareGroups.pop() ?? null : null;
|
|
1717
|
+
if (group !== null) {
|
|
1718
|
+
group.family = family;
|
|
1719
|
+
group.weight = weight;
|
|
1720
|
+
group.style = style;
|
|
1721
|
+
group.synthetic.bold = synthetic.bold;
|
|
1722
|
+
group.synthetic.italic = synthetic.italic;
|
|
1723
|
+
group.source = source;
|
|
1724
|
+
group.page = page;
|
|
1725
|
+
group.fill = run.fill;
|
|
1726
|
+
} else {
|
|
1727
|
+
group = Object.defineProperties({
|
|
1728
|
+
family,
|
|
1729
|
+
weight,
|
|
1730
|
+
style,
|
|
1731
|
+
synthetic: { bold: synthetic.bold, italic: synthetic.italic },
|
|
1732
|
+
source,
|
|
1733
|
+
page,
|
|
1734
|
+
fill: run.fill,
|
|
1735
|
+
quadData: NO_QUADS,
|
|
1736
|
+
glyphs: []
|
|
1737
|
+
}, quadViews);
|
|
1738
|
+
if (stroke) group.stroke = stroke;
|
|
1739
|
+
if (source === "color") group.colorGlyphs = [];
|
|
1740
|
+
}
|
|
1741
|
+
const i = slots.length;
|
|
1742
|
+
let slot = slotPool[i];
|
|
1743
|
+
if (slot === void 0) {
|
|
1744
|
+
slot = { group, run: g.run, paint };
|
|
1745
|
+
if (i < SLOT_POOL_MAX) slotPool[i] = slot;
|
|
1746
|
+
} else {
|
|
1747
|
+
slot.group = group;
|
|
1748
|
+
slot.run = g.run;
|
|
1749
|
+
slot.paint = paint;
|
|
1750
|
+
}
|
|
1751
|
+
slots.push(slot);
|
|
1752
|
+
}
|
|
1753
|
+
last.group = group;
|
|
1754
|
+
last.run = g.run;
|
|
1755
|
+
last.family = family;
|
|
1756
|
+
last.weight = weight;
|
|
1757
|
+
last.style = style;
|
|
1758
|
+
last.bold = synthetic.bold;
|
|
1759
|
+
last.italic = synthetic.italic;
|
|
1760
|
+
last.source = source;
|
|
1761
|
+
last.page = page;
|
|
1762
|
+
return group;
|
|
1763
|
+
}
|
|
1764
|
+
var NO_QUADS = [];
|
|
1765
|
+
var spareGroups = [];
|
|
1766
|
+
var SPARE_GROUPS_MAX = 1024;
|
|
1767
|
+
function giveGroup(group) {
|
|
1768
|
+
if (spareGroups.length >= SPARE_GROUPS_MAX || group.stroke !== void 0 || group.colorGlyphs !== void 0 || quadsViewed.has(group)) return;
|
|
1769
|
+
group.quadData = NO_QUADS;
|
|
1770
|
+
group.glyphs.length = 0;
|
|
1771
|
+
spareGroups.push(group);
|
|
1772
|
+
}
|
|
1773
|
+
var slots = [];
|
|
1774
|
+
var slotPool = [];
|
|
1775
|
+
var SLOT_POOL_MAX = 64;
|
|
1776
|
+
var last = {
|
|
1777
|
+
group: null,
|
|
1778
|
+
run: -1,
|
|
1779
|
+
family: "",
|
|
1780
|
+
weight: 0,
|
|
1781
|
+
style: "normal",
|
|
1782
|
+
bold: false,
|
|
1783
|
+
italic: false,
|
|
1784
|
+
source: "atlas",
|
|
1785
|
+
page: 0
|
|
1786
|
+
};
|
|
1787
|
+
function takeGroups(out) {
|
|
1788
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1789
|
+
out.push(slots[i].group);
|
|
1790
|
+
slots[i].group = null;
|
|
1791
|
+
}
|
|
1792
|
+
slots.length = 0;
|
|
1793
|
+
last.group = null;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
// src/layout/paintRuns.ts
|
|
1797
|
+
function glyphOutlineD(g, run, minSize) {
|
|
1798
|
+
const outlineOnly = g.resolved.source === "outline";
|
|
1799
|
+
if (!outlineOnly) {
|
|
1800
|
+
if (minSize === void 0) return null;
|
|
1801
|
+
if (run.fontSize < minSize && !strokeHasInk(run.stroke)) return null;
|
|
1802
|
+
}
|
|
1803
|
+
const d = faceOutlineD(g);
|
|
1804
|
+
if (d === null) return null;
|
|
1805
|
+
const { family, weight, style } = g.resolved.resolved;
|
|
1806
|
+
const key = g.shaped ? `${family}|${weight}|${style}|#${g.shaped.key}` : `${family}|${weight}|${style}|${g.cp}`;
|
|
1807
|
+
if (outlineOnly || !g.resolved.synthetic.bold) return { d, key };
|
|
1808
|
+
const bold = emboldenGlyphD(d, g.resolved);
|
|
1809
|
+
return bold && { d: bold.d, key: `${key}|${bold.tag}` };
|
|
1810
|
+
}
|
|
1811
|
+
function faceOutlineD(g) {
|
|
1812
|
+
if (g.shaped) return g.shaped.d;
|
|
1813
|
+
if (g.glyph?.color) return null;
|
|
1814
|
+
const { family, weight, style } = g.resolved.resolved;
|
|
1815
|
+
if (g.resolved.source !== "outline" && g.glyph === null) return null;
|
|
1816
|
+
return glyphOutline(family, weight, style, g.cp);
|
|
1817
|
+
}
|
|
1818
|
+
function runFaces(runs) {
|
|
1819
|
+
const faces = runs.map((r) => faceMetricsOf(resolveFontVariant(r.fontFamily, r.fontWeight, r.fontStyle)));
|
|
1820
|
+
return (run) => faces[run];
|
|
1821
|
+
}
|
|
1822
|
+
var isDecorated = (r) => r.underline || r.strikethrough || r.overline;
|
|
1823
|
+
var cursor = blankGlyph();
|
|
1824
|
+
var scratch = [];
|
|
1825
|
+
var SCRATCH_MAX2 = 1 << 14;
|
|
1826
|
+
function paintRuns(laid, runs, opts = {}) {
|
|
1827
|
+
return paintRunsInto(laid, runs, opts, { groups: [], decorations: [] });
|
|
1828
|
+
}
|
|
1829
|
+
function paintRunsInto(laid, runs, opts, out) {
|
|
1830
|
+
const { groups, decorations } = out;
|
|
1831
|
+
groups.length = 0;
|
|
1832
|
+
decorations.length = 0;
|
|
1833
|
+
const faceOf = runs.some(isDecorated) ? runFaces(runs) : null;
|
|
1834
|
+
const rulePaint = faceOf && ((run) => fillHasInk(runs[run].fill) ? paintKey(runs[run].fill.paint) : null);
|
|
1835
|
+
let glyphCount = 0;
|
|
1836
|
+
const { lines } = laid;
|
|
1837
|
+
for (let i = 0; i < lines.length; i++) glyphCount += LineBox.count(lines[i]);
|
|
1838
|
+
const need = glyphCount * QUAD_STRIDE;
|
|
1839
|
+
if (need <= SCRATCH_MAX2 && scratch.length < need) scratch = doubles(need);
|
|
1840
|
+
const buf = need <= SCRATCH_MAX2 ? scratch : doubles(need);
|
|
1841
|
+
let sized = null;
|
|
1842
|
+
let sizedAt = 0;
|
|
1843
|
+
for (let li = 0; li < lines.length; li++) {
|
|
1844
|
+
const line = lines[li];
|
|
1845
|
+
const cols = LineBox.columns(line);
|
|
1846
|
+
const start = cols !== null ? LineBox.start(line) : 0;
|
|
1847
|
+
const count = LineBox.count(line);
|
|
1848
|
+
const rules = faceOf && lineDecorations(runs, faceOf, rulePaint);
|
|
1849
|
+
for (let slot = 0; slot < count; slot++) {
|
|
1850
|
+
const pos = cols !== null ? cols.visual(start, slot) : -1;
|
|
1851
|
+
const g = cols !== null ? cols.glyph(start, pos, cursor) : line.glyphs[slot];
|
|
1852
|
+
rules?.add(g);
|
|
1853
|
+
const run = runs[g.run];
|
|
1854
|
+
const inks = cols !== null ? cols.drawsInk(start, pos) : line.cells[g.cell].drawsInk;
|
|
1855
|
+
const outline = inks ? glyphOutlineD(g, run, opts.outlineMinSize) : null;
|
|
1856
|
+
if (!fillHasInk(run.fill) && !(outline !== null && strokeHasInk(run.stroke))) continue;
|
|
1857
|
+
if (outline !== null) {
|
|
1858
|
+
const placed2 = { ...outline, x: g.x, baselineY: g.baselineY, scale: g.fontSize };
|
|
1859
|
+
if (g.rotate) placed2.rotate = g.rotate;
|
|
1860
|
+
groupFor(runs, g, "outline").glyphs.push(placed2);
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
if (!hasGlyphQuad(g)) continue;
|
|
1864
|
+
const group = groupFor(runs, g, g.glyph.color ? "color" : g.resolved.source);
|
|
1865
|
+
if (sized === null) {
|
|
1866
|
+
sized = group;
|
|
1867
|
+
group.quadData = buf;
|
|
1868
|
+
}
|
|
1869
|
+
let quads = group.quadData;
|
|
1870
|
+
if (quads === NO_QUADS) group.quadData = quads = [];
|
|
1871
|
+
if (group === sized) {
|
|
1872
|
+
writeGlyphQuad(g, quads, sizedAt);
|
|
1873
|
+
sizedAt += QUAD_STRIDE;
|
|
1874
|
+
} else {
|
|
1875
|
+
writeGlyphQuad(g, quads, quads.length);
|
|
1876
|
+
}
|
|
1877
|
+
group.colorGlyphs?.push(g.glyph);
|
|
1878
|
+
}
|
|
1879
|
+
if (!rules) continue;
|
|
1880
|
+
for (const rule of rules.end()) {
|
|
1881
|
+
const { run, ...rect } = rule;
|
|
1882
|
+
decorations.push({ ...rect, fill: runs[run].fill });
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
if (sized !== null && buf !== scratch) {
|
|
1886
|
+
buf.length = sizedAt;
|
|
1887
|
+
} else if (sized !== null) {
|
|
1888
|
+
const quads = takeDoubles(sizedAt);
|
|
1889
|
+
for (let k = 0; k < sizedAt; k++) quads[k] = scratch[k];
|
|
1890
|
+
sized.quadData = quads;
|
|
1891
|
+
}
|
|
1892
|
+
takeGroups(groups);
|
|
1893
|
+
return out;
|
|
1894
|
+
}
|
|
1895
|
+
var PAINT_CACHE_VARIANT_LIMIT = 32;
|
|
1896
|
+
var own = /* @__PURE__ */ new WeakMap();
|
|
1897
|
+
var shared2 = /* @__PURE__ */ new WeakMap();
|
|
1898
|
+
function listOf(laid) {
|
|
1899
|
+
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
1900
|
+
if (cols !== null) return cols.paintings;
|
|
1901
|
+
let list = shared2.get(laid);
|
|
1902
|
+
if (list === void 0) shared2.set(laid, list = []);
|
|
1903
|
+
return list;
|
|
1904
|
+
}
|
|
1905
|
+
var spare2 = [];
|
|
1906
|
+
var SPARE_MAX2 = 1024;
|
|
1907
|
+
function painting(laid, runs, opts, generation, key, bucket) {
|
|
1908
|
+
const p = spare2.pop();
|
|
1909
|
+
if (p === void 0) {
|
|
1910
|
+
return {
|
|
1911
|
+
generation,
|
|
1912
|
+
key,
|
|
1913
|
+
bucket,
|
|
1914
|
+
runs: key === null ? runs : null,
|
|
1915
|
+
painted: paintRunsInto(laid, runs, opts, { groups: [], decorations: [] }),
|
|
1916
|
+
pinned: false
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
p.generation = generation;
|
|
1920
|
+
p.key = key;
|
|
1921
|
+
p.bucket = bucket;
|
|
1922
|
+
p.runs = key === null ? runs : null;
|
|
1923
|
+
p.pinned = false;
|
|
1924
|
+
paintRunsInto(laid, runs, opts, p.painted);
|
|
1925
|
+
return p;
|
|
1926
|
+
}
|
|
1927
|
+
function outlineBucket(runs, min) {
|
|
1928
|
+
if (min === void 0) return -1;
|
|
1929
|
+
let n = 0;
|
|
1930
|
+
for (let i = 0; i < runs.length; i++) {
|
|
1931
|
+
const size = runs[i].fontSize;
|
|
1932
|
+
if (!(size >= min)) continue;
|
|
1933
|
+
let seen = false;
|
|
1934
|
+
for (let j = 0; j < i && !seen; j++) seen = runs[j].fontSize === size;
|
|
1935
|
+
if (!seen) n++;
|
|
1936
|
+
}
|
|
1937
|
+
return n;
|
|
1938
|
+
}
|
|
1939
|
+
function variantKey(runs, bucket) {
|
|
1940
|
+
let out = `${bucket}`;
|
|
1941
|
+
for (const r of runs) {
|
|
1942
|
+
out += `|${r.underline ? 1 : 0}${r.strikethrough ? 1 : 0}${r.overline ? 1 : 0}${paintKey(r.fill?.paint)}|${strokeKey(r.stroke)}`;
|
|
1943
|
+
}
|
|
1944
|
+
return out;
|
|
1945
|
+
}
|
|
1946
|
+
function keyOf(p) {
|
|
1947
|
+
if (p.key === null) {
|
|
1948
|
+
p.key = variantKey(p.runs, p.bucket);
|
|
1949
|
+
p.runs = null;
|
|
1950
|
+
}
|
|
1951
|
+
return p.key;
|
|
1952
|
+
}
|
|
1953
|
+
function cachedPaintRuns(laid, runs, opts = {}, use = "keep") {
|
|
1954
|
+
const generation = glyphGeneration();
|
|
1955
|
+
const min = opts.outlineMinSize;
|
|
1956
|
+
const mine = own.get(runs);
|
|
1957
|
+
const mineHere = mine !== void 0 && mine.laid === laid && mine.painting.generation === generation;
|
|
1958
|
+
if (mineHere && mine.min === min) return handOut(mine.painting, use);
|
|
1959
|
+
const bucket = outlineBucket(runs, min);
|
|
1960
|
+
if (mineHere && mine.painting.bucket === bucket) {
|
|
1961
|
+
mine.min = min;
|
|
1962
|
+
return handOut(mine.painting, use);
|
|
1963
|
+
}
|
|
1964
|
+
const list = listOf(laid);
|
|
1965
|
+
let p = null;
|
|
1966
|
+
if (list.length > 0) {
|
|
1967
|
+
const key = variantKey(runs, bucket);
|
|
1968
|
+
for (let i = 0; i < list.length; i++) {
|
|
1969
|
+
const held2 = list[i];
|
|
1970
|
+
if (held2.bucket !== bucket || keyOf(held2) !== key) continue;
|
|
1971
|
+
list.splice(i, 1);
|
|
1972
|
+
if (held2.generation === generation) p = held2;
|
|
1973
|
+
break;
|
|
1974
|
+
}
|
|
1975
|
+
p ??= painting(laid, runs, opts, generation, key, bucket);
|
|
1976
|
+
} else {
|
|
1977
|
+
p = painting(laid, runs, opts, generation, null, bucket);
|
|
1978
|
+
}
|
|
1979
|
+
if (list.length >= PAINT_CACHE_VARIANT_LIMIT) list.shift();
|
|
1980
|
+
list.push(p);
|
|
1981
|
+
if (mine !== void 0) {
|
|
1982
|
+
mine.laid = laid;
|
|
1983
|
+
mine.painting = p;
|
|
1984
|
+
mine.min = min;
|
|
1985
|
+
} else {
|
|
1986
|
+
const o = spareOwn.pop();
|
|
1987
|
+
if (o === void 0) {
|
|
1988
|
+
own.set(runs, { laid, painting: p, min });
|
|
1989
|
+
} else {
|
|
1990
|
+
o.laid = laid;
|
|
1991
|
+
o.painting = p;
|
|
1992
|
+
o.min = min;
|
|
1993
|
+
own.set(runs, o);
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return handOut(p, use);
|
|
1997
|
+
}
|
|
1998
|
+
function handOut(p, use) {
|
|
1999
|
+
if (use === "keep") p.pinned = true;
|
|
2000
|
+
return p.painted;
|
|
2001
|
+
}
|
|
2002
|
+
function forgetPaintRuns(runs) {
|
|
2003
|
+
const mine = own.get(runs);
|
|
2004
|
+
if (mine === void 0) return;
|
|
2005
|
+
own.delete(runs);
|
|
2006
|
+
if (spareOwn.length < SPARE_MAX2) spareOwn.push(mine);
|
|
2007
|
+
}
|
|
2008
|
+
var spareOwn = [];
|
|
2009
|
+
function recyclePaintings(laid) {
|
|
2010
|
+
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
2011
|
+
let list;
|
|
2012
|
+
if (cols !== null) {
|
|
2013
|
+
list = cols.paintings;
|
|
2014
|
+
} else {
|
|
2015
|
+
list = shared2.get(laid);
|
|
2016
|
+
if (list === void 0) return;
|
|
2017
|
+
shared2.delete(laid);
|
|
2018
|
+
}
|
|
2019
|
+
for (let i = 0; i < list.length; i++) {
|
|
2020
|
+
const p = list[i];
|
|
2021
|
+
if (p.pinned) continue;
|
|
2022
|
+
const { groups } = p.painted;
|
|
2023
|
+
for (let k = 0; k < groups.length; k++) {
|
|
2024
|
+
const group = groups[k];
|
|
2025
|
+
if (group.quadData.length > 0) giveDoubles(group.quadData);
|
|
2026
|
+
group.quadData = NO_QUADS;
|
|
2027
|
+
giveGroup(group);
|
|
2028
|
+
}
|
|
2029
|
+
groups.length = 0;
|
|
2030
|
+
p.painted.decorations.length = 0;
|
|
2031
|
+
p.runs = null;
|
|
2032
|
+
p.key = null;
|
|
2033
|
+
if (spare2.length < SPARE_MAX2) spare2.push(p);
|
|
2034
|
+
}
|
|
2035
|
+
list.length = 0;
|
|
2036
|
+
}
|
|
2037
|
+
var LAYOUT_CACHE_VARIANT_LIMIT = 8;
|
|
2038
|
+
var LAYOUT_CACHE_STRUCTURAL_LIMIT = 64;
|
|
2039
|
+
var cache2 = /* @__PURE__ */ new WeakMap();
|
|
2040
|
+
var structural = [];
|
|
2041
|
+
var structuralGeneration = -1;
|
|
2042
|
+
var clock = 0;
|
|
2043
|
+
var same = (a, b) => a === b || a !== a && b !== b;
|
|
2044
|
+
function matches(v, opts, bidi) {
|
|
2045
|
+
return same(v.maxWidth, opts.maxWidth) && same(v.alignWidth, opts.alignWidth ?? opts.maxWidth) && same(v.lineHeight, opts.lineHeight) && v.align === opts.align && v.justify === (opts.justify === true || opts.align === "justify") && v.direction === (opts.direction ?? "auto") && same(v.tabSize, opts.tabSize ?? DEFAULT_TAB_SIZE) && v.bidi === bidi && v.shaper === layoutShaper(opts);
|
|
2046
|
+
}
|
|
2047
|
+
var columnsOf = (laid) => laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
2048
|
+
function handOut2(laid, use) {
|
|
2049
|
+
if (use === "keep") {
|
|
2050
|
+
const cols = columnsOf(laid);
|
|
2051
|
+
if (cols !== null) cols.pinned = true;
|
|
2052
|
+
}
|
|
2053
|
+
return laid;
|
|
2054
|
+
}
|
|
2055
|
+
function release(laid) {
|
|
2056
|
+
const cols = columnsOf(laid);
|
|
2057
|
+
if (cols === null || cols.owners > 0 || cols.listed || cols.pinned) return;
|
|
2058
|
+
recyclePaintings(laid);
|
|
2059
|
+
cols.recycle();
|
|
2060
|
+
}
|
|
2061
|
+
var spareEntries = [];
|
|
2062
|
+
var spareVariants = [];
|
|
2063
|
+
var SPARE_MAX3 = 1024;
|
|
2064
|
+
function disown(vs) {
|
|
2065
|
+
for (let i = 0; i < vs.length; i++) {
|
|
2066
|
+
const v = vs[i];
|
|
2067
|
+
const cols = columnsOf(v.laid);
|
|
2068
|
+
if (cols !== null) {
|
|
2069
|
+
cols.owners--;
|
|
2070
|
+
release(v.laid);
|
|
2071
|
+
}
|
|
2072
|
+
v.laid = NO_LAYOUT;
|
|
2073
|
+
if (spareVariants.length < SPARE_MAX3) spareVariants.push(v);
|
|
2074
|
+
}
|
|
2075
|
+
vs.length = 0;
|
|
2076
|
+
}
|
|
2077
|
+
var NO_LAYOUT = { lines: [], bounds: { width: 0, height: 0 } };
|
|
2078
|
+
function fill(v, opts, bidi, laid) {
|
|
2079
|
+
v.maxWidth = opts.maxWidth;
|
|
2080
|
+
v.alignWidth = opts.alignWidth ?? opts.maxWidth;
|
|
2081
|
+
v.lineHeight = opts.lineHeight;
|
|
2082
|
+
v.align = opts.align;
|
|
2083
|
+
v.justify = opts.justify === true || opts.align === "justify";
|
|
2084
|
+
v.direction = opts.direction ?? "auto";
|
|
2085
|
+
v.tabSize = opts.tabSize ?? DEFAULT_TAB_SIZE;
|
|
2086
|
+
v.bidi = bidi;
|
|
2087
|
+
v.shaper = layoutShaper(opts);
|
|
2088
|
+
v.laid = laid;
|
|
2089
|
+
return v;
|
|
2090
|
+
}
|
|
2091
|
+
function variant(opts, bidi, laid) {
|
|
2092
|
+
const spare3 = spareVariants.pop();
|
|
2093
|
+
if (spare3 !== void 0) return fill(spare3, opts, bidi, laid);
|
|
2094
|
+
return {
|
|
2095
|
+
maxWidth: opts.maxWidth,
|
|
2096
|
+
alignWidth: opts.alignWidth ?? opts.maxWidth,
|
|
2097
|
+
lineHeight: opts.lineHeight,
|
|
2098
|
+
align: opts.align,
|
|
2099
|
+
justify: opts.justify === true || opts.align === "justify",
|
|
2100
|
+
direction: opts.direction ?? "auto",
|
|
2101
|
+
tabSize: opts.tabSize ?? DEFAULT_TAB_SIZE,
|
|
2102
|
+
bidi,
|
|
2103
|
+
shaper: layoutShaper(opts),
|
|
2104
|
+
laid
|
|
2105
|
+
};
|
|
2106
|
+
}
|
|
2107
|
+
function mix(h, n) {
|
|
2108
|
+
return Math.imul(h ^ n, 16777619);
|
|
2109
|
+
}
|
|
2110
|
+
function mixNum(h, x) {
|
|
2111
|
+
return mix(h, x === (x | 0) ? x : Math.round(x * 4096));
|
|
2112
|
+
}
|
|
2113
|
+
function mixStr(h, s) {
|
|
2114
|
+
h = mix(h, s.length);
|
|
2115
|
+
for (let i = 0; i < s.length; i++) h = mix(h, s.charCodeAt(i));
|
|
2116
|
+
return h;
|
|
2117
|
+
}
|
|
2118
|
+
function runsHash(runs) {
|
|
2119
|
+
let h = mix(2166136261, runs.length);
|
|
2120
|
+
for (let i = 0; i < runs.length; i++) {
|
|
2121
|
+
const r = runs[i];
|
|
2122
|
+
h = mixStr(h, r.text);
|
|
2123
|
+
h = mixStr(h, r.fontFamily);
|
|
2124
|
+
h = mixNum(h, r.fontSize);
|
|
2125
|
+
h = mixNum(h, r.fontWeight);
|
|
2126
|
+
h = mix(h, r.fontStyle === "italic" ? 1 : 0);
|
|
2127
|
+
h = mixNum(h, r.letterSpacing);
|
|
2128
|
+
h = mixNum(h, r.baselineShift);
|
|
2129
|
+
h = mixNum(h, r.rotate ?? 0);
|
|
2130
|
+
h = mixNum(h, r.strutSize ?? -1);
|
|
2131
|
+
h = mix(h, r.fontFeatures?.length ?? 0);
|
|
2132
|
+
h = mixStr(h, r.lang ?? "");
|
|
2133
|
+
}
|
|
2134
|
+
return h;
|
|
2135
|
+
}
|
|
2136
|
+
function sameNums(a, b) {
|
|
2137
|
+
if (a === b) return true;
|
|
2138
|
+
if (a === void 0 || b === void 0 || a.length !== b.length) return false;
|
|
2139
|
+
for (let i = 0; i < a.length; i++) if (!same(a[i], b[i])) return false;
|
|
2140
|
+
return true;
|
|
2141
|
+
}
|
|
2142
|
+
function sameStrs(a, b) {
|
|
2143
|
+
if (a === b) return true;
|
|
2144
|
+
if ((a?.length ?? 0) !== (b?.length ?? 0)) return false;
|
|
2145
|
+
for (let i = 0; i < (a?.length ?? 0); i++) if (a[i] !== b[i]) return false;
|
|
2146
|
+
return true;
|
|
2147
|
+
}
|
|
2148
|
+
function sameRuns(a, b) {
|
|
2149
|
+
if (a.length !== b.length) return false;
|
|
2150
|
+
for (let i = 0; i < a.length; i++) {
|
|
2151
|
+
const x = a[i], y = b[i];
|
|
2152
|
+
if (x === y) continue;
|
|
2153
|
+
if (x.text !== y.text || x.fontFamily !== y.fontFamily || !same(x.fontSize, y.fontSize) || !same(x.fontWeight, y.fontWeight) || x.fontStyle !== y.fontStyle || !same(x.letterSpacing, y.letterSpacing) || !same(x.baselineShift, y.baselineShift) || !same(x.strutSize, y.strutSize) || !same(x.rotate ?? 0, y.rotate ?? 0) || !sameNums(x.sizeMap, y.sizeMap) || !sameStrs(x.fontFeatures, y.fontFeatures) || x.lang !== y.lang) return false;
|
|
2154
|
+
const sx = x.srcMap, sy = y.srcMap;
|
|
2155
|
+
if (sx !== sy && (sx === void 0 || sy === void 0 || sx.length !== sy.length || !sameNums(sx.starts, sy.starts))) return false;
|
|
2156
|
+
}
|
|
2157
|
+
return true;
|
|
2158
|
+
}
|
|
2159
|
+
function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
2160
|
+
const fonts = faceGeneration();
|
|
2161
|
+
const bidi = layoutBidi(opts);
|
|
2162
|
+
let entry = cache2.get(runs);
|
|
2163
|
+
if (entry === void 0) {
|
|
2164
|
+
entry = spareEntries.pop() ?? { generation: fonts, variants: [] };
|
|
2165
|
+
entry.generation = fonts;
|
|
2166
|
+
cache2.set(runs, entry);
|
|
2167
|
+
} else if (entry.generation !== fonts) {
|
|
2168
|
+
entry.generation = fonts;
|
|
2169
|
+
disown(entry.variants);
|
|
2170
|
+
} else {
|
|
2171
|
+
const vs2 = entry.variants;
|
|
2172
|
+
for (let i = 0; i < vs2.length; i++) {
|
|
2173
|
+
const v = vs2[i];
|
|
2174
|
+
if (!matches(v, opts, bidi)) continue;
|
|
2175
|
+
for (let k = i; k > 0; k--) vs2[k] = vs2[k - 1];
|
|
2176
|
+
vs2[0] = v;
|
|
2177
|
+
return handOut2(v.laid, use);
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
const laid = structuralLayout(runs, opts, bidi, fonts);
|
|
2181
|
+
const vs = entry.variants;
|
|
2182
|
+
if (vs.length >= LAYOUT_CACHE_VARIANT_LIMIT) disown(vs);
|
|
2183
|
+
vs.unshift(variant(opts, bidi, laid));
|
|
2184
|
+
const cols = columnsOf(laid);
|
|
2185
|
+
if (cols !== null) cols.owners++;
|
|
2186
|
+
return handOut2(laid, use);
|
|
2187
|
+
}
|
|
2188
|
+
function dropRuns(runs) {
|
|
2189
|
+
const entry = cache2.get(runs);
|
|
2190
|
+
forgetPaintRuns(runs);
|
|
2191
|
+
if (entry === void 0) return;
|
|
2192
|
+
cache2.delete(runs);
|
|
2193
|
+
disown(entry.variants);
|
|
2194
|
+
if (spareEntries.length < SPARE_MAX3) spareEntries.push(entry);
|
|
2195
|
+
}
|
|
2196
|
+
function structuralLayout(runs, opts, bidi, fonts) {
|
|
2197
|
+
if (structuralGeneration !== fonts) {
|
|
2198
|
+
for (const s of structural) unlist(s);
|
|
2199
|
+
structural = [];
|
|
2200
|
+
structuralGeneration = fonts;
|
|
2201
|
+
}
|
|
2202
|
+
const hash = runsHash(runs);
|
|
2203
|
+
let oldest = 0;
|
|
2204
|
+
for (let i = 0; i < structural.length; i++) {
|
|
2205
|
+
const s = structural[i];
|
|
2206
|
+
if (s.hash === hash && matches(s, opts, bidi) && sameRuns(s.runs, runs)) {
|
|
2207
|
+
s.used = ++clock;
|
|
2208
|
+
return s.laid;
|
|
2209
|
+
}
|
|
2210
|
+
if (s.used < structural[oldest].used) oldest = i;
|
|
2211
|
+
}
|
|
2212
|
+
const full = structural.length >= LAYOUT_CACHE_STRUCTURAL_LIMIT;
|
|
2213
|
+
if (full) unlist(structural[oldest]);
|
|
2214
|
+
const laid = layoutRuns(runs, opts);
|
|
2215
|
+
const filled = full ? fill(structural[oldest], opts, bidi, laid) : structuralEntry(opts, bidi, laid);
|
|
2216
|
+
filled.hash = hash;
|
|
2217
|
+
filled.runs = runs;
|
|
2218
|
+
filled.used = ++clock;
|
|
2219
|
+
const cols = columnsOf(laid);
|
|
2220
|
+
if (cols !== null) cols.listed = true;
|
|
2221
|
+
if (!full) structural.push(filled);
|
|
2222
|
+
return laid;
|
|
2223
|
+
}
|
|
2224
|
+
function structuralEntry(opts, bidi, laid) {
|
|
2225
|
+
return fill({
|
|
2226
|
+
maxWidth: 0,
|
|
2227
|
+
alignWidth: 0,
|
|
2228
|
+
lineHeight: 0,
|
|
2229
|
+
align: "left",
|
|
2230
|
+
justify: false,
|
|
2231
|
+
direction: "auto",
|
|
2232
|
+
tabSize: 0,
|
|
2233
|
+
bidi: null,
|
|
2234
|
+
shaper: null,
|
|
2235
|
+
laid,
|
|
2236
|
+
hash: 0,
|
|
2237
|
+
runs: [],
|
|
2238
|
+
used: 0
|
|
2239
|
+
}, opts, bidi, laid);
|
|
2240
|
+
}
|
|
2241
|
+
function unlist(s) {
|
|
2242
|
+
const cols = columnsOf(s.laid);
|
|
2243
|
+
if (cols === null) return;
|
|
2244
|
+
cols.listed = false;
|
|
2245
|
+
release(s.laid);
|
|
2246
|
+
}
|
|
2247
|
+
function _resetLayoutCacheForTests() {
|
|
2248
|
+
cache2 = /* @__PURE__ */ new WeakMap();
|
|
2249
|
+
structural = [];
|
|
2250
|
+
structuralGeneration = -1;
|
|
2251
|
+
clock = 0;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
export { BREAK_ALLOWED, BREAK_MANDATORY, DECORATION_KINDS, DEFAULT_DECORATION_METRICS, DEFAULT_TAB_SIZE, DEFAULT_TEXT_FILL, DEFAULT_TEXT_STYLE, LAYOUT_CACHE_STRUCTURAL_LIMIT, LAYOUT_CACHE_VARIANT_LIMIT, NO_BREAK, QUAD_STRIDE, _resetBidiWarningForTests, _resetLayoutCacheForTests, cachedLayoutRuns, cachedPaintRuns, decorationMetrics, decorationRule, dropRuns, emboldenGlyph, emboldenGlyphD, faceOutlineD, fontString, graphemeCount, hangs, hasGlyphQuad, isHardLineBreak, layoutRuns, lineBreakOpportunities, lineDecorations, paintRuns, paragraphDirection, registerBidi, registerShaper, resolveAlign, resolveTextStyle, runFaces, shapesWithFeature, syntheticBoldOffset, tabAdvance, widthWithTabs, wrapLines };
|
|
2255
|
+
//# sourceMappingURL=chunk-FODNMBHI.js.map
|
|
2256
|
+
//# sourceMappingURL=chunk-FODNMBHI.js.map
|