@weasel-js/text 1.14.1 → 1.15.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 → chunk-ZNSU5C43.js} +536 -400
- package/dist/chunk-ZNSU5C43.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +58 -29
- package/dist/index.js.map +1 -1
- package/dist/{test-seams-DHGfE_6p.d.ts → test-seams-Ck0mfD3U.d.ts} +34 -1
- package/dist/test-seams.d.ts +1 -1
- package/dist/test-seams.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-FODNMBHI.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isSolidPaint, resolveFill, resolveScreenLength, fillHasInk, strokeHasInk, paintKey, strokeKey } from '@weasel-js/paint';
|
|
2
|
-
import { cssFamilyName,
|
|
2
|
+
import { cssFamilyName, cachedFontVariant, syntheticBoldGrowth, glyphOutline, faceMetricsOf, glyphGeneration, faceGeneration, metricsOf, warnNoMetrics, resolveColorCluster, glyphIn, resolveGlyph } from '@weasel-js/font';
|
|
3
3
|
import { mergeRegion, growRegion, pathToD, pathFromD } from '@weasel-js/geom';
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -15,16 +15,16 @@ function tabAdvance(x, stop, min) {
|
|
|
15
15
|
const toNext = (Math.floor(x / stop) + 1) * stop - x;
|
|
16
16
|
return toNext < min ? toNext + stop : toNext;
|
|
17
17
|
}
|
|
18
|
-
function widthWithTabs(
|
|
18
|
+
function widthWithTabs(start2, end, tabs2, stopOf2, flatWidth2, piece) {
|
|
19
19
|
let x = 0;
|
|
20
|
-
let from =
|
|
20
|
+
let from = start2;
|
|
21
21
|
const lay = (to) => {
|
|
22
22
|
if (to <= from) return;
|
|
23
23
|
piece?.(from, to, x);
|
|
24
24
|
x += flatWidth2(from, to);
|
|
25
25
|
};
|
|
26
26
|
for (const t of tabs2) {
|
|
27
|
-
if (t <
|
|
27
|
+
if (t < start2) continue;
|
|
28
28
|
if (t >= end) break;
|
|
29
29
|
lay(t);
|
|
30
30
|
const { stop, min } = stopOf2(t);
|
|
@@ -76,53 +76,51 @@ var DEFAULT_TEXT_STYLE = {
|
|
|
76
76
|
textTransform: "none",
|
|
77
77
|
fontVariantCaps: "normal"
|
|
78
78
|
};
|
|
79
|
-
var NOTHING = Object.freeze({});
|
|
80
79
|
function resolveTextStyle(style, paint, scale = 1) {
|
|
80
|
+
if (!style && resolveFill(paint?.fill) === null && (paint?.stroke ?? void 0) === void 0) {
|
|
81
|
+
return DEFAULT_TEXT_STYLE;
|
|
82
|
+
}
|
|
83
|
+
return resolveTextStyleInto({ ...DEFAULT_TEXT_STYLE }, style, paint, scale);
|
|
84
|
+
}
|
|
85
|
+
function resolveTextStyleInto(out, style, paint, scale = 1) {
|
|
86
|
+
const s = style ?? NO_STYLE;
|
|
81
87
|
const fill2 = resolveFill(paint?.fill);
|
|
82
88
|
const stroke = paint?.stroke ?? void 0;
|
|
83
|
-
|
|
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);
|
|
89
|
+
const caretColor = s.caretColor ?? paintColor(fill2?.paint ?? null);
|
|
93
90
|
let selectionBackground;
|
|
94
|
-
if (
|
|
91
|
+
if (s.selectionBackground === "none") {
|
|
95
92
|
selectionBackground = null;
|
|
96
|
-
} else if (
|
|
97
|
-
selectionBackground =
|
|
93
|
+
} else if (s.selectionBackground != null) {
|
|
94
|
+
selectionBackground = s.selectionBackground;
|
|
98
95
|
} else {
|
|
99
96
|
selectionBackground = defaultSelectionBackground(caretColor);
|
|
100
97
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
98
|
+
out.fontSize = resolveScreenLength(s.fontSize ?? DEFAULT_TEXT_STYLE.fontSize, scale);
|
|
99
|
+
out.fontFamily = s.fontFamily ?? DEFAULT_TEXT_STYLE.fontFamily;
|
|
100
|
+
out.fontWeight = s.fontWeight ?? DEFAULT_TEXT_STYLE.fontWeight;
|
|
101
|
+
out.fontStyle = s.fontStyle ?? DEFAULT_TEXT_STYLE.fontStyle;
|
|
102
|
+
out.align = s.align ?? DEFAULT_TEXT_STYLE.align;
|
|
103
|
+
out.direction = s.direction ?? DEFAULT_TEXT_STYLE.direction;
|
|
104
|
+
out.lineHeight = s.lineHeight ?? DEFAULT_TEXT_STYLE.lineHeight;
|
|
105
|
+
out.tabSize = s.tabSize ?? DEFAULT_TEXT_STYLE.tabSize;
|
|
106
|
+
out.wrap = s.wrap ?? DEFAULT_TEXT_STYLE.wrap;
|
|
107
|
+
out.fill = fill2;
|
|
108
|
+
out.caretColor = caretColor;
|
|
109
|
+
out.selectionBackground = selectionBackground;
|
|
110
|
+
out.selectionColor = s.selectionColor ?? null;
|
|
111
|
+
out.letterSpacing = resolveScreenLength(s.letterSpacing ?? DEFAULT_TEXT_STYLE.letterSpacing, scale);
|
|
112
|
+
out.underline = s.underline ?? DEFAULT_TEXT_STYLE.underline;
|
|
113
|
+
out.strikethrough = s.strikethrough ?? DEFAULT_TEXT_STYLE.strikethrough;
|
|
114
|
+
out.overline = s.overline ?? DEFAULT_TEXT_STYLE.overline;
|
|
115
|
+
out.textTransform = s.textTransform ?? DEFAULT_TEXT_STYLE.textTransform;
|
|
116
|
+
out.fontVariantCaps = s.fontVariantCaps ?? DEFAULT_TEXT_STYLE.fontVariantCaps;
|
|
117
|
+
if (s.script !== void 0 || out.script !== void 0) out.script = s.script;
|
|
118
|
+
const lang = s.lang || void 0;
|
|
119
|
+
if (lang !== void 0 || out.lang !== void 0) out.lang = lang;
|
|
120
|
+
if (stroke !== void 0 || out.stroke !== void 0) out.stroke = stroke;
|
|
121
|
+
return out;
|
|
125
122
|
}
|
|
123
|
+
var NO_STYLE = Object.freeze({});
|
|
126
124
|
function fontString(s) {
|
|
127
125
|
return `${s.fontStyle} ${s.fontWeight} ${s.fontSize}px ${cssFamilyName(s.fontFamily)}`;
|
|
128
126
|
}
|
|
@@ -149,7 +147,7 @@ function shapeableBytes(resolved2) {
|
|
|
149
147
|
}
|
|
150
148
|
function shapesWithFeature(family, weight, style, tag, shaper = registered) {
|
|
151
149
|
if (shaper === null) return false;
|
|
152
|
-
const bytes = shapeableBytes(
|
|
150
|
+
const bytes = shapeableBytes(cachedFontVariant(family, weight, style));
|
|
153
151
|
return bytes !== null && shaper.hasFeature(bytes, tag);
|
|
154
152
|
}
|
|
155
153
|
|
|
@@ -333,7 +331,7 @@ function decode() {
|
|
|
333
331
|
const values = new Uint8Array(RUNS);
|
|
334
332
|
const slot = new Uint8Array(128);
|
|
335
333
|
for (let i = 0; i < ALPHABET.length; i++) slot[ALPHABET.charCodeAt(i)] = PALETTE[i];
|
|
336
|
-
let
|
|
334
|
+
let cp2 = 0;
|
|
337
335
|
let run = 0;
|
|
338
336
|
let len = 0;
|
|
339
337
|
for (let i = 0; i < PACKED.length; i++) {
|
|
@@ -341,11 +339,11 @@ function decode() {
|
|
|
341
339
|
if (code <= 57 && code >= 48) len = len * 10 + code - 48;
|
|
342
340
|
else {
|
|
343
341
|
const v = slot[code];
|
|
344
|
-
starts[run] =
|
|
342
|
+
starts[run] = cp2;
|
|
345
343
|
values[run] = v;
|
|
346
|
-
if (
|
|
344
|
+
if (cp2 < 65536) direct.fill(v, cp2, Math.min(cp2 + len, 65536));
|
|
347
345
|
run++;
|
|
348
|
-
|
|
346
|
+
cp2 += len;
|
|
349
347
|
len = 0;
|
|
350
348
|
}
|
|
351
349
|
}
|
|
@@ -353,16 +351,16 @@ function decode() {
|
|
|
353
351
|
astralStarts = starts;
|
|
354
352
|
astralValues = values;
|
|
355
353
|
}
|
|
356
|
-
function lineBreakPropsOf(
|
|
354
|
+
function lineBreakPropsOf(cp2) {
|
|
357
355
|
if (bmp === null) decode();
|
|
358
|
-
if (
|
|
359
|
-
if (
|
|
356
|
+
if (cp2 < 65536) return bmp[cp2];
|
|
357
|
+
if (cp2 > 1114111) return AL;
|
|
360
358
|
const starts = astralStarts;
|
|
361
359
|
let lo = 0;
|
|
362
360
|
let hi = starts.length - 1;
|
|
363
361
|
while (lo < hi) {
|
|
364
362
|
const mid = lo + hi + 1 >> 1;
|
|
365
|
-
if (starts[mid] <=
|
|
363
|
+
if (starts[mid] <= cp2) lo = mid;
|
|
366
364
|
else hi = mid - 1;
|
|
367
365
|
}
|
|
368
366
|
return astralValues[lo];
|
|
@@ -427,8 +425,8 @@ var HYPHEN = 8208;
|
|
|
427
425
|
var DOTTED_CIRCLE = 9676;
|
|
428
426
|
var isQU = (c) => c === QU2 || c === QU_PI2 || c === QU_PF2;
|
|
429
427
|
var isHard = (c) => c === BK2 || c === CR2 || c === LF2 || c === NL2;
|
|
430
|
-
function isHardLineBreak(
|
|
431
|
-
return isHard(lineBreakPropsOf2(
|
|
428
|
+
function isHardLineBreak(cp2) {
|
|
429
|
+
return isHard(lineBreakPropsOf2(cp2) & CLASS_MASK2);
|
|
432
430
|
}
|
|
433
431
|
var isAlpha = (c) => c === AL2 || c === HL2;
|
|
434
432
|
var isKorean = (c) => c === JL2 || c === JV2 || c === JT2 || c === H22 || c === H32;
|
|
@@ -446,14 +444,28 @@ function growScratch(n) {
|
|
|
446
444
|
if (shared.cls.length < n) shared = newScratch(Math.min(SCRATCH_MAX, Math.max(n, shared.cls.length * 2)));
|
|
447
445
|
return shared;
|
|
448
446
|
}
|
|
447
|
+
var NO_INPUT = [];
|
|
448
|
+
var input = NO_INPUT;
|
|
449
|
+
var cls = shared.cls;
|
|
450
|
+
var ea = shared.ea;
|
|
451
|
+
var pict = shared.pict;
|
|
452
|
+
var cp = shared.cp;
|
|
453
|
+
var start = shared.start;
|
|
454
|
+
var units = 0;
|
|
449
455
|
function lineBreakOpportunities(cps) {
|
|
456
|
+
return lineBreakOpportunitiesInto(cps, new Uint8Array(cps.length + 1));
|
|
457
|
+
}
|
|
458
|
+
function lineBreakOpportunitiesInto(cps, out) {
|
|
450
459
|
const n = cps.length;
|
|
451
|
-
|
|
452
|
-
if (n === 0)
|
|
460
|
+
for (let i = 0; i < n; i++) out[i] = NO_BREAK;
|
|
461
|
+
if (n === 0) {
|
|
462
|
+
out[0] = NO_BREAK;
|
|
463
|
+
return out;
|
|
464
|
+
}
|
|
453
465
|
out[n] = BREAK_MANDATORY;
|
|
454
466
|
const scratch2 = n <= SCRATCH_MAX ? growScratch(n) : newScratch(n);
|
|
455
|
-
|
|
456
|
-
|
|
467
|
+
input = cps;
|
|
468
|
+
({ cls, ea, pict, cp, start } = scratch2);
|
|
457
469
|
let u = 0;
|
|
458
470
|
for (let i = 0; i < n; i++) {
|
|
459
471
|
const props = lineBreakPropsOf2(cps[i]);
|
|
@@ -475,111 +487,113 @@ function lineBreakOpportunities(cps) {
|
|
|
475
487
|
start[u] = i;
|
|
476
488
|
u++;
|
|
477
489
|
}
|
|
478
|
-
|
|
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
|
-
};
|
|
490
|
+
units = u;
|
|
484
491
|
for (let b = 1; b < units; b++) {
|
|
485
492
|
out[start[b]] = decide(b);
|
|
486
493
|
}
|
|
494
|
+
input = NO_INPUT;
|
|
495
|
+
if (scratch2 !== shared) ({ cls, ea, pict, cp, start } = shared);
|
|
487
496
|
return out;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
497
|
+
}
|
|
498
|
+
var prevIsZWJ = (b) => (lineBreakPropsOf2(input[start[b] - 1]) & CLASS_MASK2) === ZWJ2;
|
|
499
|
+
function beforeSpaces(k) {
|
|
500
|
+
while (k >= 0 && cls[k] === SP2) k--;
|
|
501
|
+
return k;
|
|
502
|
+
}
|
|
503
|
+
function decide(b) {
|
|
504
|
+
const a = b - 1;
|
|
505
|
+
const A = cls[a];
|
|
506
|
+
const B = cls[b];
|
|
507
|
+
if (A === CR2 && B === LF2) return NO_BREAK;
|
|
508
|
+
if (isHard(A)) return BREAK_MANDATORY;
|
|
509
|
+
if (isHard(B) || B === SP2 || B === ZW2) return NO_BREAK;
|
|
510
|
+
const s = beforeSpaces(a);
|
|
511
|
+
if (s >= 0 && cls[s] === ZW2) return BREAK_ALLOWED;
|
|
512
|
+
if (prevIsZWJ(b)) return NO_BREAK;
|
|
513
|
+
if (A === WJ2 || B === WJ2 || A === GL2) return NO_BREAK;
|
|
514
|
+
if (B === GL2 && A !== SP2 && A !== BA2 && A !== HY2) return NO_BREAK;
|
|
515
|
+
if (B === CL2 || B === CP2 || B === EX2 || B === SY2) return NO_BREAK;
|
|
516
|
+
const S = s >= 0 ? cls[s] : -1;
|
|
517
|
+
if (S === OP2) return NO_BREAK;
|
|
518
|
+
if (S === QU_PI2) {
|
|
519
|
+
const p = s - 1;
|
|
520
|
+
if (p < 0) return NO_BREAK;
|
|
521
|
+
const P = cls[p];
|
|
522
|
+
if (isHard(P) || P === OP2 || isQU(P) || P === GL2 || P === SP2 || P === ZW2) return NO_BREAK;
|
|
523
|
+
}
|
|
524
|
+
if (B === QU_PF2) {
|
|
525
|
+
if (b + 1 >= units) return NO_BREAK;
|
|
526
|
+
const N = cls[b + 1];
|
|
527
|
+
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;
|
|
528
|
+
}
|
|
529
|
+
if (A === SP2 && B === IS2 && b + 1 < units && cls[b + 1] === NU2) return BREAK_ALLOWED;
|
|
530
|
+
if (B === IS2) return NO_BREAK;
|
|
531
|
+
if ((S === CL2 || S === CP2) && B === NS2) return NO_BREAK;
|
|
532
|
+
if (S === B22 && B === B22) return NO_BREAK;
|
|
533
|
+
if (A === SP2) return BREAK_ALLOWED;
|
|
534
|
+
if (B === QU2 || B === QU_PF2) return NO_BREAK;
|
|
535
|
+
if (A === QU2 || A === QU_PI2) return NO_BREAK;
|
|
536
|
+
if (isQU(B)) {
|
|
537
|
+
if (!ea[a]) return NO_BREAK;
|
|
538
|
+
if (b + 1 >= units || !ea[b + 1]) return NO_BREAK;
|
|
539
|
+
}
|
|
540
|
+
if (isQU(A)) {
|
|
541
|
+
if (!ea[b]) return NO_BREAK;
|
|
542
|
+
if (a === 0 || !ea[a - 1]) return NO_BREAK;
|
|
543
|
+
}
|
|
544
|
+
if (A === CB2 || B === CB2) return BREAK_ALLOWED;
|
|
545
|
+
if ((A === HY2 || cp[a] === HYPHEN) && B === AL2) {
|
|
546
|
+
if (a === 0) return NO_BREAK;
|
|
547
|
+
const P = cls[a - 1];
|
|
548
|
+
if (isHard(P) || P === SP2 || P === ZW2 || P === CB2 || P === GL2) return NO_BREAK;
|
|
549
|
+
}
|
|
550
|
+
if (B === BA2 || B === HY2 || B === NS2 || A === BB2) return NO_BREAK;
|
|
551
|
+
if (a > 0 && cls[a - 1] === HL2 && (A === HY2 || A === BA2 && !ea[a]) && B !== HL2) return NO_BREAK;
|
|
552
|
+
if (A === SY2 && B === HL2) return NO_BREAK;
|
|
553
|
+
if (B === IN2) return NO_BREAK;
|
|
554
|
+
if (isAlpha(A) && B === NU2 || A === NU2 && isAlpha(B)) return NO_BREAK;
|
|
555
|
+
if (A === PR2 && isIdeoLike(B) || isIdeoLike(A) && B === PO2) return NO_BREAK;
|
|
556
|
+
if ((A === PR2 || A === PO2) && isAlpha(B) || isAlpha(A) && (B === PR2 || B === PO2)) return NO_BREAK;
|
|
557
|
+
if (B === PO2 || B === PR2) {
|
|
558
|
+
let k = A === CL2 || A === CP2 ? a - 1 : a;
|
|
559
|
+
while (k >= 0 && (cls[k] === SY2 || cls[k] === IS2)) k--;
|
|
560
|
+
if (k >= 0 && cls[k] === NU2) return NO_BREAK;
|
|
561
|
+
}
|
|
562
|
+
if (A === PO2 || A === PR2) {
|
|
563
|
+
if (B === NU2) return NO_BREAK;
|
|
564
|
+
if (B === OP2 && b + 1 < units) {
|
|
511
565
|
const N = cls[b + 1];
|
|
512
|
-
if (N ===
|
|
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;
|
|
566
|
+
if (N === NU2) return NO_BREAK;
|
|
567
|
+
if (N === IS2 && b + 2 < units && cls[b + 2] === NU2) return NO_BREAK;
|
|
560
568
|
}
|
|
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
569
|
}
|
|
570
|
+
if ((A === HY2 || A === IS2) && B === NU2) return NO_BREAK;
|
|
571
|
+
if (B === NU2) {
|
|
572
|
+
let k = a;
|
|
573
|
+
while (k >= 0 && (cls[k] === SY2 || cls[k] === IS2)) k--;
|
|
574
|
+
if (k >= 0 && cls[k] === NU2) return NO_BREAK;
|
|
575
|
+
}
|
|
576
|
+
if (A === JL2 && (B === JL2 || B === JV2 || B === H22 || B === H32)) return NO_BREAK;
|
|
577
|
+
if ((A === JV2 || A === H22) && (B === JV2 || B === JT2)) return NO_BREAK;
|
|
578
|
+
if ((A === JT2 || A === H32) && B === JT2) return NO_BREAK;
|
|
579
|
+
if (isKorean(A) && B === PO2 || A === PR2 && isKorean(B)) return NO_BREAK;
|
|
580
|
+
if (isAlpha(A) && isAlpha(B)) return NO_BREAK;
|
|
581
|
+
const aksaraA = A === AK2 || A === AS2 || cp[a] === DOTTED_CIRCLE;
|
|
582
|
+
const aksaraB = B === AK2 || B === AS2 || cp[b] === DOTTED_CIRCLE;
|
|
583
|
+
if (A === AP2 && aksaraB) return NO_BREAK;
|
|
584
|
+
if (aksaraA && (B === VF2 || B === VI2)) return NO_BREAK;
|
|
585
|
+
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;
|
|
586
|
+
if (aksaraA && aksaraB && b + 1 < units && cls[b + 1] === VF2) return NO_BREAK;
|
|
587
|
+
if (A === IS2 && isAlpha(B)) return NO_BREAK;
|
|
588
|
+
if ((isAlpha(A) || A === NU2) && B === OP2 && !ea[b]) return NO_BREAK;
|
|
589
|
+
if (A === CP2 && !ea[a] && (isAlpha(B) || B === NU2)) return NO_BREAK;
|
|
590
|
+
if (A === RI2 && B === RI2) {
|
|
591
|
+
let k = a;
|
|
592
|
+
while (k >= 0 && cls[k] === RI2) k--;
|
|
593
|
+
if ((a - k) % 2 === 1) return NO_BREAK;
|
|
594
|
+
}
|
|
595
|
+
if (B === EM2 && (A === EB2 || pict[a])) return NO_BREAK;
|
|
596
|
+
return BREAK_ALLOWED;
|
|
583
597
|
}
|
|
584
598
|
|
|
585
599
|
// src/layout/bidiRegistry.ts
|
|
@@ -601,9 +615,9 @@ function paragraphDirection(text, direction = "auto", engine = registered2) {
|
|
|
601
615
|
if (engine === null) return "ltr";
|
|
602
616
|
const cps = [];
|
|
603
617
|
for (const ch of text) {
|
|
604
|
-
const
|
|
605
|
-
if (isHardLineBreak(
|
|
606
|
-
cps.push(
|
|
618
|
+
const cp2 = ch.codePointAt(0);
|
|
619
|
+
if (isHardLineBreak(cp2)) break;
|
|
620
|
+
cps.push(cp2);
|
|
607
621
|
}
|
|
608
622
|
return directionOfLevel(engine.baseLevel(engine.analyze(cps, "auto")));
|
|
609
623
|
}
|
|
@@ -630,21 +644,21 @@ var RTL_BLOCK_NEUTRALS = [
|
|
|
630
644
|
[64830, 64831],
|
|
631
645
|
[65279, 65279]
|
|
632
646
|
];
|
|
633
|
-
function within(ranges,
|
|
634
|
-
for (let i = 0; i < ranges.length; i++) if (
|
|
647
|
+
function within(ranges, cp2) {
|
|
648
|
+
for (let i = 0; i < ranges.length; i++) if (cp2 >= ranges[i][0] && cp2 <= ranges[i][1]) return true;
|
|
635
649
|
return false;
|
|
636
650
|
}
|
|
637
651
|
var warnedLogicalRtl = false;
|
|
638
|
-
function warnRtlWithoutEngine(codePoints) {
|
|
652
|
+
function warnRtlWithoutEngine(codePoints, who = "weasel layoutRuns") {
|
|
639
653
|
if (warnedLogicalRtl) return;
|
|
640
654
|
for (let i = 0; i < codePoints.length; i++) {
|
|
641
|
-
const
|
|
642
|
-
if (!within(RTL_BLOCKS,
|
|
655
|
+
const cp2 = codePoints[i];
|
|
656
|
+
if (!within(RTL_BLOCKS, cp2) || within(RTL_BLOCK_NUMBERS, cp2) || within(RTL_BLOCK_NEUTRALS, cp2)) continue;
|
|
643
657
|
warnedLogicalRtl = true;
|
|
644
658
|
console.warn(
|
|
645
659
|
// Naming the import in `from "<pkg>"` form would trip labkit's
|
|
646
660
|
// consumer smoke test, which greps dist for that exact shape.
|
|
647
|
-
|
|
661
|
+
`${who}: 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
662
|
);
|
|
649
663
|
return;
|
|
650
664
|
}
|
|
@@ -656,13 +670,13 @@ function _resetBidiWarningForTests() {
|
|
|
656
670
|
// src/layout/bidiLines.ts
|
|
657
671
|
function analyzeParagraphs(engine, codePoints, isBreak, direction) {
|
|
658
672
|
const paragraphs = [];
|
|
659
|
-
let
|
|
673
|
+
let start2 = 0;
|
|
660
674
|
for (let i = 0; i <= codePoints.length; i++) {
|
|
661
675
|
if (i < codePoints.length && !isBreak(i)) continue;
|
|
662
|
-
if (i >
|
|
663
|
-
paragraphs.push({ start, end: i, analysis: engine.analyze(codePoints.slice(
|
|
676
|
+
if (i > start2) {
|
|
677
|
+
paragraphs.push({ start: start2, end: i, analysis: engine.analyze(codePoints.slice(start2, i), direction) });
|
|
664
678
|
}
|
|
665
|
-
|
|
679
|
+
start2 = i + 1;
|
|
666
680
|
}
|
|
667
681
|
const holding = (at) => {
|
|
668
682
|
let lo = 0;
|
|
@@ -729,17 +743,20 @@ function logicalOrder(count) {
|
|
|
729
743
|
if (count <= SHARED_ORDER_LIMIT) logicalOrders[count] = order;
|
|
730
744
|
return order;
|
|
731
745
|
}
|
|
732
|
-
function orderLine(paragraphs,
|
|
746
|
+
function orderLine(paragraphs, start2, count) {
|
|
733
747
|
if (paragraphs === null || count === 0) return logicalOrder(count);
|
|
748
|
+
return reorderedLine(paragraphs, start2, count);
|
|
749
|
+
}
|
|
750
|
+
function reorderedLine(paragraphs, start2, count) {
|
|
734
751
|
const levels = new Array(count).fill(0);
|
|
735
|
-
const r = paragraphs.reorder(
|
|
752
|
+
const r = paragraphs.reorder(start2, start2 + count);
|
|
736
753
|
for (let pos = 0; pos < count; pos++) {
|
|
737
754
|
const level = r.levels[pos];
|
|
738
755
|
if (typeof level === "number" && level >= 0) levels[pos] = level;
|
|
739
756
|
}
|
|
740
757
|
const kept = /* @__PURE__ */ new Set();
|
|
741
758
|
for (const at of r.order) {
|
|
742
|
-
const pos = at -
|
|
759
|
+
const pos = at - start2;
|
|
743
760
|
if (Number.isInteger(pos) && pos >= 0 && pos < count) kept.add(pos);
|
|
744
761
|
}
|
|
745
762
|
return { visual: restoreRemoved([...kept], count, (pos) => levels[pos] % 2 === 1), levels };
|
|
@@ -785,6 +802,9 @@ function giveDoubles(a) {
|
|
|
785
802
|
function giveRefs(a) {
|
|
786
803
|
give(refs, a);
|
|
787
804
|
}
|
|
805
|
+
function truncate(a, n) {
|
|
806
|
+
while (a.length > n) a.pop();
|
|
807
|
+
}
|
|
788
808
|
|
|
789
809
|
// src/layout/layoutColumns.ts
|
|
790
810
|
var NUM = 13;
|
|
@@ -808,12 +828,21 @@ var EMPTY_NUM = [];
|
|
|
808
828
|
var EMPTY_REF = [];
|
|
809
829
|
var spare = [];
|
|
810
830
|
var SPARE_MAX = 1024;
|
|
831
|
+
var stamps = 0;
|
|
811
832
|
var LayoutColumns = class _LayoutColumns {
|
|
812
833
|
num;
|
|
813
834
|
ref;
|
|
814
835
|
/** The layout's line boxes, its `lines`. A recycled layout's are refilled
|
|
815
836
|
* by the next layout to take its columns. */
|
|
816
837
|
boxes = [];
|
|
838
|
+
/** The layout's `bounds`, refilled like its boxes. */
|
|
839
|
+
bounds = { width: 0.5, height: 0.5 };
|
|
840
|
+
/** The layout itself, `{ lines: boxes, bounds }`, handed to every layout
|
|
841
|
+
* that takes these columns. */
|
|
842
|
+
laid = null;
|
|
843
|
+
/** Which of those layouts this is, new each time the columns are taken:
|
|
844
|
+
* what tells a layout apart from the one these columns held before. */
|
|
845
|
+
stamp = 0;
|
|
817
846
|
/** The paint cache's paintings of this layout, kept here rather than in a
|
|
818
847
|
* map keyed by the layout, so that recycling one deletes no map entry. */
|
|
819
848
|
paintings = [];
|
|
@@ -831,15 +860,20 @@ var LayoutColumns = class _LayoutColumns {
|
|
|
831
860
|
/** Columns for `size` code points: a recycled layout's, refilled, when the
|
|
832
861
|
* pool holds one. */
|
|
833
862
|
static take(size) {
|
|
834
|
-
|
|
835
|
-
if (cols === void 0)
|
|
836
|
-
|
|
837
|
-
|
|
863
|
+
let cols = spare.pop();
|
|
864
|
+
if (cols === void 0) {
|
|
865
|
+
cols = new _LayoutColumns(size);
|
|
866
|
+
} else {
|
|
867
|
+
cols.num = takeDoubles(size * NUM);
|
|
868
|
+
cols.ref = takeRefs(size * REF);
|
|
869
|
+
}
|
|
870
|
+
cols.stamp = ++stamps;
|
|
838
871
|
return cols;
|
|
839
872
|
}
|
|
840
873
|
/** Give the arrays back to the pool, and these columns with their line
|
|
841
|
-
* boxes to the next layout. A line box still held
|
|
842
|
-
* layout's code points, so only a layout nobody holds
|
|
874
|
+
* boxes and result to the next layout. A line box or result still held
|
|
875
|
+
* afterwards reads that layout's code points, so only a layout nobody holds
|
|
876
|
+
* is recycled. */
|
|
843
877
|
recycle() {
|
|
844
878
|
giveDoubles(this.num);
|
|
845
879
|
const { ref } = this;
|
|
@@ -847,7 +881,7 @@ var LayoutColumns = class _LayoutColumns {
|
|
|
847
881
|
giveRefs(ref);
|
|
848
882
|
this.num = EMPTY_NUM;
|
|
849
883
|
this.ref = EMPTY_REF;
|
|
850
|
-
this.paintings
|
|
884
|
+
truncate(this.paintings, 0);
|
|
851
885
|
this.owners = 0;
|
|
852
886
|
this.listed = false;
|
|
853
887
|
this.pinned = false;
|
|
@@ -882,17 +916,17 @@ var LayoutColumns = class _LayoutColumns {
|
|
|
882
916
|
}
|
|
883
917
|
/** Record that the `slot`-th code point the pen reaches on the line starting
|
|
884
918
|
* at `start` is the line's `pos`-th in logical order. */
|
|
885
|
-
setVisual(
|
|
886
|
-
this.num[(
|
|
919
|
+
setVisual(start2, slot, pos) {
|
|
920
|
+
this.num[(start2 + slot) * NUM + VISUAL] = pos;
|
|
887
921
|
}
|
|
888
922
|
/** Logical index, within its line, of the glyph at visual `slot`. */
|
|
889
|
-
visual(
|
|
890
|
-
return this.num[(
|
|
923
|
+
visual(start2, slot) {
|
|
924
|
+
return this.num[(start2 + slot) * NUM + VISUAL];
|
|
891
925
|
}
|
|
892
926
|
/** Fill `out` with code point `start + pos`'s placed glyph and return it.
|
|
893
927
|
* Every field is overwritten, so one object can walk a whole layout. */
|
|
894
|
-
glyph(
|
|
895
|
-
const i =
|
|
928
|
+
glyph(start2, pos, out) {
|
|
929
|
+
const i = start2 + pos;
|
|
896
930
|
const n = i * NUM, r = i * REF;
|
|
897
931
|
const { num, ref } = this;
|
|
898
932
|
out.run = num[n + RUN];
|
|
@@ -912,12 +946,12 @@ var LayoutColumns = class _LayoutColumns {
|
|
|
912
946
|
return out;
|
|
913
947
|
}
|
|
914
948
|
/** Code point `start + pos`'s `LaidOutCell.drawsInk`, without building the cell. */
|
|
915
|
-
drawsInk(
|
|
916
|
-
return (this.num[(
|
|
949
|
+
drawsInk(start2, pos) {
|
|
950
|
+
return (this.num[(start2 + pos) * NUM + FLAGS] & DRAWS_INK) !== 0;
|
|
917
951
|
}
|
|
918
952
|
/** Code point `start + pos`'s cell, as a new object. */
|
|
919
|
-
cell(
|
|
920
|
-
const n = (
|
|
953
|
+
cell(start2, pos) {
|
|
954
|
+
const n = (start2 + pos) * NUM;
|
|
921
955
|
const { num } = this;
|
|
922
956
|
const flags = num[n + FLAGS];
|
|
923
957
|
return {
|
|
@@ -951,19 +985,12 @@ function blankGlyph() {
|
|
|
951
985
|
};
|
|
952
986
|
}
|
|
953
987
|
var LineBox = class _LineBox {
|
|
954
|
-
x0;
|
|
955
|
-
y0;
|
|
956
|
-
x1;
|
|
957
|
-
y1;
|
|
958
|
-
baselineY;
|
|
959
|
-
srcEnd;
|
|
960
|
-
justified;
|
|
961
988
|
#cols;
|
|
962
989
|
#start;
|
|
963
990
|
#count;
|
|
964
991
|
/** Whether a view was built, replacing its accessor with a value. */
|
|
965
992
|
#viewed = false;
|
|
966
|
-
constructor(x0, y0, x1, y1, baselineY, srcEnd, justified, cols,
|
|
993
|
+
constructor(x0, y0, x1, y1, baselineY, srcEnd, justified, cols, start2, count) {
|
|
967
994
|
this.x0 = x0;
|
|
968
995
|
this.y0 = y0;
|
|
969
996
|
this.x1 = x1;
|
|
@@ -972,13 +999,13 @@ var LineBox = class _LineBox {
|
|
|
972
999
|
this.srcEnd = srcEnd;
|
|
973
1000
|
this.justified = justified;
|
|
974
1001
|
this.#cols = cols;
|
|
975
|
-
this.#start =
|
|
1002
|
+
this.#start = start2;
|
|
976
1003
|
this.#count = count;
|
|
977
1004
|
Object.defineProperties(this, _LineBox.#views);
|
|
978
1005
|
}
|
|
979
1006
|
/** Set this box to another line of the same columns, as the constructor
|
|
980
1007
|
* would, its views unbuilt again. */
|
|
981
|
-
refill(x0, y0, x1, y1, baselineY, srcEnd, justified,
|
|
1008
|
+
refill(x0, y0, x1, y1, baselineY, srcEnd, justified, start2, count) {
|
|
982
1009
|
this.x0 = x0;
|
|
983
1010
|
this.y0 = y0;
|
|
984
1011
|
this.x1 = x1;
|
|
@@ -986,7 +1013,7 @@ var LineBox = class _LineBox {
|
|
|
986
1013
|
this.baselineY = baselineY;
|
|
987
1014
|
this.srcEnd = srcEnd;
|
|
988
1015
|
this.justified = justified;
|
|
989
|
-
this.#start =
|
|
1016
|
+
this.#start = start2;
|
|
990
1017
|
this.#count = count;
|
|
991
1018
|
if (this.#viewed) {
|
|
992
1019
|
this.#viewed = false;
|
|
@@ -1052,7 +1079,7 @@ function graphemeEnds(text, into) {
|
|
|
1052
1079
|
} else {
|
|
1053
1080
|
const seg = graphemeSegmenter();
|
|
1054
1081
|
if (seg) {
|
|
1055
|
-
|
|
1082
|
+
n = segmentedEnds(seg, text, out);
|
|
1056
1083
|
} else {
|
|
1057
1084
|
let at = 0;
|
|
1058
1085
|
for (const ch of text) out[n++] = at += ch.length;
|
|
@@ -1061,6 +1088,32 @@ function graphemeEnds(text, into) {
|
|
|
1061
1088
|
out.length = n;
|
|
1062
1089
|
return out;
|
|
1063
1090
|
}
|
|
1091
|
+
var plain = (u) => u < 768 && u !== 13;
|
|
1092
|
+
function segmentedEnds(seg, text, out) {
|
|
1093
|
+
const len = text.length;
|
|
1094
|
+
let segments = null;
|
|
1095
|
+
let n = 0;
|
|
1096
|
+
let i = 0;
|
|
1097
|
+
while (i < len) {
|
|
1098
|
+
if (plain(text.charCodeAt(i)) && (i + 1 === len || plain(text.charCodeAt(i + 1)))) {
|
|
1099
|
+
out[n++] = ++i;
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
let end = i + 1;
|
|
1103
|
+
for (; ; ) {
|
|
1104
|
+
while (end < len && !plain(text.charCodeAt(end))) end++;
|
|
1105
|
+
if (end === len) break;
|
|
1106
|
+
end++;
|
|
1107
|
+
if (end === len || plain(text.charCodeAt(end))) break;
|
|
1108
|
+
}
|
|
1109
|
+
segments ??= seg.segment(text);
|
|
1110
|
+
while (i < end) {
|
|
1111
|
+
const s = segments.containing(i);
|
|
1112
|
+
out[n++] = i = s.index + s.segment.length;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
return n;
|
|
1116
|
+
}
|
|
1064
1117
|
function graphemeCount(text) {
|
|
1065
1118
|
return graphemeEnds(text).length;
|
|
1066
1119
|
}
|
|
@@ -1087,20 +1140,20 @@ function slotsFor(shaper, face, text, glyphs) {
|
|
|
1087
1140
|
let g = 0;
|
|
1088
1141
|
let i = 0;
|
|
1089
1142
|
while (i < glyphs.length) {
|
|
1090
|
-
const
|
|
1143
|
+
const start2 = glyphs[i].cluster;
|
|
1091
1144
|
let j = i;
|
|
1092
|
-
while (j < glyphs.length && glyphs[j].cluster ===
|
|
1145
|
+
while (j < glyphs.length && glyphs[j].cluster === start2) j++;
|
|
1093
1146
|
const end = j < glyphs.length ? glyphs[j].cluster : text.length;
|
|
1094
|
-
while (g < ends.length && ends[g] <=
|
|
1147
|
+
while (g < ends.length && ends[g] <= start2) g++;
|
|
1095
1148
|
let inner = 0;
|
|
1096
1149
|
for (let k = g; k < ends.length && ends[k] < end; k++) inner++;
|
|
1097
1150
|
if (!holdsNotdef(glyphs, i, j)) {
|
|
1098
1151
|
const total = advanceOf(glyphs, i, j);
|
|
1099
1152
|
const share = total / (inner + 1);
|
|
1100
1153
|
const shift = glyphs[i].rtl ? share - total : 0;
|
|
1101
|
-
slots2[
|
|
1154
|
+
slots2[start2] = clusterSlot(shaper, face, glyphs, i, j, text.slice(start2, end), shift, share);
|
|
1102
1155
|
const opens = share === 0 ? COVERED : { cluster: NOTHING_DRAWN, advance: share };
|
|
1103
|
-
for (let at =
|
|
1156
|
+
for (let at = start2 + 1, k = g; at < end; at++) {
|
|
1104
1157
|
const opening = k < ends.length && ends[k] === at;
|
|
1105
1158
|
if (opening) k++;
|
|
1106
1159
|
slots2[at] = opening ? opens : COVERED;
|
|
@@ -1138,13 +1191,13 @@ function clusterSlot(shaper, face, glyphs, from, to, text, shift, advance) {
|
|
|
1138
1191
|
// src/layout/layoutEntries.ts
|
|
1139
1192
|
var NONSPACING_MARK = /^[\p{Mn}\p{Me}]$/u;
|
|
1140
1193
|
function measureRuns(runs, tabSize, pool, into, shaper = null) {
|
|
1141
|
-
const
|
|
1194
|
+
const entries2 = into ?? [];
|
|
1142
1195
|
let n = 0;
|
|
1143
1196
|
let prev;
|
|
1144
1197
|
let srcIndex = 0;
|
|
1145
1198
|
for (let runIndex = 0; runIndex < runs.length; runIndex++) {
|
|
1146
1199
|
const run = runs[runIndex];
|
|
1147
|
-
const resolved2 =
|
|
1200
|
+
const resolved2 = cachedFontVariant(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
1148
1201
|
const metrics = metricsOf(resolved2);
|
|
1149
1202
|
if (!metrics) {
|
|
1150
1203
|
warnNoMetrics(run.fontFamily, run.fontWeight, run.fontStyle);
|
|
@@ -1162,8 +1215,8 @@ function measureRuns(runs, tabSize, pool, into, shaper = null) {
|
|
|
1162
1215
|
let at = 0;
|
|
1163
1216
|
const text = run.text;
|
|
1164
1217
|
while (at < text.length) {
|
|
1165
|
-
const
|
|
1166
|
-
const len =
|
|
1218
|
+
const cp2 = text.codePointAt(at);
|
|
1219
|
+
const len = cp2 > 65535 ? 2 : 1;
|
|
1167
1220
|
const slot = shaped?.[at];
|
|
1168
1221
|
const fontSize = run.sizeMap ? run.sizeMap[at] : run.fontSize;
|
|
1169
1222
|
if (at === clusterStart) {
|
|
@@ -1182,72 +1235,69 @@ function measureRuns(runs, tabSize, pool, into, shaper = null) {
|
|
|
1182
1235
|
const srcEnd = map ? runBase + map.ends[at] : runBase + at + len;
|
|
1183
1236
|
at += len;
|
|
1184
1237
|
srcIndex = map ? runBase + map.length : srcEnd;
|
|
1185
|
-
const mark = isNonspacingMark(
|
|
1186
|
-
const kerningBefore = prev && !mark ? prev.metrics.kernOf(prev.cp,
|
|
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
|
-
);
|
|
1238
|
+
const mark = isNonspacingMark(cp2);
|
|
1239
|
+
const kerningBefore = prev && !mark ? prev.metrics.kernOf(prev.cp, cp2) * (prev.fontSize / prev.metrics.size) : 0;
|
|
1240
|
+
const blank = blankEntry(pool, n, runIndex, run, cp2, fontSize, srcStart, srcEnd, clusterEnd, resolved2, metrics);
|
|
1203
1241
|
if (color) {
|
|
1204
|
-
|
|
1242
|
+
if (clusterEnd) {
|
|
1243
|
+
blank.tracking = tracking;
|
|
1244
|
+
ink(blank, color);
|
|
1245
|
+
}
|
|
1246
|
+
entries2[n++] = blank;
|
|
1205
1247
|
prev = void 0;
|
|
1206
|
-
} else if (isHardLineBreak(
|
|
1207
|
-
|
|
1248
|
+
} else if (isHardLineBreak(cp2)) {
|
|
1249
|
+
entries2[n++] = blank;
|
|
1208
1250
|
prev = void 0;
|
|
1209
|
-
} else if (
|
|
1251
|
+
} else if (cp2 === 9 || cp2 === 32) {
|
|
1210
1252
|
const space = metrics.advanceOf(32);
|
|
1211
1253
|
const advance = space !== null ? space * (fontSize / metrics.size) : fontSize * 0.25;
|
|
1212
|
-
if (
|
|
1213
|
-
|
|
1254
|
+
if (cp2 === 9) {
|
|
1255
|
+
entries2[n++] = { ...blank, tab: { stop: tabSize * (advance + run.letterSpacing), min: advance / 2 } };
|
|
1214
1256
|
prev = void 0;
|
|
1215
1257
|
} else {
|
|
1216
|
-
const
|
|
1217
|
-
blank.font =
|
|
1218
|
-
blank.glyph =
|
|
1258
|
+
const own = glyphIn(resolved2, 32, HIT);
|
|
1259
|
+
blank.font = own?.font ?? null;
|
|
1260
|
+
blank.glyph = own?.glyph ?? null;
|
|
1219
1261
|
blank.advance = advance;
|
|
1220
1262
|
blank.tracking = tracking;
|
|
1221
1263
|
blank.kerningBefore = kerningBefore;
|
|
1222
1264
|
prev = blank;
|
|
1223
|
-
|
|
1265
|
+
entries2[n++] = prev;
|
|
1224
1266
|
}
|
|
1225
1267
|
} else if (slot !== void 0) {
|
|
1226
|
-
|
|
1268
|
+
blank.tracking = tracking;
|
|
1269
|
+
entries2[n++] = shape(blank, slot);
|
|
1227
1270
|
prev = void 0;
|
|
1228
1271
|
} else {
|
|
1229
|
-
const hit = resolveGlyph(resolved2, run.fontFamily, run.fontWeight, run.fontStyle,
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1272
|
+
const hit = resolveGlyph(resolved2, run.fontFamily, run.fontWeight, run.fontStyle, cp2, true, HIT);
|
|
1273
|
+
if (hit) {
|
|
1274
|
+
blank.kerningBefore = kerningBefore;
|
|
1275
|
+
blank.tracking = tracking;
|
|
1276
|
+
ink(blank, hit);
|
|
1277
|
+
}
|
|
1278
|
+
entries2[n++] = blank;
|
|
1279
|
+
if (!mark) prev = blank;
|
|
1233
1280
|
}
|
|
1234
1281
|
}
|
|
1235
1282
|
}
|
|
1236
|
-
|
|
1237
|
-
return
|
|
1283
|
+
entries2.length = n;
|
|
1284
|
+
return entries2;
|
|
1238
1285
|
}
|
|
1239
|
-
function isNonspacingMark(
|
|
1240
|
-
return
|
|
1286
|
+
function isNonspacingMark(cp2) {
|
|
1287
|
+
return cp2 >= 768 && NONSPACING_MARK.test(String.fromCodePoint(cp2));
|
|
1241
1288
|
}
|
|
1242
1289
|
var CLUSTER_ENDS = [];
|
|
1243
1290
|
var HIT = { resolved: null, metrics: null, advance: 0, font: null, glyph: null };
|
|
1244
1291
|
var POOL_MAX = 4096;
|
|
1245
|
-
function blankEntry(pool, i, run,
|
|
1292
|
+
function blankEntry(pool, i, run, r, cp2, fontSize, srcIndex, srcEnd, clusterEnd, resolved2, metrics) {
|
|
1293
|
+
const lineSize = Math.max(r.fontSize, r.strutSize ?? 0);
|
|
1294
|
+
const baselineShift = r.baselineShift ?? 0;
|
|
1295
|
+
const rotate = r.rotate ?? 0;
|
|
1246
1296
|
const e = pool?.[i];
|
|
1247
1297
|
if (!e) {
|
|
1248
1298
|
const made = {
|
|
1249
1299
|
run,
|
|
1250
|
-
cp,
|
|
1300
|
+
cp: cp2,
|
|
1251
1301
|
fontSize,
|
|
1252
1302
|
lineSize,
|
|
1253
1303
|
baselineShift,
|
|
@@ -1270,7 +1320,7 @@ function blankEntry(pool, i, run, cp, fontSize, lineSize, baselineShift, rotate,
|
|
|
1270
1320
|
return made;
|
|
1271
1321
|
}
|
|
1272
1322
|
e.run = run;
|
|
1273
|
-
e.cp =
|
|
1323
|
+
e.cp = cp2;
|
|
1274
1324
|
e.fontSize = fontSize;
|
|
1275
1325
|
e.lineSize = lineSize;
|
|
1276
1326
|
e.baselineShift = baselineShift;
|
|
@@ -1290,26 +1340,22 @@ function blankEntry(pool, i, run, cp, fontSize, lineSize, baselineShift, rotate,
|
|
|
1290
1340
|
e.drawsInk = false;
|
|
1291
1341
|
return e;
|
|
1292
1342
|
}
|
|
1293
|
-
function ink(e, hit
|
|
1343
|
+
function ink(e, hit) {
|
|
1294
1344
|
e.resolved = hit.resolved;
|
|
1295
1345
|
e.metrics = hit.metrics;
|
|
1296
1346
|
e.font = hit.font;
|
|
1297
1347
|
e.glyph = hit.glyph;
|
|
1298
1348
|
e.advance = hit.advance * (e.fontSize / hit.metrics.size);
|
|
1299
|
-
e.tracking = tracking;
|
|
1300
|
-
e.kerningBefore = kerning;
|
|
1301
1349
|
e.drawsInk = true;
|
|
1302
|
-
return e;
|
|
1303
1350
|
}
|
|
1304
|
-
function shape(e, slot
|
|
1351
|
+
function shape(e, slot) {
|
|
1305
1352
|
e.shaped = slot.cluster;
|
|
1306
1353
|
e.advance = slot.advance * e.fontSize;
|
|
1307
|
-
e.tracking = tracking;
|
|
1308
1354
|
e.drawsInk = slot.cluster.d !== null;
|
|
1309
1355
|
return e;
|
|
1310
1356
|
}
|
|
1311
|
-
function mirrorEntries(
|
|
1312
|
-
return
|
|
1357
|
+
function mirrorEntries(entries2, levels, mirror, runs) {
|
|
1358
|
+
return entries2.map((entry, pos) => {
|
|
1313
1359
|
const odd = levels[pos] % 2 === 1;
|
|
1314
1360
|
if (entry.shaped !== null && entry.shaped.rtl !== odd) {
|
|
1315
1361
|
const flipped = mirror(entry.cp);
|
|
@@ -1317,39 +1363,57 @@ function mirrorEntries(entries, levels, mirror, runs) {
|
|
|
1317
1363
|
}
|
|
1318
1364
|
if (!odd) return entry;
|
|
1319
1365
|
if (entry.shaped !== null) return entry;
|
|
1320
|
-
const
|
|
1321
|
-
if (
|
|
1322
|
-
if (entry.font === null) return { ...entry, cp };
|
|
1366
|
+
const cp2 = mirror(entry.cp);
|
|
1367
|
+
if (cp2 === null || cp2 === entry.cp) return entry;
|
|
1368
|
+
if (entry.font === null) return { ...entry, cp: cp2 };
|
|
1323
1369
|
const run = runs[entry.run];
|
|
1324
|
-
const hit = resolveGlyph(entry.resolved, run.fontFamily, run.fontWeight, run.fontStyle,
|
|
1370
|
+
const hit = resolveGlyph(entry.resolved, run.fontFamily, run.fontWeight, run.fontStyle, cp2, false);
|
|
1325
1371
|
if (!hit) return entry;
|
|
1326
|
-
return { ...entry, cp, resolved: hit.resolved, metrics: hit.metrics, font: hit.font, glyph: hit.glyph };
|
|
1372
|
+
return { ...entry, cp: cp2, resolved: hit.resolved, metrics: hit.metrics, font: hit.font, glyph: hit.glyph };
|
|
1327
1373
|
});
|
|
1328
1374
|
}
|
|
1329
1375
|
|
|
1330
1376
|
// src/layout/lineBreak/wrapLines.ts
|
|
1331
|
-
var hangs = (
|
|
1377
|
+
var hangs = (cp2) => cp2 === 32 || cp2 === 9;
|
|
1332
1378
|
function wrapLines(cps, maxWidth, widthOf) {
|
|
1333
1379
|
const lines = [];
|
|
1334
|
-
wrapSpans(cps, maxWidth, widthOf, (
|
|
1335
|
-
lines.push({ start, end, wrapped });
|
|
1380
|
+
wrapSpans(cps, { maxWidth }, widthOf, (start2, end, wrapped) => {
|
|
1381
|
+
lines.push({ start: start2, end, wrapped });
|
|
1336
1382
|
});
|
|
1337
1383
|
return lines;
|
|
1338
1384
|
}
|
|
1339
|
-
|
|
1385
|
+
var breakScratch = new Uint8Array(64);
|
|
1386
|
+
var breakScratchTaken = false;
|
|
1387
|
+
var BREAK_SCRATCH_MAX = 1 << 16;
|
|
1388
|
+
function wrapSpans(cps, box, widthOf, emit) {
|
|
1340
1389
|
const n = cps.length;
|
|
1341
|
-
|
|
1342
|
-
|
|
1390
|
+
if (!Number.isFinite(box.maxWidth)) {
|
|
1391
|
+
wrapAt(cps, box, widthOf, emit, null);
|
|
1392
|
+
} else if (breakScratchTaken || n >= BREAK_SCRATCH_MAX) {
|
|
1393
|
+
wrapAt(cps, box, widthOf, emit, lineBreakOpportunities(cps));
|
|
1394
|
+
} else {
|
|
1395
|
+
if (breakScratch.length < n + 1) breakScratch = new Uint8Array(Math.max(n + 1, breakScratch.length * 2));
|
|
1396
|
+
breakScratchTaken = true;
|
|
1397
|
+
try {
|
|
1398
|
+
wrapAt(cps, box, widthOf, emit, lineBreakOpportunitiesInto(cps, breakScratch));
|
|
1399
|
+
} finally {
|
|
1400
|
+
breakScratchTaken = false;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function wrapAt(cps, box, widthOf, emit, breaks) {
|
|
1405
|
+
const n = cps.length;
|
|
1406
|
+
let start2 = 0;
|
|
1343
1407
|
let i = 0;
|
|
1344
1408
|
while (i < n) {
|
|
1345
|
-
const
|
|
1346
|
-
if (isHardLineBreak(
|
|
1347
|
-
emit(
|
|
1348
|
-
i +=
|
|
1349
|
-
|
|
1409
|
+
const cp2 = cps[i];
|
|
1410
|
+
if (isHardLineBreak(cp2)) {
|
|
1411
|
+
emit(start2, i, false);
|
|
1412
|
+
i += cp2 === 13 && cps[i + 1] === 10 ? 2 : 1;
|
|
1413
|
+
start2 = i;
|
|
1350
1414
|
continue;
|
|
1351
1415
|
}
|
|
1352
|
-
if (hangs(
|
|
1416
|
+
if (hangs(cp2)) {
|
|
1353
1417
|
i++;
|
|
1354
1418
|
continue;
|
|
1355
1419
|
}
|
|
@@ -1359,13 +1423,13 @@ function wrapSpans(cps, maxWidth, widthOf, emit) {
|
|
|
1359
1423
|
if (!hangs(cps[j])) ink2 = j + 1;
|
|
1360
1424
|
j++;
|
|
1361
1425
|
}
|
|
1362
|
-
if (breaks && i >
|
|
1363
|
-
emit(
|
|
1364
|
-
|
|
1426
|
+
if (breaks && i > start2 && widthOf(start2, ink2) > box.maxWidth) {
|
|
1427
|
+
emit(start2, i, true);
|
|
1428
|
+
start2 = i;
|
|
1365
1429
|
}
|
|
1366
1430
|
i = j;
|
|
1367
1431
|
}
|
|
1368
|
-
if (
|
|
1432
|
+
if (start2 < n) emit(start2, n, false);
|
|
1369
1433
|
}
|
|
1370
1434
|
|
|
1371
1435
|
// src/layout/layoutLines.ts
|
|
@@ -1383,21 +1447,21 @@ var broken = [];
|
|
|
1383
1447
|
var brokenCount = 0;
|
|
1384
1448
|
var linePool = [];
|
|
1385
1449
|
var LINE_POOL_MAX = 64;
|
|
1386
|
-
function flatWidth(
|
|
1387
|
-
return cur[
|
|
1450
|
+
function flatWidth(start2, end) {
|
|
1451
|
+
return cur[start2].advance + cur[start2].tracking + sum[end] - sum[start2 + 1];
|
|
1388
1452
|
}
|
|
1389
1453
|
var stopOf = (k) => cur[k].tab;
|
|
1390
|
-
function tabbedWidth(
|
|
1391
|
-
return widthWithTabs(
|
|
1454
|
+
function tabbedWidth(start2, end) {
|
|
1455
|
+
return widthWithTabs(start2, end, tabs, stopOf, flatWidth);
|
|
1392
1456
|
}
|
|
1393
|
-
function pushSpan(
|
|
1457
|
+
function pushSpan(start2, end, wrapped) {
|
|
1394
1458
|
const i = brokenCount++;
|
|
1395
1459
|
let line = linePool[i];
|
|
1396
1460
|
if (line === void 0) {
|
|
1397
1461
|
line = { start: 0, entries: [], width: 0.5, height: 0.5, ascent: 0.5, wrapped: false, srcEnd: 0, end: 0 };
|
|
1398
1462
|
if (i < LINE_POOL_MAX) linePool[i] = line;
|
|
1399
1463
|
}
|
|
1400
|
-
line.start =
|
|
1464
|
+
line.start = start2;
|
|
1401
1465
|
line.end = end;
|
|
1402
1466
|
line.wrapped = wrapped;
|
|
1403
1467
|
line.width = 0;
|
|
@@ -1406,34 +1470,35 @@ function pushSpan(start, end, wrapped) {
|
|
|
1406
1470
|
line.srcEnd = 0;
|
|
1407
1471
|
broken[i] = line;
|
|
1408
1472
|
}
|
|
1409
|
-
function breakLines(
|
|
1410
|
-
|
|
1473
|
+
function breakLines(entries2, cps, opts) {
|
|
1474
|
+
const { lineHeight } = opts;
|
|
1475
|
+
if (sum.length < entries2.length + 1) sum = doubles(entries2.length + 1);
|
|
1411
1476
|
sum[0] = 0;
|
|
1412
1477
|
let tabCount = 0;
|
|
1413
1478
|
brokenCount = 0;
|
|
1414
|
-
for (let k = 0; k <
|
|
1415
|
-
const e =
|
|
1479
|
+
for (let k = 0; k < entries2.length; k++) {
|
|
1480
|
+
const e = entries2[k];
|
|
1416
1481
|
sum[k + 1] = sum[k] + e.kerningBefore + e.advance + e.tracking;
|
|
1417
1482
|
if (e.tab) tabs[tabCount++] = k;
|
|
1418
1483
|
}
|
|
1419
1484
|
tabs.length = tabCount;
|
|
1420
|
-
cur =
|
|
1421
|
-
wrapSpans(cps,
|
|
1485
|
+
cur = entries2;
|
|
1486
|
+
wrapSpans(cps, opts, tabCount === 0 ? flatWidth : tabbedWidth, pushSpan);
|
|
1422
1487
|
cur = NONE;
|
|
1423
1488
|
broken.length = brokenCount;
|
|
1424
1489
|
for (let i = 0; i < broken.length; i++) {
|
|
1425
1490
|
const line = broken[i];
|
|
1426
1491
|
if (line.start === line.end) {
|
|
1427
|
-
const brk =
|
|
1492
|
+
const brk = entries2[line.end];
|
|
1428
1493
|
line.height = brk.lineSize * lineHeight;
|
|
1429
1494
|
line.ascent = aboveBaseline(brk, lineHeight);
|
|
1430
1495
|
line.srcEnd = brk.srcIndex;
|
|
1431
|
-
line.entries
|
|
1496
|
+
truncate(line.entries, 0);
|
|
1432
1497
|
continue;
|
|
1433
1498
|
}
|
|
1434
1499
|
const out = line.entries;
|
|
1435
1500
|
for (let k = line.start; k < line.end; k++) {
|
|
1436
|
-
const e =
|
|
1501
|
+
const e = entries2[k];
|
|
1437
1502
|
if (k === line.start) e.kerningBefore = 0;
|
|
1438
1503
|
if (e.tab) e.advance = tabAdvance(line.width, e.tab.stop, e.tab.min);
|
|
1439
1504
|
out[k - line.start] = e;
|
|
@@ -1442,25 +1507,25 @@ function breakLines(entries, cps, maxWidth, lineHeight) {
|
|
|
1442
1507
|
line.ascent = Math.max(line.ascent, aboveBaseline(e, lineHeight));
|
|
1443
1508
|
}
|
|
1444
1509
|
out.length = line.end - line.start;
|
|
1445
|
-
line.srcEnd =
|
|
1510
|
+
line.srcEnd = entries2[line.end - 1].srcEnd;
|
|
1446
1511
|
}
|
|
1447
1512
|
return broken;
|
|
1448
1513
|
}
|
|
1449
|
-
function hungWidth(
|
|
1514
|
+
function hungWidth(entries2) {
|
|
1450
1515
|
let hung = 0;
|
|
1451
|
-
for (let k =
|
|
1452
|
-
const e =
|
|
1516
|
+
for (let k = entries2.length - 1; k >= 0 && hangs(entries2[k].cp); k--) {
|
|
1517
|
+
const e = entries2[k];
|
|
1453
1518
|
hung += e.kerningBefore + e.advance + e.tracking;
|
|
1454
1519
|
}
|
|
1455
1520
|
return hung;
|
|
1456
1521
|
}
|
|
1457
|
-
function wordGaps(
|
|
1522
|
+
function wordGaps(entries2) {
|
|
1458
1523
|
const gaps = /* @__PURE__ */ new Set();
|
|
1459
1524
|
let first = 0;
|
|
1460
|
-
while (first <
|
|
1461
|
-
let last2 =
|
|
1462
|
-
while (last2 > first &&
|
|
1463
|
-
for (let k = first + 1; k < last2; k++) if (
|
|
1525
|
+
while (first < entries2.length && entries2[first].cp === 32) first++;
|
|
1526
|
+
let last2 = entries2.length - 1;
|
|
1527
|
+
while (last2 > first && entries2[last2].cp === 32) last2--;
|
|
1528
|
+
for (let k = first + 1; k < last2; k++) if (entries2[k].cp === 32) gaps.add(k);
|
|
1464
1529
|
return gaps;
|
|
1465
1530
|
}
|
|
1466
1531
|
function alignOffset(align, alignWidth, inkWidth) {
|
|
@@ -1471,16 +1536,17 @@ function alignOffset(align, alignWidth, inkWidth) {
|
|
|
1471
1536
|
}
|
|
1472
1537
|
var NO_GAPS = /* @__PURE__ */ new Set();
|
|
1473
1538
|
var placed = { box: null, inkWidth: 0.5 };
|
|
1474
|
-
function placeLine(line, y, order, align,
|
|
1475
|
-
const {
|
|
1476
|
-
const
|
|
1539
|
+
function placeLine(line, y, order, align, opts, cols, start2, at) {
|
|
1540
|
+
const { alignWidth, justify } = opts;
|
|
1541
|
+
const { entries: entries2 } = line;
|
|
1542
|
+
const hung = hungWidth(entries2);
|
|
1477
1543
|
const inkWidth = line.width - hung;
|
|
1478
1544
|
const slack = alignWidth - inkWidth;
|
|
1479
|
-
const gaps = justify && line.wrapped && Number.isFinite(alignWidth) && slack > 0 ? wordGaps(
|
|
1545
|
+
const gaps = justify && line.wrapped && Number.isFinite(alignWidth) && slack > 0 ? wordGaps(entries2) : NO_GAPS;
|
|
1480
1546
|
const gapExtra = gaps.size > 0 ? slack / gaps.size : 0;
|
|
1481
1547
|
const spread = gapExtra * gaps.size;
|
|
1482
1548
|
const inkLeft = spread > 0 ? 0 : alignOffset(align, alignWidth, inkWidth);
|
|
1483
|
-
const hangsLeft = hung > 0 && order.levels[
|
|
1549
|
+
const hangsLeft = hung > 0 && order.levels[entries2.length - 1] % 2 === 1;
|
|
1484
1550
|
const left = hangsLeft ? inkLeft - hung : inkLeft;
|
|
1485
1551
|
const lineBaselineY = y + line.ascent;
|
|
1486
1552
|
let penX = left;
|
|
@@ -1490,21 +1556,21 @@ function placeLine(line, y, order, align, alignWidth, justify, cols, start, at)
|
|
|
1490
1556
|
const { visual } = order;
|
|
1491
1557
|
for (let v = 0; v < visual.length; v++) {
|
|
1492
1558
|
const pos = visual[v];
|
|
1493
|
-
const e =
|
|
1494
|
-
const kern = prevPos < 0 ? 0 : pos === prevPos + 1 ? e.kerningBefore : prevPos === pos + 1 ?
|
|
1495
|
-
if (kern !== 0) cols.widen(
|
|
1559
|
+
const e = entries2[pos];
|
|
1560
|
+
const kern = prevPos < 0 ? 0 : pos === prevPos + 1 ? e.kerningBefore : prevPos === pos + 1 ? entries2[prevPos].kerningBefore : 0;
|
|
1561
|
+
if (kern !== 0) cols.widen(start2 + (wide >= 0 ? wide : prevPos), kern);
|
|
1496
1562
|
penX += kern;
|
|
1497
1563
|
prevPos = pos;
|
|
1498
1564
|
const step = e.advance + e.tracking + (gaps.has(pos) ? gapExtra : 0);
|
|
1499
1565
|
if (step !== 0) wide = pos;
|
|
1500
|
-
cols.set(
|
|
1501
|
-
cols.setVisual(
|
|
1566
|
+
cols.set(start2 + pos, e, order.levels[pos], penX, step, lineBaselineY - e.baselineShift);
|
|
1567
|
+
cols.setVisual(start2, slot++, pos);
|
|
1502
1568
|
penX += step;
|
|
1503
1569
|
}
|
|
1504
1570
|
const x1 = left + line.width + spread;
|
|
1505
1571
|
const y1 = y + line.height;
|
|
1506
1572
|
const prior = cols.boxes[at];
|
|
1507
|
-
placed.box = prior !== void 0 ? prior.refill(left, y, x1, y1, lineBaselineY, line.srcEnd, spread > 0,
|
|
1573
|
+
placed.box = prior !== void 0 ? prior.refill(left, y, x1, y1, lineBaselineY, line.srcEnd, spread > 0, start2, entries2.length) : cols.boxes[at] = new LineBox(left, y, x1, y1, lineBaselineY, line.srcEnd, spread > 0, cols, start2, entries2.length);
|
|
1508
1574
|
placed.inkWidth = inkWidth + spread;
|
|
1509
1575
|
return placed;
|
|
1510
1576
|
}
|
|
@@ -1522,7 +1588,7 @@ function resolveLayoutOpts(opts, out = {
|
|
|
1522
1588
|
tabSize: 0
|
|
1523
1589
|
}) {
|
|
1524
1590
|
out.maxWidth = opts.maxWidth;
|
|
1525
|
-
out
|
|
1591
|
+
storeAlignWidth(out, opts);
|
|
1526
1592
|
out.lineHeight = opts.lineHeight;
|
|
1527
1593
|
out.align = opts.align;
|
|
1528
1594
|
out.justify = opts.justify === true || opts.align === "justify";
|
|
@@ -1532,6 +1598,10 @@ function resolveLayoutOpts(opts, out = {
|
|
|
1532
1598
|
out.tabSize = opts.tabSize ?? DEFAULT_TAB_SIZE;
|
|
1533
1599
|
return out;
|
|
1534
1600
|
}
|
|
1601
|
+
function storeAlignWidth(out, opts) {
|
|
1602
|
+
if (opts.alignWidth === void 0) out.alignWidth = opts.maxWidth;
|
|
1603
|
+
else out.alignWidth = opts.alignWidth;
|
|
1604
|
+
}
|
|
1535
1605
|
function layoutBidi(opts) {
|
|
1536
1606
|
return opts.bidi ?? registeredBidi();
|
|
1537
1607
|
}
|
|
@@ -1544,6 +1614,11 @@ var ENTRY_POOL = [];
|
|
|
1544
1614
|
var ENTRIES = [];
|
|
1545
1615
|
var CPS = [];
|
|
1546
1616
|
var OPTS = resolveLayoutOpts({ maxWidth: 0, lineHeight: 0, align: "left" });
|
|
1617
|
+
var LINE_OPTS = { maxWidth: 0.5, alignWidth: 0.5, lineHeight: 0.5, justify: false };
|
|
1618
|
+
var hardBreakAt = (i) => isHardLineBreak(CPS[i]);
|
|
1619
|
+
function mirrorLine(bidi, entries2, levels, runs) {
|
|
1620
|
+
return mirrorEntries(entries2, levels, (cp2) => bidi.mirror(cp2), runs);
|
|
1621
|
+
}
|
|
1547
1622
|
function layoutRuns(runs, opts) {
|
|
1548
1623
|
const {
|
|
1549
1624
|
maxWidth,
|
|
@@ -1556,42 +1631,49 @@ function layoutRuns(runs, opts) {
|
|
|
1556
1631
|
direction,
|
|
1557
1632
|
tabSize
|
|
1558
1633
|
} = resolveLayoutOpts(opts, OPTS);
|
|
1559
|
-
const
|
|
1634
|
+
const entries2 = measureRuns(runs, tabSize, ENTRY_POOL, ENTRIES, shaper);
|
|
1560
1635
|
const cps = CPS;
|
|
1561
|
-
cps.length =
|
|
1562
|
-
for (let k = 0; k <
|
|
1563
|
-
const paragraphs = bidi ? analyzeParagraphs(bidi, cps,
|
|
1636
|
+
cps.length = entries2.length;
|
|
1637
|
+
for (let k = 0; k < entries2.length; k++) cps[k] = entries2[k].cp;
|
|
1638
|
+
const paragraphs = bidi ? analyzeParagraphs(bidi, cps, hardBreakAt, direction) : null;
|
|
1564
1639
|
if (!bidi) warnRtlWithoutEngine(cps);
|
|
1565
|
-
const
|
|
1640
|
+
const lineOpts = LINE_OPTS;
|
|
1641
|
+
lineOpts.maxWidth = maxWidth;
|
|
1642
|
+
lineOpts.alignWidth = alignWidth;
|
|
1643
|
+
lineOpts.lineHeight = lineHeight;
|
|
1644
|
+
lineOpts.justify = justify;
|
|
1645
|
+
const broken2 = breakLines(entries2, cps, lineOpts);
|
|
1566
1646
|
let size = 0;
|
|
1567
1647
|
for (let i = 0; i < broken2.length; i++) size += broken2[i].entries.length;
|
|
1568
1648
|
const cols = broken2.length > 0 ? LayoutColumns.take(size) : null;
|
|
1569
1649
|
const lines = cols !== null ? cols.boxes : [];
|
|
1570
1650
|
let y = 0;
|
|
1571
1651
|
let width = 0;
|
|
1572
|
-
let
|
|
1652
|
+
let start2 = 0;
|
|
1573
1653
|
for (let i = 0; i < broken2.length; i++) {
|
|
1574
1654
|
const line = broken2[i];
|
|
1575
1655
|
const order = orderLine(paragraphs, line.start, line.entries.length);
|
|
1576
|
-
if (bidi) line.entries =
|
|
1656
|
+
if (bidi) line.entries = mirrorLine(bidi, line.entries, order.levels, runs);
|
|
1577
1657
|
const reads = direction !== "auto" ? direction : directionOfLevel(line.entries.length > 0 ? paragraphs?.baseLevel(line.start) ?? 0 : 0);
|
|
1578
1658
|
const placed2 = placeLine(
|
|
1579
1659
|
line,
|
|
1580
1660
|
y,
|
|
1581
1661
|
order,
|
|
1582
1662
|
resolveAlign(align, reads),
|
|
1583
|
-
|
|
1584
|
-
justify,
|
|
1663
|
+
lineOpts,
|
|
1585
1664
|
cols,
|
|
1586
|
-
|
|
1665
|
+
start2,
|
|
1587
1666
|
i
|
|
1588
1667
|
);
|
|
1589
|
-
|
|
1668
|
+
start2 += line.entries.length;
|
|
1590
1669
|
width = Math.max(width, placed2.inkWidth);
|
|
1591
1670
|
y += line.height;
|
|
1592
1671
|
}
|
|
1593
1672
|
lines.length = broken2.length;
|
|
1594
|
-
return { lines, bounds: { width, height: y } };
|
|
1673
|
+
if (cols === null) return { lines, bounds: { width, height: y } };
|
|
1674
|
+
cols.bounds.width = width;
|
|
1675
|
+
cols.bounds.height = y;
|
|
1676
|
+
return cols.laid ??= { lines, bounds: cols.bounds };
|
|
1595
1677
|
}
|
|
1596
1678
|
|
|
1597
1679
|
// src/layout/glyphQuads.ts
|
|
@@ -1767,7 +1849,7 @@ var SPARE_GROUPS_MAX = 1024;
|
|
|
1767
1849
|
function giveGroup(group) {
|
|
1768
1850
|
if (spareGroups.length >= SPARE_GROUPS_MAX || group.stroke !== void 0 || group.colorGlyphs !== void 0 || quadsViewed.has(group)) return;
|
|
1769
1851
|
group.quadData = NO_QUADS;
|
|
1770
|
-
group.glyphs
|
|
1852
|
+
truncate(group.glyphs, 0);
|
|
1771
1853
|
spareGroups.push(group);
|
|
1772
1854
|
}
|
|
1773
1855
|
var slots = [];
|
|
@@ -1789,7 +1871,7 @@ function takeGroups(out) {
|
|
|
1789
1871
|
out.push(slots[i].group);
|
|
1790
1872
|
slots[i].group = null;
|
|
1791
1873
|
}
|
|
1792
|
-
slots
|
|
1874
|
+
truncate(slots, 0);
|
|
1793
1875
|
last.group = null;
|
|
1794
1876
|
}
|
|
1795
1877
|
|
|
@@ -1816,10 +1898,13 @@ function faceOutlineD(g) {
|
|
|
1816
1898
|
return glyphOutline(family, weight, style, g.cp);
|
|
1817
1899
|
}
|
|
1818
1900
|
function runFaces(runs) {
|
|
1819
|
-
const faces = runs.map((r) => faceMetricsOf(
|
|
1901
|
+
const faces = runs.map((r) => faceMetricsOf(cachedFontVariant(r.fontFamily, r.fontWeight, r.fontStyle)));
|
|
1820
1902
|
return (run) => faces[run];
|
|
1821
1903
|
}
|
|
1822
1904
|
var isDecorated = (r) => r.underline || r.strikethrough || r.overline;
|
|
1905
|
+
function rulePaintOf(runs) {
|
|
1906
|
+
return (run) => fillHasInk(runs[run].fill) ? paintKey(runs[run].fill.paint) : null;
|
|
1907
|
+
}
|
|
1823
1908
|
var cursor = blankGlyph();
|
|
1824
1909
|
var scratch = [];
|
|
1825
1910
|
var SCRATCH_MAX2 = 1 << 14;
|
|
@@ -1828,10 +1913,10 @@ function paintRuns(laid, runs, opts = {}) {
|
|
|
1828
1913
|
}
|
|
1829
1914
|
function paintRunsInto(laid, runs, opts, out) {
|
|
1830
1915
|
const { groups, decorations } = out;
|
|
1831
|
-
groups
|
|
1832
|
-
decorations
|
|
1916
|
+
truncate(groups, 0);
|
|
1917
|
+
truncate(decorations, 0);
|
|
1833
1918
|
const faceOf = runs.some(isDecorated) ? runFaces(runs) : null;
|
|
1834
|
-
const rulePaint = faceOf && (
|
|
1919
|
+
const rulePaint = faceOf && rulePaintOf(runs);
|
|
1835
1920
|
let glyphCount = 0;
|
|
1836
1921
|
const { lines } = laid;
|
|
1837
1922
|
for (let i = 0; i < lines.length; i++) glyphCount += LineBox.count(lines[i]);
|
|
@@ -1843,15 +1928,15 @@ function paintRunsInto(laid, runs, opts, out) {
|
|
|
1843
1928
|
for (let li = 0; li < lines.length; li++) {
|
|
1844
1929
|
const line = lines[li];
|
|
1845
1930
|
const cols = LineBox.columns(line);
|
|
1846
|
-
const
|
|
1931
|
+
const start2 = cols !== null ? LineBox.start(line) : 0;
|
|
1847
1932
|
const count = LineBox.count(line);
|
|
1848
1933
|
const rules = faceOf && lineDecorations(runs, faceOf, rulePaint);
|
|
1849
1934
|
for (let slot = 0; slot < count; slot++) {
|
|
1850
|
-
const pos = cols !== null ? cols.visual(
|
|
1851
|
-
const g = cols !== null ? cols.glyph(
|
|
1935
|
+
const pos = cols !== null ? cols.visual(start2, slot) : -1;
|
|
1936
|
+
const g = cols !== null ? cols.glyph(start2, pos, cursor) : line.glyphs[slot];
|
|
1852
1937
|
rules?.add(g);
|
|
1853
1938
|
const run = runs[g.run];
|
|
1854
|
-
const inks = cols !== null ? cols.drawsInk(
|
|
1939
|
+
const inks = cols !== null ? cols.drawsInk(start2, pos) : line.cells[g.cell].drawsInk;
|
|
1855
1940
|
const outline = inks ? glyphOutlineD(g, run, opts.outlineMinSize) : null;
|
|
1856
1941
|
if (!fillHasInk(run.fill) && !(outline !== null && strokeHasInk(run.stroke))) continue;
|
|
1857
1942
|
if (outline !== null) {
|
|
@@ -1892,9 +1977,56 @@ function paintRunsInto(laid, runs, opts, out) {
|
|
|
1892
1977
|
takeGroups(groups);
|
|
1893
1978
|
return out;
|
|
1894
1979
|
}
|
|
1980
|
+
|
|
1981
|
+
// src/layout/runsEntries.ts
|
|
1982
|
+
var entries = /* @__PURE__ */ new WeakMap();
|
|
1983
|
+
var spare2 = [];
|
|
1984
|
+
var SPARE_MAX2 = 1024;
|
|
1985
|
+
function entryOf(runs) {
|
|
1986
|
+
return entries.get(runs);
|
|
1987
|
+
}
|
|
1988
|
+
function entryFor(runs) {
|
|
1989
|
+
let e = entries.get(runs);
|
|
1990
|
+
if (e === void 0) {
|
|
1991
|
+
e = spare2.pop() ?? {
|
|
1992
|
+
generation: -1,
|
|
1993
|
+
variants: [],
|
|
1994
|
+
painting: null,
|
|
1995
|
+
paintedOn: null,
|
|
1996
|
+
paintedStamp: 0,
|
|
1997
|
+
paintMin: void 0,
|
|
1998
|
+
listed: null
|
|
1999
|
+
};
|
|
2000
|
+
entries.set(runs, e);
|
|
2001
|
+
}
|
|
2002
|
+
return e;
|
|
2003
|
+
}
|
|
2004
|
+
function dropEntry(runs) {
|
|
2005
|
+
const e = entries.get(runs);
|
|
2006
|
+
if (e !== void 0) entries.delete(runs);
|
|
2007
|
+
return e;
|
|
2008
|
+
}
|
|
2009
|
+
function emptyEntry(e) {
|
|
2010
|
+
e.generation = -1;
|
|
2011
|
+
e.painting = null;
|
|
2012
|
+
e.paintedOn = null;
|
|
2013
|
+
e.paintMin = void 0;
|
|
2014
|
+
e.listed = null;
|
|
2015
|
+
}
|
|
2016
|
+
function giveEntry(e) {
|
|
2017
|
+
emptyEntry(e);
|
|
2018
|
+
if (spare2.length < SPARE_MAX2) spare2.push(e);
|
|
2019
|
+
}
|
|
2020
|
+
function _resetRunsEntriesForTests() {
|
|
2021
|
+
entries = /* @__PURE__ */ new WeakMap();
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// src/layout/paintCache.ts
|
|
1895
2025
|
var PAINT_CACHE_VARIANT_LIMIT = 32;
|
|
1896
|
-
var own = /* @__PURE__ */ new WeakMap();
|
|
1897
2026
|
var shared2 = /* @__PURE__ */ new WeakMap();
|
|
2027
|
+
function stampOf(laid) {
|
|
2028
|
+
return laid.lines.length > 0 ? LineBox.columns(laid.lines[0])?.stamp ?? 0 : 0;
|
|
2029
|
+
}
|
|
1898
2030
|
function listOf(laid) {
|
|
1899
2031
|
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
1900
2032
|
if (cols !== null) return cols.paintings;
|
|
@@ -1902,10 +2034,10 @@ function listOf(laid) {
|
|
|
1902
2034
|
if (list === void 0) shared2.set(laid, list = []);
|
|
1903
2035
|
return list;
|
|
1904
2036
|
}
|
|
1905
|
-
var
|
|
1906
|
-
var
|
|
2037
|
+
var spare3 = [];
|
|
2038
|
+
var SPARE_MAX3 = 1024;
|
|
1907
2039
|
function painting(laid, runs, opts, generation, key, bucket) {
|
|
1908
|
-
const p =
|
|
2040
|
+
const p = spare3.pop();
|
|
1909
2041
|
if (p === void 0) {
|
|
1910
2042
|
return {
|
|
1911
2043
|
generation,
|
|
@@ -1953,13 +2085,15 @@ function keyOf(p) {
|
|
|
1953
2085
|
function cachedPaintRuns(laid, runs, opts = {}, use = "keep") {
|
|
1954
2086
|
const generation = glyphGeneration();
|
|
1955
2087
|
const min = opts.outlineMinSize;
|
|
1956
|
-
const mine =
|
|
1957
|
-
const
|
|
1958
|
-
|
|
2088
|
+
const mine = entryOf(runs);
|
|
2089
|
+
const stamp = stampOf(laid);
|
|
2090
|
+
const own = mine !== void 0 && mine.paintedOn === laid && mine.paintedStamp === stamp ? mine.painting : null;
|
|
2091
|
+
const mineHere = own !== null && own.generation === generation;
|
|
2092
|
+
if (mineHere && mine.paintMin === min) return handOut(own, use);
|
|
1959
2093
|
const bucket = outlineBucket(runs, min);
|
|
1960
|
-
if (mineHere &&
|
|
1961
|
-
mine.
|
|
1962
|
-
return handOut(
|
|
2094
|
+
if (mineHere && own.bucket === bucket) {
|
|
2095
|
+
mine.paintMin = min;
|
|
2096
|
+
return handOut(own, use);
|
|
1963
2097
|
}
|
|
1964
2098
|
const list = listOf(laid);
|
|
1965
2099
|
let p = null;
|
|
@@ -1978,34 +2112,21 @@ function cachedPaintRuns(laid, runs, opts = {}, use = "keep") {
|
|
|
1978
2112
|
}
|
|
1979
2113
|
if (list.length >= PAINT_CACHE_VARIANT_LIMIT) list.shift();
|
|
1980
2114
|
list.push(p);
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
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
|
-
}
|
|
2115
|
+
const e = mine ?? entryFor(runs);
|
|
2116
|
+
if (e.painting !== null && e.painting !== p) settlePainting(e.painting, runs);
|
|
2117
|
+
e.paintedOn = laid;
|
|
2118
|
+
e.paintedStamp = stamp;
|
|
2119
|
+
e.painting = p;
|
|
2120
|
+
e.paintMin = min;
|
|
1996
2121
|
return handOut(p, use);
|
|
1997
2122
|
}
|
|
2123
|
+
function settlePainting(p, runs) {
|
|
2124
|
+
if (p.runs === runs) keyOf(p);
|
|
2125
|
+
}
|
|
1998
2126
|
function handOut(p, use) {
|
|
1999
2127
|
if (use === "keep") p.pinned = true;
|
|
2000
2128
|
return p.painted;
|
|
2001
2129
|
}
|
|
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
2130
|
function recyclePaintings(laid) {
|
|
2010
2131
|
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
2011
2132
|
let list;
|
|
@@ -2026,17 +2147,16 @@ function recyclePaintings(laid) {
|
|
|
2026
2147
|
group.quadData = NO_QUADS;
|
|
2027
2148
|
giveGroup(group);
|
|
2028
2149
|
}
|
|
2029
|
-
groups
|
|
2030
|
-
p.painted.decorations
|
|
2150
|
+
truncate(groups, 0);
|
|
2151
|
+
truncate(p.painted.decorations, 0);
|
|
2031
2152
|
p.runs = null;
|
|
2032
2153
|
p.key = null;
|
|
2033
|
-
if (
|
|
2154
|
+
if (spare3.length < SPARE_MAX3) spare3.push(p);
|
|
2034
2155
|
}
|
|
2035
|
-
list
|
|
2156
|
+
truncate(list, 0);
|
|
2036
2157
|
}
|
|
2037
2158
|
var LAYOUT_CACHE_VARIANT_LIMIT = 8;
|
|
2038
2159
|
var LAYOUT_CACHE_STRUCTURAL_LIMIT = 64;
|
|
2039
|
-
var cache2 = /* @__PURE__ */ new WeakMap();
|
|
2040
2160
|
var structural = [];
|
|
2041
2161
|
var structuralGeneration = -1;
|
|
2042
2162
|
var clock = 0;
|
|
@@ -2058,9 +2178,8 @@ function release(laid) {
|
|
|
2058
2178
|
recyclePaintings(laid);
|
|
2059
2179
|
cols.recycle();
|
|
2060
2180
|
}
|
|
2061
|
-
var spareEntries = [];
|
|
2062
2181
|
var spareVariants = [];
|
|
2063
|
-
var
|
|
2182
|
+
var SPARE_MAX4 = 1024;
|
|
2064
2183
|
function disown(vs) {
|
|
2065
2184
|
for (let i = 0; i < vs.length; i++) {
|
|
2066
2185
|
const v = vs[i];
|
|
@@ -2070,14 +2189,14 @@ function disown(vs) {
|
|
|
2070
2189
|
release(v.laid);
|
|
2071
2190
|
}
|
|
2072
2191
|
v.laid = NO_LAYOUT;
|
|
2073
|
-
if (spareVariants.length <
|
|
2192
|
+
if (spareVariants.length < SPARE_MAX4) spareVariants.push(v);
|
|
2074
2193
|
}
|
|
2075
|
-
vs
|
|
2194
|
+
truncate(vs, 0);
|
|
2076
2195
|
}
|
|
2077
2196
|
var NO_LAYOUT = { lines: [], bounds: { width: 0, height: 0 } };
|
|
2078
2197
|
function fill(v, opts, bidi, laid) {
|
|
2079
2198
|
v.maxWidth = opts.maxWidth;
|
|
2080
|
-
v
|
|
2199
|
+
storeAlignWidth(v, opts);
|
|
2081
2200
|
v.lineHeight = opts.lineHeight;
|
|
2082
2201
|
v.align = opts.align;
|
|
2083
2202
|
v.justify = opts.justify === true || opts.align === "justify";
|
|
@@ -2089,11 +2208,11 @@ function fill(v, opts, bidi, laid) {
|
|
|
2089
2208
|
return v;
|
|
2090
2209
|
}
|
|
2091
2210
|
function variant(opts, bidi, laid) {
|
|
2092
|
-
const
|
|
2093
|
-
if (
|
|
2094
|
-
|
|
2211
|
+
const spare4 = spareVariants.pop();
|
|
2212
|
+
if (spare4 !== void 0) return fill(spare4, opts, bidi, laid);
|
|
2213
|
+
const v = {
|
|
2095
2214
|
maxWidth: opts.maxWidth,
|
|
2096
|
-
alignWidth: opts.
|
|
2215
|
+
alignWidth: opts.maxWidth,
|
|
2097
2216
|
lineHeight: opts.lineHeight,
|
|
2098
2217
|
align: opts.align,
|
|
2099
2218
|
justify: opts.justify === true || opts.align === "justify",
|
|
@@ -2103,6 +2222,8 @@ function variant(opts, bidi, laid) {
|
|
|
2103
2222
|
shaper: layoutShaper(opts),
|
|
2104
2223
|
laid
|
|
2105
2224
|
};
|
|
2225
|
+
storeAlignWidth(v, opts);
|
|
2226
|
+
return v;
|
|
2106
2227
|
}
|
|
2107
2228
|
function mix(h, n) {
|
|
2108
2229
|
return Math.imul(h ^ n, 16777619);
|
|
@@ -2131,7 +2252,7 @@ function runsHash(runs) {
|
|
|
2131
2252
|
h = mix(h, r.fontFeatures?.length ?? 0);
|
|
2132
2253
|
h = mixStr(h, r.lang ?? "");
|
|
2133
2254
|
}
|
|
2134
|
-
return h;
|
|
2255
|
+
return h & 1073741823;
|
|
2135
2256
|
}
|
|
2136
2257
|
function sameNums(a, b) {
|
|
2137
2258
|
if (a === b) return true;
|
|
@@ -2159,12 +2280,8 @@ function sameRuns(a, b) {
|
|
|
2159
2280
|
function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
2160
2281
|
const fonts = faceGeneration();
|
|
2161
2282
|
const bidi = layoutBidi(opts);
|
|
2162
|
-
|
|
2163
|
-
if (entry
|
|
2164
|
-
entry = spareEntries.pop() ?? { generation: fonts, variants: [] };
|
|
2165
|
-
entry.generation = fonts;
|
|
2166
|
-
cache2.set(runs, entry);
|
|
2167
|
-
} else if (entry.generation !== fonts) {
|
|
2283
|
+
const entry = entryFor(runs);
|
|
2284
|
+
if (entry.generation !== fonts) {
|
|
2168
2285
|
entry.generation = fonts;
|
|
2169
2286
|
disown(entry.variants);
|
|
2170
2287
|
} else {
|
|
@@ -2177,7 +2294,7 @@ function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
|
2177
2294
|
return handOut2(v.laid, use);
|
|
2178
2295
|
}
|
|
2179
2296
|
}
|
|
2180
|
-
const laid = structuralLayout(runs, opts, bidi, fonts);
|
|
2297
|
+
const laid = structuralLayout(runs, opts, bidi, fonts, entry);
|
|
2181
2298
|
const vs = entry.variants;
|
|
2182
2299
|
if (vs.length >= LAYOUT_CACHE_VARIANT_LIMIT) disown(vs);
|
|
2183
2300
|
vs.unshift(variant(opts, bidi, laid));
|
|
@@ -2186,16 +2303,17 @@ function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
|
2186
2303
|
return handOut2(laid, use);
|
|
2187
2304
|
}
|
|
2188
2305
|
function dropRuns(runs) {
|
|
2189
|
-
const entry =
|
|
2190
|
-
forgetPaintRuns(runs);
|
|
2306
|
+
const entry = dropEntry(runs);
|
|
2191
2307
|
if (entry === void 0) return;
|
|
2192
|
-
cache2.delete(runs);
|
|
2193
2308
|
disown(entry.variants);
|
|
2194
|
-
|
|
2309
|
+
giveEntry(entry);
|
|
2195
2310
|
}
|
|
2196
|
-
function structuralLayout(runs, opts, bidi, fonts) {
|
|
2311
|
+
function structuralLayout(runs, opts, bidi, fonts, entry) {
|
|
2197
2312
|
if (structuralGeneration !== fonts) {
|
|
2198
|
-
for (const s of structural)
|
|
2313
|
+
for (const s of structural) {
|
|
2314
|
+
unlist(s);
|
|
2315
|
+
s.runs = NO_RUNS;
|
|
2316
|
+
}
|
|
2199
2317
|
structural = [];
|
|
2200
2318
|
structuralGeneration = fonts;
|
|
2201
2319
|
}
|
|
@@ -2216,11 +2334,29 @@ function structuralLayout(runs, opts, bidi, fonts) {
|
|
|
2216
2334
|
filled.hash = hash;
|
|
2217
2335
|
filled.runs = runs;
|
|
2218
2336
|
filled.used = ++clock;
|
|
2337
|
+
entry.listed = filled;
|
|
2219
2338
|
const cols = columnsOf(laid);
|
|
2220
2339
|
if (cols !== null) cols.listed = true;
|
|
2221
2340
|
if (!full) structural.push(filled);
|
|
2222
2341
|
return laid;
|
|
2223
2342
|
}
|
|
2343
|
+
function clearRuns(runs) {
|
|
2344
|
+
const entry = entryOf(runs);
|
|
2345
|
+
if (entry === void 0) return;
|
|
2346
|
+
const s = entry.listed;
|
|
2347
|
+
if (s !== null && s.runs === runs) {
|
|
2348
|
+
unlist(s);
|
|
2349
|
+
s.laid = NO_LAYOUT;
|
|
2350
|
+
s.runs = NO_RUNS;
|
|
2351
|
+
s.hash = -1;
|
|
2352
|
+
s.used = 0;
|
|
2353
|
+
}
|
|
2354
|
+
const p = entry.painting;
|
|
2355
|
+
disown(entry.variants);
|
|
2356
|
+
if (p !== null) settlePainting(p, runs);
|
|
2357
|
+
emptyEntry(entry);
|
|
2358
|
+
}
|
|
2359
|
+
var NO_RUNS = [];
|
|
2224
2360
|
function structuralEntry(opts, bidi, laid) {
|
|
2225
2361
|
return fill({
|
|
2226
2362
|
maxWidth: 0,
|
|
@@ -2245,12 +2381,12 @@ function unlist(s) {
|
|
|
2245
2381
|
release(s.laid);
|
|
2246
2382
|
}
|
|
2247
2383
|
function _resetLayoutCacheForTests() {
|
|
2248
|
-
|
|
2384
|
+
_resetRunsEntriesForTests();
|
|
2249
2385
|
structural = [];
|
|
2250
2386
|
structuralGeneration = -1;
|
|
2251
2387
|
clock = 0;
|
|
2252
2388
|
}
|
|
2253
2389
|
|
|
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-
|
|
2256
|
-
//# sourceMappingURL=chunk-
|
|
2390
|
+
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, clearRuns, decorationMetrics, decorationRule, dropRuns, emboldenGlyph, emboldenGlyphD, faceOutlineD, fontString, graphemeCount, hangs, hasGlyphQuad, isHardLineBreak, layoutRuns, lineBreakOpportunities, lineDecorations, paintRuns, paragraphDirection, registerBidi, registerShaper, registeredBidi, resolveAlign, resolveTextStyle, resolveTextStyleInto, runFaces, shapesWithFeature, syntheticBoldOffset, tabAdvance, warnRtlWithoutEngine, widthWithTabs, wrapLines };
|
|
2391
|
+
//# sourceMappingURL=chunk-ZNSU5C43.js.map
|
|
2392
|
+
//# sourceMappingURL=chunk-ZNSU5C43.js.map
|