@weasel-js/text 1.14.0 → 1.14.2
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-5BJN6MC6.js} +487 -387
- package/dist/chunk-5BJN6MC6.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +15 -16
- package/dist/index.js.map +1 -1
- package/dist/{test-seams-DHGfE_6p.d.ts → test-seams-D6uEFbAw.d.ts} +7 -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
|
@@ -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
|
}
|
|
@@ -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;
|
|
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;
|
|
566
|
+
if (N === NU2) return NO_BREAK;
|
|
567
|
+
if (N === IS2 && b + 2 < units && cls[b + 2] === NU2) return NO_BREAK;
|
|
579
568
|
}
|
|
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,16 +644,16 @@ 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
652
|
function warnRtlWithoutEngine(codePoints) {
|
|
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
|
|
@@ -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,7 +1191,7 @@ 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;
|
|
@@ -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) {
|
|
1389
|
+
const n = cps.length;
|
|
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) {
|
|
1340
1405
|
const n = cps.length;
|
|
1341
|
-
|
|
1342
|
-
let start = 0;
|
|
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
|
}
|
|
@@ -1544,6 +1610,11 @@ var ENTRY_POOL = [];
|
|
|
1544
1610
|
var ENTRIES = [];
|
|
1545
1611
|
var CPS = [];
|
|
1546
1612
|
var OPTS = resolveLayoutOpts({ maxWidth: 0, lineHeight: 0, align: "left" });
|
|
1613
|
+
var LINE_OPTS = { maxWidth: 0.5, alignWidth: 0.5, lineHeight: 0.5, justify: false };
|
|
1614
|
+
var hardBreakAt = (i) => isHardLineBreak(CPS[i]);
|
|
1615
|
+
function mirrorLine(bidi, entries2, levels, runs) {
|
|
1616
|
+
return mirrorEntries(entries2, levels, (cp2) => bidi.mirror(cp2), runs);
|
|
1617
|
+
}
|
|
1547
1618
|
function layoutRuns(runs, opts) {
|
|
1548
1619
|
const {
|
|
1549
1620
|
maxWidth,
|
|
@@ -1556,42 +1627,49 @@ function layoutRuns(runs, opts) {
|
|
|
1556
1627
|
direction,
|
|
1557
1628
|
tabSize
|
|
1558
1629
|
} = resolveLayoutOpts(opts, OPTS);
|
|
1559
|
-
const
|
|
1630
|
+
const entries2 = measureRuns(runs, tabSize, ENTRY_POOL, ENTRIES, shaper);
|
|
1560
1631
|
const cps = CPS;
|
|
1561
|
-
cps.length =
|
|
1562
|
-
for (let k = 0; k <
|
|
1563
|
-
const paragraphs = bidi ? analyzeParagraphs(bidi, cps,
|
|
1632
|
+
cps.length = entries2.length;
|
|
1633
|
+
for (let k = 0; k < entries2.length; k++) cps[k] = entries2[k].cp;
|
|
1634
|
+
const paragraphs = bidi ? analyzeParagraphs(bidi, cps, hardBreakAt, direction) : null;
|
|
1564
1635
|
if (!bidi) warnRtlWithoutEngine(cps);
|
|
1565
|
-
const
|
|
1636
|
+
const lineOpts = LINE_OPTS;
|
|
1637
|
+
lineOpts.maxWidth = maxWidth;
|
|
1638
|
+
lineOpts.alignWidth = alignWidth;
|
|
1639
|
+
lineOpts.lineHeight = lineHeight;
|
|
1640
|
+
lineOpts.justify = justify;
|
|
1641
|
+
const broken2 = breakLines(entries2, cps, lineOpts);
|
|
1566
1642
|
let size = 0;
|
|
1567
1643
|
for (let i = 0; i < broken2.length; i++) size += broken2[i].entries.length;
|
|
1568
1644
|
const cols = broken2.length > 0 ? LayoutColumns.take(size) : null;
|
|
1569
1645
|
const lines = cols !== null ? cols.boxes : [];
|
|
1570
1646
|
let y = 0;
|
|
1571
1647
|
let width = 0;
|
|
1572
|
-
let
|
|
1648
|
+
let start2 = 0;
|
|
1573
1649
|
for (let i = 0; i < broken2.length; i++) {
|
|
1574
1650
|
const line = broken2[i];
|
|
1575
1651
|
const order = orderLine(paragraphs, line.start, line.entries.length);
|
|
1576
|
-
if (bidi) line.entries =
|
|
1652
|
+
if (bidi) line.entries = mirrorLine(bidi, line.entries, order.levels, runs);
|
|
1577
1653
|
const reads = direction !== "auto" ? direction : directionOfLevel(line.entries.length > 0 ? paragraphs?.baseLevel(line.start) ?? 0 : 0);
|
|
1578
1654
|
const placed2 = placeLine(
|
|
1579
1655
|
line,
|
|
1580
1656
|
y,
|
|
1581
1657
|
order,
|
|
1582
1658
|
resolveAlign(align, reads),
|
|
1583
|
-
|
|
1584
|
-
justify,
|
|
1659
|
+
lineOpts,
|
|
1585
1660
|
cols,
|
|
1586
|
-
|
|
1661
|
+
start2,
|
|
1587
1662
|
i
|
|
1588
1663
|
);
|
|
1589
|
-
|
|
1664
|
+
start2 += line.entries.length;
|
|
1590
1665
|
width = Math.max(width, placed2.inkWidth);
|
|
1591
1666
|
y += line.height;
|
|
1592
1667
|
}
|
|
1593
1668
|
lines.length = broken2.length;
|
|
1594
|
-
return { lines, bounds: { width, height: y } };
|
|
1669
|
+
if (cols === null) return { lines, bounds: { width, height: y } };
|
|
1670
|
+
cols.bounds.width = width;
|
|
1671
|
+
cols.bounds.height = y;
|
|
1672
|
+
return cols.laid ??= { lines, bounds: cols.bounds };
|
|
1595
1673
|
}
|
|
1596
1674
|
|
|
1597
1675
|
// src/layout/glyphQuads.ts
|
|
@@ -1767,7 +1845,7 @@ var SPARE_GROUPS_MAX = 1024;
|
|
|
1767
1845
|
function giveGroup(group) {
|
|
1768
1846
|
if (spareGroups.length >= SPARE_GROUPS_MAX || group.stroke !== void 0 || group.colorGlyphs !== void 0 || quadsViewed.has(group)) return;
|
|
1769
1847
|
group.quadData = NO_QUADS;
|
|
1770
|
-
group.glyphs
|
|
1848
|
+
truncate(group.glyphs, 0);
|
|
1771
1849
|
spareGroups.push(group);
|
|
1772
1850
|
}
|
|
1773
1851
|
var slots = [];
|
|
@@ -1789,7 +1867,7 @@ function takeGroups(out) {
|
|
|
1789
1867
|
out.push(slots[i].group);
|
|
1790
1868
|
slots[i].group = null;
|
|
1791
1869
|
}
|
|
1792
|
-
slots
|
|
1870
|
+
truncate(slots, 0);
|
|
1793
1871
|
last.group = null;
|
|
1794
1872
|
}
|
|
1795
1873
|
|
|
@@ -1820,6 +1898,9 @@ function runFaces(runs) {
|
|
|
1820
1898
|
return (run) => faces[run];
|
|
1821
1899
|
}
|
|
1822
1900
|
var isDecorated = (r) => r.underline || r.strikethrough || r.overline;
|
|
1901
|
+
function rulePaintOf(runs) {
|
|
1902
|
+
return (run) => fillHasInk(runs[run].fill) ? paintKey(runs[run].fill.paint) : null;
|
|
1903
|
+
}
|
|
1823
1904
|
var cursor = blankGlyph();
|
|
1824
1905
|
var scratch = [];
|
|
1825
1906
|
var SCRATCH_MAX2 = 1 << 14;
|
|
@@ -1828,10 +1909,10 @@ function paintRuns(laid, runs, opts = {}) {
|
|
|
1828
1909
|
}
|
|
1829
1910
|
function paintRunsInto(laid, runs, opts, out) {
|
|
1830
1911
|
const { groups, decorations } = out;
|
|
1831
|
-
groups
|
|
1832
|
-
decorations
|
|
1912
|
+
truncate(groups, 0);
|
|
1913
|
+
truncate(decorations, 0);
|
|
1833
1914
|
const faceOf = runs.some(isDecorated) ? runFaces(runs) : null;
|
|
1834
|
-
const rulePaint = faceOf && (
|
|
1915
|
+
const rulePaint = faceOf && rulePaintOf(runs);
|
|
1835
1916
|
let glyphCount = 0;
|
|
1836
1917
|
const { lines } = laid;
|
|
1837
1918
|
for (let i = 0; i < lines.length; i++) glyphCount += LineBox.count(lines[i]);
|
|
@@ -1843,15 +1924,15 @@ function paintRunsInto(laid, runs, opts, out) {
|
|
|
1843
1924
|
for (let li = 0; li < lines.length; li++) {
|
|
1844
1925
|
const line = lines[li];
|
|
1845
1926
|
const cols = LineBox.columns(line);
|
|
1846
|
-
const
|
|
1927
|
+
const start2 = cols !== null ? LineBox.start(line) : 0;
|
|
1847
1928
|
const count = LineBox.count(line);
|
|
1848
1929
|
const rules = faceOf && lineDecorations(runs, faceOf, rulePaint);
|
|
1849
1930
|
for (let slot = 0; slot < count; slot++) {
|
|
1850
|
-
const pos = cols !== null ? cols.visual(
|
|
1851
|
-
const g = cols !== null ? cols.glyph(
|
|
1931
|
+
const pos = cols !== null ? cols.visual(start2, slot) : -1;
|
|
1932
|
+
const g = cols !== null ? cols.glyph(start2, pos, cursor) : line.glyphs[slot];
|
|
1852
1933
|
rules?.add(g);
|
|
1853
1934
|
const run = runs[g.run];
|
|
1854
|
-
const inks = cols !== null ? cols.drawsInk(
|
|
1935
|
+
const inks = cols !== null ? cols.drawsInk(start2, pos) : line.cells[g.cell].drawsInk;
|
|
1855
1936
|
const outline = inks ? glyphOutlineD(g, run, opts.outlineMinSize) : null;
|
|
1856
1937
|
if (!fillHasInk(run.fill) && !(outline !== null && strokeHasInk(run.stroke))) continue;
|
|
1857
1938
|
if (outline !== null) {
|
|
@@ -1892,9 +1973,51 @@ function paintRunsInto(laid, runs, opts, out) {
|
|
|
1892
1973
|
takeGroups(groups);
|
|
1893
1974
|
return out;
|
|
1894
1975
|
}
|
|
1976
|
+
|
|
1977
|
+
// src/layout/runsEntries.ts
|
|
1978
|
+
var entries = /* @__PURE__ */ new WeakMap();
|
|
1979
|
+
var spare2 = [];
|
|
1980
|
+
var SPARE_MAX2 = 1024;
|
|
1981
|
+
function entryOf(runs) {
|
|
1982
|
+
return entries.get(runs);
|
|
1983
|
+
}
|
|
1984
|
+
function entryFor(runs) {
|
|
1985
|
+
let e = entries.get(runs);
|
|
1986
|
+
if (e === void 0) {
|
|
1987
|
+
e = spare2.pop() ?? {
|
|
1988
|
+
generation: -1,
|
|
1989
|
+
variants: [],
|
|
1990
|
+
painting: null,
|
|
1991
|
+
paintedOn: null,
|
|
1992
|
+
paintedStamp: 0,
|
|
1993
|
+
paintMin: void 0
|
|
1994
|
+
};
|
|
1995
|
+
entries.set(runs, e);
|
|
1996
|
+
}
|
|
1997
|
+
return e;
|
|
1998
|
+
}
|
|
1999
|
+
function dropEntry(runs) {
|
|
2000
|
+
const e = entries.get(runs);
|
|
2001
|
+
if (e !== void 0) entries.delete(runs);
|
|
2002
|
+
return e;
|
|
2003
|
+
}
|
|
2004
|
+
function giveEntry(e) {
|
|
2005
|
+
e.generation = -1;
|
|
2006
|
+
e.painting = null;
|
|
2007
|
+
e.paintedOn = null;
|
|
2008
|
+
e.paintMin = void 0;
|
|
2009
|
+
if (spare2.length < SPARE_MAX2) spare2.push(e);
|
|
2010
|
+
}
|
|
2011
|
+
function _resetRunsEntriesForTests() {
|
|
2012
|
+
entries = /* @__PURE__ */ new WeakMap();
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
// src/layout/paintCache.ts
|
|
1895
2016
|
var PAINT_CACHE_VARIANT_LIMIT = 32;
|
|
1896
|
-
var own = /* @__PURE__ */ new WeakMap();
|
|
1897
2017
|
var shared2 = /* @__PURE__ */ new WeakMap();
|
|
2018
|
+
function stampOf(laid) {
|
|
2019
|
+
return laid.lines.length > 0 ? LineBox.columns(laid.lines[0])?.stamp ?? 0 : 0;
|
|
2020
|
+
}
|
|
1898
2021
|
function listOf(laid) {
|
|
1899
2022
|
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
1900
2023
|
if (cols !== null) return cols.paintings;
|
|
@@ -1902,10 +2025,10 @@ function listOf(laid) {
|
|
|
1902
2025
|
if (list === void 0) shared2.set(laid, list = []);
|
|
1903
2026
|
return list;
|
|
1904
2027
|
}
|
|
1905
|
-
var
|
|
1906
|
-
var
|
|
2028
|
+
var spare3 = [];
|
|
2029
|
+
var SPARE_MAX3 = 1024;
|
|
1907
2030
|
function painting(laid, runs, opts, generation, key, bucket) {
|
|
1908
|
-
const p =
|
|
2031
|
+
const p = spare3.pop();
|
|
1909
2032
|
if (p === void 0) {
|
|
1910
2033
|
return {
|
|
1911
2034
|
generation,
|
|
@@ -1953,13 +2076,15 @@ function keyOf(p) {
|
|
|
1953
2076
|
function cachedPaintRuns(laid, runs, opts = {}, use = "keep") {
|
|
1954
2077
|
const generation = glyphGeneration();
|
|
1955
2078
|
const min = opts.outlineMinSize;
|
|
1956
|
-
const mine =
|
|
1957
|
-
const
|
|
1958
|
-
|
|
2079
|
+
const mine = entryOf(runs);
|
|
2080
|
+
const stamp = stampOf(laid);
|
|
2081
|
+
const own = mine !== void 0 && mine.paintedOn === laid && mine.paintedStamp === stamp ? mine.painting : null;
|
|
2082
|
+
const mineHere = own !== null && own.generation === generation;
|
|
2083
|
+
if (mineHere && mine.paintMin === min) return handOut(own, use);
|
|
1959
2084
|
const bucket = outlineBucket(runs, min);
|
|
1960
|
-
if (mineHere &&
|
|
1961
|
-
mine.
|
|
1962
|
-
return handOut(
|
|
2085
|
+
if (mineHere && own.bucket === bucket) {
|
|
2086
|
+
mine.paintMin = min;
|
|
2087
|
+
return handOut(own, use);
|
|
1963
2088
|
}
|
|
1964
2089
|
const list = listOf(laid);
|
|
1965
2090
|
let p = null;
|
|
@@ -1978,34 +2103,17 @@ function cachedPaintRuns(laid, runs, opts = {}, use = "keep") {
|
|
|
1978
2103
|
}
|
|
1979
2104
|
if (list.length >= PAINT_CACHE_VARIANT_LIMIT) list.shift();
|
|
1980
2105
|
list.push(p);
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
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
|
-
}
|
|
2106
|
+
const e = mine ?? entryFor(runs);
|
|
2107
|
+
e.paintedOn = laid;
|
|
2108
|
+
e.paintedStamp = stamp;
|
|
2109
|
+
e.painting = p;
|
|
2110
|
+
e.paintMin = min;
|
|
1996
2111
|
return handOut(p, use);
|
|
1997
2112
|
}
|
|
1998
2113
|
function handOut(p, use) {
|
|
1999
2114
|
if (use === "keep") p.pinned = true;
|
|
2000
2115
|
return p.painted;
|
|
2001
2116
|
}
|
|
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
2117
|
function recyclePaintings(laid) {
|
|
2010
2118
|
const cols = laid.lines.length > 0 ? LineBox.columns(laid.lines[0]) : null;
|
|
2011
2119
|
let list;
|
|
@@ -2026,17 +2134,16 @@ function recyclePaintings(laid) {
|
|
|
2026
2134
|
group.quadData = NO_QUADS;
|
|
2027
2135
|
giveGroup(group);
|
|
2028
2136
|
}
|
|
2029
|
-
groups
|
|
2030
|
-
p.painted.decorations
|
|
2137
|
+
truncate(groups, 0);
|
|
2138
|
+
truncate(p.painted.decorations, 0);
|
|
2031
2139
|
p.runs = null;
|
|
2032
2140
|
p.key = null;
|
|
2033
|
-
if (
|
|
2141
|
+
if (spare3.length < SPARE_MAX3) spare3.push(p);
|
|
2034
2142
|
}
|
|
2035
|
-
list
|
|
2143
|
+
truncate(list, 0);
|
|
2036
2144
|
}
|
|
2037
2145
|
var LAYOUT_CACHE_VARIANT_LIMIT = 8;
|
|
2038
2146
|
var LAYOUT_CACHE_STRUCTURAL_LIMIT = 64;
|
|
2039
|
-
var cache2 = /* @__PURE__ */ new WeakMap();
|
|
2040
2147
|
var structural = [];
|
|
2041
2148
|
var structuralGeneration = -1;
|
|
2042
2149
|
var clock = 0;
|
|
@@ -2058,9 +2165,8 @@ function release(laid) {
|
|
|
2058
2165
|
recyclePaintings(laid);
|
|
2059
2166
|
cols.recycle();
|
|
2060
2167
|
}
|
|
2061
|
-
var spareEntries = [];
|
|
2062
2168
|
var spareVariants = [];
|
|
2063
|
-
var
|
|
2169
|
+
var SPARE_MAX4 = 1024;
|
|
2064
2170
|
function disown(vs) {
|
|
2065
2171
|
for (let i = 0; i < vs.length; i++) {
|
|
2066
2172
|
const v = vs[i];
|
|
@@ -2070,9 +2176,9 @@ function disown(vs) {
|
|
|
2070
2176
|
release(v.laid);
|
|
2071
2177
|
}
|
|
2072
2178
|
v.laid = NO_LAYOUT;
|
|
2073
|
-
if (spareVariants.length <
|
|
2179
|
+
if (spareVariants.length < SPARE_MAX4) spareVariants.push(v);
|
|
2074
2180
|
}
|
|
2075
|
-
vs
|
|
2181
|
+
truncate(vs, 0);
|
|
2076
2182
|
}
|
|
2077
2183
|
var NO_LAYOUT = { lines: [], bounds: { width: 0, height: 0 } };
|
|
2078
2184
|
function fill(v, opts, bidi, laid) {
|
|
@@ -2089,8 +2195,8 @@ function fill(v, opts, bidi, laid) {
|
|
|
2089
2195
|
return v;
|
|
2090
2196
|
}
|
|
2091
2197
|
function variant(opts, bidi, laid) {
|
|
2092
|
-
const
|
|
2093
|
-
if (
|
|
2198
|
+
const spare4 = spareVariants.pop();
|
|
2199
|
+
if (spare4 !== void 0) return fill(spare4, opts, bidi, laid);
|
|
2094
2200
|
return {
|
|
2095
2201
|
maxWidth: opts.maxWidth,
|
|
2096
2202
|
alignWidth: opts.alignWidth ?? opts.maxWidth,
|
|
@@ -2131,7 +2237,7 @@ function runsHash(runs) {
|
|
|
2131
2237
|
h = mix(h, r.fontFeatures?.length ?? 0);
|
|
2132
2238
|
h = mixStr(h, r.lang ?? "");
|
|
2133
2239
|
}
|
|
2134
|
-
return h;
|
|
2240
|
+
return h & 1073741823;
|
|
2135
2241
|
}
|
|
2136
2242
|
function sameNums(a, b) {
|
|
2137
2243
|
if (a === b) return true;
|
|
@@ -2159,12 +2265,8 @@ function sameRuns(a, b) {
|
|
|
2159
2265
|
function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
2160
2266
|
const fonts = faceGeneration();
|
|
2161
2267
|
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) {
|
|
2268
|
+
const entry = entryFor(runs);
|
|
2269
|
+
if (entry.generation !== fonts) {
|
|
2168
2270
|
entry.generation = fonts;
|
|
2169
2271
|
disown(entry.variants);
|
|
2170
2272
|
} else {
|
|
@@ -2186,12 +2288,10 @@ function cachedLayoutRuns(runs, opts, use = "keep") {
|
|
|
2186
2288
|
return handOut2(laid, use);
|
|
2187
2289
|
}
|
|
2188
2290
|
function dropRuns(runs) {
|
|
2189
|
-
const entry =
|
|
2190
|
-
forgetPaintRuns(runs);
|
|
2291
|
+
const entry = dropEntry(runs);
|
|
2191
2292
|
if (entry === void 0) return;
|
|
2192
|
-
cache2.delete(runs);
|
|
2193
2293
|
disown(entry.variants);
|
|
2194
|
-
|
|
2294
|
+
giveEntry(entry);
|
|
2195
2295
|
}
|
|
2196
2296
|
function structuralLayout(runs, opts, bidi, fonts) {
|
|
2197
2297
|
if (structuralGeneration !== fonts) {
|
|
@@ -2245,12 +2345,12 @@ function unlist(s) {
|
|
|
2245
2345
|
release(s.laid);
|
|
2246
2346
|
}
|
|
2247
2347
|
function _resetLayoutCacheForTests() {
|
|
2248
|
-
|
|
2348
|
+
_resetRunsEntriesForTests();
|
|
2249
2349
|
structural = [];
|
|
2250
2350
|
structuralGeneration = -1;
|
|
2251
2351
|
clock = 0;
|
|
2252
2352
|
}
|
|
2253
2353
|
|
|
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-
|
|
2354
|
+
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, resolveTextStyleInto, runFaces, shapesWithFeature, syntheticBoldOffset, tabAdvance, widthWithTabs, wrapLines };
|
|
2355
|
+
//# sourceMappingURL=chunk-5BJN6MC6.js.map
|
|
2356
|
+
//# sourceMappingURL=chunk-5BJN6MC6.js.map
|