@shotstack/shotstack-canvas 2.0.13 → 2.0.14
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/entry.node.cjs +216 -33
- package/dist/entry.node.d.cts +11 -1
- package/dist/entry.node.d.ts +11 -1
- package/dist/entry.node.js +210 -33
- package/dist/entry.web.d.ts +11 -1
- package/dist/entry.web.js +978 -33
- package/package.json +66 -65
package/dist/entry.node.cjs
CHANGED
|
@@ -371,6 +371,7 @@ __export(entry_node_exports, {
|
|
|
371
371
|
calculateAnimationStatesForGroup: () => calculateAnimationStatesForGroup,
|
|
372
372
|
commandsToPathString: () => commandsToPathString,
|
|
373
373
|
computeSimplePathBounds: () => computeSimplePathBounds,
|
|
374
|
+
containsRTLCharacters: () => containsRTLCharacters,
|
|
374
375
|
createDefaultGeneratorConfig: () => createDefaultGeneratorConfig,
|
|
375
376
|
createFrameSchedule: () => createFrameSchedule,
|
|
376
377
|
createNodePainter: () => createNodePainter,
|
|
@@ -378,6 +379,8 @@ __export(entry_node_exports, {
|
|
|
378
379
|
createRichCaptionRenderer: () => createRichCaptionRenderer,
|
|
379
380
|
createTextEngine: () => createTextEngine,
|
|
380
381
|
createVideoEncoder: () => createVideoEncoder,
|
|
382
|
+
detectParagraphDirection: () => detectParagraphDirection,
|
|
383
|
+
detectParagraphDirectionFromWords: () => detectParagraphDirectionFromWords,
|
|
381
384
|
detectPlatform: () => detectPlatform,
|
|
382
385
|
detectSubtitleFormat: () => detectSubtitleFormat,
|
|
383
386
|
extractCaptionPadding: () => extractCaptionPadding,
|
|
@@ -389,10 +392,12 @@ __export(entry_node_exports, {
|
|
|
389
392
|
getDrawCaptionWordOps: () => getDrawCaptionWordOps,
|
|
390
393
|
getEncoderCapabilities: () => getEncoderCapabilities,
|
|
391
394
|
getEncoderWarning: () => getEncoderWarning,
|
|
395
|
+
getVisibleText: () => getVisibleText,
|
|
392
396
|
groupWordsByPause: () => groupWordsByPause,
|
|
393
397
|
isDrawCaptionWordOp: () => isDrawCaptionWordOp,
|
|
394
398
|
isRTLText: () => isRTLText,
|
|
395
399
|
isWebCodecsH264Supported: () => isWebCodecsH264Supported,
|
|
400
|
+
mirrorAnimationDirection: () => mirrorAnimationDirection,
|
|
396
401
|
normalizePath: () => normalizePath,
|
|
397
402
|
normalizePathString: () => normalizePathString,
|
|
398
403
|
parseSubtitleToWords: () => parseSubtitleToWords,
|
|
@@ -400,6 +405,7 @@ __export(entry_node_exports, {
|
|
|
400
405
|
quadraticToCubic: () => quadraticToCubic,
|
|
401
406
|
renderSvgAssetToPng: () => renderSvgAssetToPng,
|
|
402
407
|
renderSvgToPng: () => renderSvgToPng,
|
|
408
|
+
reorderWordsForLine: () => reorderWordsForLine,
|
|
403
409
|
richCaptionAssetSchema: () => richCaptionAssetSchema,
|
|
404
410
|
shapeToSvgString: () => shapeToSvgString,
|
|
405
411
|
svgAssetSchema: () => import_zod2.svgAssetSchema,
|
|
@@ -1280,6 +1286,96 @@ var FontRegistry = class _FontRegistry {
|
|
|
1280
1286
|
}
|
|
1281
1287
|
};
|
|
1282
1288
|
|
|
1289
|
+
// src/core/bidi.ts
|
|
1290
|
+
var import_bidi_js = __toESM(require("bidi-js"), 1);
|
|
1291
|
+
var bidiInstance = null;
|
|
1292
|
+
function getBidi() {
|
|
1293
|
+
if (!bidiInstance) {
|
|
1294
|
+
bidiInstance = (0, import_bidi_js.default)();
|
|
1295
|
+
}
|
|
1296
|
+
return bidiInstance;
|
|
1297
|
+
}
|
|
1298
|
+
var RTL_SCRIPT_REGEX = /[--ۿ܀-ݏݐ-ݿހ-߀-߿ࠀ-ࡀ-ࡠ-ࢠ-ࣿיִ-ﭏﭐ-﷿ﹰ-𐴀-𐹠-𞠀-𞤀-𞥟--𞸀-]/u;
|
|
1299
|
+
function containsRTLCharacters(text) {
|
|
1300
|
+
return RTL_SCRIPT_REGEX.test(text);
|
|
1301
|
+
}
|
|
1302
|
+
function detectParagraphDirection(text) {
|
|
1303
|
+
const bidi = getBidi();
|
|
1304
|
+
const { paragraphs } = bidi.getEmbeddingLevels(text);
|
|
1305
|
+
if (paragraphs.length === 0) {
|
|
1306
|
+
return "ltr";
|
|
1307
|
+
}
|
|
1308
|
+
return paragraphs[0].level % 2 === 1 ? "rtl" : "ltr";
|
|
1309
|
+
}
|
|
1310
|
+
function detectParagraphDirectionFromWords(words) {
|
|
1311
|
+
const combined = words.join(" ");
|
|
1312
|
+
return detectParagraphDirection(combined);
|
|
1313
|
+
}
|
|
1314
|
+
function reorderWordsForLine(wordTexts, paragraphDirection) {
|
|
1315
|
+
if (wordTexts.length <= 1) {
|
|
1316
|
+
return wordTexts.map((_, i) => i);
|
|
1317
|
+
}
|
|
1318
|
+
const lineText = wordTexts.join(" ");
|
|
1319
|
+
const bidi = getBidi();
|
|
1320
|
+
const { levels } = bidi.getEmbeddingLevels(lineText, paragraphDirection);
|
|
1321
|
+
const wordLevels = [];
|
|
1322
|
+
let charIndex = 0;
|
|
1323
|
+
for (let i = 0; i < wordTexts.length; i++) {
|
|
1324
|
+
const wordLevel = levels[charIndex];
|
|
1325
|
+
wordLevels.push(wordLevel);
|
|
1326
|
+
charIndex += wordTexts[i].length;
|
|
1327
|
+
if (i < wordTexts.length - 1) {
|
|
1328
|
+
charIndex += 1;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
const indices = wordTexts.map((_, i) => i);
|
|
1332
|
+
const maxLevel = Math.max(...wordLevels);
|
|
1333
|
+
const minOddLevel = paragraphDirection === "rtl" ? 1 : Math.min(...wordLevels.filter((l) => l % 2 === 1), maxLevel + 1);
|
|
1334
|
+
for (let level = maxLevel; level >= minOddLevel; level--) {
|
|
1335
|
+
let start = 0;
|
|
1336
|
+
while (start < indices.length) {
|
|
1337
|
+
if (wordLevels[indices[start]] >= level) {
|
|
1338
|
+
let end = start;
|
|
1339
|
+
while (end + 1 < indices.length && wordLevels[indices[end + 1]] >= level) {
|
|
1340
|
+
end++;
|
|
1341
|
+
}
|
|
1342
|
+
if (start < end) {
|
|
1343
|
+
let left = start;
|
|
1344
|
+
let right = end;
|
|
1345
|
+
while (left < right) {
|
|
1346
|
+
const tmp = indices[left];
|
|
1347
|
+
indices[left] = indices[right];
|
|
1348
|
+
indices[right] = tmp;
|
|
1349
|
+
left++;
|
|
1350
|
+
right--;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
start = end + 1;
|
|
1354
|
+
} else {
|
|
1355
|
+
start++;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
return indices;
|
|
1360
|
+
}
|
|
1361
|
+
function getVisibleText(text, visibleCharacters, isRTL) {
|
|
1362
|
+
if (visibleCharacters < 0 || visibleCharacters >= text.length) {
|
|
1363
|
+
return text;
|
|
1364
|
+
}
|
|
1365
|
+
if (visibleCharacters === 0) {
|
|
1366
|
+
return "";
|
|
1367
|
+
}
|
|
1368
|
+
return text.slice(0, visibleCharacters);
|
|
1369
|
+
}
|
|
1370
|
+
function mirrorAnimationDirection(direction, isRTL) {
|
|
1371
|
+
if (!isRTL) {
|
|
1372
|
+
return direction;
|
|
1373
|
+
}
|
|
1374
|
+
if (direction === "left") return "right";
|
|
1375
|
+
if (direction === "right") return "left";
|
|
1376
|
+
return direction;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1283
1379
|
// src/core/layout.ts
|
|
1284
1380
|
function isEmoji(char) {
|
|
1285
1381
|
const code = char.codePointAt(0);
|
|
@@ -1309,7 +1405,7 @@ var LayoutEngine = class {
|
|
|
1309
1405
|
return t;
|
|
1310
1406
|
}
|
|
1311
1407
|
}
|
|
1312
|
-
async shapeFull(text, desc) {
|
|
1408
|
+
async shapeFull(text, desc, direction) {
|
|
1313
1409
|
try {
|
|
1314
1410
|
const hb = await this.fonts.getHB();
|
|
1315
1411
|
const buffer = hb.createBuffer();
|
|
@@ -1348,7 +1444,8 @@ var LayoutEngine = class {
|
|
|
1348
1444
|
let shaped;
|
|
1349
1445
|
try {
|
|
1350
1446
|
if (!emojiFallback) {
|
|
1351
|
-
|
|
1447
|
+
const textDirection = containsRTLCharacters(input) ? "rtl" : void 0;
|
|
1448
|
+
shaped = await this.shapeFull(input, desc, textDirection);
|
|
1352
1449
|
} else {
|
|
1353
1450
|
const chars = Array.from(input);
|
|
1354
1451
|
const runs = [];
|
|
@@ -1369,7 +1466,8 @@ var LayoutEngine = class {
|
|
|
1369
1466
|
shaped = [];
|
|
1370
1467
|
for (const run of runs) {
|
|
1371
1468
|
const runFont = run.isEmoji ? emojiFallback : desc;
|
|
1372
|
-
const
|
|
1469
|
+
const runDirection = containsRTLCharacters(run.text) ? "rtl" : void 0;
|
|
1470
|
+
const runShaped = await this.shapeFull(run.text, runFont, runDirection);
|
|
1373
1471
|
for (const glyph of runShaped) {
|
|
1374
1472
|
glyph.cl += run.startIndex;
|
|
1375
1473
|
glyph.fontDesc = runFont;
|
|
@@ -1470,9 +1568,11 @@ var LayoutEngine = class {
|
|
|
1470
1568
|
y: 0
|
|
1471
1569
|
});
|
|
1472
1570
|
}
|
|
1571
|
+
const textIsRTL = containsRTLCharacters(input);
|
|
1473
1572
|
const lineHeight = params.lineHeight * fontSize;
|
|
1474
1573
|
for (let i = 0; i < lines.length; i++) {
|
|
1475
1574
|
lines[i].y = (i + 1) * lineHeight;
|
|
1575
|
+
lines[i].isRTL = textIsRTL;
|
|
1476
1576
|
}
|
|
1477
1577
|
return lines;
|
|
1478
1578
|
} catch (err) {
|
|
@@ -1511,6 +1611,14 @@ function normalizePadding(padding) {
|
|
|
1511
1611
|
}
|
|
1512
1612
|
return padding;
|
|
1513
1613
|
}
|
|
1614
|
+
function resolveHorizontalAlign(align, isRTL) {
|
|
1615
|
+
if (!isRTL || align === "center") {
|
|
1616
|
+
return align;
|
|
1617
|
+
}
|
|
1618
|
+
if (align === "left") return "right";
|
|
1619
|
+
if (align === "right") return "left";
|
|
1620
|
+
return align;
|
|
1621
|
+
}
|
|
1514
1622
|
async function buildDrawOps(p) {
|
|
1515
1623
|
const ops = [];
|
|
1516
1624
|
const padding = normalizePadding(p.padding);
|
|
@@ -1551,7 +1659,8 @@ async function buildDrawOps(p) {
|
|
|
1551
1659
|
let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;
|
|
1552
1660
|
for (const line of p.lines) {
|
|
1553
1661
|
let lineX;
|
|
1554
|
-
|
|
1662
|
+
const effectiveAlign = resolveHorizontalAlign(p.align.horizontal, line.isRTL);
|
|
1663
|
+
switch (effectiveAlign) {
|
|
1555
1664
|
case "left":
|
|
1556
1665
|
lineX = 0;
|
|
1557
1666
|
break;
|
|
@@ -1679,7 +1788,7 @@ async function buildDrawOps(p) {
|
|
|
1679
1788
|
const contentWidth = p.contentRect?.width ?? p.canvas.width;
|
|
1680
1789
|
const contentHeight = p.contentRect?.height ?? p.canvas.height;
|
|
1681
1790
|
const borderWidth2 = p.border?.width ?? 0;
|
|
1682
|
-
const borderRadius = p.border?.radius ?? 0;
|
|
1791
|
+
const borderRadius = p.border?.radius ?? p.background?.borderRadius ?? 0;
|
|
1683
1792
|
const halfBorder = borderWidth2 / 2;
|
|
1684
1793
|
const canvasCenterX = p.canvas.width / 2;
|
|
1685
1794
|
const canvasCenterY = p.canvas.height / 2;
|
|
@@ -1797,7 +1906,15 @@ function applyAnimation(ops, lines, p) {
|
|
|
1797
1906
|
case "fadeIn":
|
|
1798
1907
|
return applyFadeInAnimation(ops, lines, progress, p.anim.style, p.fontSize, duration);
|
|
1799
1908
|
case "slideIn":
|
|
1800
|
-
return applySlideInAnimation(
|
|
1909
|
+
return applySlideInAnimation(
|
|
1910
|
+
ops,
|
|
1911
|
+
lines,
|
|
1912
|
+
progress,
|
|
1913
|
+
p.anim.direction ?? "left",
|
|
1914
|
+
p.fontSize,
|
|
1915
|
+
p.anim.style,
|
|
1916
|
+
duration
|
|
1917
|
+
);
|
|
1801
1918
|
case "shift":
|
|
1802
1919
|
return applyShiftAnimation(
|
|
1803
1920
|
ops,
|
|
@@ -1825,6 +1942,9 @@ function applyAnimation(ops, lines, p) {
|
|
|
1825
1942
|
}
|
|
1826
1943
|
var isShadowFill = (op) => op.op === "FillPath" && op.isShadow === true;
|
|
1827
1944
|
var isGlyphFill = (op) => op.op === "FillPath" && !op.isShadow === true;
|
|
1945
|
+
function isRTLLines(lines) {
|
|
1946
|
+
return lines.length > 0 && lines[0].isRTL === true;
|
|
1947
|
+
}
|
|
1828
1948
|
function getTextColorFromOps(ops) {
|
|
1829
1949
|
for (const op of ops) {
|
|
1830
1950
|
if (op.op === "FillPath") {
|
|
@@ -1844,28 +1964,32 @@ function applyTypewriterAnimation(ops, lines, progress, style, fontSize, time, d
|
|
|
1844
1964
|
const totalWords = wordSegments.length;
|
|
1845
1965
|
const visibleWords = Math.floor(progress * totalWords);
|
|
1846
1966
|
if (visibleWords === 0) {
|
|
1847
|
-
return ops.filter(
|
|
1967
|
+
return ops.filter(
|
|
1968
|
+
(x) => x.op === "BeginFrame" || x.op === "Rectangle" || x.op === "RectangleStroke"
|
|
1969
|
+
);
|
|
1848
1970
|
}
|
|
1849
1971
|
let totalVisibleGlyphs = 0;
|
|
1850
1972
|
for (let i = 0; i < Math.min(visibleWords, wordSegments.length); i++) {
|
|
1851
1973
|
totalVisibleGlyphs += wordSegments[i].glyphCount;
|
|
1852
1974
|
}
|
|
1853
|
-
const visibleOpsRaw = sliceGlyphOps(ops, totalVisibleGlyphs);
|
|
1975
|
+
const visibleOpsRaw = isRTLLines(lines) ? sliceGlyphOpsFromEnd(ops, totalVisibleGlyphs) : sliceGlyphOps(ops, totalVisibleGlyphs);
|
|
1854
1976
|
const visibleOps = progress >= DECORATION_DONE_THRESHOLD ? visibleOpsRaw : visibleOpsRaw.filter((o) => o.op !== "DecorationLine");
|
|
1855
1977
|
if (progress < 1 && totalVisibleGlyphs > 0) {
|
|
1856
|
-
return addTypewriterCursor(visibleOps, totalVisibleGlyphs, fontSize, time);
|
|
1978
|
+
return addTypewriterCursor(visibleOps, totalVisibleGlyphs, fontSize, time, isRTLLines(lines));
|
|
1857
1979
|
}
|
|
1858
1980
|
return visibleOps;
|
|
1859
1981
|
} else {
|
|
1860
1982
|
const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);
|
|
1861
1983
|
const visibleGlyphs = Math.floor(progress * totalGlyphs);
|
|
1862
1984
|
if (visibleGlyphs === 0) {
|
|
1863
|
-
return ops.filter(
|
|
1985
|
+
return ops.filter(
|
|
1986
|
+
(x) => x.op === "BeginFrame" || x.op === "Rectangle" || x.op === "RectangleStroke"
|
|
1987
|
+
);
|
|
1864
1988
|
}
|
|
1865
|
-
const visibleOpsRaw = sliceGlyphOps(ops, visibleGlyphs);
|
|
1989
|
+
const visibleOpsRaw = isRTLLines(lines) ? sliceGlyphOpsFromEnd(ops, visibleGlyphs) : sliceGlyphOps(ops, visibleGlyphs);
|
|
1866
1990
|
const visibleOps = progress >= DECORATION_DONE_THRESHOLD ? visibleOpsRaw : visibleOpsRaw.filter((o) => o.op !== "DecorationLine");
|
|
1867
1991
|
if (progress < 1 && visibleGlyphs > 0) {
|
|
1868
|
-
return addTypewriterCursor(visibleOps, visibleGlyphs, fontSize, time);
|
|
1992
|
+
return addTypewriterCursor(visibleOps, visibleGlyphs, fontSize, time, isRTLLines(lines));
|
|
1869
1993
|
}
|
|
1870
1994
|
return visibleOps;
|
|
1871
1995
|
}
|
|
@@ -1896,7 +2020,8 @@ function applyAscendAnimation(ops, lines, progress, direction, fontSize, duratio
|
|
|
1896
2020
|
acc += gcount;
|
|
1897
2021
|
}
|
|
1898
2022
|
if (wordIndex >= 0) {
|
|
1899
|
-
const
|
|
2023
|
+
const effectiveWordIndex = isRTLLines(lines) ? Math.max(0, totalWords - 1 - wordIndex) : wordIndex;
|
|
2024
|
+
const startF = effectiveWordIndex / Math.max(1, totalWords) * (duration / duration);
|
|
1900
2025
|
const endF = Math.min(1, startF + 0.3);
|
|
1901
2026
|
if (progress >= endF) {
|
|
1902
2027
|
result.push(op);
|
|
@@ -1976,7 +2101,8 @@ function applyShiftAnimation(ops, lines, progress, direction, fontSize, style, d
|
|
|
1976
2101
|
}
|
|
1977
2102
|
unitIndex = Math.max(0, wordIndex);
|
|
1978
2103
|
}
|
|
1979
|
-
const
|
|
2104
|
+
const effectiveUnit = isRTLLines(lines) ? Math.max(0, totalUnits - 1 - unitIndex) : unitIndex;
|
|
2105
|
+
const { startF, endF } = windowFor(effectiveUnit);
|
|
1980
2106
|
if (progress <= startF) {
|
|
1981
2107
|
const animated = { ...op, x: op.x + offset.x, y: op.y + offset.y };
|
|
1982
2108
|
if (op.op === "FillPath") {
|
|
@@ -2057,7 +2183,8 @@ function applyFadeInAnimation(ops, lines, progress, style, fontSize, duration) {
|
|
|
2057
2183
|
}
|
|
2058
2184
|
unitIndex = Math.max(0, wordIndex);
|
|
2059
2185
|
}
|
|
2060
|
-
const
|
|
2186
|
+
const effectiveUnit = isRTLLines(lines) ? Math.max(0, totalUnits - 1 - unitIndex) : unitIndex;
|
|
2187
|
+
const { startF, endF } = windowFor(effectiveUnit);
|
|
2061
2188
|
if (progress <= startF) {
|
|
2062
2189
|
const animated = { ...op };
|
|
2063
2190
|
if (op.op === "FillPath") {
|
|
@@ -2144,7 +2271,8 @@ function applySlideInAnimation(ops, lines, progress, direction, fontSize, style,
|
|
|
2144
2271
|
}
|
|
2145
2272
|
unitIndex = Math.max(0, wordIndex);
|
|
2146
2273
|
}
|
|
2147
|
-
const
|
|
2274
|
+
const effectiveUnit = isRTLLines(lines) ? Math.max(0, totalUnits - 1 - unitIndex) : unitIndex;
|
|
2275
|
+
const { startF, endF } = windowFor(effectiveUnit);
|
|
2148
2276
|
if (progress <= startF) {
|
|
2149
2277
|
const animated = { ...op, x: op.x + offset.x, y: op.y + offset.y };
|
|
2150
2278
|
if (op.op === "FillPath") {
|
|
@@ -2211,6 +2339,43 @@ function segmentLineBySpaces(line) {
|
|
|
2211
2339
|
if (current.length) words.push(current);
|
|
2212
2340
|
return words;
|
|
2213
2341
|
}
|
|
2342
|
+
function sliceGlyphOpsFromEnd(ops, maxGlyphs) {
|
|
2343
|
+
let totalGlyphs = 0;
|
|
2344
|
+
for (const op of ops) {
|
|
2345
|
+
if (op.op === "FillPath" && !isShadowFill(op)) totalGlyphs++;
|
|
2346
|
+
}
|
|
2347
|
+
const skipCount = Math.max(0, totalGlyphs - maxGlyphs);
|
|
2348
|
+
const result = [];
|
|
2349
|
+
let glyphCount = 0;
|
|
2350
|
+
let foundGlyphs = false;
|
|
2351
|
+
for (const op of ops) {
|
|
2352
|
+
if (op.op === "BeginFrame" || op.op === "Rectangle" || op.op === "RectangleStroke") {
|
|
2353
|
+
result.push(op);
|
|
2354
|
+
continue;
|
|
2355
|
+
}
|
|
2356
|
+
if (op.op === "FillPath" && !isShadowFill(op)) {
|
|
2357
|
+
if (glyphCount >= skipCount) {
|
|
2358
|
+
result.push(op);
|
|
2359
|
+
foundGlyphs = true;
|
|
2360
|
+
}
|
|
2361
|
+
glyphCount++;
|
|
2362
|
+
continue;
|
|
2363
|
+
}
|
|
2364
|
+
if (op.op === "StrokePath") {
|
|
2365
|
+
if (glyphCount >= skipCount) result.push(op);
|
|
2366
|
+
continue;
|
|
2367
|
+
}
|
|
2368
|
+
if (op.op === "FillPath" && isShadowFill(op)) {
|
|
2369
|
+
if (glyphCount >= skipCount) result.push(op);
|
|
2370
|
+
continue;
|
|
2371
|
+
}
|
|
2372
|
+
if (op.op === "DecorationLine" && foundGlyphs) {
|
|
2373
|
+
result.push(op);
|
|
2374
|
+
continue;
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return result;
|
|
2378
|
+
}
|
|
2214
2379
|
function sliceGlyphOps(ops, maxGlyphs) {
|
|
2215
2380
|
const result = [];
|
|
2216
2381
|
let glyphCount = 0;
|
|
@@ -2243,27 +2408,30 @@ function sliceGlyphOps(ops, maxGlyphs) {
|
|
|
2243
2408
|
}
|
|
2244
2409
|
return result;
|
|
2245
2410
|
}
|
|
2246
|
-
function addTypewriterCursor(ops, glyphCount, fontSize, time) {
|
|
2411
|
+
function addTypewriterCursor(ops, glyphCount, fontSize, time, isRTL = false) {
|
|
2247
2412
|
if (glyphCount === 0) return ops;
|
|
2248
2413
|
const blinkRate = 1;
|
|
2249
2414
|
const cursorVisible = Math.floor(time * blinkRate * 2) % 2 === 0;
|
|
2250
2415
|
const alwaysShowCursor = true;
|
|
2251
2416
|
if (!alwaysShowCursor && !cursorVisible) return ops;
|
|
2252
2417
|
let last = null;
|
|
2418
|
+
let first = null;
|
|
2253
2419
|
let count = 0;
|
|
2254
2420
|
for (const op of ops) {
|
|
2255
2421
|
if (op.op === "FillPath" && !isShadowFill(op)) {
|
|
2256
2422
|
count++;
|
|
2423
|
+
if (count === 1) first = op;
|
|
2257
2424
|
if (count === glyphCount) {
|
|
2258
2425
|
last = op;
|
|
2259
2426
|
break;
|
|
2260
2427
|
}
|
|
2261
2428
|
}
|
|
2262
2429
|
}
|
|
2263
|
-
|
|
2430
|
+
const cursorAnchor = isRTL && first ? first : last;
|
|
2431
|
+
if (cursorAnchor && cursorAnchor.op === "FillPath") {
|
|
2264
2432
|
const color = getTextColorFromOps(ops);
|
|
2265
|
-
const cursorX =
|
|
2266
|
-
const cursorY =
|
|
2433
|
+
const cursorX = isRTL && first ? first.x - fontSize * 0.15 : cursorAnchor.x + fontSize * 0.5;
|
|
2434
|
+
const cursorY = cursorAnchor.y;
|
|
2267
2435
|
const cursorWidth = Math.max(3, fontSize / 15);
|
|
2268
2436
|
const cursorOp = {
|
|
2269
2437
|
op: "DecorationLine",
|
|
@@ -2623,7 +2791,7 @@ function calculateNoneState(ctx) {
|
|
|
2623
2791
|
isActive: isWordActive(ctx)
|
|
2624
2792
|
};
|
|
2625
2793
|
}
|
|
2626
|
-
function calculateWordAnimationState(wordStart, wordEnd, currentTime, config, activeScale = 1, charCount = 0, fontSize = 48) {
|
|
2794
|
+
function calculateWordAnimationState(wordStart, wordEnd, currentTime, config, activeScale = 1, charCount = 0, fontSize = 48, isRTL = false) {
|
|
2627
2795
|
const safeSpeed = config.speed > 0 ? config.speed : 1;
|
|
2628
2796
|
const ctx = {
|
|
2629
2797
|
wordStart,
|
|
@@ -2646,9 +2814,11 @@ function calculateWordAnimationState(wordStart, wordEnd, currentTime, config, ac
|
|
|
2646
2814
|
case "fade":
|
|
2647
2815
|
partialState = calculateFadeState(ctx, safeSpeed);
|
|
2648
2816
|
break;
|
|
2649
|
-
case "slide":
|
|
2650
|
-
|
|
2817
|
+
case "slide": {
|
|
2818
|
+
const slideDir = mirrorAnimationDirection(config.direction, isRTL);
|
|
2819
|
+
partialState = calculateSlideState(ctx, slideDir, config.speed, fontSize);
|
|
2651
2820
|
break;
|
|
2821
|
+
}
|
|
2652
2822
|
case "bounce":
|
|
2653
2823
|
partialState = calculateBounceState(ctx, safeSpeed, fontSize);
|
|
2654
2824
|
break;
|
|
@@ -2676,7 +2846,8 @@ function calculateAnimationStatesForGroup(words, currentTime, config, activeScal
|
|
|
2676
2846
|
config,
|
|
2677
2847
|
activeScale,
|
|
2678
2848
|
word.text.length,
|
|
2679
|
-
fontSize
|
|
2849
|
+
fontSize,
|
|
2850
|
+
word.isRTL
|
|
2680
2851
|
);
|
|
2681
2852
|
states.set(word.wordIndex, state);
|
|
2682
2853
|
}
|
|
@@ -2820,7 +2991,7 @@ function extractActiveScale(asset) {
|
|
|
2820
2991
|
}
|
|
2821
2992
|
function createDrawCaptionWordOp(word, animState, asset, fontConfig) {
|
|
2822
2993
|
const isActive = animState.isActive;
|
|
2823
|
-
const displayText =
|
|
2994
|
+
const displayText = getVisibleText(word.text, animState.visibleCharacters, word.isRTL);
|
|
2824
2995
|
return {
|
|
2825
2996
|
op: "DrawCaptionWord",
|
|
2826
2997
|
text: displayText,
|
|
@@ -3275,7 +3446,7 @@ async function createNodePainter(opts) {
|
|
|
3275
3446
|
renderToBoth((context) => {
|
|
3276
3447
|
for (const wordOp of captionWordOps) {
|
|
3277
3448
|
if (!wordOp.background) continue;
|
|
3278
|
-
const wordDisplayText = wordOp.
|
|
3449
|
+
const wordDisplayText = getVisibleText(wordOp.text, wordOp.visibleCharacters, wordOp.isRTL);
|
|
3279
3450
|
if (wordDisplayText.length === 0) continue;
|
|
3280
3451
|
context.save();
|
|
3281
3452
|
const bgTx = Math.round(wordOp.x + wordOp.transform.translateX);
|
|
@@ -3309,7 +3480,7 @@ async function createNodePainter(opts) {
|
|
|
3309
3480
|
context.restore();
|
|
3310
3481
|
}
|
|
3311
3482
|
for (const wordOp of captionWordOps) {
|
|
3312
|
-
const displayText = wordOp.
|
|
3483
|
+
const displayText = getVisibleText(wordOp.text, wordOp.visibleCharacters, wordOp.isRTL);
|
|
3313
3484
|
if (displayText.length === 0) continue;
|
|
3314
3485
|
context.save();
|
|
3315
3486
|
const tx = Math.round(wordOp.x + wordOp.transform.translateX);
|
|
@@ -4841,9 +5012,8 @@ function extractSvgDimensions(svgString) {
|
|
|
4841
5012
|
|
|
4842
5013
|
// src/core/rich-caption-layout.ts
|
|
4843
5014
|
var import_lru_cache = require("lru-cache");
|
|
4844
|
-
var RTL_RANGES = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/;
|
|
4845
5015
|
function isRTLText(text) {
|
|
4846
|
-
return
|
|
5016
|
+
return containsRTLCharacters(text);
|
|
4847
5017
|
}
|
|
4848
5018
|
var WordTimingStore = class {
|
|
4849
5019
|
startTimes;
|
|
@@ -5102,6 +5272,8 @@ var CaptionLayoutEngine = class {
|
|
|
5102
5272
|
return (config.frameHeight - totalHeight) / 2 + config.fontSize;
|
|
5103
5273
|
}
|
|
5104
5274
|
};
|
|
5275
|
+
const allWordTexts = store.words.slice(0, store.length);
|
|
5276
|
+
const paragraphDirection = detectParagraphDirectionFromWords(allWordTexts);
|
|
5105
5277
|
const calculateLineX = (lineWidth) => {
|
|
5106
5278
|
switch (config.horizontalAlign) {
|
|
5107
5279
|
case "left":
|
|
@@ -5119,8 +5291,11 @@ var CaptionLayoutEngine = class {
|
|
|
5119
5291
|
const line = group.lines[lineIdx];
|
|
5120
5292
|
line.x = calculateLineX(line.width);
|
|
5121
5293
|
line.y = baseY + lineIdx * config.fontSize * config.lineHeight;
|
|
5294
|
+
const lineWordTexts = line.wordIndices.map((idx) => store.words[idx]);
|
|
5295
|
+
const visualOrder = reorderWordsForLine(lineWordTexts, paragraphDirection);
|
|
5122
5296
|
let xCursor = line.x;
|
|
5123
|
-
for (const
|
|
5297
|
+
for (const visualIdx of visualOrder) {
|
|
5298
|
+
const wordIdx = line.wordIndices[visualIdx];
|
|
5124
5299
|
store.xPositions[wordIdx] = xCursor;
|
|
5125
5300
|
store.yPositions[wordIdx] = line.y;
|
|
5126
5301
|
xCursor += store.widths[wordIdx] + spaceWidth;
|
|
@@ -5130,7 +5305,8 @@ var CaptionLayoutEngine = class {
|
|
|
5130
5305
|
return {
|
|
5131
5306
|
store,
|
|
5132
5307
|
groups,
|
|
5133
|
-
shapedWords
|
|
5308
|
+
shapedWords,
|
|
5309
|
+
paragraphDirection
|
|
5134
5310
|
};
|
|
5135
5311
|
}
|
|
5136
5312
|
getVisibleWordsAtTime(layout, timeMs) {
|
|
@@ -6601,7 +6777,7 @@ async function createTextEngine(opts = {}) {
|
|
|
6601
6777
|
horizontal: asset.align?.horizontal ?? "center",
|
|
6602
6778
|
vertical: asset.align?.vertical ?? "middle"
|
|
6603
6779
|
},
|
|
6604
|
-
background: asset.background,
|
|
6780
|
+
background: asset.background ? { color: asset.background.color, opacity: asset.background.opacity, borderRadius: typeof asset.background.borderRadius === "number" ? asset.background.borderRadius : Number(asset.background.borderRadius) || 0 } : void 0,
|
|
6605
6781
|
border: asset.border,
|
|
6606
6782
|
padding: asset.padding,
|
|
6607
6783
|
glyphPathProvider: (gid, fontDesc) => fonts.glyphPath(fontDesc || desc, gid),
|
|
@@ -6656,7 +6832,8 @@ async function createTextEngine(opts = {}) {
|
|
|
6656
6832
|
try {
|
|
6657
6833
|
const hasBackground = !!asset.background?.color;
|
|
6658
6834
|
const hasAnimation = !!asset.animation?.preset;
|
|
6659
|
-
const
|
|
6835
|
+
const bgBorderRadius = typeof asset.background?.borderRadius === "number" ? asset.background.borderRadius : Number(asset.background?.borderRadius) || 0;
|
|
6836
|
+
const hasBorderRadius = (asset.border?.radius ?? 0) > 0 || bgBorderRadius > 0;
|
|
6660
6837
|
const needsAlpha = !hasBackground && hasAnimation || hasBorderRadius;
|
|
6661
6838
|
console.log(
|
|
6662
6839
|
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, BorderRadius=${hasBorderRadius}, Alpha=${needsAlpha}`
|
|
@@ -6715,6 +6892,7 @@ async function createTextEngine(opts = {}) {
|
|
|
6715
6892
|
calculateAnimationStatesForGroup,
|
|
6716
6893
|
commandsToPathString,
|
|
6717
6894
|
computeSimplePathBounds,
|
|
6895
|
+
containsRTLCharacters,
|
|
6718
6896
|
createDefaultGeneratorConfig,
|
|
6719
6897
|
createFrameSchedule,
|
|
6720
6898
|
createNodePainter,
|
|
@@ -6722,6 +6900,8 @@ async function createTextEngine(opts = {}) {
|
|
|
6722
6900
|
createRichCaptionRenderer,
|
|
6723
6901
|
createTextEngine,
|
|
6724
6902
|
createVideoEncoder,
|
|
6903
|
+
detectParagraphDirection,
|
|
6904
|
+
detectParagraphDirectionFromWords,
|
|
6725
6905
|
detectPlatform,
|
|
6726
6906
|
detectSubtitleFormat,
|
|
6727
6907
|
extractCaptionPadding,
|
|
@@ -6733,10 +6913,12 @@ async function createTextEngine(opts = {}) {
|
|
|
6733
6913
|
getDrawCaptionWordOps,
|
|
6734
6914
|
getEncoderCapabilities,
|
|
6735
6915
|
getEncoderWarning,
|
|
6916
|
+
getVisibleText,
|
|
6736
6917
|
groupWordsByPause,
|
|
6737
6918
|
isDrawCaptionWordOp,
|
|
6738
6919
|
isRTLText,
|
|
6739
6920
|
isWebCodecsH264Supported,
|
|
6921
|
+
mirrorAnimationDirection,
|
|
6740
6922
|
normalizePath,
|
|
6741
6923
|
normalizePathString,
|
|
6742
6924
|
parseSubtitleToWords,
|
|
@@ -6744,6 +6926,7 @@ async function createTextEngine(opts = {}) {
|
|
|
6744
6926
|
quadraticToCubic,
|
|
6745
6927
|
renderSvgAssetToPng,
|
|
6746
6928
|
renderSvgToPng,
|
|
6929
|
+
reorderWordsForLine,
|
|
6747
6930
|
richCaptionAssetSchema,
|
|
6748
6931
|
shapeToSvgString,
|
|
6749
6932
|
svgAssetSchema,
|
package/dist/entry.node.d.cts
CHANGED
|
@@ -594,6 +594,14 @@ declare class FontRegistry {
|
|
|
594
594
|
destroy(): void;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
declare function containsRTLCharacters(text: string): boolean;
|
|
598
|
+
type ParagraphDirection = "ltr" | "rtl";
|
|
599
|
+
declare function detectParagraphDirection(text: string): ParagraphDirection;
|
|
600
|
+
declare function detectParagraphDirectionFromWords(words: string[]): ParagraphDirection;
|
|
601
|
+
declare function reorderWordsForLine(wordTexts: string[], paragraphDirection: ParagraphDirection): number[];
|
|
602
|
+
declare function getVisibleText(text: string, visibleCharacters: number, isRTL: boolean): string;
|
|
603
|
+
declare function mirrorAnimationDirection(direction: "left" | "right" | "up" | "down", isRTL: boolean): "left" | "right" | "up" | "down";
|
|
604
|
+
|
|
597
605
|
interface WordTiming {
|
|
598
606
|
text: string;
|
|
599
607
|
start: number;
|
|
@@ -658,6 +666,7 @@ interface CaptionLayout {
|
|
|
658
666
|
store: WordTimingStore;
|
|
659
667
|
groups: CaptionGroup[];
|
|
660
668
|
shapedWords: ShapedWord[];
|
|
669
|
+
paragraphDirection: ParagraphDirection;
|
|
661
670
|
}
|
|
662
671
|
declare function isRTLText(text: string): boolean;
|
|
663
672
|
declare class WordTimingStore {
|
|
@@ -771,6 +780,7 @@ type ShapedLine = {
|
|
|
771
780
|
glyphs: Glyph[];
|
|
772
781
|
width: number;
|
|
773
782
|
y: number;
|
|
783
|
+
isRTL?: boolean;
|
|
774
784
|
};
|
|
775
785
|
type DrawOp = {
|
|
776
786
|
op: "BeginFrame";
|
|
@@ -1331,4 +1341,4 @@ declare function createTextEngine(opts?: {
|
|
|
1331
1341
|
destroy(): void;
|
|
1332
1342
|
}>;
|
|
1333
1343
|
|
|
1334
|
-
export { ASCENT_RATIO, type AnimationDirection, type AnimationStyle, type ArcCommand, type BackgroundConfig, type BoundingBox, type CanvasRichCaptionAsset, CanvasRichCaptionAssetSchema, type CanvasRichTextAsset, CanvasRichTextAssetSchema, type CanvasSvgAsset, CanvasSvgAssetSchema, type CaptionGroup, type CaptionLayout, type CaptionLayoutConfig, CaptionLayoutEngine, type CaptionLine, type ClosePathCommand, type CubicBezierCommand, DESCENT_RATIO, type DrawOp, type EngineInit, type FastVideoOptions, type FastVideoResult, type FontConfig, FontRegistry, type FrameSchedule, type Glyph, type GradientSpec, type IVideoEncoder, type LineToCommand, type MoveToCommand, NodeRawEncoder, type NormalizedPathCommand, type ParsedPathCommand, type PathCommandType, type Point2D, type PositionedWord, type QuadraticBezierCommand, type RGBA, type RenderFrame, type RenderStats, type Renderer, type ResvgRenderOptions, type ResvgRenderResult, type RichCaptionGeneratorConfig, RichCaptionRenderer, type RichCaptionRendererOptions, type ShadowConfig, type ShapedLine, type ShapedWord, type ShapedWordGlyph, type ShotstackRichTextAsset, type ShotstackSvgAsset, type StrokeConfig, type StrokeSpec, type ValidAsset, type VideoEncoderCapabilities, type VideoEncoderConfig, type VideoEncoderProgress, WORD_BG_BORDER_RADIUS, WORD_BG_OPACITY, WORD_BG_PADDING_RATIO, type WordAnimationConfig, type WordAnimationState, type WordTiming, WordTimingStore, arcToCubicBeziers, breakIntoLines, calculateAnimationStatesForGroup, commandsToPathString, computeSimplePathBounds, createDefaultGeneratorConfig, createFrameSchedule, createNodePainter, createNodeRawEncoder, createRichCaptionRenderer, createTextEngine, createVideoEncoder, detectPlatform, detectSubtitleFormat, extractCaptionPadding, findWordAtTime, generateRichCaptionDrawOps, generateRichCaptionFrame, generateShapePathData, getDefaultAnimationConfig, getDrawCaptionWordOps, getEncoderCapabilities, getEncoderWarning, groupWordsByPause, isDrawCaptionWordOp, isRTLText, isWebCodecsH264Supported, normalizePath, normalizePathString, parseSubtitleToWords, parseSvgPath, quadraticToCubic, renderSvgAssetToPng, renderSvgToPng, richCaptionAssetSchema, shapeToSvgString };
|
|
1344
|
+
export { ASCENT_RATIO, type AnimationDirection, type AnimationStyle, type ArcCommand, type BackgroundConfig, type BoundingBox, type CanvasRichCaptionAsset, CanvasRichCaptionAssetSchema, type CanvasRichTextAsset, CanvasRichTextAssetSchema, type CanvasSvgAsset, CanvasSvgAssetSchema, type CaptionGroup, type CaptionLayout, type CaptionLayoutConfig, CaptionLayoutEngine, type CaptionLine, type ClosePathCommand, type CubicBezierCommand, DESCENT_RATIO, type DrawOp, type EngineInit, type FastVideoOptions, type FastVideoResult, type FontConfig, FontRegistry, type FrameSchedule, type Glyph, type GradientSpec, type IVideoEncoder, type LineToCommand, type MoveToCommand, NodeRawEncoder, type NormalizedPathCommand, type ParagraphDirection, type ParsedPathCommand, type PathCommandType, type Point2D, type PositionedWord, type QuadraticBezierCommand, type RGBA, type RenderFrame, type RenderStats, type Renderer, type ResvgRenderOptions, type ResvgRenderResult, type RichCaptionGeneratorConfig, RichCaptionRenderer, type RichCaptionRendererOptions, type ShadowConfig, type ShapedLine, type ShapedWord, type ShapedWordGlyph, type ShotstackRichTextAsset, type ShotstackSvgAsset, type StrokeConfig, type StrokeSpec, type ValidAsset, type VideoEncoderCapabilities, type VideoEncoderConfig, type VideoEncoderProgress, WORD_BG_BORDER_RADIUS, WORD_BG_OPACITY, WORD_BG_PADDING_RATIO, type WordAnimationConfig, type WordAnimationState, type WordTiming, WordTimingStore, arcToCubicBeziers, breakIntoLines, calculateAnimationStatesForGroup, commandsToPathString, computeSimplePathBounds, containsRTLCharacters, createDefaultGeneratorConfig, createFrameSchedule, createNodePainter, createNodeRawEncoder, createRichCaptionRenderer, createTextEngine, createVideoEncoder, detectParagraphDirection, detectParagraphDirectionFromWords, detectPlatform, detectSubtitleFormat, extractCaptionPadding, findWordAtTime, generateRichCaptionDrawOps, generateRichCaptionFrame, generateShapePathData, getDefaultAnimationConfig, getDrawCaptionWordOps, getEncoderCapabilities, getEncoderWarning, getVisibleText, groupWordsByPause, isDrawCaptionWordOp, isRTLText, isWebCodecsH264Supported, mirrorAnimationDirection, normalizePath, normalizePathString, parseSubtitleToWords, parseSvgPath, quadraticToCubic, renderSvgAssetToPng, renderSvgToPng, reorderWordsForLine, richCaptionAssetSchema, shapeToSvgString };
|
package/dist/entry.node.d.ts
CHANGED
|
@@ -594,6 +594,14 @@ declare class FontRegistry {
|
|
|
594
594
|
destroy(): void;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
declare function containsRTLCharacters(text: string): boolean;
|
|
598
|
+
type ParagraphDirection = "ltr" | "rtl";
|
|
599
|
+
declare function detectParagraphDirection(text: string): ParagraphDirection;
|
|
600
|
+
declare function detectParagraphDirectionFromWords(words: string[]): ParagraphDirection;
|
|
601
|
+
declare function reorderWordsForLine(wordTexts: string[], paragraphDirection: ParagraphDirection): number[];
|
|
602
|
+
declare function getVisibleText(text: string, visibleCharacters: number, isRTL: boolean): string;
|
|
603
|
+
declare function mirrorAnimationDirection(direction: "left" | "right" | "up" | "down", isRTL: boolean): "left" | "right" | "up" | "down";
|
|
604
|
+
|
|
597
605
|
interface WordTiming {
|
|
598
606
|
text: string;
|
|
599
607
|
start: number;
|
|
@@ -658,6 +666,7 @@ interface CaptionLayout {
|
|
|
658
666
|
store: WordTimingStore;
|
|
659
667
|
groups: CaptionGroup[];
|
|
660
668
|
shapedWords: ShapedWord[];
|
|
669
|
+
paragraphDirection: ParagraphDirection;
|
|
661
670
|
}
|
|
662
671
|
declare function isRTLText(text: string): boolean;
|
|
663
672
|
declare class WordTimingStore {
|
|
@@ -771,6 +780,7 @@ type ShapedLine = {
|
|
|
771
780
|
glyphs: Glyph[];
|
|
772
781
|
width: number;
|
|
773
782
|
y: number;
|
|
783
|
+
isRTL?: boolean;
|
|
774
784
|
};
|
|
775
785
|
type DrawOp = {
|
|
776
786
|
op: "BeginFrame";
|
|
@@ -1331,4 +1341,4 @@ declare function createTextEngine(opts?: {
|
|
|
1331
1341
|
destroy(): void;
|
|
1332
1342
|
}>;
|
|
1333
1343
|
|
|
1334
|
-
export { ASCENT_RATIO, type AnimationDirection, type AnimationStyle, type ArcCommand, type BackgroundConfig, type BoundingBox, type CanvasRichCaptionAsset, CanvasRichCaptionAssetSchema, type CanvasRichTextAsset, CanvasRichTextAssetSchema, type CanvasSvgAsset, CanvasSvgAssetSchema, type CaptionGroup, type CaptionLayout, type CaptionLayoutConfig, CaptionLayoutEngine, type CaptionLine, type ClosePathCommand, type CubicBezierCommand, DESCENT_RATIO, type DrawOp, type EngineInit, type FastVideoOptions, type FastVideoResult, type FontConfig, FontRegistry, type FrameSchedule, type Glyph, type GradientSpec, type IVideoEncoder, type LineToCommand, type MoveToCommand, NodeRawEncoder, type NormalizedPathCommand, type ParsedPathCommand, type PathCommandType, type Point2D, type PositionedWord, type QuadraticBezierCommand, type RGBA, type RenderFrame, type RenderStats, type Renderer, type ResvgRenderOptions, type ResvgRenderResult, type RichCaptionGeneratorConfig, RichCaptionRenderer, type RichCaptionRendererOptions, type ShadowConfig, type ShapedLine, type ShapedWord, type ShapedWordGlyph, type ShotstackRichTextAsset, type ShotstackSvgAsset, type StrokeConfig, type StrokeSpec, type ValidAsset, type VideoEncoderCapabilities, type VideoEncoderConfig, type VideoEncoderProgress, WORD_BG_BORDER_RADIUS, WORD_BG_OPACITY, WORD_BG_PADDING_RATIO, type WordAnimationConfig, type WordAnimationState, type WordTiming, WordTimingStore, arcToCubicBeziers, breakIntoLines, calculateAnimationStatesForGroup, commandsToPathString, computeSimplePathBounds, createDefaultGeneratorConfig, createFrameSchedule, createNodePainter, createNodeRawEncoder, createRichCaptionRenderer, createTextEngine, createVideoEncoder, detectPlatform, detectSubtitleFormat, extractCaptionPadding, findWordAtTime, generateRichCaptionDrawOps, generateRichCaptionFrame, generateShapePathData, getDefaultAnimationConfig, getDrawCaptionWordOps, getEncoderCapabilities, getEncoderWarning, groupWordsByPause, isDrawCaptionWordOp, isRTLText, isWebCodecsH264Supported, normalizePath, normalizePathString, parseSubtitleToWords, parseSvgPath, quadraticToCubic, renderSvgAssetToPng, renderSvgToPng, richCaptionAssetSchema, shapeToSvgString };
|
|
1344
|
+
export { ASCENT_RATIO, type AnimationDirection, type AnimationStyle, type ArcCommand, type BackgroundConfig, type BoundingBox, type CanvasRichCaptionAsset, CanvasRichCaptionAssetSchema, type CanvasRichTextAsset, CanvasRichTextAssetSchema, type CanvasSvgAsset, CanvasSvgAssetSchema, type CaptionGroup, type CaptionLayout, type CaptionLayoutConfig, CaptionLayoutEngine, type CaptionLine, type ClosePathCommand, type CubicBezierCommand, DESCENT_RATIO, type DrawOp, type EngineInit, type FastVideoOptions, type FastVideoResult, type FontConfig, FontRegistry, type FrameSchedule, type Glyph, type GradientSpec, type IVideoEncoder, type LineToCommand, type MoveToCommand, NodeRawEncoder, type NormalizedPathCommand, type ParagraphDirection, type ParsedPathCommand, type PathCommandType, type Point2D, type PositionedWord, type QuadraticBezierCommand, type RGBA, type RenderFrame, type RenderStats, type Renderer, type ResvgRenderOptions, type ResvgRenderResult, type RichCaptionGeneratorConfig, RichCaptionRenderer, type RichCaptionRendererOptions, type ShadowConfig, type ShapedLine, type ShapedWord, type ShapedWordGlyph, type ShotstackRichTextAsset, type ShotstackSvgAsset, type StrokeConfig, type StrokeSpec, type ValidAsset, type VideoEncoderCapabilities, type VideoEncoderConfig, type VideoEncoderProgress, WORD_BG_BORDER_RADIUS, WORD_BG_OPACITY, WORD_BG_PADDING_RATIO, type WordAnimationConfig, type WordAnimationState, type WordTiming, WordTimingStore, arcToCubicBeziers, breakIntoLines, calculateAnimationStatesForGroup, commandsToPathString, computeSimplePathBounds, containsRTLCharacters, createDefaultGeneratorConfig, createFrameSchedule, createNodePainter, createNodeRawEncoder, createRichCaptionRenderer, createTextEngine, createVideoEncoder, detectParagraphDirection, detectParagraphDirectionFromWords, detectPlatform, detectSubtitleFormat, extractCaptionPadding, findWordAtTime, generateRichCaptionDrawOps, generateRichCaptionFrame, generateShapePathData, getDefaultAnimationConfig, getDrawCaptionWordOps, getEncoderCapabilities, getEncoderWarning, getVisibleText, groupWordsByPause, isDrawCaptionWordOp, isRTLText, isWebCodecsH264Supported, mirrorAnimationDirection, normalizePath, normalizePathString, parseSubtitleToWords, parseSvgPath, quadraticToCubic, renderSvgAssetToPng, renderSvgToPng, reorderWordsForLine, richCaptionAssetSchema, shapeToSvgString };
|