@remotion/web-renderer 4.0.404 → 4.0.406

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.
@@ -632,20 +632,14 @@ var UpdateTime = ({
632
632
  });
633
633
  };
634
634
 
635
- // src/with-resolvers.ts
636
- var withResolvers = function() {
637
- let resolve;
638
- let reject;
639
- const promise = new Promise((res, rej) => {
640
- resolve = res;
641
- reject = rej;
642
- });
643
- return { promise, resolve, reject };
644
- };
645
-
646
635
  // src/create-scaffold.tsx
647
636
  import { jsx as jsx2 } from "react/jsx-runtime";
648
- async function createScaffold({
637
+ function checkForError(errorHolder) {
638
+ if (errorHolder.error) {
639
+ throw errorHolder.error;
640
+ }
641
+ }
642
+ function createScaffold({
649
643
  width,
650
644
  height,
651
645
  delayRenderTimeoutInMilliseconds,
@@ -684,10 +678,10 @@ async function createScaffold({
684
678
  div.className = scaffoldClassName;
685
679
  const cleanupCSS = Internals3.CSSUtils.injectCSS(Internals3.CSSUtils.makeDefaultPreviewCSS(`.${scaffoldClassName}`, "white"));
686
680
  document.body.appendChild(div);
687
- const { promise, resolve, reject } = withResolvers();
681
+ const errorHolder = { error: null };
688
682
  const root = ReactDOM.createRoot(div, {
689
683
  onUncaughtError: (err) => {
690
- reject(err);
684
+ errorHolder.error = err instanceof Error ? err : new Error(String(err));
691
685
  }
692
686
  });
693
687
  const delayRenderScope = {
@@ -770,11 +764,10 @@ async function createScaffold({
770
764
  })
771
765
  }));
772
766
  });
773
- resolve();
774
- await promise;
775
767
  return {
776
768
  delayRenderScope,
777
769
  div,
770
+ errorHolder,
778
771
  [Symbol.dispose]: () => {
779
772
  root.unmount();
780
773
  div.remove();
@@ -976,6 +969,38 @@ var sendUsageEvent = async ({
976
969
  });
977
970
  };
978
971
 
972
+ // src/tree-walker-cleanup-after-children.ts
973
+ var createTreeWalkerCleanupAfterChildren = (treeWalker) => {
974
+ const cleanupAfterChildren = [];
975
+ const checkCleanUpAtBeginningOfIteration = () => {
976
+ for (let i = 0;i < cleanupAfterChildren.length; ) {
977
+ const cleanup = cleanupAfterChildren[i];
978
+ if (!(cleanup.element === treeWalker.currentNode || cleanup.element.contains(treeWalker.currentNode))) {
979
+ cleanup.cleanupFn();
980
+ cleanupAfterChildren.splice(i, 1);
981
+ } else {
982
+ i++;
983
+ }
984
+ }
985
+ };
986
+ const addCleanup = (element, cleanupFn) => {
987
+ cleanupAfterChildren.unshift({
988
+ element,
989
+ cleanupFn
990
+ });
991
+ };
992
+ const cleanupInTheEndOfTheIteration = () => {
993
+ for (const cleanup of cleanupAfterChildren) {
994
+ cleanup.cleanupFn();
995
+ }
996
+ };
997
+ return {
998
+ checkCleanUpAtBeginningOfIteration,
999
+ addCleanup,
1000
+ [Symbol.dispose]: cleanupInTheEndOfTheIteration
1001
+ };
1002
+ };
1003
+
979
1004
  // src/drawing/calculate-object-fit.ts
980
1005
  var calculateFill = ({
981
1006
  containerSize,
@@ -1934,24 +1959,35 @@ function setBorderRadius({
1934
1959
  };
1935
1960
  }
1936
1961
 
1937
- // src/drawing/get-clipped-background.ts
1938
- var getClippedBackground = async ({
1939
- element,
1962
+ // src/drawing/get-background-fill.ts
1963
+ var isColorTransparent = (color) => {
1964
+ return color === "transparent" || color.startsWith("rgba") && (color.endsWith(", 0)") || color.endsWith(",0"));
1965
+ };
1966
+ var getBackgroundFill = ({
1967
+ backgroundColor,
1968
+ backgroundImage,
1969
+ contextToDraw,
1940
1970
  boundingRect,
1941
- logLevel,
1942
- internalState
1971
+ offsetLeft,
1972
+ offsetTop
1943
1973
  }) => {
1944
- const tempCanvas = new OffscreenCanvas(boundingRect.width, boundingRect.height);
1945
- const tempContext = tempCanvas.getContext("2d");
1946
- await compose({
1947
- element,
1948
- context: tempContext,
1949
- logLevel,
1950
- parentRect: boundingRect,
1951
- internalState,
1952
- onlyBackgroundClip: true
1953
- });
1954
- return tempContext;
1974
+ if (backgroundImage && backgroundImage !== "none") {
1975
+ const gradientInfo = parseLinearGradient(backgroundImage);
1976
+ if (gradientInfo) {
1977
+ const gradient = createCanvasGradient({
1978
+ ctx: contextToDraw,
1979
+ rect: boundingRect,
1980
+ gradientInfo,
1981
+ offsetLeft,
1982
+ offsetTop
1983
+ });
1984
+ return gradient;
1985
+ }
1986
+ }
1987
+ if (backgroundColor && backgroundColor !== "transparent" && !isColorTransparent(backgroundColor)) {
1988
+ return backgroundColor;
1989
+ }
1990
+ return null;
1955
1991
  };
1956
1992
 
1957
1993
  // src/drawing/draw-background.ts
@@ -1966,61 +2002,65 @@ var drawBackground = async ({
1966
2002
  internalState,
1967
2003
  computedStyle,
1968
2004
  offsetLeft: parentOffsetLeft,
1969
- offsetTop: parentOffsetTop
2005
+ offsetTop: parentOffsetTop,
2006
+ scale
1970
2007
  }) => {
1971
- let contextToDraw = context;
1972
- const originalCompositeOperation = context.globalCompositeOperation;
1973
- let offsetLeft = 0;
1974
- let offsetTop = 0;
1975
- const finish = () => {
1976
- context.globalCompositeOperation = originalCompositeOperation;
1977
- if (context !== contextToDraw) {
1978
- context.drawImage(contextToDraw.canvas, offsetLeft, offsetTop, contextToDraw.canvas.width, contextToDraw.canvas.height);
2008
+ let __stack = [];
2009
+ try {
2010
+ let contextToDraw = context;
2011
+ const originalCompositeOperation = context.globalCompositeOperation;
2012
+ let offsetLeft = 0;
2013
+ let offsetTop = 0;
2014
+ const _ = __using(__stack, {
2015
+ [Symbol.dispose]: () => {
2016
+ context.globalCompositeOperation = originalCompositeOperation;
2017
+ if (context !== contextToDraw) {
2018
+ context.drawImage(contextToDraw.canvas, offsetLeft, offsetTop, contextToDraw.canvas.width / scale, contextToDraw.canvas.height / scale);
2019
+ }
2020
+ }
2021
+ }, 0);
2022
+ const boundingRect = getBoxBasedOnBackgroundClip(rect, computedStyle, backgroundClip);
2023
+ if (backgroundClip.includes("text")) {
2024
+ offsetLeft = boundingRect.left;
2025
+ offsetTop = boundingRect.top;
2026
+ const originalBackgroundClip = element.style.backgroundClip;
2027
+ const originalWebkitBackgroundClip = element.style.webkitBackgroundClip;
2028
+ element.style.backgroundClip = "initial";
2029
+ element.style.webkitBackgroundClip = "initial";
2030
+ const onlyBackgroundClipText = await createLayer({
2031
+ element,
2032
+ cutout: new DOMRect(boundingRect.left + parentOffsetLeft, boundingRect.top + parentOffsetTop, boundingRect.width, boundingRect.height),
2033
+ logLevel,
2034
+ internalState,
2035
+ scale,
2036
+ onlyBackgroundClipText: true
2037
+ });
2038
+ onlyBackgroundClipText.setTransform(new DOMMatrix().scale(scale, scale));
2039
+ element.style.backgroundClip = originalBackgroundClip;
2040
+ element.style.webkitBackgroundClip = originalWebkitBackgroundClip;
2041
+ contextToDraw = onlyBackgroundClipText;
2042
+ contextToDraw.globalCompositeOperation = "source-in";
1979
2043
  }
1980
- };
1981
- const boundingRect = getBoxBasedOnBackgroundClip(rect, computedStyle, backgroundClip);
1982
- if (backgroundClip.includes("text")) {
1983
- offsetLeft = boundingRect.left;
1984
- offsetTop = boundingRect.top;
1985
- const originalBackgroundClip = element.style.backgroundClip;
1986
- const originalWebkitBackgroundClip = element.style.webkitBackgroundClip;
1987
- element.style.backgroundClip = "initial";
1988
- element.style.webkitBackgroundClip = "initial";
1989
- const drawn = await getClippedBackground({
1990
- element,
1991
- boundingRect: new DOMRect(boundingRect.left + parentOffsetLeft, boundingRect.top + parentOffsetTop, boundingRect.width, boundingRect.height),
1992
- logLevel,
1993
- internalState
2044
+ const backgroundFill = getBackgroundFill({
2045
+ backgroundImage,
2046
+ backgroundColor,
2047
+ contextToDraw,
2048
+ boundingRect,
2049
+ offsetLeft,
2050
+ offsetTop
1994
2051
  });
1995
- element.style.backgroundClip = originalBackgroundClip;
1996
- element.style.webkitBackgroundClip = originalWebkitBackgroundClip;
1997
- contextToDraw = drawn;
1998
- contextToDraw.globalCompositeOperation = "source-in";
1999
- }
2000
- if (backgroundImage && backgroundImage !== "none") {
2001
- const gradientInfo = parseLinearGradient(backgroundImage);
2002
- if (gradientInfo) {
2003
- const gradient = createCanvasGradient({
2004
- ctx: contextToDraw,
2005
- rect: boundingRect,
2006
- gradientInfo,
2007
- offsetLeft,
2008
- offsetTop
2009
- });
2010
- const originalFillStyle = contextToDraw.fillStyle;
2011
- contextToDraw.fillStyle = gradient;
2012
- contextToDraw.fillRect(boundingRect.left - offsetLeft, boundingRect.top - offsetTop, boundingRect.width, boundingRect.height);
2013
- contextToDraw.fillStyle = originalFillStyle;
2014
- return finish();
2052
+ if (!backgroundFill) {
2053
+ return;
2015
2054
  }
2016
- }
2017
- if (backgroundColor && backgroundColor !== "transparent" && !(backgroundColor.startsWith("rgba") && (backgroundColor.endsWith(", 0)") || backgroundColor.endsWith(",0")))) {
2018
2055
  const originalFillStyle = contextToDraw.fillStyle;
2019
- contextToDraw.fillStyle = backgroundColor;
2056
+ contextToDraw.fillStyle = backgroundFill;
2020
2057
  contextToDraw.fillRect(boundingRect.left - offsetLeft, boundingRect.top - offsetTop, boundingRect.width, boundingRect.height);
2021
2058
  contextToDraw.fillStyle = originalFillStyle;
2059
+ } catch (_catch) {
2060
+ var _err = _catch, _hasErr = 1;
2061
+ } finally {
2062
+ __callDispose(__stack, _err, _hasErr);
2022
2063
  }
2023
- finish();
2024
2064
  };
2025
2065
 
2026
2066
  // src/drawing/draw-border.ts
@@ -2572,9 +2612,10 @@ var setOverflowHidden = ({
2572
2612
  var setTransform = ({
2573
2613
  ctx,
2574
2614
  transform,
2575
- parentRect
2615
+ parentRect,
2616
+ scale
2576
2617
  }) => {
2577
- const offsetMatrix = new DOMMatrix().translate(-parentRect.x, -parentRect.y).multiply(transform).translate(parentRect.x, parentRect.y);
2618
+ const offsetMatrix = new DOMMatrix().scale(scale, scale).translate(-parentRect.x, -parentRect.y).multiply(transform).translate(parentRect.x, parentRect.y);
2578
2619
  ctx.setTransform(offsetMatrix);
2579
2620
  return () => {
2580
2621
  ctx.setTransform(new DOMMatrix);
@@ -2592,7 +2633,8 @@ var drawElement = async ({
2592
2633
  parentRect,
2593
2634
  logLevel,
2594
2635
  element,
2595
- internalState
2636
+ internalState,
2637
+ scale
2596
2638
  }) => {
2597
2639
  const { backgroundImage, backgroundColor, backgroundClip } = computedStyle;
2598
2640
  const borderRadius = parseBorderRadius({
@@ -2603,7 +2645,8 @@ var drawElement = async ({
2603
2645
  const finishTransform = setTransform({
2604
2646
  ctx: context,
2605
2647
  transform: totalMatrix,
2606
- parentRect
2648
+ parentRect,
2649
+ scale
2607
2650
  });
2608
2651
  const finishOpacity = setOpacity({
2609
2652
  ctx: context,
@@ -2635,7 +2678,8 @@ var drawElement = async ({
2635
2678
  internalState,
2636
2679
  computedStyle,
2637
2680
  offsetLeft: parentRect.left,
2638
- offsetTop: parentRect.top
2681
+ offsetTop: parentRect.top,
2682
+ scale
2639
2683
  });
2640
2684
  await draw({ dimensions: rect, computedStyle, contextToDraw: context });
2641
2685
  finishBorderRadius();
@@ -2882,7 +2926,8 @@ var transformIn3d = ({
2882
2926
  sourceCanvas,
2883
2927
  sourceRect,
2884
2928
  destRect,
2885
- internalState
2929
+ internalState,
2930
+ scale
2886
2931
  }) => {
2887
2932
  const { canvas, gl, program, locations } = createHelperCanvas({
2888
2933
  canvasWidth: destRect.width,
@@ -2941,7 +2986,8 @@ var transformIn3d = ({
2941
2986
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
2942
2987
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
2943
2988
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, sourceCanvas);
2944
- const transformMatrix = matrix.toFloat32Array();
2989
+ const actualMatrix = scale !== 1 ? new DOMMatrix().scale(scale, scale).multiply(matrix) : matrix;
2990
+ const transformMatrix = actualMatrix.toFloat32Array();
2945
2991
  gl.uniformMatrix4fv(locations.uTransform, false, transformMatrix);
2946
2992
  gl.uniform2f(locations.uResolution, destRect.width, destRect.height);
2947
2993
  gl.uniform2f(locations.uOffset, -destRect.x, -destRect.y);
@@ -2981,7 +3027,8 @@ var handle3dTransform = ({
2981
3027
  sourceRect,
2982
3028
  tempCanvas,
2983
3029
  rectAfterTransforms,
2984
- internalState
3030
+ internalState,
3031
+ scale
2985
3032
  }) => {
2986
3033
  if (rectAfterTransforms.width <= 0 || rectAfterTransforms.height <= 0) {
2987
3034
  return null;
@@ -2991,7 +3038,8 @@ var handle3dTransform = ({
2991
3038
  matrix,
2992
3039
  sourceCanvas: tempCanvas,
2993
3040
  destRect: rectAfterTransforms,
2994
- internalState
3041
+ internalState,
3042
+ scale
2995
3043
  });
2996
3044
  return transformed;
2997
3045
  };
@@ -3005,11 +3053,10 @@ var handleMask = ({
3005
3053
  gradientInfo,
3006
3054
  rect,
3007
3055
  precomposeRect,
3008
- tempContext
3056
+ tempContext,
3057
+ scale
3009
3058
  }) => {
3010
- const rectOffsetX = rect.left - precomposeRect.left;
3011
- const rectOffsetY = rect.top - precomposeRect.top;
3012
- const rectToFill = new DOMRect(rectOffsetX, rectOffsetY, rect.width, rect.height);
3059
+ const rectToFill = new DOMRect((rect.left - precomposeRect.left) * scale, (rect.top - precomposeRect.top) * scale, rect.width * scale, rect.height * scale);
3013
3060
  const gradient = createCanvasGradient({
3014
3061
  ctx: tempContext,
3015
3062
  rect: rectToFill,
@@ -3022,24 +3069,12 @@ var handleMask = ({
3022
3069
  tempContext.fillRect(rectToFill.left, rectToFill.top, rectToFill.width, rectToFill.height);
3023
3070
  };
3024
3071
 
3025
- // src/drawing/precompose.ts
3026
- var precomposeDOMElement = async ({
3027
- boundingRect,
3028
- element,
3029
- logLevel,
3030
- internalState
3072
+ // src/drawing/scale-rect.ts
3073
+ var scaleRect = ({
3074
+ rect,
3075
+ scale
3031
3076
  }) => {
3032
- const tempCanvas = new OffscreenCanvas(boundingRect.width, boundingRect.height);
3033
- const tempContext = tempCanvas.getContext("2d");
3034
- await compose({
3035
- element,
3036
- context: tempContext,
3037
- logLevel,
3038
- parentRect: boundingRect,
3039
- internalState,
3040
- onlyBackgroundClip: false
3041
- });
3042
- return { tempCanvas, tempContext };
3077
+ return new DOMRect(rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale);
3043
3078
  };
3044
3079
 
3045
3080
  // src/drawing/transform-rect-with-matrix.ts
@@ -3070,7 +3105,8 @@ var processNode = async ({
3070
3105
  logLevel,
3071
3106
  parentRect,
3072
3107
  internalState,
3073
- rootElement
3108
+ rootElement,
3109
+ scale
3074
3110
  }) => {
3075
3111
  let __stack = [];
3076
3112
  try {
@@ -3118,23 +3154,29 @@ var processNode = async ({
3118
3154
  if (!doRectsIntersect(precomposeRect, parentRect)) {
3119
3155
  return { type: "continue", cleanupAfterChildren: null };
3120
3156
  }
3121
- const { tempCanvas, tempContext } = await precomposeDOMElement({
3122
- boundingRect: precomposeRect,
3157
+ const tempContext = await createLayer({
3158
+ cutout: precomposeRect,
3123
3159
  element,
3124
3160
  logLevel,
3125
- internalState
3161
+ internalState,
3162
+ scale,
3163
+ onlyBackgroundClipText: false
3126
3164
  });
3127
- let drawable = tempCanvas;
3128
- const rectAfterTransforms = roundToExpandRect(transformDOMRect({
3129
- rect: precomposeRect,
3130
- matrix: totalMatrix
3165
+ let drawable = tempContext.canvas;
3166
+ const rectAfterTransforms = roundToExpandRect(scaleRect({
3167
+ scale,
3168
+ rect: transformDOMRect({
3169
+ rect: precomposeRect,
3170
+ matrix: totalMatrix
3171
+ })
3131
3172
  }));
3132
3173
  if (precompositing.needsMaskImage) {
3133
3174
  handleMask({
3134
3175
  gradientInfo: precompositing.needsMaskImage,
3135
3176
  rect,
3136
3177
  precomposeRect,
3137
- tempContext
3178
+ tempContext,
3179
+ scale
3138
3180
  });
3139
3181
  }
3140
3182
  if (precompositing.needs3DTransformViaWebGL) {
@@ -3143,26 +3185,25 @@ var processNode = async ({
3143
3185
  sourceRect: precomposeRect,
3144
3186
  tempCanvas: drawable,
3145
3187
  rectAfterTransforms,
3146
- internalState
3188
+ internalState,
3189
+ scale
3147
3190
  });
3148
3191
  if (t) {
3149
3192
  drawable = t;
3150
3193
  }
3151
3194
  }
3152
3195
  const previousTransform = context.getTransform();
3153
- if (drawable) {
3154
- context.setTransform(new DOMMatrix);
3155
- context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
3156
- context.setTransform(previousTransform);
3157
- Internals6.Log.trace({
3158
- logLevel,
3159
- tag: "@remotion/web-renderer"
3160
- }, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms - helper canvas: ${drawable.width}x${drawable.height}`);
3161
- internalState.addPrecompose({
3162
- canvasWidth: precomposeRect.width,
3163
- canvasHeight: precomposeRect.height
3164
- });
3165
- }
3196
+ context.setTransform(new DOMMatrix);
3197
+ context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
3198
+ context.setTransform(previousTransform);
3199
+ Internals6.Log.trace({
3200
+ logLevel,
3201
+ tag: "@remotion/web-renderer"
3202
+ }, `Transforming element in 3D - canvas size: ${precomposeRect.width}x${precomposeRect.height} - compose: ${Date.now() - start}ms - helper canvas: ${drawable.width}x${drawable.height}`);
3203
+ internalState.addPrecompose({
3204
+ canvasWidth: precomposeRect.width,
3205
+ canvasHeight: precomposeRect.height
3206
+ });
3166
3207
  return { type: "skip-children" };
3167
3208
  }
3168
3209
  const { cleanupAfterChildren } = await drawElement({
@@ -3175,7 +3216,8 @@ var processNode = async ({
3175
3216
  parentRect,
3176
3217
  logLevel,
3177
3218
  element,
3178
- internalState
3219
+ internalState,
3220
+ scale
3179
3221
  });
3180
3222
  return { type: "continue", cleanupAfterChildren };
3181
3223
  } catch (_catch) {
@@ -3344,7 +3386,7 @@ function findLineBreaks(span, rtl) {
3344
3386
  var drawText = ({
3345
3387
  span,
3346
3388
  logLevel,
3347
- onlyBackgroundClip
3389
+ onlyBackgroundClipText
3348
3390
  }) => {
3349
3391
  const drawFn = ({ dimensions: rect, computedStyle, contextToDraw }) => {
3350
3392
  const {
@@ -3368,7 +3410,7 @@ var drawText = ({
3368
3410
  contextToDraw.save();
3369
3411
  const fontSizePx = parseFloat(fontSize);
3370
3412
  contextToDraw.font = `${fontWeight} ${fontSizePx}px ${fontFamily}`;
3371
- contextToDraw.fillStyle = onlyBackgroundClip ? "black" : webkitTextFillColor;
3413
+ contextToDraw.fillStyle = onlyBackgroundClipText ? "black" : webkitTextFillColor;
3372
3414
  contextToDraw.letterSpacing = letterSpacing;
3373
3415
  const isRTL = direction === "rtl";
3374
3416
  contextToDraw.textAlign = isRTL ? "right" : "left";
@@ -3403,7 +3445,8 @@ var handleTextNode = async ({
3403
3445
  parentRect,
3404
3446
  internalState,
3405
3447
  rootElement,
3406
- onlyBackgroundClip
3448
+ onlyBackgroundClipText,
3449
+ scale
3407
3450
  }) => {
3408
3451
  const span = document.createElement("span");
3409
3452
  const parent = node.parentNode;
@@ -3415,50 +3458,19 @@ var handleTextNode = async ({
3415
3458
  const value = await processNode({
3416
3459
  context,
3417
3460
  element: span,
3418
- draw: drawText({ span, logLevel, onlyBackgroundClip }),
3461
+ draw: drawText({ span, logLevel, onlyBackgroundClipText }),
3419
3462
  logLevel,
3420
3463
  parentRect,
3421
3464
  internalState,
3422
- rootElement
3465
+ rootElement,
3466
+ scale
3423
3467
  });
3424
3468
  parent.insertBefore(node, span);
3425
3469
  parent.removeChild(span);
3426
3470
  return value;
3427
3471
  };
3428
3472
 
3429
- // src/tree-walker-cleanup-after-children.ts
3430
- var createTreeWalkerCleanupAfterChildren = (treeWalker) => {
3431
- const cleanupAfterChildren = [];
3432
- const checkCleanUpAtBeginningOfIteration = () => {
3433
- for (let i = 0;i < cleanupAfterChildren.length; ) {
3434
- const cleanup = cleanupAfterChildren[i];
3435
- if (!(cleanup.element === treeWalker.currentNode || cleanup.element.contains(treeWalker.currentNode))) {
3436
- cleanup.cleanupFn();
3437
- cleanupAfterChildren.splice(i, 1);
3438
- } else {
3439
- i++;
3440
- }
3441
- }
3442
- };
3443
- const addCleanup = (element, cleanupFn) => {
3444
- cleanupAfterChildren.unshift({
3445
- element,
3446
- cleanupFn
3447
- });
3448
- };
3449
- const cleanupInTheEndOfTheIteration = () => {
3450
- for (const cleanup of cleanupAfterChildren) {
3451
- cleanup.cleanupFn();
3452
- }
3453
- };
3454
- return {
3455
- checkCleanUpAtBeginningOfIteration,
3456
- addCleanup,
3457
- cleanupInTheEndOfTheIteration
3458
- };
3459
- };
3460
-
3461
- // src/compose.ts
3473
+ // src/walk-over-node.ts
3462
3474
  var walkOverNode = ({
3463
3475
  node,
3464
3476
  context,
@@ -3466,7 +3478,8 @@ var walkOverNode = ({
3466
3478
  parentRect,
3467
3479
  internalState,
3468
3480
  rootElement,
3469
- onlyBackgroundClip
3481
+ onlyBackgroundClipText,
3482
+ scale
3470
3483
  }) => {
3471
3484
  if (node instanceof HTMLElement || node instanceof SVGElement) {
3472
3485
  return processNode({
@@ -3476,7 +3489,8 @@ var walkOverNode = ({
3476
3489
  logLevel,
3477
3490
  parentRect,
3478
3491
  internalState,
3479
- rootElement
3492
+ rootElement,
3493
+ scale
3480
3494
  });
3481
3495
  }
3482
3496
  if (node instanceof Text) {
@@ -3487,11 +3501,14 @@ var walkOverNode = ({
3487
3501
  parentRect,
3488
3502
  internalState,
3489
3503
  rootElement,
3490
- onlyBackgroundClip
3504
+ onlyBackgroundClipText,
3505
+ scale
3491
3506
  });
3492
3507
  }
3493
3508
  throw new Error("Unknown node type");
3494
3509
  };
3510
+
3511
+ // src/compose.ts
3495
3512
  var getFilterFunction = (node) => {
3496
3513
  if (!(node instanceof Element)) {
3497
3514
  return NodeFilter.FILTER_ACCEPT;
@@ -3511,89 +3528,78 @@ var compose = async ({
3511
3528
  logLevel,
3512
3529
  parentRect,
3513
3530
  internalState,
3514
- onlyBackgroundClip
3531
+ onlyBackgroundClipText,
3532
+ scale
3515
3533
  }) => {
3516
- const treeWalker = document.createTreeWalker(element, onlyBackgroundClip ? NodeFilter.SHOW_TEXT : NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, getFilterFunction);
3517
- if (onlyBackgroundClip) {
3518
- treeWalker.nextNode();
3519
- if (!treeWalker.currentNode) {
3520
- return;
3521
- }
3522
- }
3523
- const {
3524
- checkCleanUpAtBeginningOfIteration,
3525
- addCleanup,
3526
- cleanupInTheEndOfTheIteration
3527
- } = createTreeWalkerCleanupAfterChildren(treeWalker);
3528
- while (true) {
3529
- checkCleanUpAtBeginningOfIteration();
3530
- const val = await walkOverNode({
3531
- node: treeWalker.currentNode,
3532
- context,
3533
- logLevel,
3534
- parentRect,
3535
- internalState,
3536
- rootElement: element,
3537
- onlyBackgroundClip
3538
- });
3539
- if (val.type === "skip-children") {
3540
- if (!skipToNextNonDescendant(treeWalker)) {
3541
- break;
3542
- }
3543
- } else {
3544
- if (val.cleanupAfterChildren) {
3545
- addCleanup(treeWalker.currentNode, val.cleanupAfterChildren);
3534
+ let __stack = [];
3535
+ try {
3536
+ const treeWalker = document.createTreeWalker(element, onlyBackgroundClipText ? NodeFilter.SHOW_TEXT : NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, getFilterFunction);
3537
+ if (onlyBackgroundClipText) {
3538
+ treeWalker.nextNode();
3539
+ if (!treeWalker.currentNode) {
3540
+ return;
3546
3541
  }
3547
- if (!treeWalker.nextNode()) {
3548
- break;
3542
+ }
3543
+ const treeWalkerClean = __using(__stack, createTreeWalkerCleanupAfterChildren(treeWalker), 0);
3544
+ const { checkCleanUpAtBeginningOfIteration, addCleanup } = treeWalkerClean;
3545
+ while (true) {
3546
+ checkCleanUpAtBeginningOfIteration();
3547
+ const val = await walkOverNode({
3548
+ node: treeWalker.currentNode,
3549
+ context,
3550
+ logLevel,
3551
+ parentRect,
3552
+ internalState,
3553
+ rootElement: element,
3554
+ onlyBackgroundClipText,
3555
+ scale
3556
+ });
3557
+ if (val.type === "skip-children") {
3558
+ if (!skipToNextNonDescendant(treeWalker)) {
3559
+ break;
3560
+ }
3561
+ } else {
3562
+ if (val.cleanupAfterChildren) {
3563
+ addCleanup(treeWalker.currentNode, val.cleanupAfterChildren);
3564
+ }
3565
+ if (!treeWalker.nextNode()) {
3566
+ break;
3567
+ }
3549
3568
  }
3550
3569
  }
3570
+ } catch (_catch) {
3571
+ var _err = _catch, _hasErr = 1;
3572
+ } finally {
3573
+ __callDispose(__stack, _err, _hasErr);
3551
3574
  }
3552
- cleanupInTheEndOfTheIteration();
3553
3575
  };
3554
3576
 
3555
3577
  // src/take-screenshot.ts
3556
- var createFrame = async ({
3557
- div,
3558
- width,
3559
- height,
3578
+ var createLayer = async ({
3579
+ element,
3580
+ scale,
3560
3581
  logLevel,
3561
- internalState
3582
+ internalState,
3583
+ onlyBackgroundClipText,
3584
+ cutout
3562
3585
  }) => {
3563
- const canvas = new OffscreenCanvas(width, height);
3586
+ const scaledWidth = Math.ceil(cutout.width * scale);
3587
+ const scaledHeight = Math.ceil(cutout.height * scale);
3588
+ const canvas = new OffscreenCanvas(scaledWidth, scaledHeight);
3564
3589
  const context = canvas.getContext("2d");
3565
3590
  if (!context) {
3566
3591
  throw new Error("Could not get context");
3567
3592
  }
3568
3593
  await compose({
3569
- element: div,
3594
+ element,
3570
3595
  context,
3571
3596
  logLevel,
3572
- parentRect: new DOMRect(0, 0, width, height),
3597
+ parentRect: cutout,
3573
3598
  internalState,
3574
- onlyBackgroundClip: false
3575
- });
3576
- return canvas;
3577
- };
3578
- var takeScreenshot = async ({
3579
- div,
3580
- width,
3581
- height,
3582
- imageFormat,
3583
- logLevel,
3584
- internalState
3585
- }) => {
3586
- const frame = await createFrame({
3587
- div,
3588
- width,
3589
- height,
3590
- logLevel,
3591
- internalState
3592
- });
3593
- const imageData = await frame.convertToBlob({
3594
- type: `image/${imageFormat}`
3599
+ onlyBackgroundClipText,
3600
+ scale
3595
3601
  });
3596
- return imageData;
3602
+ return context;
3597
3603
  };
3598
3604
 
3599
3605
  // src/throttle-progress.ts
@@ -3629,7 +3635,36 @@ var createThrottledProgressCallback = (callback, throttleMs = DEFAULT_THROTTLE_M
3629
3635
  }, remainingTime);
3630
3636
  }
3631
3637
  };
3632
- return throttled;
3638
+ const cleanup = () => {
3639
+ if (timeoutId !== null) {
3640
+ clearTimeout(timeoutId);
3641
+ timeoutId = null;
3642
+ }
3643
+ pendingUpdate = null;
3644
+ };
3645
+ return { throttled, [Symbol.dispose]: cleanup };
3646
+ };
3647
+
3648
+ // src/validate-scale.ts
3649
+ var validateScale = (scale) => {
3650
+ if (typeof scale === "undefined") {
3651
+ return;
3652
+ }
3653
+ if (typeof scale !== "number") {
3654
+ throw new Error('Scale should be a number or undefined, but is "' + JSON.stringify(scale) + '"');
3655
+ }
3656
+ if (Number.isNaN(scale)) {
3657
+ throw new Error("`scale` should not be NaN, but is NaN");
3658
+ }
3659
+ if (!Number.isFinite(scale)) {
3660
+ throw new Error(`"scale" must be finite, but is ${scale}`);
3661
+ }
3662
+ if (scale <= 0) {
3663
+ throw new Error(`"scale" must be bigger than 0, but is ${scale}`);
3664
+ }
3665
+ if (scale > 16) {
3666
+ throw new Error(`"scale" must be smaller or equal than 16, but is ${scale}`);
3667
+ }
3633
3668
  };
3634
3669
 
3635
3670
  // src/validate-video-frame.ts
@@ -3661,6 +3696,17 @@ var validateVideoFrame = ({
3661
3696
  return returnedFrame;
3662
3697
  };
3663
3698
 
3699
+ // src/with-resolvers.ts
3700
+ var withResolvers = function() {
3701
+ let resolve;
3702
+ let reject;
3703
+ const promise = new Promise((res, rej) => {
3704
+ resolve = res;
3705
+ reject = rej;
3706
+ });
3707
+ return { promise, resolve, reject };
3708
+ };
3709
+
3664
3710
  // src/wait-for-ready.ts
3665
3711
  var waitForReady = ({
3666
3712
  timeoutInMilliseconds,
@@ -3691,7 +3737,12 @@ var waitForReady = ({
3691
3737
  if (scope.remotion_cancelledError !== undefined) {
3692
3738
  cancelled = true;
3693
3739
  internalState?.addWaitForReadyTime(performance.now() - start);
3694
- reject(scope.remotion_cancelledError);
3740
+ const stack = scope.remotion_cancelledError;
3741
+ const message = stack.split(`
3742
+ `)[0].replace(/^Error: /, "");
3743
+ const error = new Error(message);
3744
+ error.stack = stack;
3745
+ reject(error);
3695
3746
  return;
3696
3747
  }
3697
3748
  if (performance.now() - start > timeoutInMilliseconds + 3000) {
@@ -3775,10 +3826,12 @@ var internalRenderMediaOnWeb = async ({
3775
3826
  onFrame,
3776
3827
  outputTarget: userDesiredOutputTarget,
3777
3828
  licenseKey,
3778
- muted
3829
+ muted,
3830
+ scale
3779
3831
  }) => {
3780
3832
  let __stack2 = [];
3781
3833
  try {
3834
+ validateScale(scale);
3782
3835
  const outputTarget = userDesiredOutputTarget === null ? await canUseWebFsWriter() ? "web-fs" : "arraybuffer" : userDesiredOutputTarget;
3783
3836
  if (outputTarget === "web-fs") {
3784
3837
  await cleanupStaleOpfsFiles();
@@ -3819,7 +3872,7 @@ var internalRenderMediaOnWeb = async ({
3819
3872
  if (signal?.aborted) {
3820
3873
  return Promise.reject(new Error("renderMediaOnWeb() was cancelled"));
3821
3874
  }
3822
- const scaffold = __using(__stack2, await createScaffold({
3875
+ const scaffold = __using(__stack2, createScaffold({
3823
3876
  width: resolved.width,
3824
3877
  height: resolved.height,
3825
3878
  fps: resolved.fps,
@@ -3837,7 +3890,7 @@ var internalRenderMediaOnWeb = async ({
3837
3890
  defaultCodec: resolved.defaultCodec,
3838
3891
  defaultOutName: resolved.defaultOutName
3839
3892
  }), 0);
3840
- const { delayRenderScope, div, timeUpdater, collectAssets } = scaffold;
3893
+ const { delayRenderScope, div, timeUpdater, collectAssets, errorHolder } = scaffold;
3841
3894
  const internalState = __using(__stack2, makeInternalState(), 0);
3842
3895
  const keepalive = __using(__stack2, createBackgroundKeepalive({
3843
3896
  fps: resolved.fps,
@@ -3850,6 +3903,8 @@ var internalRenderMediaOnWeb = async ({
3850
3903
  format,
3851
3904
  target
3852
3905
  }), 0);
3906
+ const throttledProgress = __using(__stack2, createThrottledProgressCallback(onProgress), 0);
3907
+ const throttledOnProgress = throttledProgress?.throttled ?? null;
3853
3908
  try {
3854
3909
  let __stack = [];
3855
3910
  try {
@@ -3864,6 +3919,7 @@ var internalRenderMediaOnWeb = async ({
3864
3919
  internalState,
3865
3920
  keepalive
3866
3921
  });
3922
+ checkForError(errorHolder);
3867
3923
  if (signal?.aborted) {
3868
3924
  throw new Error("renderMediaOnWeb() was cancelled");
3869
3925
  }
@@ -3893,7 +3949,6 @@ var internalRenderMediaOnWeb = async ({
3893
3949
  renderedFrames: 0,
3894
3950
  encodedFrames: 0
3895
3951
  };
3896
- const throttledOnProgress = createThrottledProgressCallback(onProgress);
3897
3952
  for (let frame = realFrameRange[0];frame <= realFrameRange[1]; frame++) {
3898
3953
  if (signal?.aborted) {
3899
3954
  throw new Error("renderMediaOnWeb() was cancelled");
@@ -3907,23 +3962,25 @@ var internalRenderMediaOnWeb = async ({
3907
3962
  keepalive,
3908
3963
  internalState
3909
3964
  });
3965
+ checkForError(errorHolder);
3910
3966
  if (signal?.aborted) {
3911
3967
  throw new Error("renderMediaOnWeb() was cancelled");
3912
3968
  }
3913
3969
  const createFrameStart = performance.now();
3914
- const imageData = await createFrame({
3915
- div,
3916
- width: resolved.width,
3917
- height: resolved.height,
3970
+ const layer = await createLayer({
3971
+ element: div,
3972
+ scale,
3918
3973
  logLevel,
3919
- internalState
3974
+ internalState,
3975
+ onlyBackgroundClipText: false,
3976
+ cutout: new DOMRect(0, 0, resolved.width, resolved.height)
3920
3977
  });
3921
3978
  internalState.addCreateFrameTime(performance.now() - createFrameStart);
3922
3979
  if (signal?.aborted) {
3923
3980
  throw new Error("renderMediaOnWeb() was cancelled");
3924
3981
  }
3925
3982
  const timestamp = Math.round((frame - realFrameRange[0]) / resolved.fps * 1e6);
3926
- const videoFrame = new VideoFrame(imageData, {
3983
+ const videoFrame = new VideoFrame(layer.canvas, {
3927
3984
  timestamp
3928
3985
  });
3929
3986
  progress.renderedFrames++;
@@ -3937,8 +3994,8 @@ var internalRenderMediaOnWeb = async ({
3937
3994
  frameToEncode = validateVideoFrame({
3938
3995
  originalFrame: videoFrame,
3939
3996
  returnedFrame,
3940
- expectedWidth: resolved.width,
3941
- expectedHeight: resolved.height,
3997
+ expectedWidth: Math.round(resolved.width * scale),
3998
+ expectedHeight: Math.round(resolved.height * scale),
3942
3999
  expectedTimestamp: timestamp
3943
4000
  });
3944
4001
  }
@@ -3946,7 +4003,7 @@ var internalRenderMediaOnWeb = async ({
3946
4003
  const assets = collectAssets.current.collectAssets();
3947
4004
  if (onArtifact) {
3948
4005
  await artifactsHandler.handle({
3949
- imageData,
4006
+ imageData: layer.canvas,
3950
4007
  frame,
3951
4008
  assets,
3952
4009
  onArtifact
@@ -4052,7 +4109,8 @@ var renderMediaOnWeb = (options) => {
4052
4109
  onFrame: options.onFrame ?? null,
4053
4110
  outputTarget: options.outputTarget ?? null,
4054
4111
  licenseKey: options.licenseKey ?? undefined,
4055
- muted: options.muted ?? false
4112
+ muted: options.muted ?? false,
4113
+ scale: options.scale ?? 1
4056
4114
  }));
4057
4115
  return onlyOneRenderAtATimeQueue.ref;
4058
4116
  };
@@ -4071,10 +4129,12 @@ async function internalRenderStillOnWeb({
4071
4129
  composition,
4072
4130
  signal,
4073
4131
  onArtifact,
4074
- licenseKey
4132
+ licenseKey,
4133
+ scale
4075
4134
  }) {
4076
4135
  let __stack = [];
4077
4136
  try {
4137
+ validateScale(scale);
4078
4138
  const resolved = await Internals9.resolveVideoConfig({
4079
4139
  calculateMetadata: composition.calculateMetadata ?? null,
4080
4140
  signal: signal ?? new AbortController().signal,
@@ -4090,7 +4150,7 @@ async function internalRenderStillOnWeb({
4090
4150
  return Promise.reject(new Error("renderStillOnWeb() was cancelled"));
4091
4151
  }
4092
4152
  const internalState = __using(__stack, makeInternalState(), 0);
4093
- const scaffold = __using(__stack, await createScaffold({
4153
+ const scaffold = __using(__stack, createScaffold({
4094
4154
  width: resolved.width,
4095
4155
  height: resolved.height,
4096
4156
  delayRenderTimeoutInMilliseconds,
@@ -4108,7 +4168,7 @@ async function internalRenderStillOnWeb({
4108
4168
  defaultCodec: resolved.defaultCodec,
4109
4169
  defaultOutName: resolved.defaultOutName
4110
4170
  }), 0);
4111
- const { delayRenderScope, div, collectAssets } = scaffold;
4171
+ const { delayRenderScope, div, collectAssets, errorHolder } = scaffold;
4112
4172
  const artifactsHandler = handleArtifacts();
4113
4173
  try {
4114
4174
  if (signal?.aborted) {
@@ -4122,16 +4182,20 @@ async function internalRenderStillOnWeb({
4122
4182
  internalState: null,
4123
4183
  keepalive: null
4124
4184
  });
4185
+ checkForError(errorHolder);
4125
4186
  if (signal?.aborted) {
4126
4187
  throw new Error("renderStillOnWeb() was cancelled");
4127
4188
  }
4128
- const imageData = await takeScreenshot({
4129
- div,
4130
- width: resolved.width,
4131
- height: resolved.height,
4132
- imageFormat,
4189
+ const capturedFrame = await createLayer({
4190
+ element: div,
4191
+ scale,
4133
4192
  logLevel,
4134
- internalState
4193
+ internalState,
4194
+ onlyBackgroundClipText: false,
4195
+ cutout: new DOMRect(0, 0, resolved.width, resolved.height)
4196
+ });
4197
+ const imageData = await capturedFrame.canvas.convertToBlob({
4198
+ type: `image/${imageFormat}`
4135
4199
  });
4136
4200
  const assets = collectAssets.current.collectAssets();
4137
4201
  if (onArtifact) {
@@ -4170,7 +4234,8 @@ var renderStillOnWeb = (options) => {
4170
4234
  mediaCacheSizeInBytes: options.mediaCacheSizeInBytes ?? null,
4171
4235
  signal: options.signal ?? null,
4172
4236
  onArtifact: options.onArtifact ?? null,
4173
- licenseKey: options.licenseKey ?? undefined
4237
+ licenseKey: options.licenseKey ?? undefined,
4238
+ scale: options.scale ?? 1
4174
4239
  }));
4175
4240
  return onlyOneRenderAtATimeQueue.ref;
4176
4241
  };