@remotion/web-renderer 4.0.405 → 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
3599
+ onlyBackgroundClipText,
3600
+ scale
3575
3601
  });
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}`
3595
- });
3596
- return imageData;
3602
+ return context;
3597
3603
  };
3598
3604
 
3599
3605
  // src/throttle-progress.ts
@@ -3639,6 +3645,28 @@ var createThrottledProgressCallback = (callback, throttleMs = DEFAULT_THROTTLE_M
3639
3645
  return { throttled, [Symbol.dispose]: cleanup };
3640
3646
  };
3641
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
+ }
3668
+ };
3669
+
3642
3670
  // src/validate-video-frame.ts
3643
3671
  var validateVideoFrame = ({
3644
3672
  originalFrame,
@@ -3668,6 +3696,17 @@ var validateVideoFrame = ({
3668
3696
  return returnedFrame;
3669
3697
  };
3670
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
+
3671
3710
  // src/wait-for-ready.ts
3672
3711
  var waitForReady = ({
3673
3712
  timeoutInMilliseconds,
@@ -3698,7 +3737,12 @@ var waitForReady = ({
3698
3737
  if (scope.remotion_cancelledError !== undefined) {
3699
3738
  cancelled = true;
3700
3739
  internalState?.addWaitForReadyTime(performance.now() - start);
3701
- 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);
3702
3746
  return;
3703
3747
  }
3704
3748
  if (performance.now() - start > timeoutInMilliseconds + 3000) {
@@ -3782,10 +3826,12 @@ var internalRenderMediaOnWeb = async ({
3782
3826
  onFrame,
3783
3827
  outputTarget: userDesiredOutputTarget,
3784
3828
  licenseKey,
3785
- muted
3829
+ muted,
3830
+ scale
3786
3831
  }) => {
3787
3832
  let __stack2 = [];
3788
3833
  try {
3834
+ validateScale(scale);
3789
3835
  const outputTarget = userDesiredOutputTarget === null ? await canUseWebFsWriter() ? "web-fs" : "arraybuffer" : userDesiredOutputTarget;
3790
3836
  if (outputTarget === "web-fs") {
3791
3837
  await cleanupStaleOpfsFiles();
@@ -3826,7 +3872,7 @@ var internalRenderMediaOnWeb = async ({
3826
3872
  if (signal?.aborted) {
3827
3873
  return Promise.reject(new Error("renderMediaOnWeb() was cancelled"));
3828
3874
  }
3829
- const scaffold = __using(__stack2, await createScaffold({
3875
+ const scaffold = __using(__stack2, createScaffold({
3830
3876
  width: resolved.width,
3831
3877
  height: resolved.height,
3832
3878
  fps: resolved.fps,
@@ -3844,7 +3890,7 @@ var internalRenderMediaOnWeb = async ({
3844
3890
  defaultCodec: resolved.defaultCodec,
3845
3891
  defaultOutName: resolved.defaultOutName
3846
3892
  }), 0);
3847
- const { delayRenderScope, div, timeUpdater, collectAssets } = scaffold;
3893
+ const { delayRenderScope, div, timeUpdater, collectAssets, errorHolder } = scaffold;
3848
3894
  const internalState = __using(__stack2, makeInternalState(), 0);
3849
3895
  const keepalive = __using(__stack2, createBackgroundKeepalive({
3850
3896
  fps: resolved.fps,
@@ -3873,6 +3919,7 @@ var internalRenderMediaOnWeb = async ({
3873
3919
  internalState,
3874
3920
  keepalive
3875
3921
  });
3922
+ checkForError(errorHolder);
3876
3923
  if (signal?.aborted) {
3877
3924
  throw new Error("renderMediaOnWeb() was cancelled");
3878
3925
  }
@@ -3915,23 +3962,25 @@ var internalRenderMediaOnWeb = async ({
3915
3962
  keepalive,
3916
3963
  internalState
3917
3964
  });
3965
+ checkForError(errorHolder);
3918
3966
  if (signal?.aborted) {
3919
3967
  throw new Error("renderMediaOnWeb() was cancelled");
3920
3968
  }
3921
3969
  const createFrameStart = performance.now();
3922
- const imageData = await createFrame({
3923
- div,
3924
- width: resolved.width,
3925
- height: resolved.height,
3970
+ const layer = await createLayer({
3971
+ element: div,
3972
+ scale,
3926
3973
  logLevel,
3927
- internalState
3974
+ internalState,
3975
+ onlyBackgroundClipText: false,
3976
+ cutout: new DOMRect(0, 0, resolved.width, resolved.height)
3928
3977
  });
3929
3978
  internalState.addCreateFrameTime(performance.now() - createFrameStart);
3930
3979
  if (signal?.aborted) {
3931
3980
  throw new Error("renderMediaOnWeb() was cancelled");
3932
3981
  }
3933
3982
  const timestamp = Math.round((frame - realFrameRange[0]) / resolved.fps * 1e6);
3934
- const videoFrame = new VideoFrame(imageData, {
3983
+ const videoFrame = new VideoFrame(layer.canvas, {
3935
3984
  timestamp
3936
3985
  });
3937
3986
  progress.renderedFrames++;
@@ -3945,8 +3994,8 @@ var internalRenderMediaOnWeb = async ({
3945
3994
  frameToEncode = validateVideoFrame({
3946
3995
  originalFrame: videoFrame,
3947
3996
  returnedFrame,
3948
- expectedWidth: resolved.width,
3949
- expectedHeight: resolved.height,
3997
+ expectedWidth: Math.round(resolved.width * scale),
3998
+ expectedHeight: Math.round(resolved.height * scale),
3950
3999
  expectedTimestamp: timestamp
3951
4000
  });
3952
4001
  }
@@ -3954,7 +4003,7 @@ var internalRenderMediaOnWeb = async ({
3954
4003
  const assets = collectAssets.current.collectAssets();
3955
4004
  if (onArtifact) {
3956
4005
  await artifactsHandler.handle({
3957
- imageData,
4006
+ imageData: layer.canvas,
3958
4007
  frame,
3959
4008
  assets,
3960
4009
  onArtifact
@@ -4060,7 +4109,8 @@ var renderMediaOnWeb = (options) => {
4060
4109
  onFrame: options.onFrame ?? null,
4061
4110
  outputTarget: options.outputTarget ?? null,
4062
4111
  licenseKey: options.licenseKey ?? undefined,
4063
- muted: options.muted ?? false
4112
+ muted: options.muted ?? false,
4113
+ scale: options.scale ?? 1
4064
4114
  }));
4065
4115
  return onlyOneRenderAtATimeQueue.ref;
4066
4116
  };
@@ -4079,10 +4129,12 @@ async function internalRenderStillOnWeb({
4079
4129
  composition,
4080
4130
  signal,
4081
4131
  onArtifact,
4082
- licenseKey
4132
+ licenseKey,
4133
+ scale
4083
4134
  }) {
4084
4135
  let __stack = [];
4085
4136
  try {
4137
+ validateScale(scale);
4086
4138
  const resolved = await Internals9.resolveVideoConfig({
4087
4139
  calculateMetadata: composition.calculateMetadata ?? null,
4088
4140
  signal: signal ?? new AbortController().signal,
@@ -4098,7 +4150,7 @@ async function internalRenderStillOnWeb({
4098
4150
  return Promise.reject(new Error("renderStillOnWeb() was cancelled"));
4099
4151
  }
4100
4152
  const internalState = __using(__stack, makeInternalState(), 0);
4101
- const scaffold = __using(__stack, await createScaffold({
4153
+ const scaffold = __using(__stack, createScaffold({
4102
4154
  width: resolved.width,
4103
4155
  height: resolved.height,
4104
4156
  delayRenderTimeoutInMilliseconds,
@@ -4116,7 +4168,7 @@ async function internalRenderStillOnWeb({
4116
4168
  defaultCodec: resolved.defaultCodec,
4117
4169
  defaultOutName: resolved.defaultOutName
4118
4170
  }), 0);
4119
- const { delayRenderScope, div, collectAssets } = scaffold;
4171
+ const { delayRenderScope, div, collectAssets, errorHolder } = scaffold;
4120
4172
  const artifactsHandler = handleArtifacts();
4121
4173
  try {
4122
4174
  if (signal?.aborted) {
@@ -4130,16 +4182,20 @@ async function internalRenderStillOnWeb({
4130
4182
  internalState: null,
4131
4183
  keepalive: null
4132
4184
  });
4185
+ checkForError(errorHolder);
4133
4186
  if (signal?.aborted) {
4134
4187
  throw new Error("renderStillOnWeb() was cancelled");
4135
4188
  }
4136
- const imageData = await takeScreenshot({
4137
- div,
4138
- width: resolved.width,
4139
- height: resolved.height,
4140
- imageFormat,
4189
+ const capturedFrame = await createLayer({
4190
+ element: div,
4191
+ scale,
4141
4192
  logLevel,
4142
- 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}`
4143
4199
  });
4144
4200
  const assets = collectAssets.current.collectAssets();
4145
4201
  if (onArtifact) {
@@ -4178,7 +4234,8 @@ var renderStillOnWeb = (options) => {
4178
4234
  mediaCacheSizeInBytes: options.mediaCacheSizeInBytes ?? null,
4179
4235
  signal: options.signal ?? null,
4180
4236
  onArtifact: options.onArtifact ?? null,
4181
- licenseKey: options.licenseKey ?? undefined
4237
+ licenseKey: options.licenseKey ?? undefined,
4238
+ scale: options.scale ?? 1
4182
4239
  }));
4183
4240
  return onlyOneRenderAtATimeQueue.ref;
4184
4241
  };