@weasel-js/text 1.13.0-rc.0 → 1.13.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-ADRQIIHS.js → chunk-DOTR55MR.js} +197 -41
- package/dist/chunk-DOTR55MR.js.map +1 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +101 -45
- package/dist/index.js.map +1 -1
- package/dist/test-seams.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-ADRQIIHS.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_TAB_SIZE, resolveTextStyle, cachedLayoutRuns, graphemeCount, wrapLines, hangs, layoutRuns, tabAdvance, widthWithTabs } from './chunk-
|
|
2
|
-
export { BREAK_ALLOWED, BREAK_MANDATORY, DEFAULT_TEXT_FILL, DEFAULT_TEXT_STYLE, LAYOUT_CACHE_STRUCTURAL_LIMIT, LAYOUT_CACHE_VARIANT_LIMIT, NO_BREAK, cachedLayoutRuns, fontString, isHardLineBreak, layoutRuns, lineBreakOpportunities, paragraphDirection, registerBidi, resolveAlign, resolveTextStyle } from './chunk-
|
|
1
|
+
import { lazy, DEFAULT_TAB_SIZE, resolveTextStyle, cachedLayoutRuns, blankGlyph, LineBox, doubles, graphemeCount, wrapLines, hangs, layoutRuns, tabAdvance, widthWithTabs } from './chunk-DOTR55MR.js';
|
|
2
|
+
export { BREAK_ALLOWED, BREAK_MANDATORY, DEFAULT_TEXT_FILL, DEFAULT_TEXT_STYLE, LAYOUT_CACHE_STRUCTURAL_LIMIT, LAYOUT_CACHE_VARIANT_LIMIT, NO_BREAK, cachedLayoutRuns, fontString, isHardLineBreak, layoutRuns, lineBreakOpportunities, paragraphDirection, registerBidi, resolveAlign, resolveTextStyle } from './chunk-DOTR55MR.js';
|
|
3
3
|
import { resolveScreenLength, fillHasInk, strokeHasInk, paintKey, strokeKey } from '@weasel-js/paint';
|
|
4
4
|
import { faceMetricsOf, resolveFontVariant, syntheticBoldGrowth, glyphGeneration, loadFontOutlines, faceMetricsFor, glyphOutline, outlineStatus, cssFamilyName } from '@weasel-js/font';
|
|
5
5
|
import { pathToD, pathFromD, mergeRegion, growRegion, poseFrameOf, transformPath, PATH_M, PATH_L, PATH_Z, pathSignedArea, reversePath } from '@weasel-js/geom';
|
|
@@ -398,7 +398,7 @@ function decorationRule(kind, baselineY, fontSize, face) {
|
|
|
398
398
|
const y0 = baselineY + fontSize * m.offset;
|
|
399
399
|
return { y0, y1: y0 + fontSize * m.thickness };
|
|
400
400
|
}
|
|
401
|
-
function lineDecorations(
|
|
401
|
+
function lineDecorations(runs, faceOf, paintOf) {
|
|
402
402
|
const rules = [];
|
|
403
403
|
let open = null;
|
|
404
404
|
const close = () => {
|
|
@@ -411,24 +411,28 @@ function lineDecorations(glyphs, runs, faceOf, paintOf) {
|
|
|
411
411
|
rules.push({ kind, x0: s.x0, y0, x1: s.x1, y1, run: s.run });
|
|
412
412
|
}
|
|
413
413
|
};
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
414
|
+
return {
|
|
415
|
+
add(g) {
|
|
416
|
+
const style = runs[g.run];
|
|
417
|
+
const paint = style.underline || style.strikethrough || style.overline ? paintOf(g.run) : null;
|
|
418
|
+
if (paint === null) {
|
|
419
|
+
if (open !== null) close();
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const face = faceOf(g.run);
|
|
423
|
+
const joins = open !== null && DECORATION_KINDS.every((kind) => open.style[kind] === style[kind]) && open.style.fontSize === style.fontSize && open.face === face && open.baselineY === g.baselineY && open.paint === paint;
|
|
424
|
+
if (joins) {
|
|
425
|
+
open.x1 = g.x + g.step;
|
|
426
|
+
} else {
|
|
427
|
+
close();
|
|
428
|
+
open = { run: g.run, style, face, paint, baselineY: g.baselineY, x0: g.x, x1: g.x + g.step };
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
end() {
|
|
426
432
|
close();
|
|
427
|
-
|
|
433
|
+
return rules;
|
|
428
434
|
}
|
|
429
|
-
}
|
|
430
|
-
close();
|
|
431
|
-
return rules;
|
|
435
|
+
};
|
|
432
436
|
}
|
|
433
437
|
|
|
434
438
|
// src/measure/verticalAlign.ts
|
|
@@ -527,28 +531,53 @@ function faceOutlineD(g) {
|
|
|
527
531
|
if (g.resolved.source !== "outline" && g.glyph === null) return null;
|
|
528
532
|
return glyphOutline(family, weight, style, g.cp);
|
|
529
533
|
}
|
|
530
|
-
|
|
534
|
+
var QUAD_STRIDE = 9;
|
|
535
|
+
function hasGlyphQuad(g) {
|
|
531
536
|
const { font, glyph } = g;
|
|
532
|
-
|
|
537
|
+
return font !== null && glyph !== null && glyph.width !== 0 && glyph.page >= 0;
|
|
538
|
+
}
|
|
539
|
+
function writeGlyphQuad(g, out, at) {
|
|
540
|
+
const font = g.font, glyph = g.glyph;
|
|
533
541
|
const scale = g.fontSize / g.metrics.size;
|
|
534
542
|
const x0 = g.x + glyph.xoffset * scale;
|
|
535
543
|
const y0 = g.baselineY + (glyph.yoffset - g.metrics.base) * scale;
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
544
|
+
out[at] = x0;
|
|
545
|
+
out[at + 1] = y0;
|
|
546
|
+
out[at + 2] = x0 + glyph.width * scale;
|
|
547
|
+
out[at + 3] = y0 + glyph.height * scale;
|
|
548
|
+
out[at + 4] = glyph.x / font.common.scaleW;
|
|
549
|
+
out[at + 5] = glyph.y / font.common.scaleH;
|
|
550
|
+
out[at + 6] = (glyph.x + glyph.width) / font.common.scaleW;
|
|
551
|
+
out[at + 7] = (glyph.y + glyph.height) / font.common.scaleH;
|
|
552
|
+
out[at + 8] = g.baselineY;
|
|
553
|
+
}
|
|
554
|
+
var groupViews = {
|
|
555
|
+
quads: lazy("quads", (group) => {
|
|
556
|
+
const d = group.quadData;
|
|
557
|
+
const out = [];
|
|
558
|
+
for (let at = 0, k = 0; at < d.length; at += QUAD_STRIDE, k++) {
|
|
559
|
+
const q = {
|
|
560
|
+
x0: d[at],
|
|
561
|
+
y0: d[at + 1],
|
|
562
|
+
x1: d[at + 2],
|
|
563
|
+
y1: d[at + 3],
|
|
564
|
+
u0: d[at + 4],
|
|
565
|
+
v0: d[at + 5],
|
|
566
|
+
u1: d[at + 6],
|
|
567
|
+
v1: d[at + 7],
|
|
568
|
+
baselineY: d[at + 8]
|
|
569
|
+
};
|
|
570
|
+
if (group.colorGlyphs) q.colorGlyph = group.colorGlyphs[k];
|
|
571
|
+
out.push(q);
|
|
572
|
+
}
|
|
573
|
+
return out;
|
|
574
|
+
})
|
|
575
|
+
};
|
|
548
576
|
function runFaces(runs) {
|
|
549
577
|
const faces = runs.map((r) => faceMetricsOf(resolveFontVariant(r.fontFamily, r.fontWeight, r.fontStyle)));
|
|
550
578
|
return (run) => faces[run];
|
|
551
579
|
}
|
|
580
|
+
var isDecorated = (r) => r.underline || r.strikethrough || r.overline;
|
|
552
581
|
function groupFor(groups, g, run, source, last) {
|
|
553
582
|
const { family, weight, style } = g.resolved.resolved;
|
|
554
583
|
const { synthetic } = g.resolved;
|
|
@@ -569,7 +598,8 @@ function groupFor(groups, g, run, source, last) {
|
|
|
569
598
|
page,
|
|
570
599
|
fill: run.fill,
|
|
571
600
|
...stroke ? { stroke } : {},
|
|
572
|
-
|
|
601
|
+
quadData: [],
|
|
602
|
+
...source === "color" ? { colorGlyphs: [] } : {},
|
|
573
603
|
glyphs: []
|
|
574
604
|
};
|
|
575
605
|
groups.set(key, group);
|
|
@@ -599,10 +629,20 @@ function paintRuns(laid, runs, opts = {}) {
|
|
|
599
629
|
page: 0
|
|
600
630
|
};
|
|
601
631
|
const decorations = [];
|
|
602
|
-
const faceOf = runFaces(runs);
|
|
632
|
+
const faceOf = runs.some(isDecorated) ? runFaces(runs) : null;
|
|
603
633
|
const rulePaint = (run) => fillHasInk(runs[run].fill) ? paintKey(runs[run].fill.paint) : null;
|
|
634
|
+
const cursor = blankGlyph();
|
|
635
|
+
let glyphCount = 0;
|
|
636
|
+
for (const line of laid.lines) glyphCount += LineBox.count(line);
|
|
637
|
+
let sized = null;
|
|
638
|
+
let sizedAt = 0;
|
|
604
639
|
for (const line of laid.lines) {
|
|
605
|
-
|
|
640
|
+
const span = LineBox.span(line);
|
|
641
|
+
const count = LineBox.count(line);
|
|
642
|
+
const rules = faceOf && lineDecorations(runs, faceOf, rulePaint);
|
|
643
|
+
for (let slot = 0; slot < count; slot++) {
|
|
644
|
+
const g = span ? span.cols.glyph(span.start, span.cols.visual(span.start, slot), cursor) : line.glyphs[slot];
|
|
645
|
+
rules?.add(g);
|
|
606
646
|
const run = runs[g.run];
|
|
607
647
|
const outline = glyphOutlineD(g, run, opts.outlineMinSize);
|
|
608
648
|
if (!fillHasInk(run.fill) && !(outline !== null && strokeHasInk(run.stroke))) continue;
|
|
@@ -615,17 +655,31 @@ function paintRuns(laid, runs, opts = {}) {
|
|
|
615
655
|
});
|
|
616
656
|
continue;
|
|
617
657
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
if (
|
|
621
|
-
|
|
658
|
+
if (!hasGlyphQuad(g)) continue;
|
|
659
|
+
const group = groupFor(groups, g, run, g.glyph.color ? "color" : g.resolved.source, last);
|
|
660
|
+
if (sized === null) {
|
|
661
|
+
sized = group;
|
|
662
|
+
group.quadData = doubles(glyphCount * QUAD_STRIDE);
|
|
663
|
+
}
|
|
664
|
+
const quads = group.quadData;
|
|
665
|
+
if (group === sized) {
|
|
666
|
+
writeGlyphQuad(g, quads, sizedAt);
|
|
667
|
+
sizedAt += QUAD_STRIDE;
|
|
668
|
+
} else {
|
|
669
|
+
writeGlyphQuad(g, quads, quads.length);
|
|
670
|
+
}
|
|
671
|
+
group.colorGlyphs?.push(g.glyph);
|
|
622
672
|
}
|
|
623
|
-
|
|
673
|
+
if (!rules) continue;
|
|
674
|
+
for (const rule of rules.end()) {
|
|
624
675
|
const { run, ...rect } = rule;
|
|
625
676
|
decorations.push({ ...rect, fill: runs[run].fill });
|
|
626
677
|
}
|
|
627
678
|
}
|
|
628
|
-
|
|
679
|
+
if (sized !== null) sized.quadData.length = sizedAt;
|
|
680
|
+
const out = [];
|
|
681
|
+
for (const group of groups.values()) out.push(Object.defineProperties(group, groupViews));
|
|
682
|
+
return { groups: out, decorations };
|
|
629
683
|
}
|
|
630
684
|
var PAINT_CACHE_VARIANT_LIMIT = 32;
|
|
631
685
|
var own = /* @__PURE__ */ new WeakMap();
|
|
@@ -1370,7 +1424,7 @@ function emGlyph(d) {
|
|
|
1370
1424
|
function placedGlyphOutline(g, dx, dy, caller, blankFallback = false) {
|
|
1371
1425
|
const d = faceOutlineD(g);
|
|
1372
1426
|
if (d === null) {
|
|
1373
|
-
if (!blankFallback &&
|
|
1427
|
+
if (!blankFallback && hasGlyphQuad(g)) {
|
|
1374
1428
|
const { family, weight, style } = g.resolved.resolved;
|
|
1375
1429
|
throw new TextOutlinesError(
|
|
1376
1430
|
"no-outlines",
|
|
@@ -1464,12 +1518,14 @@ function walkOutlines(data, pose, opts) {
|
|
|
1464
1518
|
const rules = paints.map(() => []);
|
|
1465
1519
|
const faceOf = runFaces(runs);
|
|
1466
1520
|
for (const line of laid.lines) {
|
|
1521
|
+
const deco = lineDecorations(runs, faceOf, (run) => String(paintOf[run]));
|
|
1467
1522
|
for (const g of line.glyphs) {
|
|
1523
|
+
deco.add(g);
|
|
1468
1524
|
if (g.glyph?.color) throw colorGlyphError(runs[g.run], "textToPath");
|
|
1469
1525
|
const glyph = placedGlyphOutline(g, dx, dy, "textToPath");
|
|
1470
1526
|
if (glyph) parts[paintOf[g.run]].push(glyph);
|
|
1471
1527
|
}
|
|
1472
|
-
for (const r of
|
|
1528
|
+
for (const r of deco.end()) {
|
|
1473
1529
|
rules[paintOf[r.run]].push(ruleContour(r.x0 + dx, r.y0 + dy, r.x1 + dx, r.y1 + dy));
|
|
1474
1530
|
}
|
|
1475
1531
|
}
|
|
@@ -1545,6 +1601,6 @@ function textClusters(data, opts = {}) {
|
|
|
1545
1601
|
});
|
|
1546
1602
|
}
|
|
1547
1603
|
|
|
1548
|
-
export { DEFAULT_DECORATION_METRICS, MARKDOWN_RUN_GRAMMAR, SCRIPT_METRICS, SMALL_CAPS_SCALE, SYNTHETIC_ITALIC_RADIANS, TextOutlinesError, applyStyleToRange, cachedPaintRuns, caretIndexAt, createMarkdownRenderer, decorationMetrics, defaultLabelTextRenderer, effectiveRangeStyle, emboldenGlyphD, fitTextPose, isBoldWeight, isSmallCapsLetter, isTextData, layoutMarkdown, layoutTextPose, loadTextOutlines, markdownToRuns, measureText, measureTextBounds, measuredWidth, nodeHasFlag, numericWeight, paintRuns, patchRangeStyle, pointInTextPose, rangeWeight, renderLabel, resolveRunFace, resolveRuns, runsCarryStyling, runsToMarkdown, runsToPlainText, scriptMetrics, scriptMetricsFor, setFlagOverRange, smallCapsScale, smallCapsScaleFor, smallCapsText, styleAtRange, supersededKey, syntheticBoldOffset, textClusters, textLineBoxes, textPoseLayoutInput, textToPath, textToPathsByPaint, toRuns, transformRunTexts, unboldPatch, verticalAlignOffset };
|
|
1604
|
+
export { DEFAULT_DECORATION_METRICS, MARKDOWN_RUN_GRAMMAR, QUAD_STRIDE, SCRIPT_METRICS, SMALL_CAPS_SCALE, SYNTHETIC_ITALIC_RADIANS, TextOutlinesError, applyStyleToRange, cachedPaintRuns, caretIndexAt, createMarkdownRenderer, decorationMetrics, defaultLabelTextRenderer, effectiveRangeStyle, emboldenGlyphD, fitTextPose, isBoldWeight, isSmallCapsLetter, isTextData, layoutMarkdown, layoutTextPose, loadTextOutlines, markdownToRuns, measureText, measureTextBounds, measuredWidth, nodeHasFlag, numericWeight, paintRuns, patchRangeStyle, pointInTextPose, rangeWeight, renderLabel, resolveRunFace, resolveRuns, runsCarryStyling, runsToMarkdown, runsToPlainText, scriptMetrics, scriptMetricsFor, setFlagOverRange, smallCapsScale, smallCapsScaleFor, smallCapsText, styleAtRange, supersededKey, syntheticBoldOffset, textClusters, textLineBoxes, textPoseLayoutInput, textToPath, textToPathsByPaint, toRuns, transformRunTexts, unboldPatch, verticalAlignOffset };
|
|
1549
1605
|
//# sourceMappingURL=index.js.map
|
|
1550
1606
|
//# sourceMappingURL=index.js.map
|