@clypra/engine 1.2.0 → 1.3.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.js CHANGED
@@ -73,35 +73,26 @@ function wrapTextToWidth(ctx, text, maxWidth, letterSpacing) {
73
73
  const paragraphs = text.split("\n");
74
74
  const lines = [];
75
75
  for (const para of paragraphs) {
76
- if (!para.trim()) {
76
+ if (para === "") {
77
77
  lines.push("");
78
78
  continue;
79
79
  }
80
- const words = para.split(/\s+/).filter(Boolean);
81
80
  let current = "";
82
- for (const word of words) {
83
- const candidate = current ? `${current} ${word}` : word;
84
- if (measureLine(ctx, candidate, letterSpacing) <= maxWidth) {
85
- current = candidate;
81
+ for (let i = 0; i < para.length; i++) {
82
+ const char = para[i];
83
+ const tryLine = current + char;
84
+ if (measureLine(ctx, tryLine, letterSpacing) <= maxWidth) {
85
+ current = tryLine;
86
86
  } else {
87
- if (current) lines.push(current);
88
- if (measureLine(ctx, word, letterSpacing) > maxWidth) {
89
- let chunk = "";
90
- for (const ch of word) {
91
- const tryChunk = chunk + ch;
92
- if (measureLine(ctx, tryChunk, letterSpacing) <= maxWidth) chunk = tryChunk;
93
- else {
94
- if (chunk) lines.push(chunk);
95
- chunk = ch;
96
- }
97
- }
98
- current = chunk;
99
- } else {
100
- current = word;
87
+ if (current) {
88
+ lines.push(current);
101
89
  }
90
+ current = char;
102
91
  }
103
92
  }
104
- if (current) lines.push(current);
93
+ if (current) {
94
+ lines.push(current);
95
+ }
105
96
  }
106
97
  return lines.length > 0 ? lines : [""];
107
98
  }
@@ -127,17 +118,17 @@ function layoutWithFontSize(ctx, cfg, fontSize, lines) {
127
118
  } else {
128
119
  startX = safe.x + safe.width / 2;
129
120
  }
130
- let startY = safe.y + (safe.height - textBlockHeight) / 2 + fontSize * 0.82;
121
+ let startY = safe.y + (safe.height - textBlockHeight) / 2 + fontSize * 0.85;
131
122
  if (cfg.textPosY === "top") {
132
- startY = safe.y + fontSize * 0.82;
123
+ startY = safe.y + fontSize * 0.85;
133
124
  } else if (cfg.textPosY === "bottom") {
134
- startY = safe.y + safe.height - textBlockHeight + fontSize * 0.82;
125
+ startY = safe.y + safe.height - textBlockHeight + fontSize * 0.85;
135
126
  }
136
127
  let xMin = startX;
137
128
  if (align === "center") xMin = startX - maxLineWidth / 2;
138
129
  else if (align === "right") xMin = startX - maxLineWidth;
139
130
  const yMin = startY - fontSize * 0.85;
140
- const yMax = startY + (lines.length - 1) * fontSize * lineHeight + fontSize * 0.25;
131
+ const yMax = startY + (lines.length - 1) * fontSize * lineHeight + fontSize * 0.15;
141
132
  return {
142
133
  lines,
143
134
  fontSize,
@@ -576,11 +567,11 @@ var InkBrushEngine = class {
576
567
  if (letterSpacing !== 0) {
577
568
  ctx.letterSpacing = `${letterSpacing}px`;
578
569
  }
579
- let startY = (height - textBlockHeight) / 2 + fontSize * 0.8;
570
+ let startY = (height - textBlockHeight) / 2 + fontSize * 0.85;
580
571
  if (textPosY === "top") {
581
- startY = 40 + fontSize * 0.8;
572
+ startY = 40 + fontSize * 0.85;
582
573
  } else if (textPosY === "bottom") {
583
- startY = height - 40 - textBlockHeight + fontSize * 0.8;
574
+ startY = height - 40 - textBlockHeight + fontSize * 0.85;
584
575
  }
585
576
  ctx.save();
586
577
  if (skewX !== 0) {
@@ -728,11 +719,11 @@ var InkBrushEngine = class {
728
719
  if (letterSpacing !== 0) {
729
720
  ctx.letterSpacing = `${letterSpacing}px`;
730
721
  }
731
- let startY = (height - textBlockHeight) / 2 + fontSize * 0.8;
722
+ let startY = (height - textBlockHeight) / 2 + fontSize * 0.85;
732
723
  if (textPosY === "top") {
733
- startY = 40 + fontSize * 0.8;
724
+ startY = 40 + fontSize * 0.85;
734
725
  } else if (textPosY === "bottom") {
735
- startY = height - 40 - textBlockHeight + fontSize * 0.8;
726
+ startY = height - 40 - textBlockHeight + fontSize * 0.85;
736
727
  }
737
728
  ctx.save();
738
729
  if (skewX !== 0) {
@@ -6451,6 +6442,821 @@ function duplicateTrackAtPlayhead(doc, trackIndex, previewTime) {
6451
6442
  const value = layer2 ? readLayerScalar(layer2, track.paramPath) : 0;
6452
6443
  return addKeyframeAtTime(doc, trackIndex, previewTime, value);
6453
6444
  }
6445
+
6446
+ // src/engine/api.ts
6447
+ function updateSceneText(doc, patch) {
6448
+ const nextText = { ...doc.text };
6449
+ if (patch.content !== void 0) nextText.content = patch.content;
6450
+ if (patch.fontFamily !== void 0) nextText.fontFamily = patch.fontFamily;
6451
+ if (patch.fontWeight !== void 0) nextText.fontWeight = patch.fontWeight;
6452
+ if (patch.fontStyle !== void 0) nextText.fontStyle = patch.fontStyle;
6453
+ if (patch.fontSize !== void 0) nextText.fontSize = patch.fontSize;
6454
+ if (patch.letterSpacing !== void 0) nextText.letterSpacing = patch.letterSpacing;
6455
+ if (patch.lineHeight !== void 0) nextText.lineHeight = patch.lineHeight;
6456
+ if (patch.textPosX !== void 0) nextText.textPosX = patch.textPosX;
6457
+ if (patch.textPosY !== void 0) nextText.textPosY = patch.textPosY;
6458
+ if (patch.wrapText !== void 0) nextText.wrapText = patch.wrapText;
6459
+ if (patch.autoFitText !== void 0) nextText.autoFitText = patch.autoFitText;
6460
+ if (patch.perCharFillEnabled !== void 0) nextText.perCharFillEnabled = patch.perCharFillEnabled;
6461
+ if (patch.charFillColors !== void 0) nextText.charFillColors = patch.charFillColors;
6462
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6463
+ if (nextLegacyConfig) {
6464
+ if (patch.content !== void 0) nextLegacyConfig.text = patch.content;
6465
+ if (patch.fontFamily !== void 0) nextLegacyConfig.fontFamily = patch.fontFamily;
6466
+ if (patch.fontWeight !== void 0) nextLegacyConfig.fontWeight = patch.fontWeight;
6467
+ if (patch.fontStyle !== void 0) nextLegacyConfig.fontStyle = patch.fontStyle;
6468
+ if (patch.fontSize !== void 0) nextLegacyConfig.fontSize = patch.fontSize;
6469
+ if (patch.letterSpacing !== void 0) nextLegacyConfig.letterSpacing = patch.letterSpacing;
6470
+ if (patch.lineHeight !== void 0) nextLegacyConfig.lineHeight = patch.lineHeight;
6471
+ if (patch.textPosX !== void 0) nextLegacyConfig.textPosX = patch.textPosX;
6472
+ if (patch.textPosY !== void 0) nextLegacyConfig.textPosY = patch.textPosY;
6473
+ if (patch.wrapText !== void 0) nextLegacyConfig.wrapText = patch.wrapText;
6474
+ if (patch.autoFitText !== void 0) nextLegacyConfig.autoFitText = patch.autoFitText;
6475
+ if (patch.perCharFillEnabled !== void 0) nextLegacyConfig.perCharFillEnabled = patch.perCharFillEnabled;
6476
+ if (patch.charFillColors !== void 0) nextLegacyConfig.charFillColors = patch.charFillColors;
6477
+ }
6478
+ return {
6479
+ ...doc,
6480
+ text: nextText,
6481
+ legacyConfig: nextLegacyConfig
6482
+ };
6483
+ }
6484
+ function updateScenePanel(doc, patch) {
6485
+ let panelFound = false;
6486
+ const nextLayers = doc.effectLayers.map((layer2) => {
6487
+ if (layer2.type === "panel") {
6488
+ panelFound = true;
6489
+ const nextParams = { ...layer2.params };
6490
+ if (patch.color !== void 0) nextParams.panelColor = patch.color;
6491
+ if (patch.opacity !== void 0) nextParams.panelOpacity = patch.opacity;
6492
+ if (patch.radius !== void 0) nextParams.panelRadius = patch.radius;
6493
+ if (patch.paddingX !== void 0) nextParams.panelPaddingX = patch.paddingX;
6494
+ if (patch.paddingY !== void 0) nextParams.panelPaddingY = patch.paddingY;
6495
+ if (patch.strokeEnabled !== void 0) nextParams.panelStrokeEnabled = patch.strokeEnabled;
6496
+ if (patch.strokeColor !== void 0) nextParams.panelStrokeColor = patch.strokeColor;
6497
+ if (patch.strokeWidth !== void 0) nextParams.panelStrokeWidth = patch.strokeWidth;
6498
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6499
+ if (patch.enabled !== void 0) {
6500
+ nextParams.panelEnabled = patch.enabled;
6501
+ }
6502
+ return {
6503
+ ...layer2,
6504
+ enabled,
6505
+ params: nextParams
6506
+ };
6507
+ }
6508
+ return layer2;
6509
+ });
6510
+ const layers = [...nextLayers];
6511
+ if (!panelFound) {
6512
+ const defaultParams = {
6513
+ panelEnabled: patch.enabled ?? true,
6514
+ panelColor: patch.color ?? "#1E1E26",
6515
+ panelOpacity: patch.opacity ?? 80,
6516
+ panelRadius: patch.radius ?? 12,
6517
+ panelPaddingX: patch.paddingX ?? 40,
6518
+ panelPaddingY: patch.paddingY ?? 20,
6519
+ panelStrokeEnabled: patch.strokeEnabled ?? false,
6520
+ panelStrokeColor: patch.strokeColor ?? "#2A2A38",
6521
+ panelStrokeWidth: patch.strokeWidth ?? 2
6522
+ };
6523
+ const newL = {
6524
+ id: newLayerId(),
6525
+ type: "panel",
6526
+ name: "Background Panel",
6527
+ enabled: patch.enabled ?? true,
6528
+ opacity: 1,
6529
+ blendMode: "source-over",
6530
+ target: "scene",
6531
+ params: defaultParams
6532
+ };
6533
+ layers.unshift(newL);
6534
+ }
6535
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6536
+ if (nextLegacyConfig) {
6537
+ if (patch.enabled !== void 0) nextLegacyConfig.panelEnabled = patch.enabled;
6538
+ if (patch.color !== void 0) nextLegacyConfig.panelColor = patch.color;
6539
+ if (patch.opacity !== void 0) nextLegacyConfig.panelOpacity = patch.opacity;
6540
+ if (patch.radius !== void 0) nextLegacyConfig.panelRadius = patch.radius;
6541
+ if (patch.paddingX !== void 0) nextLegacyConfig.panelPaddingX = patch.paddingX;
6542
+ if (patch.paddingY !== void 0) nextLegacyConfig.panelPaddingY = patch.paddingY;
6543
+ if (patch.strokeEnabled !== void 0) nextLegacyConfig.panelStrokeEnabled = patch.strokeEnabled;
6544
+ if (patch.strokeColor !== void 0) nextLegacyConfig.panelStrokeColor = patch.strokeColor;
6545
+ if (patch.strokeWidth !== void 0) nextLegacyConfig.panelStrokeWidth = patch.strokeWidth;
6546
+ }
6547
+ return {
6548
+ ...doc,
6549
+ effectLayers: layers,
6550
+ legacyConfig: nextLegacyConfig
6551
+ };
6552
+ }
6553
+ function updateSceneStroke(doc, patch) {
6554
+ let found = false;
6555
+ const nextLayers = doc.effectLayers.map((layer2) => {
6556
+ if (layer2.type === "stroke") {
6557
+ found = true;
6558
+ const nextParams = { ...layer2.params };
6559
+ if (patch.strokeColor !== void 0) nextParams.strokeColor = patch.strokeColor;
6560
+ if (patch.strokeWidth !== void 0) nextParams.strokeWidth = patch.strokeWidth;
6561
+ if (patch.strokePosition !== void 0) nextParams.strokePosition = patch.strokePosition;
6562
+ if (patch.strokeOpacity !== void 0) nextParams.strokeOpacity = patch.strokeOpacity;
6563
+ if (patch.strokeLineJoin !== void 0) nextParams.strokeLineJoin = patch.strokeLineJoin;
6564
+ if (patch.strokeBlur !== void 0) nextParams.strokeBlur = patch.strokeBlur;
6565
+ if (patch.strokeType !== void 0) nextParams.strokeType = patch.strokeType;
6566
+ if (patch.strokeColorSecondary !== void 0) nextParams.strokeColorSecondary = patch.strokeColorSecondary;
6567
+ if (patch.strokeWidthSecondary !== void 0) nextParams.strokeWidthSecondary = patch.strokeWidthSecondary;
6568
+ if (patch.strokeFadeRange !== void 0) nextParams.strokeFadeRange = patch.strokeFadeRange;
6569
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6570
+ if (patch.enabled !== void 0) {
6571
+ nextParams.strokeEnabled = patch.enabled;
6572
+ }
6573
+ return {
6574
+ ...layer2,
6575
+ enabled,
6576
+ params: nextParams
6577
+ };
6578
+ }
6579
+ return layer2;
6580
+ });
6581
+ const layers = [...nextLayers];
6582
+ if (!found) {
6583
+ const defaultParams = {
6584
+ strokeEnabled: patch.enabled ?? true,
6585
+ strokeColor: patch.strokeColor ?? "#7C6FFF",
6586
+ strokeWidth: patch.strokeWidth ?? 4,
6587
+ strokePosition: patch.strokePosition ?? "outside",
6588
+ strokeOpacity: patch.strokeOpacity ?? 100,
6589
+ strokeLineJoin: patch.strokeLineJoin ?? "round",
6590
+ strokeBlur: patch.strokeBlur ?? 0,
6591
+ strokeType: patch.strokeType ?? "single",
6592
+ strokeColorSecondary: patch.strokeColorSecondary ?? "#FFFFFF",
6593
+ strokeWidthSecondary: patch.strokeWidthSecondary ?? 4,
6594
+ strokeFadeRange: patch.strokeFadeRange ?? 0
6595
+ };
6596
+ const newL = {
6597
+ id: newLayerId(),
6598
+ type: "stroke",
6599
+ name: "Stroke",
6600
+ enabled: patch.enabled ?? true,
6601
+ opacity: 1,
6602
+ blendMode: "source-over",
6603
+ target: "text",
6604
+ params: defaultParams
6605
+ };
6606
+ const fillIdx = layers.findIndex((l) => l.type === "fill");
6607
+ if (fillIdx >= 0) {
6608
+ layers.splice(fillIdx, 0, newL);
6609
+ } else {
6610
+ const maskIdx = layers.findIndex((l) => l.type === "mask" || l.type === "filter");
6611
+ if (maskIdx >= 0) {
6612
+ layers.splice(maskIdx, 0, newL);
6613
+ } else {
6614
+ layers.push(newL);
6615
+ }
6616
+ }
6617
+ }
6618
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6619
+ if (nextLegacyConfig) {
6620
+ if (patch.enabled !== void 0) nextLegacyConfig.strokeEnabled = patch.enabled;
6621
+ if (patch.strokeColor !== void 0) nextLegacyConfig.strokeColor = patch.strokeColor;
6622
+ if (patch.strokeWidth !== void 0) nextLegacyConfig.strokeWidth = patch.strokeWidth;
6623
+ if (patch.strokePosition !== void 0) nextLegacyConfig.strokePosition = patch.strokePosition;
6624
+ if (patch.strokeOpacity !== void 0) nextLegacyConfig.strokeOpacity = patch.strokeOpacity;
6625
+ if (patch.strokeLineJoin !== void 0) nextLegacyConfig.strokeLineJoin = patch.strokeLineJoin;
6626
+ if (patch.strokeBlur !== void 0) nextLegacyConfig.strokeBlur = patch.strokeBlur;
6627
+ if (patch.strokeType !== void 0) nextLegacyConfig.strokeType = patch.strokeType;
6628
+ if (patch.strokeColorSecondary !== void 0) nextLegacyConfig.strokeColorSecondary = patch.strokeColorSecondary;
6629
+ if (patch.strokeWidthSecondary !== void 0) nextLegacyConfig.strokeWidthSecondary = patch.strokeWidthSecondary;
6630
+ if (patch.strokeFadeRange !== void 0) nextLegacyConfig.strokeFadeRange = patch.strokeFadeRange;
6631
+ }
6632
+ return {
6633
+ ...doc,
6634
+ effectLayers: layers,
6635
+ legacyConfig: nextLegacyConfig
6636
+ };
6637
+ }
6638
+ function updateSceneShadow(doc, patch) {
6639
+ let found = false;
6640
+ const nextLayers = doc.effectLayers.map((layer2) => {
6641
+ if (layer2.type === "shadow") {
6642
+ found = true;
6643
+ const nextParams = { ...layer2.params };
6644
+ if (patch.shadowColor !== void 0) nextParams.shadowColor = patch.shadowColor;
6645
+ if (patch.shadowBlur !== void 0) nextParams.shadowBlur = patch.shadowBlur;
6646
+ if (patch.shadowOffsetX !== void 0) nextParams.shadowOffsetX = patch.shadowOffsetX;
6647
+ if (patch.shadowOffsetY !== void 0) nextParams.shadowOffsetY = patch.shadowOffsetY;
6648
+ if (patch.shadowOpacity !== void 0) nextParams.shadowOpacity = patch.shadowOpacity;
6649
+ if (patch.shadowType !== void 0) nextParams.shadowType = patch.shadowType;
6650
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6651
+ if (patch.enabled !== void 0) {
6652
+ nextParams.shadowEnabled = patch.enabled;
6653
+ }
6654
+ return {
6655
+ ...layer2,
6656
+ enabled,
6657
+ params: nextParams
6658
+ };
6659
+ }
6660
+ return layer2;
6661
+ });
6662
+ const layers = [...nextLayers];
6663
+ if (!found) {
6664
+ const defaultParams = {
6665
+ shadowEnabled: patch.enabled ?? true,
6666
+ shadowColor: patch.shadowColor ?? "#000000",
6667
+ shadowBlur: patch.shadowBlur ?? 10,
6668
+ shadowOffsetX: patch.shadowOffsetX ?? 5,
6669
+ shadowOffsetY: patch.shadowOffsetY ?? 5,
6670
+ shadowOpacity: patch.shadowOpacity ?? 80,
6671
+ shadowType: patch.shadowType ?? "drop"
6672
+ };
6673
+ const newL = {
6674
+ id: newLayerId(),
6675
+ type: "shadow",
6676
+ name: "Shadow",
6677
+ enabled: patch.enabled ?? true,
6678
+ opacity: 1,
6679
+ blendMode: "source-over",
6680
+ target: "text",
6681
+ params: defaultParams
6682
+ };
6683
+ const panelIdx = layers.findIndex((l) => l.type === "panel");
6684
+ if (panelIdx >= 0) {
6685
+ layers.splice(panelIdx + 1, 0, newL);
6686
+ } else {
6687
+ layers.unshift(newL);
6688
+ }
6689
+ }
6690
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6691
+ if (nextLegacyConfig) {
6692
+ if (patch.enabled !== void 0) nextLegacyConfig.shadowEnabled = patch.enabled;
6693
+ if (patch.shadowColor !== void 0) nextLegacyConfig.shadowColor = patch.shadowColor;
6694
+ if (patch.shadowBlur !== void 0) nextLegacyConfig.shadowBlur = patch.shadowBlur;
6695
+ if (patch.shadowOffsetX !== void 0) nextLegacyConfig.shadowOffsetX = patch.shadowOffsetX;
6696
+ if (patch.shadowOffsetY !== void 0) nextLegacyConfig.shadowOffsetY = patch.shadowOffsetY;
6697
+ if (patch.shadowOpacity !== void 0) nextLegacyConfig.shadowOpacity = patch.shadowOpacity;
6698
+ if (patch.shadowType !== void 0) nextLegacyConfig.shadowType = patch.shadowType;
6699
+ }
6700
+ return {
6701
+ ...doc,
6702
+ effectLayers: layers,
6703
+ legacyConfig: nextLegacyConfig
6704
+ };
6705
+ }
6706
+ function updateSceneBevel(doc, patch) {
6707
+ let found = false;
6708
+ const nextLayers = doc.effectLayers.map((layer2) => {
6709
+ if (layer2.type === "extrusion") {
6710
+ found = true;
6711
+ const nextParams = { ...layer2.params };
6712
+ if (patch.bevelDepth !== void 0) nextParams.bevelDepth = patch.bevelDepth;
6713
+ if (patch.bevelHighlight !== void 0) nextParams.bevelHighlight = patch.bevelHighlight;
6714
+ if (patch.bevelShadow !== void 0) nextParams.bevelShadow = patch.bevelShadow;
6715
+ if (patch.bevelDirection !== void 0) nextParams.bevelDirection = patch.bevelDirection;
6716
+ if (patch.bevelCoreColor !== void 0) nextParams.bevelCoreColor = patch.bevelCoreColor;
6717
+ if (patch.bevelEdgeColor !== void 0) nextParams.bevelEdgeColor = patch.bevelEdgeColor;
6718
+ if (patch.bevelEdgeWidth !== void 0) nextParams.bevelEdgeWidth = patch.bevelEdgeWidth;
6719
+ if (patch.bevelBlur !== void 0) nextParams.bevelBlur = patch.bevelBlur;
6720
+ if (patch.bevelBlurColor !== void 0) nextParams.bevelBlurColor = patch.bevelBlurColor;
6721
+ if (patch.bevelPerspectiveEnabled !== void 0) nextParams.bevelPerspectiveEnabled = patch.bevelPerspectiveEnabled;
6722
+ if (patch.bevelVanishingPointX !== void 0) nextParams.bevelVanishingPointX = patch.bevelVanishingPointX;
6723
+ if (patch.bevelVanishingPointY !== void 0) nextParams.bevelVanishingPointY = patch.bevelVanishingPointY;
6724
+ if (patch.bevelFocalLength !== void 0) nextParams.bevelFocalLength = patch.bevelFocalLength;
6725
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6726
+ if (patch.enabled !== void 0) {
6727
+ nextParams.bevelEnabled = patch.enabled;
6728
+ }
6729
+ return {
6730
+ ...layer2,
6731
+ enabled,
6732
+ params: nextParams
6733
+ };
6734
+ }
6735
+ return layer2;
6736
+ });
6737
+ const layers = [...nextLayers];
6738
+ if (!found) {
6739
+ const defaultParams = {
6740
+ bevelEnabled: patch.enabled ?? true,
6741
+ bevelDepth: patch.bevelDepth ?? 5,
6742
+ bevelHighlight: patch.bevelHighlight ?? "#FFFFFF",
6743
+ bevelShadow: patch.bevelShadow ?? "#000000",
6744
+ bevelDirection: patch.bevelDirection ?? "bottom-right",
6745
+ bevelCoreColor: patch.bevelCoreColor ?? "#000000",
6746
+ bevelEdgeColor: patch.bevelEdgeColor ?? "#2A2A38",
6747
+ bevelEdgeWidth: patch.bevelEdgeWidth ?? 0,
6748
+ bevelBlur: patch.bevelBlur ?? 0,
6749
+ bevelBlurColor: patch.bevelBlurColor ?? "#000000",
6750
+ bevelPerspectiveEnabled: patch.bevelPerspectiveEnabled ?? false,
6751
+ bevelVanishingPointX: patch.bevelVanishingPointX ?? 40,
6752
+ bevelVanishingPointY: patch.bevelVanishingPointY ?? 80,
6753
+ bevelFocalLength: patch.bevelFocalLength ?? 400
6754
+ };
6755
+ const newL = {
6756
+ id: newLayerId(),
6757
+ type: "extrusion",
6758
+ name: "Bevel / Extrusion",
6759
+ enabled: patch.enabled ?? true,
6760
+ opacity: 1,
6761
+ blendMode: "source-over",
6762
+ target: "text",
6763
+ params: defaultParams
6764
+ };
6765
+ const stackIdx = layers.findIndex((l) => l.type === "duplicateStack");
6766
+ if (stackIdx >= 0) {
6767
+ layers.splice(stackIdx, 0, newL);
6768
+ } else {
6769
+ const strokeIdx = layers.findIndex((l) => l.type === "stroke");
6770
+ if (strokeIdx >= 0) {
6771
+ layers.splice(strokeIdx, 0, newL);
6772
+ } else {
6773
+ const maskIdx = layers.findIndex((l) => l.type === "mask" || l.type === "filter");
6774
+ if (maskIdx >= 0) {
6775
+ layers.splice(maskIdx, 0, newL);
6776
+ } else {
6777
+ layers.push(newL);
6778
+ }
6779
+ }
6780
+ }
6781
+ }
6782
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6783
+ if (nextLegacyConfig) {
6784
+ if (patch.enabled !== void 0) nextLegacyConfig.bevelEnabled = patch.enabled;
6785
+ if (patch.bevelDepth !== void 0) nextLegacyConfig.bevelDepth = patch.bevelDepth;
6786
+ if (patch.bevelHighlight !== void 0) nextLegacyConfig.bevelHighlight = patch.bevelHighlight;
6787
+ if (patch.bevelShadow !== void 0) nextLegacyConfig.bevelShadow = patch.bevelShadow;
6788
+ if (patch.bevelDirection !== void 0) nextLegacyConfig.bevelDirection = patch.bevelDirection;
6789
+ if (patch.bevelCoreColor !== void 0) nextLegacyConfig.bevelCoreColor = patch.bevelCoreColor;
6790
+ if (patch.bevelEdgeColor !== void 0) nextLegacyConfig.bevelEdgeColor = patch.bevelEdgeColor;
6791
+ if (patch.bevelEdgeWidth !== void 0) nextLegacyConfig.bevelEdgeWidth = patch.bevelEdgeWidth;
6792
+ if (patch.bevelBlur !== void 0) nextLegacyConfig.bevelBlur = patch.bevelBlur;
6793
+ if (patch.bevelBlurColor !== void 0) nextLegacyConfig.bevelBlurColor = patch.bevelBlurColor;
6794
+ if (patch.bevelPerspectiveEnabled !== void 0) nextLegacyConfig.bevelPerspectiveEnabled = patch.bevelPerspectiveEnabled;
6795
+ if (patch.bevelVanishingPointX !== void 0) nextLegacyConfig.bevelVanishingPointX = patch.bevelVanishingPointX;
6796
+ if (patch.bevelVanishingPointY !== void 0) nextLegacyConfig.bevelVanishingPointY = patch.bevelVanishingPointY;
6797
+ if (patch.bevelFocalLength !== void 0) nextLegacyConfig.bevelFocalLength = patch.bevelFocalLength;
6798
+ }
6799
+ return {
6800
+ ...doc,
6801
+ effectLayers: layers,
6802
+ legacyConfig: nextLegacyConfig
6803
+ };
6804
+ }
6805
+ function updateSceneStack(doc, patch) {
6806
+ let found = false;
6807
+ const nextLayers = doc.effectLayers.map((layer2) => {
6808
+ if (layer2.type === "duplicateStack") {
6809
+ found = true;
6810
+ const nextParams = { ...layer2.params };
6811
+ if (patch.stackCount !== void 0) nextParams.stackCount = patch.stackCount;
6812
+ if (patch.stackOffsetX !== void 0) nextParams.stackOffsetX = patch.stackOffsetX;
6813
+ if (patch.stackOffsetY !== void 0) nextParams.stackOffsetY = patch.stackOffsetY;
6814
+ if (patch.stackOpacityDecay !== void 0) nextParams.stackOpacityDecay = patch.stackOpacityDecay;
6815
+ if (patch.stackColor1 !== void 0) nextParams.stackColor1 = patch.stackColor1;
6816
+ if (patch.stackColor2 !== void 0) nextParams.stackColor2 = patch.stackColor2;
6817
+ if (patch.stackColor3 !== void 0) nextParams.stackColor3 = patch.stackColor3;
6818
+ if (patch.stackColor4 !== void 0) nextParams.stackColor4 = patch.stackColor4;
6819
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6820
+ if (patch.enabled !== void 0) {
6821
+ nextParams.stackEnabled = patch.enabled;
6822
+ }
6823
+ return {
6824
+ ...layer2,
6825
+ enabled,
6826
+ params: nextParams
6827
+ };
6828
+ }
6829
+ return layer2;
6830
+ });
6831
+ const layers = [...nextLayers];
6832
+ if (!found) {
6833
+ const defaultParams = {
6834
+ stackEnabled: patch.enabled ?? true,
6835
+ stackCount: patch.stackCount ?? 3,
6836
+ stackOffsetX: patch.stackOffsetX ?? 10,
6837
+ stackOffsetY: patch.stackOffsetY ?? -10,
6838
+ stackOpacityDecay: patch.stackOpacityDecay ?? 20,
6839
+ stackColor1: patch.stackColor1 ?? "#FF7C00",
6840
+ stackColor2: patch.stackColor2 ?? "#00FFDD",
6841
+ stackColor3: patch.stackColor3 ?? "#FF00AA",
6842
+ stackColor4: patch.stackColor4 ?? "#AA00FF"
6843
+ };
6844
+ const newL = {
6845
+ id: newLayerId(),
6846
+ type: "duplicateStack",
6847
+ name: "Stack Extrusion",
6848
+ enabled: patch.enabled ?? true,
6849
+ opacity: 1,
6850
+ blendMode: "source-over",
6851
+ target: "text",
6852
+ params: defaultParams
6853
+ };
6854
+ const strokeIdx = layers.findIndex((l) => l.type === "stroke");
6855
+ if (strokeIdx >= 0) {
6856
+ layers.splice(strokeIdx, 0, newL);
6857
+ } else {
6858
+ const maskIdx = layers.findIndex((l) => l.type === "mask" || l.type === "filter");
6859
+ if (maskIdx >= 0) {
6860
+ layers.splice(maskIdx, 0, newL);
6861
+ } else {
6862
+ layers.push(newL);
6863
+ }
6864
+ }
6865
+ }
6866
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6867
+ if (nextLegacyConfig) {
6868
+ if (patch.enabled !== void 0) nextLegacyConfig.stackEnabled = patch.enabled;
6869
+ if (patch.stackCount !== void 0) nextLegacyConfig.stackCount = patch.stackCount;
6870
+ if (patch.stackOffsetX !== void 0) nextLegacyConfig.stackOffsetX = patch.stackOffsetX;
6871
+ if (patch.stackOffsetY !== void 0) nextLegacyConfig.stackOffsetY = patch.stackOffsetY;
6872
+ if (patch.stackOpacityDecay !== void 0) nextLegacyConfig.stackOpacityDecay = patch.stackOpacityDecay;
6873
+ if (patch.stackColor1 !== void 0) nextLegacyConfig.stackColor1 = patch.stackColor1;
6874
+ if (patch.stackColor2 !== void 0) nextLegacyConfig.stackColor2 = patch.stackColor2;
6875
+ if (patch.stackColor3 !== void 0) nextLegacyConfig.stackColor3 = patch.stackColor3;
6876
+ if (patch.stackColor4 !== void 0) nextLegacyConfig.stackColor4 = patch.stackColor4;
6877
+ }
6878
+ return {
6879
+ ...doc,
6880
+ effectLayers: layers,
6881
+ legacyConfig: nextLegacyConfig
6882
+ };
6883
+ }
6884
+ function updateSceneFill(doc, patch) {
6885
+ let found = false;
6886
+ const nextLayers = doc.effectLayers.map((layer2) => {
6887
+ if (layer2.type === "fill") {
6888
+ found = true;
6889
+ const nextParams = { ...layer2.params };
6890
+ if (patch.fillType !== void 0) nextParams.fillType = patch.fillType;
6891
+ if (patch.fillColor !== void 0) nextParams.fillColor = patch.fillColor;
6892
+ if (patch.fillGradientAngle !== void 0) nextParams.fillGradientAngle = patch.fillGradientAngle;
6893
+ if (patch.fillGradientStops !== void 0) nextParams.fillGradientStops = patch.fillGradientStops;
6894
+ if (patch.patternType !== void 0) nextParams.patternType = patch.patternType;
6895
+ if (patch.perCharFillEnabled !== void 0) nextParams.perCharFillEnabled = patch.perCharFillEnabled;
6896
+ if (patch.charFillColors !== void 0) nextParams.charFillColors = patch.charFillColors;
6897
+ const enabled = patch.fillType !== void 0 ? patch.fillType !== "none" : layer2.enabled;
6898
+ return {
6899
+ ...layer2,
6900
+ enabled,
6901
+ params: nextParams
6902
+ };
6903
+ }
6904
+ return layer2;
6905
+ });
6906
+ const layers = [...nextLayers];
6907
+ if (!found) {
6908
+ const defaultParams = {
6909
+ fillType: patch.fillType ?? "solid",
6910
+ fillColor: patch.fillColor ?? "#FFFFFF",
6911
+ fillGradientAngle: patch.fillGradientAngle ?? 90,
6912
+ fillGradientStops: patch.fillGradientStops ?? [
6913
+ { color: "#FFFFFF", offset: 0 },
6914
+ { color: "#E0E0E0", offset: 100 }
6915
+ ],
6916
+ patternType: patch.patternType ?? "chalk",
6917
+ perCharFillEnabled: patch.perCharFillEnabled ?? false,
6918
+ charFillColors: patch.charFillColors ?? []
6919
+ };
6920
+ const newL = {
6921
+ id: newLayerId(),
6922
+ type: "fill",
6923
+ name: "Fill",
6924
+ enabled: patch.fillType !== "none",
6925
+ opacity: 1,
6926
+ blendMode: "source-over",
6927
+ target: "text",
6928
+ params: defaultParams
6929
+ };
6930
+ const maskIdx = layers.findIndex((l) => l.type === "mask" || l.type === "filter");
6931
+ if (maskIdx >= 0) {
6932
+ layers.splice(maskIdx, 0, newL);
6933
+ } else {
6934
+ layers.push(newL);
6935
+ }
6936
+ }
6937
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
6938
+ if (nextLegacyConfig) {
6939
+ if (patch.fillType !== void 0) nextLegacyConfig.fillType = patch.fillType;
6940
+ if (patch.fillColor !== void 0) nextLegacyConfig.fillColor = patch.fillColor;
6941
+ if (patch.fillGradientAngle !== void 0) nextLegacyConfig.fillGradientAngle = patch.fillGradientAngle;
6942
+ if (patch.fillGradientStops !== void 0) nextLegacyConfig.fillGradientStops = patch.fillGradientStops;
6943
+ if (patch.patternType !== void 0) nextLegacyConfig.patternType = patch.patternType;
6944
+ if (patch.perCharFillEnabled !== void 0) nextLegacyConfig.perCharFillEnabled = patch.perCharFillEnabled;
6945
+ if (patch.charFillColors !== void 0) nextLegacyConfig.charFillColors = patch.charFillColors;
6946
+ }
6947
+ return {
6948
+ ...doc,
6949
+ effectLayers: layers,
6950
+ legacyConfig: nextLegacyConfig
6951
+ };
6952
+ }
6953
+ function updateSceneGlow(doc, index, patch) {
6954
+ const currentGlowLayers = doc.effectLayers.filter((l) => l.type === "glow");
6955
+ const layers = [...doc.effectLayers];
6956
+ if (index >= currentGlowLayers.length) {
6957
+ const needed = index - currentGlowLayers.length + 1;
6958
+ for (let i = 0; i < needed; i++) {
6959
+ const isTarget = i === needed - 1;
6960
+ const defaultGlow = {
6961
+ enabled: isTarget ? patch.enabled ?? false : false,
6962
+ color: isTarget ? patch.color ?? "#7C6FFF" : "#7C6FFF",
6963
+ blur: isTarget ? patch.blur ?? 20 : 20,
6964
+ opacity: isTarget ? patch.opacity ?? 80 : 80,
6965
+ type: isTarget ? patch.type ?? "outer" : "outer",
6966
+ strength: isTarget ? patch.strength : void 0,
6967
+ spread: isTarget ? patch.spread : void 0
6968
+ };
6969
+ const newL = {
6970
+ id: newLayerId(),
6971
+ type: "glow",
6972
+ name: `Glow ${currentGlowLayers.length + i + 1}`,
6973
+ enabled: defaultGlow.enabled,
6974
+ opacity: defaultGlow.opacity / 100,
6975
+ blendMode: "source-over",
6976
+ target: "text",
6977
+ params: defaultGlow
6978
+ };
6979
+ const lastGlowIdx = layers.map((l) => l.type).lastIndexOf("glow");
6980
+ if (lastGlowIdx >= 0) {
6981
+ layers.splice(lastGlowIdx + 1 + i, 0, newL);
6982
+ } else {
6983
+ const insertIdx = layers.findIndex((l) => l.type === "mask" || l.type === "filter");
6984
+ if (insertIdx >= 0) {
6985
+ layers.splice(insertIdx + i, 0, newL);
6986
+ } else {
6987
+ layers.push(newL);
6988
+ }
6989
+ }
6990
+ }
6991
+ } else {
6992
+ let glowCount = 0;
6993
+ for (let i = 0; i < layers.length; i++) {
6994
+ if (layers[i].type === "glow") {
6995
+ if (glowCount === index) {
6996
+ const layer2 = layers[i];
6997
+ const nextParams = { ...layer2.params, ...patch };
6998
+ const enabled = patch.enabled !== void 0 ? patch.enabled : layer2.enabled;
6999
+ const opacity = patch.opacity !== void 0 ? patch.opacity / 100 : layer2.opacity;
7000
+ layers[i] = {
7001
+ ...layer2,
7002
+ enabled,
7003
+ opacity,
7004
+ params: nextParams
7005
+ };
7006
+ break;
7007
+ }
7008
+ glowCount++;
7009
+ }
7010
+ }
7011
+ }
7012
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
7013
+ if (nextLegacyConfig) {
7014
+ if (!nextLegacyConfig.glowLayers) nextLegacyConfig.glowLayers = [];
7015
+ while (nextLegacyConfig.glowLayers.length <= index) {
7016
+ nextLegacyConfig.glowLayers.push({
7017
+ enabled: false,
7018
+ color: "#7C6FFF",
7019
+ blur: 20,
7020
+ opacity: 80,
7021
+ type: "outer"
7022
+ });
7023
+ }
7024
+ nextLegacyConfig.glowLayers[index] = { ...nextLegacyConfig.glowLayers[index], ...patch };
7025
+ }
7026
+ return {
7027
+ ...doc,
7028
+ effectLayers: layers,
7029
+ legacyConfig: nextLegacyConfig
7030
+ };
7031
+ }
7032
+ function updateSceneCanvas(doc, patch) {
7033
+ const nextCanvas = { ...doc.canvas };
7034
+ if (patch.width !== void 0) nextCanvas.width = patch.width;
7035
+ if (patch.height !== void 0) nextCanvas.height = patch.height;
7036
+ if (patch.background !== void 0) nextCanvas.background = patch.background;
7037
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
7038
+ if (nextLegacyConfig) {
7039
+ if (patch.width !== void 0) nextLegacyConfig.canvasWidth = patch.width;
7040
+ if (patch.height !== void 0) nextLegacyConfig.canvasHeight = patch.height;
7041
+ }
7042
+ return {
7043
+ ...doc,
7044
+ canvas: nextCanvas,
7045
+ legacyConfig: nextLegacyConfig
7046
+ };
7047
+ }
7048
+ function updateSceneCustomEngine(doc, patch) {
7049
+ let nextEngineId = doc.customEngineId;
7050
+ if (patch.customRenderer !== void 0) {
7051
+ nextEngineId = patch.customRenderer ? LEGACY_RENDERER_MAP[patch.customRenderer] ?? null : null;
7052
+ }
7053
+ const nextParams = { ...doc.engineParams, ...patch };
7054
+ delete nextParams.customRenderer;
7055
+ const nextLayers = doc.effectLayers.map((layer2) => {
7056
+ if (layer2.type === "customEngine") {
7057
+ if (layer2.name === "Custom Engine") {
7058
+ return {
7059
+ ...layer2,
7060
+ params: { ...layer2.params, engineId: nextEngineId }
7061
+ };
7062
+ } else if (layer2.name === "Engine Params") {
7063
+ return {
7064
+ ...layer2,
7065
+ params: { ...layer2.params, ...nextParams }
7066
+ };
7067
+ }
7068
+ }
7069
+ return layer2;
7070
+ });
7071
+ const nextLegacyConfig = doc.legacyConfig ? { ...doc.legacyConfig } : void 0;
7072
+ if (nextLegacyConfig) {
7073
+ if (patch.customRenderer !== void 0) nextLegacyConfig.customRenderer = patch.customRenderer;
7074
+ if (patch.inkColor !== void 0) nextLegacyConfig.inkColor = patch.inkColor;
7075
+ if (patch.bristleDensity !== void 0) nextLegacyConfig.bristleDensity = patch.bristleDensity;
7076
+ if (patch.bristleSkipRate !== void 0) nextLegacyConfig.bristleSkipRate = patch.bristleSkipRate;
7077
+ if (patch.dripRate !== void 0) nextLegacyConfig.dripRate = patch.dripRate;
7078
+ if (patch.dripMaxLength !== void 0) nextLegacyConfig.dripMaxLength = patch.dripMaxLength;
7079
+ if (patch.grainDensity !== void 0) nextLegacyConfig.grainDensity = patch.grainDensity;
7080
+ if (patch.skewX !== void 0) nextLegacyConfig.skewX = patch.skewX;
7081
+ }
7082
+ return {
7083
+ ...doc,
7084
+ customEngineId: nextEngineId,
7085
+ engineParams: nextParams,
7086
+ effectLayers: nextLayers,
7087
+ legacyConfig: nextLegacyConfig
7088
+ };
7089
+ }
7090
+ var TextEffectBuilder = class _TextEffectBuilder {
7091
+ config;
7092
+ constructor(initialConfig) {
7093
+ this.config = { ...defaultConfig, ...initialConfig };
7094
+ }
7095
+ /** Load builder from an existing TextEffectConfig object */
7096
+ static fromConfig(config) {
7097
+ return new _TextEffectBuilder(config);
7098
+ }
7099
+ /** Load builder from an existing SceneDocument */
7100
+ static fromScene(scene) {
7101
+ return new _TextEffectBuilder(sceneToConfig(scene));
7102
+ }
7103
+ /**
7104
+ * Load builder from a downloaded TextEffectDefinition.
7105
+ * Resolves the styling definition structure to a flat engine config.
7106
+ */
7107
+ static fromDefinition(effect, text = "CLYPRA", fontSize = 80, canvasWidth = 800, canvasHeight = 200) {
7108
+ const config = _buildConfig(effect, text, fontSize, canvasWidth, canvasHeight);
7109
+ return new _TextEffectBuilder(config);
7110
+ }
7111
+ /** Set text string content */
7112
+ setText(text) {
7113
+ this.config.text = text;
7114
+ return this;
7115
+ }
7116
+ /** Configure Font and alignment settings */
7117
+ setFont(font) {
7118
+ if (font.family !== void 0) this.config.fontFamily = font.family;
7119
+ if (font.weight !== void 0) this.config.fontWeight = font.weight;
7120
+ if (font.style !== void 0) this.config.fontStyle = font.style;
7121
+ if (font.size !== void 0) this.config.fontSize = font.size;
7122
+ if (font.letterSpacing !== void 0) this.config.letterSpacing = font.letterSpacing;
7123
+ if (font.lineHeight !== void 0) this.config.lineHeight = font.lineHeight;
7124
+ return this;
7125
+ }
7126
+ /** Configure Background Panel (bounding plate) */
7127
+ setPanel(panel) {
7128
+ if (panel.enabled !== void 0) this.config.panelEnabled = panel.enabled;
7129
+ if (panel.color !== void 0) this.config.panelColor = panel.color;
7130
+ if (panel.opacity !== void 0) this.config.panelOpacity = panel.opacity;
7131
+ if (panel.radius !== void 0) this.config.panelRadius = panel.radius;
7132
+ if (panel.paddingX !== void 0) this.config.panelPaddingX = panel.paddingX;
7133
+ if (panel.paddingY !== void 0) this.config.panelPaddingY = panel.paddingY;
7134
+ if (panel.strokeEnabled !== void 0) this.config.panelStrokeEnabled = panel.strokeEnabled;
7135
+ if (panel.strokeColor !== void 0) this.config.panelStrokeColor = panel.strokeColor;
7136
+ if (panel.strokeWidth !== void 0) this.config.panelStrokeWidth = panel.strokeWidth;
7137
+ return this;
7138
+ }
7139
+ /** Configure outline / stroke styling */
7140
+ setStroke(stroke) {
7141
+ if (stroke.enabled !== void 0) this.config.strokeEnabled = stroke.enabled;
7142
+ if (stroke.color !== void 0) this.config.strokeColor = stroke.color;
7143
+ if (stroke.width !== void 0) this.config.strokeWidth = stroke.width;
7144
+ if (stroke.position !== void 0) this.config.strokePosition = stroke.position;
7145
+ if (stroke.opacity !== void 0) this.config.strokeOpacity = stroke.opacity;
7146
+ if (stroke.lineJoin !== void 0) this.config.strokeLineJoin = stroke.lineJoin;
7147
+ if (stroke.blur !== void 0) this.config.strokeBlur = stroke.blur;
7148
+ if (stroke.type !== void 0) this.config.strokeType = stroke.type;
7149
+ if (stroke.colorSecondary !== void 0) this.config.strokeColorSecondary = stroke.colorSecondary;
7150
+ if (stroke.widthSecondary !== void 0) this.config.strokeWidthSecondary = stroke.widthSecondary;
7151
+ if (stroke.fadeRange !== void 0) this.config.strokeFadeRange = stroke.fadeRange;
7152
+ return this;
7153
+ }
7154
+ /** Configure drop shadow / inner shadow styling */
7155
+ setShadow(shadow) {
7156
+ if (shadow.enabled !== void 0) this.config.shadowEnabled = shadow.enabled;
7157
+ if (shadow.color !== void 0) this.config.shadowColor = shadow.color;
7158
+ if (shadow.blur !== void 0) this.config.shadowBlur = shadow.blur;
7159
+ if (shadow.offsetX !== void 0) this.config.shadowOffsetX = shadow.offsetX;
7160
+ if (shadow.offsetY !== void 0) this.config.shadowOffsetY = shadow.offsetY;
7161
+ if (shadow.opacity !== void 0) this.config.shadowOpacity = shadow.opacity;
7162
+ if (shadow.type !== void 0) this.config.shadowType = shadow.type;
7163
+ return this;
7164
+ }
7165
+ /** Configure a specific glow layer by index */
7166
+ setGlow(index, glow) {
7167
+ if (!this.config.glowLayers) this.config.glowLayers = [];
7168
+ while (this.config.glowLayers.length <= index) {
7169
+ this.config.glowLayers.push({ enabled: false, color: "#7C6FFF", blur: 20, opacity: 80, type: "outer" });
7170
+ }
7171
+ this.config.glowLayers[index] = { ...this.config.glowLayers[index], ...glow };
7172
+ return this;
7173
+ }
7174
+ /** Configure solid color fill */
7175
+ setFillColor(color) {
7176
+ this.config.fillType = "solid";
7177
+ this.config.fillColor = color;
7178
+ return this;
7179
+ }
7180
+ /** Configure linear gradient fill */
7181
+ setFillGradient(angle, stops) {
7182
+ this.config.fillType = "linear";
7183
+ this.config.fillGradientAngle = angle;
7184
+ this.config.fillGradientStops = stops;
7185
+ return this;
7186
+ }
7187
+ /** Configure texture pattern fill */
7188
+ setFillPattern(patternType) {
7189
+ this.config.fillType = "pattern";
7190
+ this.config.patternType = patternType;
7191
+ return this;
7192
+ }
7193
+ /** Configure per-character solid color fill overrides */
7194
+ setPerCharFill(enabled, colors) {
7195
+ this.config.perCharFillEnabled = enabled;
7196
+ this.config.charFillColors = colors;
7197
+ return this;
7198
+ }
7199
+ /** Configure 3D extrusion/bevel settings */
7200
+ setBevel(bevel) {
7201
+ if (bevel.enabled !== void 0) this.config.bevelEnabled = bevel.enabled;
7202
+ if (bevel.depth !== void 0) this.config.bevelDepth = bevel.depth;
7203
+ if (bevel.highlight !== void 0) this.config.bevelHighlight = bevel.highlight;
7204
+ if (bevel.bevelShadow !== void 0) this.config.bevelShadow = bevel.bevelShadow;
7205
+ if (bevel.direction !== void 0) this.config.bevelDirection = bevel.direction;
7206
+ if (bevel.coreColor !== void 0) this.config.bevelCoreColor = bevel.coreColor;
7207
+ if (bevel.edgeColor !== void 0) this.config.bevelEdgeColor = bevel.edgeColor;
7208
+ if (bevel.edgeWidth !== void 0) this.config.bevelEdgeWidth = bevel.edgeWidth;
7209
+ if (bevel.blur !== void 0) this.config.bevelBlur = bevel.blur;
7210
+ if (bevel.blurColor !== void 0) this.config.bevelBlurColor = bevel.blurColor;
7211
+ if (bevel.perspectiveEnabled !== void 0) this.config.bevelPerspectiveEnabled = bevel.perspectiveEnabled;
7212
+ if (bevel.vanishingPointX !== void 0) this.config.bevelVanishingPointX = bevel.vanishingPointX;
7213
+ if (bevel.vanishingPointY !== void 0) this.config.bevelVanishingPointY = bevel.vanishingPointY;
7214
+ if (bevel.focalLength !== void 0) this.config.bevelFocalLength = bevel.focalLength;
7215
+ return this;
7216
+ }
7217
+ /** Configure multi-stack duplicate extrusion */
7218
+ setStack(stack) {
7219
+ if (stack.enabled !== void 0) this.config.stackEnabled = stack.enabled;
7220
+ if (stack.count !== void 0) this.config.stackCount = stack.count;
7221
+ if (stack.offsetX !== void 0) this.config.stackOffsetX = stack.offsetX;
7222
+ if (stack.offsetY !== void 0) this.config.stackOffsetY = stack.offsetY;
7223
+ if (stack.opacityDecay !== void 0) this.config.stackOpacityDecay = stack.opacityDecay;
7224
+ if (stack.color1 !== void 0) this.config.stackColor1 = stack.color1;
7225
+ if (stack.color2 !== void 0) this.config.stackColor2 = stack.color2;
7226
+ if (stack.color3 !== void 0) this.config.stackColor3 = stack.color3;
7227
+ if (stack.color4 !== void 0) this.config.stackColor4 = stack.color4;
7228
+ return this;
7229
+ }
7230
+ /** Configure canvas viewport size, alignment positioning, and wrapping behavior */
7231
+ setCanvas(canvas) {
7232
+ if (canvas.width !== void 0) this.config.canvasWidth = canvas.width;
7233
+ if (canvas.height !== void 0) this.config.canvasHeight = canvas.height;
7234
+ if (canvas.posX !== void 0) this.config.textPosX = canvas.posX;
7235
+ if (canvas.posY !== void 0) this.config.textPosY = canvas.posY;
7236
+ if (canvas.wrapText !== void 0) this.config.wrapText = canvas.wrapText;
7237
+ if (canvas.autoFitText !== void 0) this.config.autoFitText = canvas.autoFitText;
7238
+ return this;
7239
+ }
7240
+ /** Configure procedural InkBrushEngine variables (when customRenderer = InkBrushEngine) */
7241
+ setInkBrush(ink) {
7242
+ if (ink.inkColor !== void 0) this.config.inkColor = ink.inkColor;
7243
+ if (ink.bristleDensity !== void 0) this.config.bristleDensity = ink.bristleDensity;
7244
+ if (ink.bristleSkipRate !== void 0) this.config.bristleSkipRate = ink.bristleSkipRate;
7245
+ if (ink.dripRate !== void 0) this.config.dripRate = ink.dripRate;
7246
+ if (ink.dripMaxLength !== void 0) this.config.dripMaxLength = ink.dripMaxLength;
7247
+ if (ink.grainDensity !== void 0) this.config.grainDensity = ink.grainDensity;
7248
+ if (ink.skewX !== void 0) this.config.skewX = ink.skewX;
7249
+ return this;
7250
+ }
7251
+ /** Build and return a copy of the updated TextEffectConfig */
7252
+ buildConfig() {
7253
+ return { ...this.config };
7254
+ }
7255
+ /** Build and return a SceneDocument prepared for rendering with evaluateScene */
7256
+ buildScene() {
7257
+ return textEffectConfigToScene(this.config);
7258
+ }
7259
+ };
6454
7260
  export {
6455
7261
  COMPOSITION_PRESETS,
6456
7262
  CUSTOM_ENGINE_IDS,
@@ -6475,6 +7281,7 @@ export {
6475
7281
  SCENE_VERSION,
6476
7282
  SUPPORTED_FONT_FAMILIES,
6477
7283
  TEMPLATE_CATEGORIES,
7284
+ TextEffectBuilder,
6478
7285
  TextEffectRenderer,
6479
7286
  WEBM_EXPORT_MAX_FRAMES,
6480
7287
  WebGLCompositor,
@@ -6611,6 +7418,16 @@ export {
6611
7418
  textEffectConfigToScene,
6612
7419
  trackId,
6613
7420
  updateKeyframe,
7421
+ updateSceneBevel,
7422
+ updateSceneCanvas,
7423
+ updateSceneCustomEngine,
7424
+ updateSceneFill,
7425
+ updateSceneGlow,
7426
+ updateScenePanel,
7427
+ updateSceneShadow,
7428
+ updateSceneStack,
7429
+ updateSceneStroke,
7430
+ updateSceneText,
6614
7431
  updateStaticProperty,
6615
7432
  updateTimeline,
6616
7433
  updateTrack,