@remotion/web-renderer 4.0.454 → 4.0.456

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.
@@ -16,6 +16,7 @@ export declare const calculateTransforms: ({ element, rootElement, }: {
16
16
  precompositing: {
17
17
  needs3DTransformViaWebGL: boolean;
18
18
  needsMaskImage: LinearGradientInfo | null;
19
+ needsFilterPrecompositing: string | null;
19
20
  needsPrecompositing: boolean;
20
21
  };
21
22
  };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Gets the precompose rect for an element with a filter that requires precompositing.
3
+ * Expands the element's bounding rect (including all children) to accommodate drop-shadow spread.
4
+ */
5
+ export declare const getPrecomposeRectForFilter: ({ element, filter, }: {
6
+ element: HTMLElement | SVGElement;
7
+ filter: string;
8
+ }) => DOMRect;
9
+ /**
10
+ * Applies a filter when drawing a precomposed canvas to the main context.
11
+ */
12
+ export declare const applyFilterToDrawOperation: ({ context, filter, drawFn, }: {
13
+ context: OffscreenCanvasRenderingContext2D;
14
+ filter: string;
15
+ drawFn: () => void;
16
+ }) => void;
@@ -2032,6 +2032,15 @@ var parseTransformOrigin = (transformOrigin) => {
2032
2032
  };
2033
2033
 
2034
2034
  // src/drawing/calculate-transforms.ts
2035
+ var filterRequiresPrecompositing = (filter) => {
2036
+ if (!filter || filter === "none") {
2037
+ return null;
2038
+ }
2039
+ if (filter.includes("drop-shadow")) {
2040
+ return filter;
2041
+ }
2042
+ return null;
2043
+ };
2035
2044
  var getInternalTransformOrigin = (transform) => {
2036
2045
  const centerX = transform.boundingClientRect.width / 2;
2037
2046
  const centerY = transform.boundingClientRect.height / 2;
@@ -2058,6 +2067,7 @@ var calculateTransforms = ({
2058
2067
  let opacity = 1;
2059
2068
  let elementComputedStyle = null;
2060
2069
  let maskImageInfo = null;
2070
+ let filterForPrecompositing = null;
2061
2071
  while (parent) {
2062
2072
  const originalTransition = parent.style.transition;
2063
2073
  parent.style.transition = "none";
@@ -2067,14 +2077,22 @@ var calculateTransforms = ({
2067
2077
  opacity = parseFloat(computedStyle.opacity);
2068
2078
  const maskImageValue = getMaskImageValue(computedStyle);
2069
2079
  maskImageInfo = maskImageValue ? parseMaskImage(maskImageValue) : null;
2080
+ filterForPrecompositing = filterRequiresPrecompositing(computedStyle.filter);
2070
2081
  const originalMaskImage = parent.style.maskImage;
2071
2082
  const originalWebkitMaskImage = parent.style.webkitMaskImage;
2072
2083
  parent.style.maskImage = "none";
2073
2084
  parent.style.webkitMaskImage = "none";
2085
+ const originalFilter = parent.style.filter;
2086
+ if (filterForPrecompositing) {
2087
+ parent.style.filter = "none";
2088
+ }
2074
2089
  const parentRef = parent;
2075
2090
  toReset.push(() => {
2076
2091
  parentRef.style.maskImage = originalMaskImage;
2077
2092
  parentRef.style.webkitMaskImage = originalWebkitMaskImage;
2093
+ if (filterForPrecompositing) {
2094
+ parentRef.style.filter = originalFilter;
2095
+ }
2078
2096
  });
2079
2097
  }
2080
2098
  if (hasAnyTransformCssValue(computedStyle) || parent === element) {
@@ -2136,6 +2154,7 @@ var calculateTransforms = ({
2136
2154
  }
2137
2155
  const needs3DTransformViaWebGL = !totalMatrix.is2D;
2138
2156
  const needsMaskImage = maskImageInfo !== null;
2157
+ const needsFilterPrecompositing = filterForPrecompositing !== null;
2139
2158
  return {
2140
2159
  dimensions,
2141
2160
  totalMatrix,
@@ -2151,7 +2170,8 @@ var calculateTransforms = ({
2151
2170
  precompositing: {
2152
2171
  needs3DTransformViaWebGL,
2153
2172
  needsMaskImage: maskImageInfo,
2154
- needsPrecompositing: Boolean(needs3DTransformViaWebGL || needsMaskImage)
2173
+ needsFilterPrecompositing: filterForPrecompositing,
2174
+ needsPrecompositing: Boolean(needs3DTransformViaWebGL || needsMaskImage || needsFilterPrecompositing)
2155
2175
  }
2156
2176
  };
2157
2177
  };
@@ -3777,6 +3797,64 @@ var handle3dTransform = ({
3777
3797
  return transformed;
3778
3798
  };
3779
3799
 
3800
+ // src/drawing/handle-filter.ts
3801
+ var parseDropShadowExpansion = (filter) => {
3802
+ const expansion = { left: 0, right: 0, top: 0, bottom: 0 };
3803
+ const dropShadowRegex = /drop-shadow\(((?:[^()]+|\([^()]*\))+)\)/gi;
3804
+ let match;
3805
+ while ((match = dropShadowRegex.exec(filter)) !== null) {
3806
+ const params = match[1].trim();
3807
+ const numbers = [];
3808
+ const numberRegex = /([+-]?\d*\.?\d+)(?:px)?/g;
3809
+ let numMatch;
3810
+ while ((numMatch = numberRegex.exec(params)) !== null) {
3811
+ const beforeMatch = params.slice(0, numMatch.index);
3812
+ if (!/(?:rgba?|hsla?)\([^)]*$/i.test(beforeMatch)) {
3813
+ numbers.push(parseFloat(numMatch[1]));
3814
+ }
3815
+ }
3816
+ if (numbers.length >= 2) {
3817
+ const offsetX = numbers[0];
3818
+ const offsetY = numbers[1];
3819
+ const blurRadius = numbers.length >= 3 ? numbers[2] : 0;
3820
+ const blurSpread = blurRadius * 3;
3821
+ if (offsetX > 0) {
3822
+ expansion.right = Math.max(expansion.right, offsetX + blurSpread);
3823
+ expansion.left = Math.max(expansion.left, blurSpread);
3824
+ } else {
3825
+ expansion.left = Math.max(expansion.left, Math.abs(offsetX) + blurSpread);
3826
+ expansion.right = Math.max(expansion.right, blurSpread);
3827
+ }
3828
+ if (offsetY > 0) {
3829
+ expansion.bottom = Math.max(expansion.bottom, offsetY + blurSpread);
3830
+ expansion.top = Math.max(expansion.top, blurSpread);
3831
+ } else {
3832
+ expansion.top = Math.max(expansion.top, Math.abs(offsetY) + blurSpread);
3833
+ expansion.bottom = Math.max(expansion.bottom, blurSpread);
3834
+ }
3835
+ }
3836
+ }
3837
+ return expansion;
3838
+ };
3839
+ var getPrecomposeRectForFilter = ({
3840
+ element,
3841
+ filter
3842
+ }) => {
3843
+ const elementRect = getBiggestBoundingClientRect(element);
3844
+ const expansion = parseDropShadowExpansion(filter);
3845
+ return new DOMRect(elementRect.left - expansion.left, elementRect.top - expansion.top, elementRect.width + expansion.left + expansion.right, elementRect.height + expansion.top + expansion.bottom);
3846
+ };
3847
+ var applyFilterToDrawOperation = ({
3848
+ context,
3849
+ filter,
3850
+ drawFn
3851
+ }) => {
3852
+ const previousFilter = context.filter;
3853
+ context.filter = filter;
3854
+ drawFn();
3855
+ context.filter = previousFilter;
3856
+ };
3857
+
3780
3858
  // src/drawing/handle-mask.ts
3781
3859
  var getPrecomposeRectForMask = (element) => {
3782
3860
  const boundingRect = getBiggestBoundingClientRect(element);
@@ -3878,6 +3956,16 @@ var processNode = async ({
3878
3956
  secondRect: tentativePrecomposeRect
3879
3957
  }));
3880
3958
  }
3959
+ if (precompositing.needsFilterPrecompositing) {
3960
+ const tentativePrecomposeRect = getPrecomposeRectForFilter({
3961
+ element,
3962
+ filter: precompositing.needsFilterPrecompositing
3963
+ });
3964
+ precomposeRect = roundToExpandRect(getWiderRectAndExpand({
3965
+ firstRect: precomposeRect,
3966
+ secondRect: tentativePrecomposeRect
3967
+ }));
3968
+ }
3881
3969
  if (!precomposeRect) {
3882
3970
  throw new Error("Precompose rect not found");
3883
3971
  }
@@ -3927,7 +4015,18 @@ var processNode = async ({
3927
4015
  }
3928
4016
  const previousTransform = context.getTransform();
3929
4017
  context.setTransform(new DOMMatrix);
3930
- context.drawImage(drawable, 0, drawable.height - rectAfterTransforms.height, rectAfterTransforms.width, rectAfterTransforms.height, rectAfterTransforms.left - parentRect.x, rectAfterTransforms.top - parentRect.y, rectAfterTransforms.width, rectAfterTransforms.height);
4018
+ const drawPrecomposedCanvas = () => {
4019
+ context.drawImage(drawable, 0, 0, drawable.width, drawable.height, rectAfterTransforms.left - parentRect.x * scale, rectAfterTransforms.top - parentRect.y * scale, rectAfterTransforms.width, rectAfterTransforms.height);
4020
+ };
4021
+ if (precompositing.needsFilterPrecompositing) {
4022
+ applyFilterToDrawOperation({
4023
+ context,
4024
+ filter: precompositing.needsFilterPrecompositing,
4025
+ drawFn: drawPrecomposedCanvas
4026
+ });
4027
+ } else {
4028
+ drawPrecomposedCanvas();
4029
+ }
3931
4030
  context.setTransform(previousTransform);
3932
4031
  Internals6.Log.trace({
3933
4032
  logLevel,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/web-renderer"
4
4
  },
5
5
  "name": "@remotion/web-renderer",
6
- "version": "4.0.454",
6
+ "version": "4.0.456",
7
7
  "main": "dist/index.js",
8
8
  "type": "module",
9
9
  "scripts": {
@@ -22,19 +22,19 @@
22
22
  "@mediabunny/mp3-encoder": "1.42.0",
23
23
  "@mediabunny/aac-encoder": "1.42.0",
24
24
  "@mediabunny/flac-encoder": "1.42.0",
25
- "@remotion/licensing": "4.0.454",
26
- "remotion": "4.0.454",
25
+ "@remotion/licensing": "4.0.456",
26
+ "remotion": "4.0.456",
27
27
  "mediabunny": "1.42.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@react-three/fiber": "9.2.0",
31
- "@remotion/eslint-config-internal": "4.0.454",
32
- "@remotion/paths": "4.0.454",
33
- "@remotion/player": "4.0.454",
34
- "@remotion/media": "4.0.454",
35
- "@remotion/shapes": "4.0.454",
36
- "@remotion/three": "4.0.454",
37
- "@remotion/transitions": "4.0.454",
31
+ "@remotion/eslint-config-internal": "4.0.456",
32
+ "@remotion/paths": "4.0.456",
33
+ "@remotion/player": "4.0.456",
34
+ "@remotion/media": "4.0.456",
35
+ "@remotion/shapes": "4.0.456",
36
+ "@remotion/three": "4.0.456",
37
+ "@remotion/transitions": "4.0.456",
38
38
  "@types/three": "0.170.0",
39
39
  "@typescript/native-preview": "7.0.0-dev.20260217.1",
40
40
  "@vitejs/plugin-react": "4.3.4",