@vosjs/studio-core 0.38.0 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +15 -225
- package/dist/index.js +250 -470
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -2213,7 +2213,7 @@ function htmlLayerPayload(clip) {
|
|
|
2213
2213
|
};
|
|
2214
2214
|
}
|
|
2215
2215
|
|
|
2216
|
-
//
|
|
2216
|
+
// ../elements/dist/chunk-GYJBPCR2.js
|
|
2217
2217
|
var sameStyle = (a, b) => (a.f || 0) === (b.f || 0) && a.c === b.c && a.u === b.u && a.s === b.s && a.h === b.h;
|
|
2218
2218
|
function graphemesOf(text) {
|
|
2219
2219
|
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
@@ -2375,8 +2375,6 @@ function decorationRect(kind, x, w, y, px) {
|
|
|
2375
2375
|
);
|
|
2376
2376
|
return { x: x0, y: top, w: x1 - x0, h: t };
|
|
2377
2377
|
}
|
|
2378
|
-
|
|
2379
|
-
// src/richText/runs.ts
|
|
2380
2378
|
var RUN_STYLE_KEYS = [
|
|
2381
2379
|
"weight",
|
|
2382
2380
|
"italic",
|
|
@@ -2421,6 +2419,24 @@ function normalizeRuns(text) {
|
|
|
2421
2419
|
if (out.length === 1 && !isStyled(out[0])) return out[0].text;
|
|
2422
2420
|
return out;
|
|
2423
2421
|
}
|
|
2422
|
+
function layoutLines(text, fontOf) {
|
|
2423
|
+
const lines = [[]];
|
|
2424
|
+
for (const run of runsOf(text)) {
|
|
2425
|
+
const f = fontOf(run);
|
|
2426
|
+
const set = {
|
|
2427
|
+
...f ? { f } : {},
|
|
2428
|
+
...run.color ? { c: run.color } : {},
|
|
2429
|
+
...run.underline ? { u: 1 } : {},
|
|
2430
|
+
...run.strike ? { s: 1 } : {},
|
|
2431
|
+
...run.highlight ? { h: run.highlight } : {}
|
|
2432
|
+
};
|
|
2433
|
+
run.text.split("\n").forEach((part, i) => {
|
|
2434
|
+
if (i > 0) lines.push([]);
|
|
2435
|
+
if (part) lines[lines.length - 1].push({ t: part, ...set });
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
return lines;
|
|
2439
|
+
}
|
|
2424
2440
|
function snapOffset(plain, offset, dir) {
|
|
2425
2441
|
const o = Math.max(0, Math.min(plain.length, offset));
|
|
2426
2442
|
let at = 0;
|
|
@@ -2530,6 +2546,68 @@ function diffInput(prev, next, caretAfter) {
|
|
|
2530
2546
|
};
|
|
2531
2547
|
}
|
|
2532
2548
|
|
|
2549
|
+
// ../elements/dist/text/index.js
|
|
2550
|
+
function caretStops(line, measure) {
|
|
2551
|
+
const stops = [{ o: line.a, x: 0 }];
|
|
2552
|
+
for (const fr of line.frags) {
|
|
2553
|
+
let at = 0;
|
|
2554
|
+
for (const g of graphemesOf(fr.t)) {
|
|
2555
|
+
at += g.length;
|
|
2556
|
+
stops.push({
|
|
2557
|
+
o: line.a + fr.o + at,
|
|
2558
|
+
x: fr.x + measure(fr.t.slice(0, at), fr.f || 0)
|
|
2559
|
+
});
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
return stops;
|
|
2563
|
+
}
|
|
2564
|
+
function lineOfOffset(layout, offset) {
|
|
2565
|
+
const lines = layout.lines;
|
|
2566
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2567
|
+
if (offset >= lines[i].a) return i;
|
|
2568
|
+
}
|
|
2569
|
+
return 0;
|
|
2570
|
+
}
|
|
2571
|
+
function caretAt(layout, offset, measure) {
|
|
2572
|
+
const li = lineOfOffset(layout, offset);
|
|
2573
|
+
const stops = caretStops(layout.lines[li], measure);
|
|
2574
|
+
let x = stops[stops.length - 1].x;
|
|
2575
|
+
for (const s of stops) {
|
|
2576
|
+
if (s.o >= offset) {
|
|
2577
|
+
x = s.x;
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
return { line: li, x };
|
|
2582
|
+
}
|
|
2583
|
+
function offsetAtX(line, x, measure) {
|
|
2584
|
+
const stops = caretStops(line, measure);
|
|
2585
|
+
let best = stops[0];
|
|
2586
|
+
for (const s of stops) {
|
|
2587
|
+
if (Math.abs(s.x - x) < Math.abs(best.x - x)) best = s;
|
|
2588
|
+
}
|
|
2589
|
+
return best.o;
|
|
2590
|
+
}
|
|
2591
|
+
function rangeRects(layout, start, end, measure, breakTail = 0) {
|
|
2592
|
+
const out = [];
|
|
2593
|
+
if (end <= start) return out;
|
|
2594
|
+
layout.lines.forEach((line, i) => {
|
|
2595
|
+
const lineEnd = line.a + line.n;
|
|
2596
|
+
if (end <= line.a || start > lineEnd) return;
|
|
2597
|
+
const stops = caretStops(line, measure);
|
|
2598
|
+
const xOf = (o) => {
|
|
2599
|
+
for (const s of stops) if (s.o >= o) return s.x;
|
|
2600
|
+
return stops[stops.length - 1].x;
|
|
2601
|
+
};
|
|
2602
|
+
const x0 = xOf(Math.max(start, line.a));
|
|
2603
|
+
const x1 = xOf(Math.min(end, lineEnd));
|
|
2604
|
+
const next = layout.lines[i + 1];
|
|
2605
|
+
const tail = next && next.a > lineEnd && end > lineEnd ? breakTail : 0;
|
|
2606
|
+
if (x1 + tail > x0) out.push({ line: i, x: x0, w: x1 - x0 + tail });
|
|
2607
|
+
});
|
|
2608
|
+
return out;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2533
2611
|
// src/overlayText.ts
|
|
2534
2612
|
var OVERLAY_BOX_PAD_X = 0.6;
|
|
2535
2613
|
var OVERLAY_BOX_PAD_Y = 0.35;
|
|
@@ -2699,24 +2777,13 @@ function styledTextOf(clip) {
|
|
|
2699
2777
|
}
|
|
2700
2778
|
return at;
|
|
2701
2779
|
};
|
|
2702
|
-
const l =
|
|
2703
|
-
|
|
2704
|
-
|
|
2780
|
+
const l = layoutLines(
|
|
2781
|
+
runs,
|
|
2782
|
+
(run) => fontOf(
|
|
2705
2783
|
run.weight !== void 0 ? snapRunWeight(clip, run.weight) : style.weight,
|
|
2706
2784
|
run.italic ?? italic
|
|
2707
|
-
)
|
|
2708
|
-
|
|
2709
|
-
...f ? { f } : {},
|
|
2710
|
-
...run.color ? { c: run.color } : {},
|
|
2711
|
-
...run.underline ? { u: 1 } : {},
|
|
2712
|
-
...run.strike ? { s: 1 } : {},
|
|
2713
|
-
...run.highlight ? { h: run.highlight } : {}
|
|
2714
|
-
};
|
|
2715
|
-
run.text.split("\n").forEach((part, i) => {
|
|
2716
|
-
if (i > 0) l.push([]);
|
|
2717
|
-
if (part) l[l.length - 1].push({ t: part, ...set });
|
|
2718
|
-
});
|
|
2719
|
-
}
|
|
2785
|
+
)
|
|
2786
|
+
);
|
|
2720
2787
|
const entry = familyEntryOf(clip);
|
|
2721
2788
|
const faces = [];
|
|
2722
2789
|
for (const font of fs.slice(1)) {
|
|
@@ -2740,63 +2807,30 @@ function styledTextOf(clip) {
|
|
|
2740
2807
|
h: hashOf(JSON.stringify([l, fs]))
|
|
2741
2808
|
};
|
|
2742
2809
|
}
|
|
2743
|
-
function
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
}
|
|
2754
|
-
let current = "";
|
|
2755
|
-
for (const token of overlayTokens(line)) {
|
|
2756
|
-
if (!current) {
|
|
2757
|
-
current = token;
|
|
2758
|
-
continue;
|
|
2759
|
-
}
|
|
2760
|
-
if (measure(current + token) <= maxPx) {
|
|
2761
|
-
current += token;
|
|
2762
|
-
} else {
|
|
2763
|
-
out.push(current);
|
|
2764
|
-
current = token;
|
|
2810
|
+
function textRunsOf(clip) {
|
|
2811
|
+
const styled = styledTextOf(clip);
|
|
2812
|
+
if (styled) return styled;
|
|
2813
|
+
const style = resolveOverlayStyle(clip);
|
|
2814
|
+
return {
|
|
2815
|
+
l: overlayLines(overlayPlainText(clip)).map((t) => t ? [{ t }] : []),
|
|
2816
|
+
fs: [
|
|
2817
|
+
{
|
|
2818
|
+
w: style.weight,
|
|
2819
|
+
...style.fontStyle === "italic" ? { i: 1 } : {}
|
|
2765
2820
|
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
}
|
|
2769
|
-
return out.length ? out : [""];
|
|
2770
|
-
}
|
|
2771
|
-
function graphemesOf2(line) {
|
|
2772
|
-
if (typeof Intl !== "undefined" && typeof Intl.Segmenter === "function") {
|
|
2773
|
-
return [
|
|
2774
|
-
...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(
|
|
2775
|
-
line
|
|
2776
|
-
)
|
|
2777
|
-
].map((s) => s.segment);
|
|
2778
|
-
}
|
|
2779
|
-
return [...line];
|
|
2780
|
-
}
|
|
2781
|
-
function overlaySegments(text, unit) {
|
|
2782
|
-
const lines = overlayLines(text);
|
|
2783
|
-
if (unit === "block") return [];
|
|
2784
|
-
if (unit === "line") return lines.map((l) => [l]);
|
|
2785
|
-
if (unit === "word") return lines.map(overlayTokens);
|
|
2786
|
-
return lines.map(graphemesOf2);
|
|
2821
|
+
]
|
|
2822
|
+
};
|
|
2787
2823
|
}
|
|
2788
2824
|
var FX_DIR = { forward: 0, reverse: 1, center: 2 };
|
|
2789
2825
|
function resolveOverlayFx(clip, clipDuration) {
|
|
2790
2826
|
const spec = overlayFxSpec(clip) ?? clip.fx ?? null;
|
|
2791
2827
|
if (!spec) return null;
|
|
2792
2828
|
const unit = spec.unit ?? "block";
|
|
2793
|
-
const
|
|
2794
|
-
const
|
|
2795
|
-
const
|
|
2796
|
-
const
|
|
2797
|
-
|
|
2798
|
-
0
|
|
2799
|
-
) : n;
|
|
2829
|
+
const lines = overlayLines(overlayPlainText(clip));
|
|
2830
|
+
const count = (per) => lines.reduce((sum, line) => sum + per(line), 0);
|
|
2831
|
+
const words = () => count((line) => tokenRanges(line).length);
|
|
2832
|
+
const n = unit === "block" ? 1 : unit === "line" ? lines.length : unit === "word" ? words() : count((line) => graphemesOf(line).length);
|
|
2833
|
+
const upperN = unit === "line" && clip.maxWidth ? words() : n;
|
|
2800
2834
|
const typewriter = spec.fx === "typewriter";
|
|
2801
2835
|
const dur = typewriter ? 1e-3 : Math.min(2, Math.max(0.05, spec.duration ?? OVERLAY_TRANSITION_DUR));
|
|
2802
2836
|
const defaultStagger = typewriter ? 0.05 : unit === "block" ? 0 : 0.06;
|
|
@@ -2812,9 +2846,7 @@ function resolveOverlayFx(clip, clipDuration) {
|
|
|
2812
2846
|
d: FX_DIR[spec.direction ?? "forward"] ?? 0,
|
|
2813
2847
|
st: round14(st),
|
|
2814
2848
|
dur: round14(dur),
|
|
2815
|
-
tt: round14(st * (upperN - 1) + dur)
|
|
2816
|
-
units,
|
|
2817
|
-
n
|
|
2849
|
+
tt: round14(st * (upperN - 1) + dur)
|
|
2818
2850
|
};
|
|
2819
2851
|
}
|
|
2820
2852
|
function overlayFontString(style, scale, s) {
|
|
@@ -2838,35 +2870,21 @@ function overlayRect(clip, measure, frameW, frameH = 1080, mediaAspect) {
|
|
|
2838
2870
|
return { ...base, w: w2, h: w2 / (mediaAspect || 16 / 9) };
|
|
2839
2871
|
}
|
|
2840
2872
|
const style = resolveOverlayStyle(clip);
|
|
2841
|
-
const font = overlayFontString(style, scale, 1);
|
|
2842
2873
|
const ls = style.letterSpacing * scale;
|
|
2843
|
-
const
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
)
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
);
|
|
2858
|
-
w = laid.width;
|
|
2859
|
-
lineCount = laid.lines.length;
|
|
2860
|
-
} else {
|
|
2861
|
-
const width = (t) => measure(t, font, ls);
|
|
2862
|
-
const lines = clip.maxWidth ? wrapOverlayLines(
|
|
2863
|
-
overlayLines(overlayPlainText(clip)),
|
|
2864
|
-
width,
|
|
2865
|
-
clip.maxWidth * frameW
|
|
2866
|
-
) : overlayLines(overlayPlainText(clip));
|
|
2867
|
-
for (const line of lines) w = Math.max(w, width(line));
|
|
2868
|
-
lineCount = lines.length;
|
|
2869
|
-
}
|
|
2874
|
+
const runs = textRunsOf(clip);
|
|
2875
|
+
const fonts = runs.fs.map(
|
|
2876
|
+
(f) => overlayFontString(
|
|
2877
|
+
{ ...style, weight: f.w, fontStyle: f.i ? "italic" : "normal" },
|
|
2878
|
+
scale,
|
|
2879
|
+
1
|
|
2880
|
+
)
|
|
2881
|
+
);
|
|
2882
|
+
const laid = layoutText(
|
|
2883
|
+
{ lines: runs.l, maxWidth: clip.maxWidth ? clip.maxWidth * frameW : 0 },
|
|
2884
|
+
(t, f) => measure(t, fonts[f], ls)
|
|
2885
|
+
);
|
|
2886
|
+
const w = laid.width;
|
|
2887
|
+
const lineCount = laid.lines.length;
|
|
2870
2888
|
const lineH = style.size * scale * style.lineHeight;
|
|
2871
2889
|
const box = resolveOverlayBox(clip);
|
|
2872
2890
|
const padX = box ? box.padX * scale : 0;
|
|
@@ -5117,7 +5135,7 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
5117
5135
|
var s = H / 1080 // scale design-px controls to comp px
|
|
5118
5136
|
var ns = window.__vos__ || {}
|
|
5119
5137
|
var playing = ns.isPaused === false
|
|
5120
|
-
// The styled-text layout (
|
|
5138
|
+
// The styled-text layout (the engine's text/layout.ts, generated), installed once:
|
|
5121
5139
|
// the page lays a text layer out with the code the host picks with.
|
|
5122
5140
|
if (!ns.textLayout) { ${textLayoutCode}; ns.textLayout = __vosTextLayout }
|
|
5123
5141
|
var TXL = ns.textLayout
|
|
@@ -5592,334 +5610,155 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
5592
5610
|
ovC.textAlign = 'center'
|
|
5593
5611
|
ovC.textBaseline = 'middle'
|
|
5594
5612
|
ovC.letterSpacing = ((ol.ls || 0) * olMS * s) + 'px'
|
|
5595
|
-
//
|
|
5596
|
-
//
|
|
5597
|
-
//
|
|
5598
|
-
//
|
|
5599
|
-
//
|
|
5600
|
-
//
|
|
5613
|
+
// Every text layer is laid out by the layout module, ONCE: a styled one
|
|
5614
|
+
// from its runs (ol.rt: lines of runs, each set its own way), a plain
|
|
5615
|
+
// one from its lines, each a single run in the layer's own style. The
|
|
5616
|
+
// layout is kept per clip under a key of everything it was measured
|
|
5617
|
+
// with, so a frame that only moves, fades or reveals the layer measures
|
|
5618
|
+
// nothing. Fragments draw left to right from each line's left edge; a
|
|
5619
|
+
// per-unit entrance animates the layout's units, each a few parts of
|
|
5620
|
+
// fragments.
|
|
5621
|
+
var rtFonts = [ovC.font]
|
|
5601
5622
|
if (ol.rt) {
|
|
5602
|
-
var rtFonts = [ovC.font]
|
|
5603
5623
|
for (var rfi = 1; rfi < ol.rt.fs.length; rfi++) {
|
|
5604
5624
|
rtFonts.push((ol.rt.fs[rfi].i ? 'italic ' : '') + ol.rt.fs[rfi].w + ' ' + olPx + 'px ' + ol.stack)
|
|
5605
5625
|
}
|
|
5606
|
-
var rtFx = ol.fx && ol.fx.units.length ? ol.fx : null
|
|
5607
|
-
var rtMax = ol.mw ? ol.mw * W : 0
|
|
5608
|
-
var rtKey = ol.rt.h + '|' + rtFonts[0] + '|' + ((ol.ls || 0) * olMS * s) + '|' + rtMax + '|' + (rtFx ? rtFx.u : '') + '|' + (ns.fontEpoch || 0)
|
|
5609
|
-
var rtAll = ns.textLayouts || (ns.textLayouts = {})
|
|
5610
|
-
var rtHit = rtAll[ol.id]
|
|
5611
|
-
if (!rtHit || rtHit.k !== rtKey) {
|
|
5612
|
-
rtHit = rtAll[ol.id] = {
|
|
5613
|
-
k: rtKey,
|
|
5614
|
-
L: TXL.layoutText(
|
|
5615
|
-
{ lines: ol.rt.l, maxWidth: rtMax, unit: rtFx ? rtFx.u : undefined },
|
|
5616
|
-
function (mt, mf) { ovC.font = rtFonts[mf]; return ovC.measureText(mt).width }
|
|
5617
|
-
)
|
|
5618
|
-
}
|
|
5619
|
-
ovC.font = rtFonts[0]
|
|
5620
|
-
}
|
|
5621
|
-
var rtL = rtHit.L
|
|
5622
|
-
var rtN = rtL.lines.length
|
|
5623
|
-
var rtLH = olPx * (ol.lh || ${OVERLAY_LINE_HEIGHT})
|
|
5624
|
-
var rtY0 = -((rtN - 1) * rtLH) / 2
|
|
5625
|
-
// A line's left edge: lines sit centred on the anchor and align
|
|
5626
|
-
// against the widest, as the plain layer's do.
|
|
5627
|
-
var rtLeft = function (lw) {
|
|
5628
|
-
var xo = ol.align === 'left' ? (lw - rtL.width) / 2 : ol.align === 'right' ? (rtL.width - lw) / 2 : 0
|
|
5629
|
-
return xo - lw / 2
|
|
5630
|
-
}
|
|
5631
|
-
if (ol.box) {
|
|
5632
|
-
var rbPX = ol.box.px * olMS * s
|
|
5633
|
-
var rbPY = ol.box.py * olMS * s
|
|
5634
|
-
var rbW = rtL.width + rbPX * 2
|
|
5635
|
-
var rbH = rtN * rtLH + rbPY * 2
|
|
5636
|
-
ovC.save()
|
|
5637
|
-
ovC.globalAlpha = olA * ol.box.o
|
|
5638
|
-
ovC.fillStyle = ol.box.c
|
|
5639
|
-
rr(-rbW / 2, -rbH / 2, rbW, rbH, Math.min(ol.box.r * olMS * s, rbH / 2), ovC)
|
|
5640
|
-
ovC.fill()
|
|
5641
|
-
ovC.restore()
|
|
5642
|
-
}
|
|
5643
|
-
// Highlights sit behind the words and take no legibility shadow. Under
|
|
5644
|
-
// a per-unit entrance each is drawn with its unit instead (below), so
|
|
5645
|
-
// it arrives with its word.
|
|
5646
|
-
for (var rhi = 0; !rtFx && rhi < rtN; rhi++) {
|
|
5647
|
-
var rhLine = rtL.lines[rhi]
|
|
5648
|
-
for (var rhj = 0; rhj < rhLine.frags.length; rhj++) {
|
|
5649
|
-
var rhF = rhLine.frags[rhj]
|
|
5650
|
-
if (!rhF.h) continue
|
|
5651
|
-
var rhR = TXL.decorationRect('h', rtLeft(rhLine.w) + rhF.x, rhF.w, rtY0 + rhi * rtLH, olPx)
|
|
5652
|
-
ovC.fillStyle = rhF.h
|
|
5653
|
-
ovC.fillRect(rhR.x, rhR.y, rhR.w, rhR.h)
|
|
5654
|
-
}
|
|
5655
|
-
}
|
|
5656
|
-
if (ol.shadow > 0) {
|
|
5657
|
-
ovC.shadowColor = 'rgba(0,0,0,' + ol.shadow + ')'
|
|
5658
|
-
ovC.shadowBlur = olPx * 0.25
|
|
5659
|
-
ovC.shadowOffsetY = olPx * 0.04
|
|
5660
|
-
}
|
|
5661
|
-
ovC.textAlign = 'left'
|
|
5662
|
-
// One fragment (or the part of one a unit holds): the underline under
|
|
5663
|
-
// the glyphs, stroke under fill, the strikethrough over them.
|
|
5664
|
-
var rtPart = function (p, bx, y, withH) {
|
|
5665
|
-
if (withH && p.h) {
|
|
5666
|
-
var rhU = TXL.decorationRect('h', bx + p.x, p.w, y, olPx)
|
|
5667
|
-
var rhS = ovC.shadowColor
|
|
5668
|
-
ovC.shadowColor = 'rgba(0,0,0,0)'
|
|
5669
|
-
ovC.fillStyle = p.h
|
|
5670
|
-
ovC.fillRect(rhU.x, rhU.y, rhU.w, rhU.h)
|
|
5671
|
-
ovC.shadowColor = rhS
|
|
5672
|
-
}
|
|
5673
|
-
ovC.font = rtFonts[p.f || 0]
|
|
5674
|
-
ovC.fillStyle = p.c || ol.color
|
|
5675
|
-
if (p.u) {
|
|
5676
|
-
var ru = TXL.decorationRect('u', bx + p.x, p.w, y, olPx)
|
|
5677
|
-
ovC.fillRect(ru.x, ru.y, ru.w, ru.h)
|
|
5678
|
-
}
|
|
5679
|
-
if (ol.stroke) {
|
|
5680
|
-
ovC.strokeStyle = ol.stroke.c
|
|
5681
|
-
ovC.lineWidth = ol.stroke.w * olMS * s
|
|
5682
|
-
ovC.lineJoin = 'round'
|
|
5683
|
-
ovC.strokeText(p.t, bx + p.x, y)
|
|
5684
|
-
}
|
|
5685
|
-
ovC.fillText(p.t, bx + p.x, y)
|
|
5686
|
-
if (p.s) {
|
|
5687
|
-
var rs = TXL.decorationRect('s', bx + p.x, p.w, y, olPx)
|
|
5688
|
-
ovC.fillRect(rs.x, rs.y, rs.w, rs.h)
|
|
5689
|
-
}
|
|
5690
|
-
}
|
|
5691
|
-
if (!rtFx) {
|
|
5692
|
-
for (var rli = 0; rli < rtN; rli++) {
|
|
5693
|
-
var rLine = rtL.lines[rli]
|
|
5694
|
-
var rBX = rtLeft(rLine.w)
|
|
5695
|
-
for (var rfk = 0; rfk < rLine.frags.length; rfk++) rtPart(rLine.frags[rfk], rBX, rtY0 + rli * rtLH)
|
|
5696
|
-
}
|
|
5697
|
-
} else {
|
|
5698
|
-
// Per-unit entrance, the plain layer's own arithmetic over the
|
|
5699
|
-
// layout's units: delay = order(index) x st, eased over dur.
|
|
5700
|
-
var rtCount = 0
|
|
5701
|
-
for (var rci = 0; rci < rtN; rci++) rtCount += rtL.lines[rci].units.length
|
|
5702
|
-
var rtIdx = 0
|
|
5703
|
-
for (var rui = 0; rui < rtN; rui++) {
|
|
5704
|
-
var rULine = rtL.lines[rui]
|
|
5705
|
-
var rUBX = rtLeft(rULine.w)
|
|
5706
|
-
var rUY = rtY0 + rui * rtLH
|
|
5707
|
-
for (var ruj = 0; ruj < rULine.units.length; ruj++, rtIdx++) {
|
|
5708
|
-
var rU = rULine.units[ruj]
|
|
5709
|
-
var rOrd = rtFx.d === 1 ? (rtCount - 1 - rtIdx) : rtFx.d === 2 ? Math.abs(rtIdx - (rtCount - 1) / 2) : rtIdx
|
|
5710
|
-
var rT2 = olT - rOrd * rtFx.st
|
|
5711
|
-
var rUA = 1, rUu = 1
|
|
5712
|
-
if (rtFx.k === 'typewriter') {
|
|
5713
|
-
rUA = rT2 >= 0 ? 1 : 0
|
|
5714
|
-
} else {
|
|
5715
|
-
rUu = Math.max(0, Math.min(1, rT2 / rtFx.dur))
|
|
5716
|
-
var rUE = 1 - Math.pow(1 - rUu, 3)
|
|
5717
|
-
rUA = rtFx.k === 'pop' ? Math.min(1, rUu * 2) : rUE
|
|
5718
|
-
}
|
|
5719
|
-
if (rUA <= 0.004) continue
|
|
5720
|
-
ovC.save()
|
|
5721
|
-
ovC.globalAlpha = olA * rUA
|
|
5722
|
-
if (rUu < 1) {
|
|
5723
|
-
if (rtFx.k === 'rise') {
|
|
5724
|
-
ovC.translate(0, (1 - (1 - Math.pow(1 - rUu, 3))) * 24 * s)
|
|
5725
|
-
} else if (rtFx.k === 'pop') {
|
|
5726
|
-
var rPS = 1 + 2.70158 * Math.pow(rUu - 1, 3) + 1.70158 * Math.pow(rUu - 1, 2)
|
|
5727
|
-
var rCX = rUBX + rU.x + rU.w / 2
|
|
5728
|
-
ovC.translate(rCX, rUY)
|
|
5729
|
-
ovC.scale(rPS, rPS)
|
|
5730
|
-
ovC.translate(-rCX, -rUY)
|
|
5731
|
-
} else if (rtFx.k === 'blur') {
|
|
5732
|
-
ovC.filter = 'blur(' + ((1 - rUu) * olPx * 0.12).toFixed(2) + 'px)'
|
|
5733
|
-
}
|
|
5734
|
-
}
|
|
5735
|
-
for (var rpk = 0; rpk < rU.parts.length; rpk++) rtPart(rU.parts[rpk], rUBX, rUY, true)
|
|
5736
|
-
ovC.restore()
|
|
5737
|
-
}
|
|
5738
|
-
}
|
|
5739
|
-
}
|
|
5740
|
-
ovC.restore()
|
|
5741
|
-
continue
|
|
5742
5626
|
}
|
|
5743
|
-
var
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
for (var olti = 0; olti < olToks.length; olti++) {
|
|
5761
|
-
if (!olCur) { olCur = olToks[olti]; continue }
|
|
5762
|
-
if (ovC.measureText(olCur + olToks[olti]).width <= olWMax) {
|
|
5763
|
-
olCur += olToks[olti]
|
|
5764
|
-
} else {
|
|
5765
|
-
olWrapped.push(olCur)
|
|
5766
|
-
olCur = olToks[olti]
|
|
5767
|
-
}
|
|
5768
|
-
}
|
|
5769
|
-
if (olCur) olWrapped.push(olCur)
|
|
5770
|
-
}
|
|
5771
|
-
olLines = olWrapped.length ? olWrapped : ['']
|
|
5772
|
-
}
|
|
5773
|
-
var olLH = olPx * (ol.lh || ${OVERLAY_LINE_HEIGHT})
|
|
5774
|
-
var olY0 = -((olLines.length - 1) * olLH) / 2
|
|
5775
|
-
// Per-line widths: needed by the pill, by left/right alignment (lines
|
|
5776
|
-
// draw centered; alignment is an x offset against the widest line), and
|
|
5777
|
-
// by per-unit fx (units place by prefix advance from the line's left edge).
|
|
5778
|
-
var olFx = ol.fx && ol.fx.units.length ? ol.fx : null
|
|
5779
|
-
// With wrap active, baked per-line unit arrays regroup onto the WRAPPED
|
|
5780
|
-
// lines. Wrapping never reorders: word/char units consume in flat order
|
|
5781
|
-
// by string length (wrapped lines are token concatenations); 'line'
|
|
5782
|
-
// units become one per wrapped line. Flat delay order is unchanged.
|
|
5783
|
-
if (olFx && ol.mw) {
|
|
5784
|
-
var olFlat = []
|
|
5785
|
-
for (var olfi = 0; olfi < olFx.units.length; olfi++) {
|
|
5786
|
-
for (var olfj = 0; olfj < olFx.units[olfi].length; olfj++) {
|
|
5787
|
-
olFlat.push(olFx.units[olfi][olfj])
|
|
5788
|
-
}
|
|
5789
|
-
}
|
|
5790
|
-
var olRe = []
|
|
5791
|
-
if (olFx.u === 'line') {
|
|
5792
|
-
for (var olri = 0; olri < olLines.length; olri++) olRe.push([olLines[olri]])
|
|
5793
|
-
} else {
|
|
5794
|
-
var olFk = 0
|
|
5795
|
-
for (var olri2 = 0; olri2 < olLines.length; olri2++) {
|
|
5796
|
-
var olNeed = olLines[olri2].length
|
|
5797
|
-
var olArr = []
|
|
5798
|
-
var olGot = 0
|
|
5799
|
-
while (olFk < olFlat.length && olGot < olNeed) {
|
|
5800
|
-
olArr.push(olFlat[olFk])
|
|
5801
|
-
olGot += olFlat[olFk].length
|
|
5802
|
-
olFk++
|
|
5803
|
-
}
|
|
5804
|
-
olRe.push(olArr)
|
|
5805
|
-
}
|
|
5806
|
-
}
|
|
5807
|
-
var olReN = 0
|
|
5808
|
-
for (var olrn = 0; olrn < olRe.length; olrn++) olReN += olRe[olrn].length
|
|
5809
|
-
olFx = { k: olFx.k, u: olFx.u, d: olFx.d, st: olFx.st, dur: olFx.dur, tt: olFx.tt, units: olRe, n: olReN }
|
|
5810
|
-
}
|
|
5811
|
-
var olLWs = null, olMaxW = 0
|
|
5812
|
-
if (ol.box || ol.align || olFx) {
|
|
5813
|
-
olLWs = []
|
|
5814
|
-
for (var olwi = 0; olwi < olLines.length; olwi++) {
|
|
5815
|
-
var olw = ovC.measureText(olLines[olwi]).width
|
|
5816
|
-
olLWs.push(olw)
|
|
5817
|
-
if (olw > olMaxW) olMaxW = olw
|
|
5627
|
+
var rtFx = ol.fx && ol.fx.u !== 'block' ? ol.fx : null
|
|
5628
|
+
var rtMax = ol.mw ? ol.mw * W : 0
|
|
5629
|
+
var rtKey = (ol.rt ? 'r' + ol.rt.h : 'p' + (ol.lines || ['']).join('\\n')) + '|' + rtFonts[0] + '|' + ((ol.ls || 0) * olMS * s) + '|' + rtMax + '|' + (rtFx ? rtFx.u : '') + '|' + (ns.fontEpoch || 0)
|
|
5630
|
+
var rtAll = ns.textLayouts || (ns.textLayouts = {})
|
|
5631
|
+
var rtHit = rtAll[ol.id]
|
|
5632
|
+
if (!rtHit || rtHit.k !== rtKey) {
|
|
5633
|
+
var rtIn = ol.rt ? ol.rt.l : []
|
|
5634
|
+
if (!ol.rt) {
|
|
5635
|
+
var rtPl = ol.lines || ['']
|
|
5636
|
+
for (var rpi = 0; rpi < rtPl.length; rpi++) rtIn.push(rtPl[rpi] ? [{ t: rtPl[rpi] }] : [])
|
|
5637
|
+
}
|
|
5638
|
+
rtHit = rtAll[ol.id] = {
|
|
5639
|
+
k: rtKey,
|
|
5640
|
+
L: TXL.layoutText(
|
|
5641
|
+
{ lines: rtIn, maxWidth: rtMax, unit: rtFx ? rtFx.u : undefined },
|
|
5642
|
+
function (mt, mf) { ovC.font = rtFonts[mf]; return ovC.measureText(mt).width }
|
|
5643
|
+
)
|
|
5818
5644
|
}
|
|
5645
|
+
ovC.font = rtFonts[0]
|
|
5646
|
+
}
|
|
5647
|
+
var rtL = rtHit.L
|
|
5648
|
+
var rtN = rtL.lines.length
|
|
5649
|
+
var rtLH = olPx * (ol.lh || ${OVERLAY_LINE_HEIGHT})
|
|
5650
|
+
var rtY0 = -((rtN - 1) * rtLH) / 2
|
|
5651
|
+
// A line's left edge: lines sit centred on the anchor and align
|
|
5652
|
+
// against the widest.
|
|
5653
|
+
var rtLeft = function (lw) {
|
|
5654
|
+
var xo = ol.align === 'left' ? (lw - rtL.width) / 2 : ol.align === 'right' ? (rtL.width - lw) / 2 : 0
|
|
5655
|
+
return xo - lw / 2
|
|
5819
5656
|
}
|
|
5820
|
-
// Background pill (ol.box, baked design px at fs): drawn BEFORE the text
|
|
5821
|
-
// and before the legibility shadow config, so the pill never inherits the
|
|
5822
|
-
// text shadow. Geometry mirrors overlayRect's inflation \u2014 change together.
|
|
5823
5657
|
if (ol.box) {
|
|
5824
|
-
var
|
|
5825
|
-
var
|
|
5826
|
-
var
|
|
5827
|
-
var
|
|
5828
|
-
var obR = Math.min(ol.box.r * olMS * s, obFullH / 2)
|
|
5658
|
+
var rbPX = ol.box.px * olMS * s
|
|
5659
|
+
var rbPY = ol.box.py * olMS * s
|
|
5660
|
+
var rbW = rtL.width + rbPX * 2
|
|
5661
|
+
var rbH = rtN * rtLH + rbPY * 2
|
|
5829
5662
|
ovC.save()
|
|
5830
5663
|
ovC.globalAlpha = olA * ol.box.o
|
|
5831
5664
|
ovC.fillStyle = ol.box.c
|
|
5832
|
-
rr(-
|
|
5665
|
+
rr(-rbW / 2, -rbH / 2, rbW, rbH, Math.min(ol.box.r * olMS * s, rbH / 2), ovC)
|
|
5833
5666
|
ovC.fill()
|
|
5834
5667
|
ovC.restore()
|
|
5835
5668
|
}
|
|
5669
|
+
// Highlights sit behind the words and take no legibility shadow. Under
|
|
5670
|
+
// a per-unit entrance each is drawn with its unit instead (below), so
|
|
5671
|
+
// it arrives with its word.
|
|
5672
|
+
for (var rhi = 0; !rtFx && rhi < rtN; rhi++) {
|
|
5673
|
+
var rhLine = rtL.lines[rhi]
|
|
5674
|
+
for (var rhj = 0; rhj < rhLine.frags.length; rhj++) {
|
|
5675
|
+
var rhF = rhLine.frags[rhj]
|
|
5676
|
+
if (!rhF.h) continue
|
|
5677
|
+
var rhR = TXL.decorationRect('h', rtLeft(rhLine.w) + rhF.x, rhF.w, rtY0 + rhi * rtLH, olPx)
|
|
5678
|
+
ovC.fillStyle = rhF.h
|
|
5679
|
+
ovC.fillRect(rhR.x, rhR.y, rhR.w, rhR.h)
|
|
5680
|
+
}
|
|
5681
|
+
}
|
|
5836
5682
|
if (ol.shadow > 0) {
|
|
5837
5683
|
ovC.shadowColor = 'rgba(0,0,0,' + ol.shadow + ')'
|
|
5838
5684
|
ovC.shadowBlur = olPx * 0.25
|
|
5839
5685
|
ovC.shadowOffsetY = olPx * 0.04
|
|
5840
5686
|
}
|
|
5841
|
-
ovC.
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
ovC.
|
|
5687
|
+
ovC.textAlign = 'left'
|
|
5688
|
+
// One fragment (or the part of one a unit holds): the underline under
|
|
5689
|
+
// the glyphs, stroke under fill, the strikethrough over them.
|
|
5690
|
+
var rtPart = function (p, bx, y, withH) {
|
|
5691
|
+
if (withH && p.h) {
|
|
5692
|
+
var rhU = TXL.decorationRect('h', bx + p.x, p.w, y, olPx)
|
|
5693
|
+
var rhS = ovC.shadowColor
|
|
5694
|
+
ovC.shadowColor = 'rgba(0,0,0,0)'
|
|
5695
|
+
ovC.fillStyle = p.h
|
|
5696
|
+
ovC.fillRect(rhU.x, rhU.y, rhU.w, rhU.h)
|
|
5697
|
+
ovC.shadowColor = rhS
|
|
5698
|
+
}
|
|
5699
|
+
ovC.font = rtFonts[p.f || 0]
|
|
5700
|
+
ovC.fillStyle = p.c || ol.color
|
|
5701
|
+
if (p.u) {
|
|
5702
|
+
var ru = TXL.decorationRect('u', bx + p.x, p.w, y, olPx)
|
|
5703
|
+
ovC.fillRect(ru.x, ru.y, ru.w, ru.h)
|
|
5704
|
+
}
|
|
5705
|
+
if (ol.stroke) {
|
|
5706
|
+
ovC.strokeStyle = ol.stroke.c
|
|
5707
|
+
ovC.lineWidth = ol.stroke.w * olMS * s
|
|
5708
|
+
ovC.lineJoin = 'round'
|
|
5709
|
+
ovC.strokeText(p.t, bx + p.x, y)
|
|
5710
|
+
}
|
|
5711
|
+
ovC.fillText(p.t, bx + p.x, y)
|
|
5712
|
+
if (p.s) {
|
|
5713
|
+
var rs = TXL.decorationRect('s', bx + p.x, p.w, y, olPx)
|
|
5714
|
+
ovC.fillRect(rs.x, rs.y, rs.w, rs.h)
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5717
|
+
if (!rtFx) {
|
|
5718
|
+
for (var rli = 0; rli < rtN; rli++) {
|
|
5719
|
+
var rLine = rtL.lines[rli]
|
|
5720
|
+
var rBX = rtLeft(rLine.w)
|
|
5721
|
+
for (var rfk = 0; rfk < rLine.frags.length; rfk++) rtPart(rLine.frags[rfk], rBX, rtY0 + rli * rtLH)
|
|
5858
5722
|
}
|
|
5859
5723
|
} else {
|
|
5860
|
-
// Per-unit entrance
|
|
5861
|
-
//
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
var
|
|
5869
|
-
var
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
}
|
|
5877
|
-
var olXb = olXof2 - olLW2 / 2
|
|
5878
|
-
var olPref = '', olPW = 0
|
|
5879
|
-
for (var ou = 0; ou < olUs.length; ou++, olIdx++) {
|
|
5880
|
-
var olOrd = olFx.d === 1
|
|
5881
|
-
? (olFx.n - 1 - olIdx)
|
|
5882
|
-
: olFx.d === 2
|
|
5883
|
-
? Math.abs(olIdx - (olFx.n - 1) / 2)
|
|
5884
|
-
: olIdx
|
|
5885
|
-
var olT2 = olT - olOrd * olFx.st
|
|
5886
|
-
var olNext = olPref + olUs[ou]
|
|
5887
|
-
var olNW = ovC.measureText(olNext).width
|
|
5888
|
-
var olUW = olNW - olPW
|
|
5889
|
-
var olUX = olXb + olPW
|
|
5890
|
-
var olUA = 1, olUu = 1
|
|
5891
|
-
if (olFx.k === 'typewriter') {
|
|
5892
|
-
olUA = olT2 >= 0 ? 1 : 0
|
|
5724
|
+
// Per-unit entrance, the plain layer's own arithmetic over the
|
|
5725
|
+
// layout's units: delay = order(index) x st, eased over dur.
|
|
5726
|
+
var rtCount = 0
|
|
5727
|
+
for (var rci = 0; rci < rtN; rci++) rtCount += rtL.lines[rci].units.length
|
|
5728
|
+
var rtIdx = 0
|
|
5729
|
+
for (var rui = 0; rui < rtN; rui++) {
|
|
5730
|
+
var rULine = rtL.lines[rui]
|
|
5731
|
+
var rUBX = rtLeft(rULine.w)
|
|
5732
|
+
var rUY = rtY0 + rui * rtLH
|
|
5733
|
+
for (var ruj = 0; ruj < rULine.units.length; ruj++, rtIdx++) {
|
|
5734
|
+
var rU = rULine.units[ruj]
|
|
5735
|
+
var rOrd = rtFx.d === 1 ? (rtCount - 1 - rtIdx) : rtFx.d === 2 ? Math.abs(rtIdx - (rtCount - 1) / 2) : rtIdx
|
|
5736
|
+
var rT2 = olT - rOrd * rtFx.st
|
|
5737
|
+
var rUA = 1, rUu = 1
|
|
5738
|
+
if (rtFx.k === 'typewriter') {
|
|
5739
|
+
rUA = rT2 >= 0 ? 1 : 0
|
|
5893
5740
|
} else {
|
|
5894
|
-
|
|
5895
|
-
var
|
|
5896
|
-
|
|
5741
|
+
rUu = Math.max(0, Math.min(1, rT2 / rtFx.dur))
|
|
5742
|
+
var rUE = 1 - Math.pow(1 - rUu, 3)
|
|
5743
|
+
rUA = rtFx.k === 'pop' ? Math.min(1, rUu * 2) : rUE
|
|
5897
5744
|
}
|
|
5898
|
-
|
|
5899
|
-
olPref = olNext
|
|
5900
|
-
olPW = olNW
|
|
5901
|
-
if (olUA <= 0.004) continue
|
|
5745
|
+
if (rUA <= 0.004) continue
|
|
5902
5746
|
ovC.save()
|
|
5903
|
-
ovC.globalAlpha = olA *
|
|
5904
|
-
if (
|
|
5905
|
-
if (
|
|
5906
|
-
ovC.translate(0, (1 - (1 - Math.pow(1 -
|
|
5907
|
-
} else if (
|
|
5908
|
-
var
|
|
5909
|
-
|
|
5910
|
-
ovC.
|
|
5911
|
-
ovC.
|
|
5912
|
-
|
|
5913
|
-
|
|
5747
|
+
ovC.globalAlpha = olA * rUA
|
|
5748
|
+
if (rUu < 1) {
|
|
5749
|
+
if (rtFx.k === 'rise') {
|
|
5750
|
+
ovC.translate(0, (1 - (1 - Math.pow(1 - rUu, 3))) * 24 * s)
|
|
5751
|
+
} else if (rtFx.k === 'pop') {
|
|
5752
|
+
var rPS = 1 + 2.70158 * Math.pow(rUu - 1, 3) + 1.70158 * Math.pow(rUu - 1, 2)
|
|
5753
|
+
var rCX = rUBX + rU.x + rU.w / 2
|
|
5754
|
+
ovC.translate(rCX, rUY)
|
|
5755
|
+
ovC.scale(rPS, rPS)
|
|
5756
|
+
ovC.translate(-rCX, -rUY)
|
|
5757
|
+
} else if (rtFx.k === 'blur') {
|
|
5758
|
+
ovC.filter = 'blur(' + ((1 - rUu) * olPx * 0.12).toFixed(2) + 'px)'
|
|
5914
5759
|
}
|
|
5915
5760
|
}
|
|
5916
|
-
|
|
5917
|
-
ovC.strokeStyle = ol.stroke.c
|
|
5918
|
-
ovC.lineWidth = ol.stroke.w * olMS * s
|
|
5919
|
-
ovC.lineJoin = 'round'
|
|
5920
|
-
ovC.strokeText(olUnit, olUX, olLY2)
|
|
5921
|
-
}
|
|
5922
|
-
ovC.fillText(olUnit, olUX, olLY2)
|
|
5761
|
+
for (var rpk = 0; rpk < rU.parts.length; rpk++) rtPart(rU.parts[rpk], rUBX, rUY, true)
|
|
5923
5762
|
ovC.restore()
|
|
5924
5763
|
}
|
|
5925
5764
|
}
|
|
@@ -8885,11 +8724,12 @@ function studioLayerData(input, duration, pins) {
|
|
|
8885
8724
|
return {
|
|
8886
8725
|
...base,
|
|
8887
8726
|
text: overlayPlainText(o),
|
|
8888
|
-
// The lines a person reads
|
|
8727
|
+
// The lines a person reads: what a plain layer is laid out
|
|
8728
|
+
// from, one run a line. A styled layer (rt) is laid out from
|
|
8889
8729
|
// its runs; these are then its words, for the signature.
|
|
8890
8730
|
lines: overlayLines(overlayPlainText(o)),
|
|
8891
8731
|
// The styled payload, only when the layer is set in more than
|
|
8892
|
-
// one style
|
|
8732
|
+
// one style.
|
|
8893
8733
|
...rt ? { rt } : {},
|
|
8894
8734
|
fs: st.size,
|
|
8895
8735
|
weight: st.weight,
|
|
@@ -8922,9 +8762,10 @@ function studioLayerData(input, duration, pins) {
|
|
|
8922
8762
|
r: round8(bx.radius)
|
|
8923
8763
|
}
|
|
8924
8764
|
} : {},
|
|
8925
|
-
// Entrance animation:
|
|
8926
|
-
//
|
|
8927
|
-
// per-unit progress as pure f(t). Absent = data
|
|
8765
|
+
// Entrance animation: timing normalized HERE (deterministic
|
|
8766
|
+
// doc-derived data) — ON_FRAME cuts the units from the layout
|
|
8767
|
+
// and interprets per-unit progress as pure f(t). Absent = data
|
|
8768
|
+
// byte parity.
|
|
8928
8769
|
...(() => {
|
|
8929
8770
|
const olFx = resolveOverlayFx(
|
|
8930
8771
|
o,
|
|
@@ -11023,68 +10864,6 @@ function applyLook(frame, look, size, video, placement) {
|
|
|
11023
10864
|
return out;
|
|
11024
10865
|
}
|
|
11025
10866
|
|
|
11026
|
-
// src/richText/caret.ts
|
|
11027
|
-
function caretStops(line, measure) {
|
|
11028
|
-
const stops = [{ o: line.a, x: 0 }];
|
|
11029
|
-
for (const fr of line.frags) {
|
|
11030
|
-
let at = 0;
|
|
11031
|
-
for (const g of graphemesOf(fr.t)) {
|
|
11032
|
-
at += g.length;
|
|
11033
|
-
stops.push({
|
|
11034
|
-
o: line.a + fr.o + at,
|
|
11035
|
-
x: fr.x + measure(fr.t.slice(0, at), fr.f || 0)
|
|
11036
|
-
});
|
|
11037
|
-
}
|
|
11038
|
-
}
|
|
11039
|
-
return stops;
|
|
11040
|
-
}
|
|
11041
|
-
function lineOfOffset(layout, offset) {
|
|
11042
|
-
const lines = layout.lines;
|
|
11043
|
-
for (let i = lines.length - 1; i >= 0; i--) {
|
|
11044
|
-
if (offset >= lines[i].a) return i;
|
|
11045
|
-
}
|
|
11046
|
-
return 0;
|
|
11047
|
-
}
|
|
11048
|
-
function caretAt(layout, offset, measure) {
|
|
11049
|
-
const li = lineOfOffset(layout, offset);
|
|
11050
|
-
const stops = caretStops(layout.lines[li], measure);
|
|
11051
|
-
let x = stops[stops.length - 1].x;
|
|
11052
|
-
for (const s of stops) {
|
|
11053
|
-
if (s.o >= offset) {
|
|
11054
|
-
x = s.x;
|
|
11055
|
-
break;
|
|
11056
|
-
}
|
|
11057
|
-
}
|
|
11058
|
-
return { line: li, x };
|
|
11059
|
-
}
|
|
11060
|
-
function offsetAtX(line, x, measure) {
|
|
11061
|
-
const stops = caretStops(line, measure);
|
|
11062
|
-
let best = stops[0];
|
|
11063
|
-
for (const s of stops) {
|
|
11064
|
-
if (Math.abs(s.x - x) < Math.abs(best.x - x)) best = s;
|
|
11065
|
-
}
|
|
11066
|
-
return best.o;
|
|
11067
|
-
}
|
|
11068
|
-
function rangeRects(layout, start, end, measure, breakTail = 0) {
|
|
11069
|
-
const out = [];
|
|
11070
|
-
if (end <= start) return out;
|
|
11071
|
-
layout.lines.forEach((line, i) => {
|
|
11072
|
-
const lineEnd = line.a + line.n;
|
|
11073
|
-
if (end <= line.a || start > lineEnd) return;
|
|
11074
|
-
const stops = caretStops(line, measure);
|
|
11075
|
-
const xOf = (o) => {
|
|
11076
|
-
for (const s of stops) if (s.o >= o) return s.x;
|
|
11077
|
-
return stops[stops.length - 1].x;
|
|
11078
|
-
};
|
|
11079
|
-
const x0 = xOf(Math.max(start, line.a));
|
|
11080
|
-
const x1 = xOf(Math.min(end, lineEnd));
|
|
11081
|
-
const next = layout.lines[i + 1];
|
|
11082
|
-
const tail = next && next.a > lineEnd && end > lineEnd ? breakTail : 0;
|
|
11083
|
-
if (x1 + tail > x0) out.push({ line: i, x: x0, w: x1 - x0 + tail });
|
|
11084
|
-
});
|
|
11085
|
-
return out;
|
|
11086
|
-
}
|
|
11087
|
-
|
|
11088
10867
|
// src/timeline/lanes.ts
|
|
11089
10868
|
import {
|
|
11090
10869
|
mapTime as mapTime3,
|
|
@@ -12835,6 +12614,7 @@ export {
|
|
|
12835
12614
|
styleAt,
|
|
12836
12615
|
styleOf,
|
|
12837
12616
|
styledTextOf,
|
|
12617
|
+
textRunsOf,
|
|
12838
12618
|
tiltLane,
|
|
12839
12619
|
tiltTrackFromDoc,
|
|
12840
12620
|
toggleStyle,
|