@remotion/web-renderer 4.0.395 → 4.0.396

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.
Files changed (71) hide show
  1. package/dist/border-radius.d.ts +31 -0
  2. package/dist/border-radius.js +152 -0
  3. package/dist/calculate-transforms.d.ts +2 -0
  4. package/dist/calculate-transforms.js +17 -0
  5. package/dist/composable.d.ts +2 -8
  6. package/dist/compose-canvas.js +28 -4
  7. package/dist/compose.d.ts +4 -3
  8. package/dist/compose.js +39 -12
  9. package/dist/drawing/border-radius.d.ts +3 -5
  10. package/dist/drawing/border-radius.js +12 -11
  11. package/dist/drawing/calculate-transforms.d.ts +6 -2
  12. package/dist/drawing/calculate-transforms.js +19 -22
  13. package/dist/drawing/canvas-offset-from-rect.d.ts +8 -0
  14. package/dist/drawing/canvas-offset-from-rect.js +12 -0
  15. package/dist/drawing/clamp-rect-to-parent-bounds.d.ts +4 -0
  16. package/dist/drawing/clamp-rect-to-parent-bounds.js +7 -0
  17. package/dist/drawing/compose-canvas.d.ts +1 -0
  18. package/dist/drawing/compose-canvas.js +36 -0
  19. package/dist/drawing/compose-svg.d.ts +1 -0
  20. package/dist/drawing/compose-svg.js +34 -0
  21. package/dist/drawing/compose.d.ts +5 -0
  22. package/dist/drawing/compose.js +6 -0
  23. package/dist/drawing/draw-border.d.ts +2 -5
  24. package/dist/drawing/draw-border.js +37 -37
  25. package/dist/drawing/draw-element-to-canvas.d.ts +2 -1
  26. package/dist/drawing/draw-element-to-canvas.js +8 -36
  27. package/dist/drawing/draw-element.d.ts +5 -3
  28. package/dist/drawing/draw-element.js +29 -14
  29. package/dist/drawing/draw-outline.d.ts +9 -0
  30. package/dist/drawing/draw-outline.js +116 -0
  31. package/dist/drawing/get-bounding-box-including-shadow.d.ts +1 -0
  32. package/dist/drawing/get-bounding-box-including-shadow.js +6 -0
  33. package/dist/drawing/get-computed-style-cache.d.ts +0 -0
  34. package/dist/drawing/get-computed-style-cache.js +1 -0
  35. package/dist/drawing/get-pretransform-rect.d.ts +1 -0
  36. package/dist/drawing/get-pretransform-rect.js +31 -0
  37. package/dist/drawing/handle-3d-transform.d.ts +10 -0
  38. package/dist/drawing/handle-3d-transform.js +39 -0
  39. package/dist/drawing/has-transform.d.ts +4 -0
  40. package/dist/drawing/has-transform.js +14 -0
  41. package/dist/drawing/overflow.d.ts +7 -0
  42. package/dist/drawing/overflow.js +12 -0
  43. package/dist/drawing/process-node.d.ts +17 -0
  44. package/dist/drawing/process-node.js +41 -0
  45. package/dist/drawing/text/handle-text-node.d.ts +6 -5
  46. package/dist/drawing/text/handle-text-node.js +5 -5
  47. package/dist/drawing/transform-in-3d.d.ts +7 -7
  48. package/dist/drawing/transform-in-3d.js +20 -12
  49. package/dist/drawing/transform-rect-with-matrix.d.ts +4 -0
  50. package/dist/drawing/transform-rect-with-matrix.js +19 -0
  51. package/dist/esm/index.mjs +501 -218
  52. package/dist/find-canvas-elements.d.ts +1 -0
  53. package/dist/find-canvas-elements.js +13 -0
  54. package/dist/find-capturable-elements.d.ts +1 -1
  55. package/dist/find-capturable-elements.js +20 -22
  56. package/dist/get-biggest-bounding-client-rect.js +14 -4
  57. package/dist/internal-state.d.ts +9 -0
  58. package/dist/internal-state.js +12 -0
  59. package/dist/opacity.d.ts +4 -0
  60. package/dist/opacity.js +7 -0
  61. package/dist/render-media-on-web.d.ts +2 -0
  62. package/dist/render-media-on-web.js +5 -0
  63. package/dist/render-still-on-web.d.ts +5 -1
  64. package/dist/render-still-on-web.js +4 -1
  65. package/dist/take-screenshot.d.ts +5 -2
  66. package/dist/take-screenshot.js +16 -4
  67. package/dist/transform.d.ts +4 -0
  68. package/dist/transform.js +6 -0
  69. package/package.json +6 -6
  70. package/dist/drawing/text/get-base-height.d.ts +0 -1
  71. package/dist/drawing/text/get-base-height.js +0 -13
@@ -382,6 +382,23 @@ var getDefaultAudioEncodingConfig = async () => {
382
382
  return null;
383
383
  };
384
384
 
385
+ // src/internal-state.ts
386
+ var makeInternalState = () => {
387
+ let drawn3dPixels = 0;
388
+ let drawn3dTextures = 0;
389
+ return {
390
+ getDrawn3dPixels: () => drawn3dPixels,
391
+ getDrawn3dTextures: () => drawn3dTextures,
392
+ add3DTransform: ({
393
+ canvasWidth,
394
+ canvasHeight
395
+ }) => {
396
+ drawn3dPixels += canvasWidth * canvasHeight;
397
+ drawn3dTextures++;
398
+ }
399
+ };
400
+ };
401
+
385
402
  // src/mediabunny-mappings.ts
386
403
  import {
387
404
  Mp4OutputFormat,
@@ -583,27 +600,18 @@ var drawDomElement = (node) => {
583
600
  return domDrawFn;
584
601
  };
585
602
 
586
- // src/drawing/draw-element-to-canvas.ts
587
- import { Internals as Internals4 } from "remotion";
588
-
589
- // src/get-biggest-bounding-client-rect.ts
590
- var getBiggestBoundingClientRect = (element) => {
591
- const treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
592
- let mostLeft = Infinity;
593
- let mostTop = Infinity;
594
- let mostRight = -Infinity;
595
- let mostBottom = -Infinity;
596
- while (true) {
597
- const rect = treeWalker.currentNode.getBoundingClientRect();
598
- mostLeft = Math.min(mostLeft, rect.left);
599
- mostTop = Math.min(mostTop, rect.top);
600
- mostRight = Math.max(mostRight, rect.right);
601
- mostBottom = Math.max(mostBottom, rect.bottom);
602
- if (!treeWalker.nextNode()) {
603
- break;
604
- }
605
- }
606
- return new DOMRect(mostLeft, mostTop, mostRight - mostLeft, mostBottom - mostTop);
603
+ // src/drawing/has-transform.ts
604
+ var hasTransformCssValue = (style) => {
605
+ return style.transform !== "none" && style.transform !== "";
606
+ };
607
+ var hasRotateCssValue = (style) => {
608
+ return style.rotate !== "none" && style.rotate !== "";
609
+ };
610
+ var hasScaleCssValue = (style) => {
611
+ return style.scale !== "none" && style.scale !== "";
612
+ };
613
+ var hasAnyTransformCssValue = (style) => {
614
+ return hasTransformCssValue(style) || hasRotateCssValue(style) || hasScaleCssValue(style);
607
615
  };
608
616
 
609
617
  // src/drawing/parse-transform-origin.ts
@@ -625,30 +633,33 @@ var getInternalTransformOrigin = (transform) => {
625
633
  };
626
634
  return origin;
627
635
  };
628
- var getGlobalTransformOrigin = (transform) => {
636
+ var getGlobalTransformOrigin = ({
637
+ transform,
638
+ offsetLeft,
639
+ offsetTop
640
+ }) => {
629
641
  const { x: originX, y: originY } = getInternalTransformOrigin(transform);
630
642
  return {
631
- x: originX + transform.boundingClientRect.left,
632
- y: originY + transform.boundingClientRect.top
643
+ x: originX + transform.boundingClientRect.left - offsetLeft,
644
+ y: originY + transform.boundingClientRect.top - offsetTop
633
645
  };
634
646
  };
635
- var calculateTransforms = (element) => {
647
+ var calculateTransforms = ({
648
+ element,
649
+ offsetLeft,
650
+ offsetTop
651
+ }) => {
636
652
  let parent = element;
637
653
  const transforms = [];
638
654
  const toReset = [];
639
- let opacity = 1;
640
655
  let elementComputedStyle = null;
641
656
  while (parent) {
642
657
  const computedStyle = getComputedStyle(parent);
643
- const parentOpacity = computedStyle.opacity;
644
- if (parentOpacity && parentOpacity !== "") {
645
- opacity *= parseFloat(parentOpacity);
646
- }
647
658
  if (parent === element) {
648
659
  elementComputedStyle = computedStyle;
649
660
  }
650
- if (computedStyle.transform && computedStyle.transform !== "none" || parent === element) {
651
- const toParse = computedStyle.transform === "none" || computedStyle.transform === "" ? undefined : computedStyle.transform;
661
+ if (hasAnyTransformCssValue(computedStyle) || parent === element) {
662
+ const toParse = hasTransformCssValue(computedStyle) ? computedStyle.transform : undefined;
652
663
  const matrix = new DOMMatrix(toParse);
653
664
  const { transform, scale, rotate } = parent.style;
654
665
  const additionalMatrices = [];
@@ -663,7 +674,7 @@ var calculateTransforms = (element) => {
663
674
  parent.style.scale = "none";
664
675
  parent.style.rotate = "none";
665
676
  transforms.push({
666
- rect: parent,
677
+ element: parent,
667
678
  transformOrigin: computedStyle.transformOrigin,
668
679
  boundingClientRect: null,
669
680
  matrices: additionalMatrices
@@ -678,17 +689,18 @@ var calculateTransforms = (element) => {
678
689
  parent = parent.parentElement;
679
690
  }
680
691
  for (const transform of transforms) {
681
- transform.boundingClientRect = transform.rect.getBoundingClientRect();
692
+ transform.boundingClientRect = transform.element.getBoundingClientRect();
682
693
  }
683
694
  const dimensions = transforms[0].boundingClientRect;
684
695
  const nativeTransformOrigin = getInternalTransformOrigin(transforms[0]);
685
696
  const totalMatrix = new DOMMatrix;
686
697
  for (const transform of transforms.slice().reverse()) {
687
- if (!transform.boundingClientRect) {
688
- throw new Error("Bounding client rect not found");
689
- }
690
698
  for (const matrix of transform.matrices) {
691
- const globalTransformOrigin = getGlobalTransformOrigin(transform);
699
+ const globalTransformOrigin = getGlobalTransformOrigin({
700
+ transform,
701
+ offsetLeft,
702
+ offsetTop
703
+ });
692
704
  const transformMatrix = new DOMMatrix().translate(globalTransformOrigin.x, globalTransformOrigin.y).multiply(matrix).translate(-globalTransformOrigin.x, -globalTransformOrigin.y);
693
705
  totalMatrix.multiplySelf(transformMatrix);
694
706
  }
@@ -705,8 +717,8 @@ var calculateTransforms = (element) => {
705
717
  }
706
718
  },
707
719
  nativeTransformOrigin,
708
- opacity,
709
- computedStyle: elementComputedStyle
720
+ computedStyle: elementComputedStyle,
721
+ opacity: elementComputedStyle.opacity && elementComputedStyle.opacity !== "" ? parseFloat(elementComputedStyle.opacity) : 1
710
722
  };
711
723
  };
712
724
 
@@ -811,33 +823,31 @@ function parseBorderRadius({
811
823
  }
812
824
  function setBorderRadius({
813
825
  ctx,
814
- x,
815
- y,
816
- width,
817
- height,
818
- borderRadius
826
+ rect,
827
+ borderRadius,
828
+ forceClipEvenWhenZero = false
819
829
  }) {
820
- if (borderRadius.topLeft.horizontal === 0 && borderRadius.topLeft.vertical === 0 && borderRadius.topRight.horizontal === 0 && borderRadius.topRight.vertical === 0 && borderRadius.bottomRight.horizontal === 0 && borderRadius.bottomRight.vertical === 0 && borderRadius.bottomLeft.horizontal === 0 && borderRadius.bottomLeft.vertical === 0) {
830
+ if (borderRadius.topLeft.horizontal === 0 && borderRadius.topLeft.vertical === 0 && borderRadius.topRight.horizontal === 0 && borderRadius.topRight.vertical === 0 && borderRadius.bottomRight.horizontal === 0 && borderRadius.bottomRight.vertical === 0 && borderRadius.bottomLeft.horizontal === 0 && borderRadius.bottomLeft.vertical === 0 && !forceClipEvenWhenZero) {
821
831
  return () => {};
822
832
  }
823
833
  ctx.save();
824
834
  ctx.beginPath();
825
- ctx.moveTo(x + borderRadius.topLeft.horizontal, y);
826
- ctx.lineTo(x + width - borderRadius.topRight.horizontal, y);
835
+ ctx.moveTo(rect.left + borderRadius.topLeft.horizontal, rect.top);
836
+ ctx.lineTo(rect.left + rect.width - borderRadius.topRight.horizontal, rect.top);
827
837
  if (borderRadius.topRight.horizontal > 0 || borderRadius.topRight.vertical > 0) {
828
- ctx.ellipse(x + width - borderRadius.topRight.horizontal, y + borderRadius.topRight.vertical, borderRadius.topRight.horizontal, borderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
838
+ ctx.ellipse(rect.left + rect.width - borderRadius.topRight.horizontal, rect.top + borderRadius.topRight.vertical, borderRadius.topRight.horizontal, borderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
829
839
  }
830
- ctx.lineTo(x + width, y + height - borderRadius.bottomRight.vertical);
840
+ ctx.lineTo(rect.left + rect.width, rect.top + rect.height - borderRadius.bottomRight.vertical);
831
841
  if (borderRadius.bottomRight.horizontal > 0 || borderRadius.bottomRight.vertical > 0) {
832
- ctx.ellipse(x + width - borderRadius.bottomRight.horizontal, y + height - borderRadius.bottomRight.vertical, borderRadius.bottomRight.horizontal, borderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
842
+ ctx.ellipse(rect.left + rect.width - borderRadius.bottomRight.horizontal, rect.top + rect.height - borderRadius.bottomRight.vertical, borderRadius.bottomRight.horizontal, borderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
833
843
  }
834
- ctx.lineTo(x + borderRadius.bottomLeft.horizontal, y + height);
844
+ ctx.lineTo(rect.left + borderRadius.bottomLeft.horizontal, rect.top + rect.height);
835
845
  if (borderRadius.bottomLeft.horizontal > 0 || borderRadius.bottomLeft.vertical > 0) {
836
- ctx.ellipse(x + borderRadius.bottomLeft.horizontal, y + height - borderRadius.bottomLeft.vertical, borderRadius.bottomLeft.horizontal, borderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
846
+ ctx.ellipse(rect.left + borderRadius.bottomLeft.horizontal, rect.top + rect.height - borderRadius.bottomLeft.vertical, borderRadius.bottomLeft.horizontal, borderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
837
847
  }
838
- ctx.lineTo(x, y + borderRadius.topLeft.vertical);
848
+ ctx.lineTo(rect.left, rect.top + borderRadius.topLeft.vertical);
839
849
  if (borderRadius.topLeft.horizontal > 0 || borderRadius.topLeft.vertical > 0) {
840
- ctx.ellipse(x + borderRadius.topLeft.horizontal, y + borderRadius.topLeft.vertical, borderRadius.topLeft.horizontal, borderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
850
+ ctx.ellipse(rect.left + borderRadius.topLeft.horizontal, rect.top + borderRadius.topLeft.vertical, borderRadius.topLeft.horizontal, borderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
841
851
  }
842
852
  ctx.closePath();
843
853
  ctx.clip();
@@ -1059,10 +1069,7 @@ var drawUniformBorder = ({
1059
1069
  };
1060
1070
  var drawBorder = ({
1061
1071
  ctx,
1062
- x,
1063
- y,
1064
- width,
1065
- height,
1072
+ rect,
1066
1073
  borderRadius,
1067
1074
  computedStyle
1068
1075
  }) => {
@@ -1078,10 +1085,10 @@ var drawBorder = ({
1078
1085
  if (allSidesEqual) {
1079
1086
  drawUniformBorder({
1080
1087
  ctx,
1081
- x,
1082
- y,
1083
- width,
1084
- height,
1088
+ x: rect.left,
1089
+ y: rect.top,
1090
+ width: rect.width,
1091
+ height: rect.height,
1085
1092
  borderRadius,
1086
1093
  borderWidth: borders.top.width,
1087
1094
  borderColor: borders.top.color,
@@ -1091,10 +1098,10 @@ var drawBorder = ({
1091
1098
  drawCorner({
1092
1099
  ctx,
1093
1100
  corner: "topLeft",
1094
- x,
1095
- y,
1096
- width,
1097
- height,
1101
+ x: rect.left,
1102
+ y: rect.top,
1103
+ width: rect.width,
1104
+ height: rect.height,
1098
1105
  borderRadius,
1099
1106
  topBorder: borders.top,
1100
1107
  rightBorder: borders.right,
@@ -1104,10 +1111,10 @@ var drawBorder = ({
1104
1111
  drawCorner({
1105
1112
  ctx,
1106
1113
  corner: "topRight",
1107
- x,
1108
- y,
1109
- width,
1110
- height,
1114
+ x: rect.left,
1115
+ y: rect.top,
1116
+ width: rect.width,
1117
+ height: rect.height,
1111
1118
  borderRadius,
1112
1119
  topBorder: borders.top,
1113
1120
  rightBorder: borders.right,
@@ -1117,10 +1124,10 @@ var drawBorder = ({
1117
1124
  drawCorner({
1118
1125
  ctx,
1119
1126
  corner: "bottomRight",
1120
- x,
1121
- y,
1122
- width,
1123
- height,
1127
+ x: rect.left,
1128
+ y: rect.top,
1129
+ width: rect.width,
1130
+ height: rect.height,
1124
1131
  borderRadius,
1125
1132
  topBorder: borders.top,
1126
1133
  rightBorder: borders.right,
@@ -1130,10 +1137,10 @@ var drawBorder = ({
1130
1137
  drawCorner({
1131
1138
  ctx,
1132
1139
  corner: "bottomLeft",
1133
- x,
1134
- y,
1135
- width,
1136
- height,
1140
+ x: rect.left,
1141
+ y: rect.top,
1142
+ width: rect.width,
1143
+ height: rect.height,
1137
1144
  borderRadius,
1138
1145
  topBorder: borders.top,
1139
1146
  rightBorder: borders.right,
@@ -1143,40 +1150,40 @@ var drawBorder = ({
1143
1150
  drawBorderSide({
1144
1151
  ctx,
1145
1152
  side: "top",
1146
- x,
1147
- y,
1148
- width,
1149
- height,
1153
+ x: rect.left,
1154
+ y: rect.top,
1155
+ width: rect.width,
1156
+ height: rect.height,
1150
1157
  borderRadius,
1151
1158
  borderProperties: borders.top
1152
1159
  });
1153
1160
  drawBorderSide({
1154
1161
  ctx,
1155
1162
  side: "right",
1156
- x,
1157
- y,
1158
- width,
1159
- height,
1163
+ x: rect.left,
1164
+ y: rect.top,
1165
+ width: rect.width,
1166
+ height: rect.height,
1160
1167
  borderRadius,
1161
1168
  borderProperties: borders.right
1162
1169
  });
1163
1170
  drawBorderSide({
1164
1171
  ctx,
1165
1172
  side: "bottom",
1166
- x,
1167
- y,
1168
- width,
1169
- height,
1173
+ x: rect.left,
1174
+ y: rect.top,
1175
+ width: rect.width,
1176
+ height: rect.height,
1170
1177
  borderRadius,
1171
1178
  borderProperties: borders.bottom
1172
1179
  });
1173
1180
  drawBorderSide({
1174
1181
  ctx,
1175
1182
  side: "left",
1176
- x,
1177
- y,
1178
- width,
1179
- height,
1183
+ x: rect.left,
1184
+ y: rect.top,
1185
+ width: rect.width,
1186
+ height: rect.height,
1180
1187
  borderRadius,
1181
1188
  borderProperties: borders.left
1182
1189
  });
@@ -1186,6 +1193,90 @@ var drawBorder = ({
1186
1193
  ctx.setLineDash(originalLineDash);
1187
1194
  };
1188
1195
 
1196
+ // src/drawing/draw-outline.ts
1197
+ var parseOutlineWidth = (value) => {
1198
+ return parseFloat(value) || 0;
1199
+ };
1200
+ var parseOutlineOffset = (value) => {
1201
+ return parseFloat(value) || 0;
1202
+ };
1203
+ var getLineDashPattern2 = (style, width) => {
1204
+ if (style === "dashed") {
1205
+ return [width * 2, width];
1206
+ }
1207
+ if (style === "dotted") {
1208
+ return [width, width];
1209
+ }
1210
+ return [];
1211
+ };
1212
+ var drawOutline = ({
1213
+ ctx,
1214
+ rect,
1215
+ borderRadius,
1216
+ computedStyle
1217
+ }) => {
1218
+ const outlineWidth = parseOutlineWidth(computedStyle.outlineWidth);
1219
+ const { outlineStyle } = computedStyle;
1220
+ const outlineColor = computedStyle.outlineColor || "black";
1221
+ const outlineOffset = parseOutlineOffset(computedStyle.outlineOffset);
1222
+ if (outlineWidth <= 0 || outlineStyle === "none" || outlineStyle === "hidden") {
1223
+ return;
1224
+ }
1225
+ const originalStrokeStyle = ctx.strokeStyle;
1226
+ const originalLineWidth = ctx.lineWidth;
1227
+ const originalLineDash = ctx.getLineDash();
1228
+ ctx.beginPath();
1229
+ ctx.strokeStyle = outlineColor;
1230
+ ctx.lineWidth = outlineWidth;
1231
+ ctx.setLineDash(getLineDashPattern2(outlineStyle, outlineWidth));
1232
+ const halfWidth = outlineWidth / 2;
1233
+ const offset = outlineOffset + halfWidth;
1234
+ const outlineX = rect.left - offset;
1235
+ const outlineY = rect.top - offset;
1236
+ const outlineW = rect.width + offset * 2;
1237
+ const outlineH = rect.height + offset * 2;
1238
+ const adjustedBorderRadius = {
1239
+ topLeft: {
1240
+ horizontal: borderRadius.topLeft.horizontal === 0 ? 0 : Math.max(0, borderRadius.topLeft.horizontal + offset),
1241
+ vertical: borderRadius.topLeft.vertical === 0 ? 0 : Math.max(0, borderRadius.topLeft.vertical + offset)
1242
+ },
1243
+ topRight: {
1244
+ horizontal: borderRadius.topRight.horizontal === 0 ? 0 : Math.max(0, borderRadius.topRight.horizontal + offset),
1245
+ vertical: borderRadius.topRight.vertical === 0 ? 0 : Math.max(0, borderRadius.topRight.vertical + offset)
1246
+ },
1247
+ bottomRight: {
1248
+ horizontal: borderRadius.bottomRight.horizontal === 0 ? 0 : Math.max(0, borderRadius.bottomRight.horizontal + offset),
1249
+ vertical: borderRadius.bottomRight.vertical === 0 ? 0 : Math.max(0, borderRadius.bottomRight.vertical + offset)
1250
+ },
1251
+ bottomLeft: {
1252
+ horizontal: borderRadius.bottomLeft.horizontal === 0 ? 0 : Math.max(0, borderRadius.bottomLeft.horizontal + offset),
1253
+ vertical: borderRadius.bottomLeft.vertical === 0 ? 0 : Math.max(0, borderRadius.bottomLeft.vertical + offset)
1254
+ }
1255
+ };
1256
+ ctx.moveTo(outlineX + adjustedBorderRadius.topLeft.horizontal, outlineY);
1257
+ ctx.lineTo(outlineX + outlineW - adjustedBorderRadius.topRight.horizontal, outlineY);
1258
+ if (adjustedBorderRadius.topRight.horizontal > 0 || adjustedBorderRadius.topRight.vertical > 0) {
1259
+ ctx.ellipse(outlineX + outlineW - adjustedBorderRadius.topRight.horizontal, outlineY + adjustedBorderRadius.topRight.vertical, adjustedBorderRadius.topRight.horizontal, adjustedBorderRadius.topRight.vertical, 0, -Math.PI / 2, 0);
1260
+ }
1261
+ ctx.lineTo(outlineX + outlineW, outlineY + outlineH - adjustedBorderRadius.bottomRight.vertical);
1262
+ if (adjustedBorderRadius.bottomRight.horizontal > 0 || adjustedBorderRadius.bottomRight.vertical > 0) {
1263
+ ctx.ellipse(outlineX + outlineW - adjustedBorderRadius.bottomRight.horizontal, outlineY + outlineH - adjustedBorderRadius.bottomRight.vertical, adjustedBorderRadius.bottomRight.horizontal, adjustedBorderRadius.bottomRight.vertical, 0, 0, Math.PI / 2);
1264
+ }
1265
+ ctx.lineTo(outlineX + adjustedBorderRadius.bottomLeft.horizontal, outlineY + outlineH);
1266
+ if (adjustedBorderRadius.bottomLeft.horizontal > 0 || adjustedBorderRadius.bottomLeft.vertical > 0) {
1267
+ ctx.ellipse(outlineX + adjustedBorderRadius.bottomLeft.horizontal, outlineY + outlineH - adjustedBorderRadius.bottomLeft.vertical, adjustedBorderRadius.bottomLeft.horizontal, adjustedBorderRadius.bottomLeft.vertical, 0, Math.PI / 2, Math.PI);
1268
+ }
1269
+ ctx.lineTo(outlineX, outlineY + adjustedBorderRadius.topLeft.vertical);
1270
+ if (adjustedBorderRadius.topLeft.horizontal > 0 || adjustedBorderRadius.topLeft.vertical > 0) {
1271
+ ctx.ellipse(outlineX + adjustedBorderRadius.topLeft.horizontal, outlineY + adjustedBorderRadius.topLeft.vertical, adjustedBorderRadius.topLeft.horizontal, adjustedBorderRadius.topLeft.vertical, 0, Math.PI, Math.PI * 3 / 2);
1272
+ }
1273
+ ctx.closePath();
1274
+ ctx.stroke();
1275
+ ctx.strokeStyle = originalStrokeStyle;
1276
+ ctx.lineWidth = originalLineWidth;
1277
+ ctx.setLineDash(originalLineDash);
1278
+ };
1279
+
1189
1280
  // src/drawing/opacity.ts
1190
1281
  var setOpacity = ({
1191
1282
  ctx,
@@ -1198,6 +1289,24 @@ var setOpacity = ({
1198
1289
  };
1199
1290
  };
1200
1291
 
1292
+ // src/drawing/overflow.ts
1293
+ var setOverflowHidden = ({
1294
+ ctx,
1295
+ rect,
1296
+ borderRadius,
1297
+ overflowHidden
1298
+ }) => {
1299
+ if (!overflowHidden) {
1300
+ return () => {};
1301
+ }
1302
+ return setBorderRadius({
1303
+ ctx,
1304
+ rect,
1305
+ borderRadius,
1306
+ forceClipEvenWhenZero: true
1307
+ });
1308
+ };
1309
+
1201
1310
  // src/drawing/transform.ts
1202
1311
  var setTransform = ({
1203
1312
  ctx,
@@ -1211,7 +1320,7 @@ var setTransform = ({
1211
1320
 
1212
1321
  // src/drawing/draw-element.ts
1213
1322
  var drawElement = async ({
1214
- dimensions,
1323
+ rect,
1215
1324
  computedStyle,
1216
1325
  context,
1217
1326
  draw,
@@ -1221,8 +1330,8 @@ var drawElement = async ({
1221
1330
  const background = computedStyle.backgroundColor;
1222
1331
  const borderRadius = parseBorderRadius({
1223
1332
  borderRadius: computedStyle.borderRadius,
1224
- width: dimensions.width,
1225
- height: dimensions.height
1333
+ width: rect.width,
1334
+ height: rect.height
1226
1335
  });
1227
1336
  const finishTransform = setTransform({
1228
1337
  ctx: context,
@@ -1230,11 +1339,9 @@ var drawElement = async ({
1230
1339
  });
1231
1340
  const finishBorderRadius = setBorderRadius({
1232
1341
  ctx: context,
1233
- x: dimensions.left,
1234
- y: dimensions.top,
1235
- width: dimensions.width,
1236
- height: dimensions.height,
1237
- borderRadius
1342
+ rect,
1343
+ borderRadius,
1344
+ forceClipEvenWhenZero: false
1238
1345
  });
1239
1346
  const finishOpacity = setOpacity({
1240
1347
  ctx: context,
@@ -1243,24 +1350,142 @@ var drawElement = async ({
1243
1350
  if (background && background !== "transparent" && !(background.startsWith("rgba") && (background.endsWith(", 0)") || background.endsWith(",0")))) {
1244
1351
  const originalFillStyle = context.fillStyle;
1245
1352
  context.fillStyle = background;
1246
- context.fillRect(dimensions.left, dimensions.top, dimensions.width, dimensions.height);
1353
+ context.fillRect(rect.left, rect.top, rect.width, rect.height);
1247
1354
  context.fillStyle = originalFillStyle;
1248
1355
  }
1249
- await draw({ dimensions, computedStyle, contextToDraw: context });
1356
+ await draw({ dimensions: rect, computedStyle, contextToDraw: context });
1250
1357
  drawBorder({
1251
1358
  ctx: context,
1252
- x: dimensions.left,
1253
- y: dimensions.top,
1254
- width: dimensions.width,
1255
- height: dimensions.height,
1359
+ rect,
1256
1360
  borderRadius,
1257
1361
  computedStyle
1258
1362
  });
1259
- finishOpacity();
1260
1363
  finishBorderRadius();
1364
+ drawOutline({
1365
+ ctx: context,
1366
+ rect,
1367
+ borderRadius,
1368
+ computedStyle
1369
+ });
1370
+ const finishOverflowHidden = setOverflowHidden({
1371
+ ctx: context,
1372
+ rect,
1373
+ borderRadius,
1374
+ overflowHidden: computedStyle.overflow === "hidden"
1375
+ });
1261
1376
  finishTransform();
1377
+ return {
1378
+ cleanupAfterChildren: () => {
1379
+ finishOpacity();
1380
+ finishOverflowHidden();
1381
+ }
1382
+ };
1262
1383
  };
1263
1384
 
1385
+ // src/drawing/handle-3d-transform.ts
1386
+ import { Internals as Internals4 } from "remotion";
1387
+
1388
+ // src/walk-tree.ts
1389
+ function skipToNextNonDescendant(treeWalker) {
1390
+ if (treeWalker.nextSibling()) {
1391
+ return true;
1392
+ }
1393
+ while (treeWalker.parentNode()) {
1394
+ if (treeWalker.nextSibling()) {
1395
+ return true;
1396
+ }
1397
+ }
1398
+ return false;
1399
+ }
1400
+
1401
+ // src/get-biggest-bounding-client-rect.ts
1402
+ var getBiggestBoundingClientRect = (element) => {
1403
+ const treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT);
1404
+ let mostLeft = Infinity;
1405
+ let mostTop = Infinity;
1406
+ let mostRight = -Infinity;
1407
+ let mostBottom = -Infinity;
1408
+ while (true) {
1409
+ const computedStyle = getComputedStyle(treeWalker.currentNode);
1410
+ const outlineWidth = parseOutlineWidth(computedStyle.outlineWidth);
1411
+ const outlineOffset = parseOutlineOffset(computedStyle.outlineOffset);
1412
+ const rect = treeWalker.currentNode.getBoundingClientRect();
1413
+ mostLeft = Math.min(mostLeft, rect.left - outlineOffset - outlineWidth);
1414
+ mostTop = Math.min(mostTop, rect.top - outlineOffset - outlineWidth);
1415
+ mostRight = Math.max(mostRight, rect.right + outlineOffset + outlineWidth);
1416
+ mostBottom = Math.max(mostBottom, rect.bottom + outlineOffset + outlineWidth);
1417
+ if (computedStyle.overflow === "hidden") {
1418
+ if (!skipToNextNonDescendant(treeWalker)) {
1419
+ break;
1420
+ }
1421
+ }
1422
+ if (!treeWalker.nextNode()) {
1423
+ break;
1424
+ }
1425
+ }
1426
+ return new DOMRect(mostLeft, mostTop, mostRight - mostLeft, mostBottom - mostTop);
1427
+ };
1428
+
1429
+ // src/drawing/clamp-rect-to-parent-bounds.ts
1430
+ var getNarrowerRect = ({
1431
+ firstRect,
1432
+ secondRect
1433
+ }) => {
1434
+ const left = Math.max(firstRect.left, secondRect.left);
1435
+ const top = Math.max(firstRect.top, secondRect.top);
1436
+ const bottom = Math.min(firstRect.bottom, secondRect.bottom);
1437
+ const right = Math.min(firstRect.right, secondRect.right);
1438
+ return new DOMRect(left, top, right - left, bottom - top);
1439
+ };
1440
+
1441
+ // src/drawing/get-pretransform-rect.ts
1442
+ function getPreTransformRect(targetRect, matrix) {
1443
+ const origin = new DOMPoint(0, 0).matrixTransform(matrix);
1444
+ const unitX = new DOMPoint(1, 0).matrixTransform(matrix);
1445
+ const unitY = new DOMPoint(0, 1).matrixTransform(matrix);
1446
+ const basisX = { x: unitX.x - origin.x, y: unitX.y - origin.y };
1447
+ const basisY = { x: unitY.x - origin.x, y: unitY.y - origin.y };
1448
+ const effective2D = new DOMMatrix([
1449
+ basisX.x,
1450
+ basisX.y,
1451
+ basisY.x,
1452
+ basisY.y,
1453
+ origin.x,
1454
+ origin.y
1455
+ ]);
1456
+ const inverse2D = effective2D.inverse();
1457
+ const corners = [
1458
+ new DOMPoint(targetRect.x, targetRect.y),
1459
+ new DOMPoint(targetRect.x + targetRect.width, targetRect.y),
1460
+ new DOMPoint(targetRect.x + targetRect.width, targetRect.y + targetRect.height),
1461
+ new DOMPoint(targetRect.x, targetRect.y + targetRect.height)
1462
+ ];
1463
+ const transformedCorners = corners.map((c) => c.matrixTransform(inverse2D));
1464
+ const xs = transformedCorners.map((p) => p.x);
1465
+ const ys = transformedCorners.map((p) => p.y);
1466
+ return new DOMRect(Math.min(...xs), Math.min(...ys), Math.max(...xs) - Math.min(...xs), Math.max(...ys) - Math.min(...ys));
1467
+ }
1468
+
1469
+ // src/drawing/transform-rect-with-matrix.ts
1470
+ function transformDOMRect({
1471
+ rect,
1472
+ matrix
1473
+ }) {
1474
+ const topLeft = new DOMPointReadOnly(rect.left, rect.top);
1475
+ const topRight = new DOMPointReadOnly(rect.right, rect.top);
1476
+ const bottomLeft = new DOMPointReadOnly(rect.left, rect.bottom);
1477
+ const bottomRight = new DOMPointReadOnly(rect.right, rect.bottom);
1478
+ const transformedTopLeft = topLeft.matrixTransform(matrix);
1479
+ const transformedTopRight = topRight.matrixTransform(matrix);
1480
+ const transformedBottomLeft = bottomLeft.matrixTransform(matrix);
1481
+ const transformedBottomRight = bottomRight.matrixTransform(matrix);
1482
+ const minX = Math.min(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
1483
+ const maxX = Math.max(transformedTopLeft.x / transformedTopLeft.w, transformedTopRight.x / transformedTopRight.w, transformedBottomLeft.x / transformedBottomLeft.w, transformedBottomRight.x / transformedBottomRight.w);
1484
+ const minY = Math.min(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
1485
+ const maxY = Math.max(transformedTopLeft.y / transformedTopLeft.w, transformedTopRight.y / transformedTopRight.w, transformedBottomLeft.y / transformedBottomLeft.w, transformedBottomRight.y / transformedBottomRight.w);
1486
+ return new DOMRect(minX, minY, maxX - minX, maxY - minY);
1487
+ }
1488
+
1264
1489
  // src/drawing/transform-in-3d.ts
1265
1490
  function compileShader(shaderGl, source, type) {
1266
1491
  const shader = shaderGl.createShader(type);
@@ -1336,39 +1561,43 @@ var createHelperCanvas = ({
1336
1561
  return helperCanvas;
1337
1562
  };
1338
1563
  var transformIn3d = ({
1339
- canvasWidth,
1340
- canvasHeight,
1341
1564
  matrix,
1342
1565
  sourceCanvas,
1343
- offsetLeft,
1344
- offsetTop
1566
+ untransformedRect
1345
1567
  }) => {
1346
- const { canvas, gl, program } = createHelperCanvas({ canvasWidth, canvasHeight });
1568
+ const rectAfterTransforms = transformDOMRect({
1569
+ rect: untransformedRect,
1570
+ matrix
1571
+ });
1572
+ const { canvas, gl, program } = createHelperCanvas({
1573
+ canvasWidth: Math.ceil(rectAfterTransforms.width),
1574
+ canvasHeight: Math.ceil(rectAfterTransforms.height)
1575
+ });
1347
1576
  const vertexBuffer = gl.createBuffer();
1348
1577
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
1349
1578
  const vertices = new Float32Array([
1350
- offsetLeft,
1351
- offsetTop,
1579
+ untransformedRect.x,
1580
+ untransformedRect.y,
1352
1581
  0,
1353
1582
  0,
1354
- canvasWidth + offsetLeft,
1355
- offsetTop,
1583
+ untransformedRect.x + untransformedRect.width,
1584
+ untransformedRect.y,
1356
1585
  1,
1357
1586
  0,
1358
- offsetLeft,
1359
- canvasHeight + offsetTop,
1587
+ untransformedRect.x,
1588
+ untransformedRect.y + untransformedRect.height,
1360
1589
  0,
1361
1590
  1,
1362
- offsetLeft,
1363
- canvasHeight + offsetTop,
1591
+ untransformedRect.x,
1592
+ untransformedRect.y + untransformedRect.height,
1364
1593
  0,
1365
1594
  1,
1366
- canvasWidth + offsetLeft,
1367
- offsetTop,
1595
+ untransformedRect.x + untransformedRect.width,
1596
+ untransformedRect.y,
1368
1597
  1,
1369
1598
  0,
1370
- canvasWidth + offsetLeft,
1371
- canvasHeight + offsetTop,
1599
+ untransformedRect.x + untransformedRect.width,
1600
+ untransformedRect.y + untransformedRect.height,
1372
1601
  1,
1373
1602
  1
1374
1603
  ]);
@@ -1401,8 +1630,8 @@ var transformIn3d = ({
1401
1630
  0,
1402
1631
  -2 / zScale,
1403
1632
  0,
1404
- -1,
1405
- 1,
1633
+ -1 + 2 * -rectAfterTransforms.x / canvas.width,
1634
+ 1 - 2 * -rectAfterTransforms.y / canvas.height,
1406
1635
  0,
1407
1636
  1
1408
1637
  ]);
@@ -1415,66 +1644,88 @@ var transformIn3d = ({
1415
1644
  gl.drawArrays(gl.TRIANGLES, 0, 6);
1416
1645
  gl.deleteTexture(texture);
1417
1646
  gl.deleteBuffer(vertexBuffer);
1418
- return canvas;
1647
+ return { canvas, rect: rectAfterTransforms };
1419
1648
  };
1420
1649
 
1421
- // src/drawing/draw-element-to-canvas.ts
1422
- var drawElementToCanvas = async ({
1650
+ // src/drawing/handle-3d-transform.ts
1651
+ var handle3dTransform = async ({
1652
+ element,
1653
+ matrix,
1654
+ parentRect,
1655
+ context,
1656
+ logLevel,
1657
+ internalState
1658
+ }) => {
1659
+ const unclampedBiggestBoundingClientRect = getBiggestBoundingClientRect(element);
1660
+ const biggestPossiblePretransformRect = getPreTransformRect(parentRect, matrix);
1661
+ const preTransformRect = getNarrowerRect({
1662
+ firstRect: unclampedBiggestBoundingClientRect,
1663
+ secondRect: biggestPossiblePretransformRect
1664
+ });
1665
+ const start = Date.now();
1666
+ const tempCanvas = new OffscreenCanvas(Math.ceil(preTransformRect.width), Math.ceil(preTransformRect.height));
1667
+ await compose({
1668
+ element,
1669
+ context: tempCanvas.getContext("2d"),
1670
+ logLevel,
1671
+ parentRect: preTransformRect,
1672
+ internalState
1673
+ });
1674
+ const afterCompose = Date.now();
1675
+ const { canvas: transformed, rect: transformedRect } = transformIn3d({
1676
+ untransformedRect: preTransformRect,
1677
+ matrix,
1678
+ sourceCanvas: tempCanvas
1679
+ });
1680
+ context.drawImage(transformed, transformedRect.x, transformedRect.y);
1681
+ const afterDraw = Date.now();
1682
+ Internals4.Log.trace({
1683
+ logLevel,
1684
+ tag: "@remotion/web-renderer"
1685
+ }, `Transforming element in 3D - canvas size: ${transformedRect.width}x${transformedRect.height} - compose: ${afterCompose - start}ms - draw: ${afterDraw - afterCompose}ms`);
1686
+ internalState.add3DTransform({
1687
+ canvasWidth: Math.ceil(transformedRect.width),
1688
+ canvasHeight: Math.ceil(transformedRect.height)
1689
+ });
1690
+ };
1691
+
1692
+ // src/drawing/process-node.ts
1693
+ var processNode = async ({
1423
1694
  element,
1424
1695
  context,
1425
1696
  draw,
1426
- offsetLeft,
1427
- offsetTop,
1428
- logLevel
1697
+ logLevel,
1698
+ parentRect,
1699
+ internalState
1429
1700
  }) => {
1430
- const { totalMatrix, reset, dimensions, opacity, computedStyle } = calculateTransforms(element);
1701
+ const transforms = calculateTransforms({
1702
+ element,
1703
+ offsetLeft: parentRect.x,
1704
+ offsetTop: parentRect.y
1705
+ });
1706
+ const { totalMatrix, reset, dimensions, opacity, computedStyle } = transforms;
1431
1707
  if (opacity === 0) {
1432
1708
  reset();
1433
- return "continue";
1709
+ return { type: "continue", cleanupAfterChildren: () => {} };
1434
1710
  }
1435
1711
  if (dimensions.width <= 0 || dimensions.height <= 0) {
1436
1712
  reset();
1437
- return "continue";
1713
+ return { type: "continue", cleanupAfterChildren: () => {} };
1438
1714
  }
1439
1715
  if (!totalMatrix.is2D) {
1440
- const biggestBoundingClientRect = getBiggestBoundingClientRect(element);
1441
- const canvasOffsetLeft = Math.min(biggestBoundingClientRect.left, 0);
1442
- const canvasOffsetTop = Math.min(biggestBoundingClientRect.top, 0);
1443
- const tempCanvasWidth = Math.max(biggestBoundingClientRect.width, biggestBoundingClientRect.right);
1444
- const tempCanvasHeight = Math.max(biggestBoundingClientRect.height, biggestBoundingClientRect.bottom);
1445
- const start = Date.now();
1446
- const tempCanvas = new OffscreenCanvas(tempCanvasWidth, tempCanvasHeight);
1447
- const context2 = tempCanvas.getContext("2d");
1448
- if (!context2) {
1449
- throw new Error("Could not get context");
1450
- }
1451
- await compose({
1716
+ await handle3dTransform({
1452
1717
  element,
1453
- context: context2,
1454
- offsetLeft: canvasOffsetLeft,
1455
- offsetTop: canvasOffsetTop,
1456
- logLevel
1457
- });
1458
- const afterCompose = Date.now();
1459
- const transformed = transformIn3d({
1460
- canvasWidth: tempCanvasWidth,
1461
- canvasHeight: tempCanvasHeight,
1462
1718
  matrix: totalMatrix,
1463
- sourceCanvas: tempCanvas,
1464
- offsetLeft: canvasOffsetLeft,
1465
- offsetTop: canvasOffsetTop
1719
+ parentRect,
1720
+ context,
1721
+ logLevel,
1722
+ internalState
1466
1723
  });
1467
- context.drawImage(transformed, 0, 0);
1468
- const afterDraw = Date.now();
1469
1724
  reset();
1470
- Internals4.Log.trace({
1471
- logLevel,
1472
- tag: "@remotion/web-renderer"
1473
- }, `Transforming element in 3D - canvas size: ${tempCanvasWidth}x${tempCanvasHeight} - compose: ${afterCompose - start}ms - draw: ${afterDraw - afterCompose}ms`);
1474
- return "skip-children";
1725
+ return { type: "skip-children" };
1475
1726
  }
1476
- await drawElement({
1477
- dimensions: new DOMRect(dimensions.left - offsetLeft, dimensions.top - offsetTop, dimensions.width, dimensions.height),
1727
+ const { cleanupAfterChildren } = await drawElement({
1728
+ rect: new DOMRect(dimensions.left - parentRect.x, dimensions.top - parentRect.y, dimensions.width, dimensions.height),
1478
1729
  computedStyle,
1479
1730
  context,
1480
1731
  draw,
@@ -1482,7 +1733,7 @@ var drawElementToCanvas = async ({
1482
1733
  totalMatrix
1483
1734
  });
1484
1735
  reset();
1485
- return "continue";
1736
+ return { type: "continue", cleanupAfterChildren };
1486
1737
  };
1487
1738
 
1488
1739
  // src/drawing/text/draw-text.ts
@@ -1651,9 +1902,9 @@ var drawText = (span) => {
1651
1902
  var handleTextNode = async ({
1652
1903
  node,
1653
1904
  context,
1654
- offsetLeft,
1655
- offsetTop,
1656
- logLevel
1905
+ logLevel,
1906
+ parentRect,
1907
+ internalState
1657
1908
  }) => {
1658
1909
  const span = document.createElement("span");
1659
1910
  const parent = node.parentNode;
@@ -1662,62 +1913,56 @@ var handleTextNode = async ({
1662
1913
  }
1663
1914
  parent.insertBefore(span, node);
1664
1915
  span.appendChild(node);
1665
- const value = await drawElementToCanvas({
1916
+ const value = await processNode({
1666
1917
  context,
1667
1918
  element: span,
1668
1919
  draw: drawText(span),
1669
- offsetLeft,
1670
- offsetTop,
1671
- logLevel
1920
+ logLevel,
1921
+ parentRect,
1922
+ internalState
1672
1923
  });
1673
1924
  parent.insertBefore(node, span);
1674
1925
  parent.removeChild(span);
1675
1926
  return value;
1676
1927
  };
1677
1928
 
1678
- // src/walk-tree.ts
1679
- function skipToNextNonDescendant(treeWalker) {
1680
- if (treeWalker.nextSibling()) {
1681
- return true;
1682
- }
1683
- while (treeWalker.parentNode()) {
1684
- if (treeWalker.nextSibling()) {
1685
- return true;
1686
- }
1687
- }
1688
- return false;
1689
- }
1690
-
1691
1929
  // src/compose.ts
1692
1930
  var walkOverNode = ({
1693
1931
  node,
1694
1932
  context,
1695
- offsetLeft,
1696
- offsetTop,
1697
- logLevel
1933
+ logLevel,
1934
+ parentRect,
1935
+ internalState
1698
1936
  }) => {
1699
1937
  if (node instanceof HTMLElement || node instanceof SVGElement) {
1700
- return drawElementToCanvas({
1938
+ return processNode({
1701
1939
  element: node,
1702
1940
  context,
1703
1941
  draw: drawDomElement(node),
1704
- offsetLeft,
1705
- offsetTop,
1706
- logLevel
1942
+ logLevel,
1943
+ parentRect,
1944
+ internalState
1707
1945
  });
1708
1946
  }
1709
1947
  if (node instanceof Text) {
1710
- return handleTextNode({ node, context, offsetLeft, offsetTop, logLevel });
1948
+ return handleTextNode({
1949
+ node,
1950
+ context,
1951
+ logLevel,
1952
+ parentRect,
1953
+ internalState
1954
+ });
1711
1955
  }
1712
1956
  throw new Error("Unknown node type");
1713
1957
  };
1714
1958
  var compose = async ({
1715
1959
  element,
1716
1960
  context,
1717
- offsetLeft,
1718
- offsetTop,
1719
- logLevel
1961
+ logLevel,
1962
+ parentRect,
1963
+ internalState
1720
1964
  }) => {
1965
+ const cleanupAfterChildren = [];
1721
1966
  const treeWalker = document.createTreeWalker(element, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, (node) => {
1722
1967
  if (node instanceof Element) {
1723
1968
  if (node.parentElement instanceof SVGSVGElement) {
@@ -1729,21 +1974,39 @@ var compose = async ({
1729
1974
  return NodeFilter.FILTER_ACCEPT;
1730
1975
  });
1731
1976
  while (true) {
1977
+ for (let i = 0;i < cleanupAfterChildren.length; ) {
1978
+ const cleanup = cleanupAfterChildren[i];
1979
+ if (!(cleanup.element === treeWalker.currentNode || cleanup.element.contains(treeWalker.currentNode))) {
1980
+ cleanup.cleanupFn();
1981
+ cleanupAfterChildren.splice(i, 1);
1982
+ } else {
1983
+ i++;
1984
+ }
1985
+ }
1732
1986
  const val = await walkOverNode({
1733
1987
  node: treeWalker.currentNode,
1734
1988
  context,
1735
- offsetLeft,
1736
- offsetTop,
1737
- logLevel
1989
+ logLevel,
1990
+ parentRect,
1991
+ internalState
1738
1992
  });
1739
- if (val === "skip-children") {
1993
+ if (val.type === "skip-children") {
1740
1994
  if (!skipToNextNonDescendant(treeWalker)) {
1741
1995
  break;
1742
1996
  }
1743
- } else if (!treeWalker.nextNode()) {
1744
- break;
1997
+ } else {
1998
+ cleanupAfterChildren.push({
1999
+ element: treeWalker.currentNode,
2000
+ cleanupFn: val.cleanupAfterChildren
2001
+ });
2002
+ if (!treeWalker.nextNode()) {
2003
+ break;
2004
+ }
1745
2005
  }
1746
2006
  }
2007
+ for (const cleanup of cleanupAfterChildren) {
2008
+ cleanup.cleanupFn();
2009
+ }
1747
2010
  };
1748
2011
 
1749
2012
  // src/take-screenshot.ts
@@ -1751,14 +2014,21 @@ var createFrame = async ({
1751
2014
  div,
1752
2015
  width,
1753
2016
  height,
1754
- logLevel
2017
+ logLevel,
2018
+ internalState
1755
2019
  }) => {
1756
2020
  const canvas = new OffscreenCanvas(width, height);
1757
2021
  const context = canvas.getContext("2d");
1758
2022
  if (!context) {
1759
2023
  throw new Error("Could not get context");
1760
2024
  }
1761
- await compose({ element: div, context, offsetLeft: 0, offsetTop: 0, logLevel });
2025
+ await compose({
2026
+ element: div,
2027
+ context,
2028
+ logLevel,
2029
+ parentRect: new DOMRect(0, 0, width, height),
2030
+ internalState
2031
+ });
1762
2032
  return canvas;
1763
2033
  };
1764
2034
  var takeScreenshot = async ({
@@ -1766,9 +2036,16 @@ var takeScreenshot = async ({
1766
2036
  width,
1767
2037
  height,
1768
2038
  imageFormat,
1769
- logLevel
2039
+ logLevel,
2040
+ internalState
1770
2041
  }) => {
1771
- const frame = await createFrame({ div, width, height, logLevel });
2042
+ const frame = await createFrame({
2043
+ div,
2044
+ width,
2045
+ height,
2046
+ logLevel,
2047
+ internalState
2048
+ });
1772
2049
  const imageData = await frame.convertToBlob({
1773
2050
  type: `image/${imageFormat}`
1774
2051
  });
@@ -1982,6 +2259,7 @@ var internalRenderMediaOnWeb = async ({
1982
2259
  defaultCodec: resolved.defaultCodec,
1983
2260
  defaultOutName: resolved.defaultOutName
1984
2261
  });
2262
+ const internalState = makeInternalState();
1985
2263
  const artifactsHandler = handleArtifacts();
1986
2264
  cleanupFns.push(() => {
1987
2265
  cleanupScaffold();
@@ -2060,7 +2338,8 @@ var internalRenderMediaOnWeb = async ({
2060
2338
  div,
2061
2339
  width: resolved.width,
2062
2340
  height: resolved.height,
2063
- logLevel
2341
+ logLevel,
2342
+ internalState
2064
2343
  });
2065
2344
  if (signal?.aborted) {
2066
2345
  throw new Error("renderMediaOnWeb() was cancelled");
@@ -2118,7 +2397,8 @@ var internalRenderMediaOnWeb = async ({
2118
2397
  return {
2119
2398
  getBlob: () => {
2120
2399
  return webFsTarget.getBlob();
2121
- }
2400
+ },
2401
+ internalState
2122
2402
  };
2123
2403
  }
2124
2404
  if (!(target instanceof BufferTarget)) {
@@ -2135,7 +2415,8 @@ var internalRenderMediaOnWeb = async ({
2135
2415
  throw new Error("The resulting buffer is empty");
2136
2416
  }
2137
2417
  return Promise.resolve(new Blob([target.buffer], { type: mimeType }));
2138
- }
2418
+ },
2419
+ internalState
2139
2420
  };
2140
2421
  } catch (err) {
2141
2422
  sendUsageEvent({
@@ -2206,6 +2487,7 @@ async function internalRenderStillOnWeb({
2206
2487
  if (signal?.aborted) {
2207
2488
  return Promise.reject(new Error("renderStillOnWeb() was cancelled"));
2208
2489
  }
2490
+ const internalState = makeInternalState();
2209
2491
  const { delayRenderScope, div, cleanupScaffold, collectAssets } = await createScaffold({
2210
2492
  width: resolved.width,
2211
2493
  height: resolved.height,
@@ -2243,7 +2525,8 @@ async function internalRenderStillOnWeb({
2243
2525
  width: resolved.width,
2244
2526
  height: resolved.height,
2245
2527
  imageFormat,
2246
- logLevel
2528
+ logLevel,
2529
+ internalState
2247
2530
  });
2248
2531
  const assets = collectAssets.current.collectAssets();
2249
2532
  if (onArtifact) {
@@ -2254,7 +2537,7 @@ async function internalRenderStillOnWeb({
2254
2537
  succeeded: true,
2255
2538
  apiName: "renderStillOnWeb"
2256
2539
  });
2257
- return imageData;
2540
+ return { blob: imageData, internalState };
2258
2541
  } catch (err) {
2259
2542
  sendUsageEvent({
2260
2543
  succeeded: false,