Skip to main content

webrender/
svg_filter.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use api::{FilterOpGraphPictureReference, FilterOpGraphNode, ColorF, ColorU, PropertyBinding, PropertyBindingId};
6use api::SVGFE_GRAPH_MAX;
7use api::units::*;
8use api::FilterOpGraphPictureBufferId;
9use crate::profiler::add_text_marker;
10use crate::filterdata::FilterDataHandle;
11use crate::intern::ItemUid;
12use core::time::Duration;
13
14
15#[cfg_attr(feature = "capture", derive(Serialize))]
16#[cfg_attr(feature = "replay", derive(Deserialize))]
17#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
18pub enum FilterGraphPictureBufferIdKey {
19    #[default]
20    /// empty slot in feMerge inputs
21    None,
22    /// reference to another (earlier) node in filter graph
23    BufferId(i16),
24}
25
26#[cfg_attr(feature = "capture", derive(Serialize))]
27#[cfg_attr(feature = "replay", derive(Deserialize))]
28#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
29pub struct FilterGraphPictureReferenceKey {
30    /// Id of the picture in question in a namespace unique to this filter DAG,
31    /// some are special values like
32    /// FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic.
33    pub buffer_id: FilterGraphPictureBufferIdKey,
34    /// Place the input image here in Layout space (like node.subregion)
35    pub subregion: [Au; 4],
36    /// Translate the subregion by this amount
37    pub offset: [Au; 2],
38}
39
40impl From<FilterGraphPictureReference> for FilterGraphPictureReferenceKey {
41    fn from(pic: FilterGraphPictureReference) -> Self {
42        FilterGraphPictureReferenceKey{
43            buffer_id: match pic.buffer_id {
44                FilterOpGraphPictureBufferId::None => FilterGraphPictureBufferIdKey::None,
45                FilterOpGraphPictureBufferId::BufferId(id) => FilterGraphPictureBufferIdKey::BufferId(id),
46            },
47            subregion: [
48                Au::from_f32_px(pic.subregion.min.x),
49                Au::from_f32_px(pic.subregion.min.y),
50                Au::from_f32_px(pic.subregion.max.x),
51                Au::from_f32_px(pic.subregion.max.y),
52            ],
53            offset: [
54                Au::from_f32_px(pic.offset.x),
55                Au::from_f32_px(pic.offset.y),
56            ],
57        }
58    }
59}
60
61#[cfg_attr(feature = "capture", derive(Serialize))]
62#[cfg_attr(feature = "replay", derive(Deserialize))]
63#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
64pub enum FilterGraphOpKey {
65    /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
66    /// parameters: FilterOpGraphNode
67    /// SVG filter semantics - selectable input(s), selectable between linear
68    /// (default) and sRGB color space for calculations
69    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
70    SVGFEBlendDarken,
71    /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
72    /// parameters: FilterOpGraphNode
73    /// SVG filter semantics - selectable input(s), selectable between linear
74    /// (default) and sRGB color space for calculations
75    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
76    SVGFEBlendLighten,
77    /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
78    /// parameters: FilterOpGraphNode
79    /// SVG filter semantics - selectable input(s), selectable between linear
80    /// (default) and sRGB color space for calculations
81    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
82    SVGFEBlendMultiply,
83    /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
84    /// parameters: FilterOpGraphNode
85    /// SVG filter semantics - selectable input(s), selectable between linear
86    /// (default) and sRGB color space for calculations
87    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
88    SVGFEBlendNormal,
89    /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
90    /// parameters: FilterOpGraphNode
91    /// SVG filter semantics - selectable input(s), selectable between linear
92    /// (default) and sRGB color space for calculations
93    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
94    SVGFEBlendScreen,
95    /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
96    /// parameters: FilterOpGraphNode
97    /// SVG filter semantics - selectable input(s), selectable between linear
98    /// (default) and sRGB color space for calculations
99    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
100    SVGFEBlendOverlay,
101    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
102    /// parameters: FilterOpGraphNode
103    /// SVG filter semantics - selectable input(s), selectable between linear
104    /// (default) and sRGB color space for calculations
105    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
106    SVGFEBlendColorDodge,
107    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
108    /// parameters: FilterOpGraphNode
109    /// SVG filter semantics - selectable input(s), selectable between linear
110    /// (default) and sRGB color space for calculations
111    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
112    SVGFEBlendColorBurn,
113    /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
114    /// parameters: FilterOpGraphNode
115    /// SVG filter semantics - selectable input(s), selectable between linear
116    /// (default) and sRGB color space for calculations
117    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
118    SVGFEBlendHardLight,
119    /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
120    /// parameters: FilterOpGraphNode
121    /// SVG filter semantics - selectable input(s), selectable between linear
122    /// (default) and sRGB color space for calculations
123    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
124    SVGFEBlendSoftLight,
125    /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
126    /// parameters: FilterOpGraphNode
127    /// SVG filter semantics - selectable input(s), selectable between linear
128    /// (default) and sRGB color space for calculations
129    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
130    SVGFEBlendDifference,
131    /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
132    /// parameters: FilterOpGraphNode
133    /// SVG filter semantics - selectable input(s), selectable between linear
134    /// (default) and sRGB color space for calculations
135    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
136    SVGFEBlendExclusion,
137    /// combine 2 images with SVG_FEBLEND_MODE_HUE
138    /// parameters: FilterOpGraphNode
139    /// SVG filter semantics - selectable input(s), selectable between linear
140    /// (default) and sRGB color space for calculations
141    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
142    SVGFEBlendHue,
143    /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
144    /// parameters: FilterOpGraphNode
145    /// SVG filter semantics - selectable input(s), selectable between linear
146    /// (default) and sRGB color space for calculations
147    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
148    SVGFEBlendSaturation,
149    /// combine 2 images with SVG_FEBLEND_MODE_COLOR
150    /// parameters: FilterOpGraphNode
151    /// SVG filter semantics - selectable input(s), selectable between linear
152    /// (default) and sRGB color space for calculations
153    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
154    SVGFEBlendColor,
155    /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
156    /// parameters: FilterOpGraphNode
157    /// SVG filter semantics - selectable input(s), selectable between linear
158    /// (default) and sRGB color space for calculations
159    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
160    SVGFEBlendLuminosity,
161    /// transform colors of image through 5x4 color matrix (transposed for
162    /// efficiency)
163    /// parameters: FilterOpGraphNode, matrix[5][4]
164    /// SVG filter semantics - selectable input(s), selectable between linear
165    /// (default) and sRGB color space for calculations
166    /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
167    SVGFEColorMatrix{values: [Au; 20]},
168    /// transform colors of image through configurable gradients with component
169    /// swizzle
170    /// parameters: FilterOpGraphNode, FilterData
171    /// SVG filter semantics - selectable input(s), selectable between linear
172    /// (default) and sRGB color space for calculations
173    /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
174    SVGFEComponentTransferInterned{handle: ItemUid, creates_pixels: bool},
175    /// composite 2 images with chosen composite mode with parameters for that
176    /// mode
177    /// parameters: FilterOpGraphNode, k1, k2, k3, k4
178    /// SVG filter semantics - selectable input(s), selectable between linear
179    /// (default) and sRGB color space for calculations
180    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
181    SVGFECompositeArithmetic{k1: Au, k2: Au, k3: Au, k4: Au},
182    /// composite 2 images with chosen composite mode with parameters for that
183    /// mode
184    /// parameters: FilterOpGraphNode
185    /// SVG filter semantics - selectable input(s), selectable between linear
186    /// (default) and sRGB color space for calculations
187    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
188    SVGFECompositeATop,
189    /// composite 2 images with chosen composite mode with parameters for that
190    /// mode
191    /// parameters: FilterOpGraphNode
192    /// SVG filter semantics - selectable input(s), selectable between linear
193    /// (default) and sRGB color space for calculations
194    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
195    SVGFECompositeIn,
196    /// composite 2 images with chosen composite mode with parameters for that
197    /// mode
198    /// parameters: FilterOpGraphNode
199    /// SVG filter semantics - selectable input(s), selectable between linear
200    /// (default) and sRGB color space for calculations
201    /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
202    SVGFECompositeLighter,
203    /// composite 2 images with chosen composite mode with parameters for that
204    /// mode
205    /// parameters: FilterOpGraphNode
206    /// SVG filter semantics - selectable input(s), selectable between linear
207    /// (default) and sRGB color space for calculations
208    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
209    SVGFECompositeOut,
210    /// composite 2 images with chosen composite mode with parameters for that
211    /// mode
212    /// parameters: FilterOpGraphNode
213    /// SVG filter semantics - selectable input(s), selectable between linear
214    /// (default) and sRGB color space for calculations
215    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
216    SVGFECompositeOver,
217    /// composite 2 images with chosen composite mode with parameters for that
218    /// mode
219    /// parameters: FilterOpGraphNode
220    /// SVG filter semantics - selectable input(s), selectable between linear
221    /// (default) and sRGB color space for calculations
222    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
223    SVGFECompositeXOR,
224    /// transform image through convolution matrix of up to 25 values (spec
225    /// allows more but for performance reasons we do not)
226    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
227    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
228    ///  preserveAlpha
229    /// SVG filter semantics - selectable input(s), selectable between linear
230    /// (default) and sRGB color space for calculations
231    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
232    SVGFEConvolveMatrixEdgeModeDuplicate{order_x: i32, order_y: i32,
233        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
234        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
235        kernel_unit_length_y: Au, preserve_alpha: i32},
236    /// transform image through convolution matrix of up to 25 values (spec
237    /// allows more but for performance reasons we do not)
238    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
239    /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
240    /// preserveAlpha
241    /// SVG filter semantics - selectable input(s), selectable between linear
242    /// (default) and sRGB color space for calculations
243    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
244    SVGFEConvolveMatrixEdgeModeNone{order_x: i32, order_y: i32,
245        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
246        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
247        kernel_unit_length_y: Au, preserve_alpha: i32},
248    /// transform image through convolution matrix of up to 25 values (spec
249    /// allows more but for performance reasons we do not)
250    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
251    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
252    ///  preserveAlpha
253    /// SVG filter semantics - selectable input(s), selectable between linear
254    /// (default) and sRGB color space for calculations
255    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
256    SVGFEConvolveMatrixEdgeModeWrap{order_x: i32, order_y: i32,
257        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
258        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
259        kernel_unit_length_y: Au, preserve_alpha: i32},
260    /// calculate lighting based on heightmap image with provided values for a
261    /// distant light source with specified direction
262    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
263    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
264    /// SVG filter semantics - selectable input(s), selectable between linear
265    /// (default) and sRGB color space for calculations
266    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
267    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
268    SVGFEDiffuseLightingDistant{surface_scale: Au, diffuse_constant: Au,
269        kernel_unit_length_x: Au, kernel_unit_length_y: Au, azimuth: Au,
270        elevation: Au},
271    /// calculate lighting based on heightmap image with provided values for a
272    /// point light source at specified location
273    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
274    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z
275    /// SVG filter semantics - selectable input(s), selectable between linear
276    /// (default) and sRGB color space for calculations
277    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
278    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
279    SVGFEDiffuseLightingPoint{surface_scale: Au, diffuse_constant: Au,
280        kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au,
281        z: Au},
282    /// calculate lighting based on heightmap image with provided values for a
283    /// spot light source at specified location pointing at specified target
284    /// location with specified hotspot sharpness and cone angle
285    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
286    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
287    ///  pointsAtZ, specularExponent, limitingConeAngle
288    /// SVG filter semantics - selectable input(s), selectable between linear
289    /// (default) and sRGB color space for calculations
290    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
291    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
292    SVGFEDiffuseLightingSpot{surface_scale: Au, diffuse_constant: Au,
293        kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au, z: Au,
294        points_at_x: Au, points_at_y: Au, points_at_z: Au, cone_exponent: Au,
295        limiting_cone_angle: Au},
296    /// calculate a distorted version of first input image using offset values
297    /// from second input image at specified intensity
298    /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
299    /// SVG filter semantics - selectable input(s), selectable between linear
300    /// (default) and sRGB color space for calculations
301    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
302    SVGFEDisplacementMap{scale: Au, x_channel_selector: u32,
303        y_channel_selector: u32},
304    /// create and merge a dropshadow version of the specified image's alpha
305    /// channel with specified offset and blur radius
306    /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
307    ///  stdDeviationX, stdDeviationY
308    /// SVG filter semantics - selectable input(s), selectable between linear
309    /// (default) and sRGB color space for calculations
310    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
311    SVGFEDropShadow{color: ColorU, dx: Au, dy: Au, std_deviation_x: Au,
312        std_deviation_y: Au},
313    /// synthesize a new image of specified size containing a solid color
314    /// parameters: FilterOpGraphNode, color
315    /// SVG filter semantics - selectable input(s), selectable between linear
316    /// (default) and sRGB color space for calculations
317    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
318    SVGFEFlood{color: ColorU},
319    /// create a blurred version of the input image
320    /// parameters: FilterOpGraphNode, stdDeviationX, stdDeviationY
321    /// SVG filter semantics - selectable input(s), selectable between linear
322    /// (default) and sRGB color space for calculations
323    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
324    SVGFEGaussianBlur{std_deviation_x: Au, std_deviation_y: Au},
325    /// Filter that does no transformation of the colors, needed for
326    /// debug purposes, and is the default value in impl_default_for_enums.
327    SVGFEIdentity,
328    /// synthesize a new image based on a url (i.e. blob image source)
329    /// parameters: FilterOpGraphNode, sampling_filter (see SamplingFilter in
330    /// Types.h), transform
331    /// SVG filter semantics - selectable input(s), selectable between linear
332    /// (default) and sRGB color space for calculations
333    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
334    SVGFEImage{sampling_filter: u32, matrix: [Au; 6]},
335    /// create a new image based on the input image with the contour stretched
336    /// outward (dilate operator)
337    /// parameters: FilterOpGraphNode, radiusX, radiusY
338    /// SVG filter semantics - selectable input(s), selectable between linear
339    /// (default) and sRGB color space for calculations
340    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
341    SVGFEMorphologyDilate{radius_x: Au, radius_y: Au},
342    /// create a new image based on the input image with the contour shrunken
343    /// inward (erode operator)
344    /// parameters: FilterOpGraphNode, radiusX, radiusY
345    /// SVG filter semantics - selectable input(s), selectable between linear
346    /// (default) and sRGB color space for calculations
347    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
348    SVGFEMorphologyErode{radius_x: Au, radius_y: Au},
349    /// represents CSS opacity property as a graph node like the rest of the
350    /// SVGFE* filters
351    /// parameters: FilterOpGraphNode
352    /// SVG filter semantics - selectable input(s), selectable between linear
353    /// (default) and sRGB color space for calculations
354    SVGFEOpacity{value: Au},
355    /// represents CSS opacity property as a graph node like the rest of the
356    /// SVGFE* filters
357    /// parameters: FilterOpGraphNode
358    /// SVG filter semantics - selectable input(s), selectable between linear
359    /// (default) and sRGB color space for calculations
360    SVGFEOpacityBinding{valuebindingid: PropertyBindingId, value: Au},
361    /// Filter that copies the SourceGraphic image into the specified subregion,
362    /// This is intentionally the only way to get SourceGraphic into the graph,
363    /// as the filter region must be applied before it is used.
364    /// parameters: FilterOpGraphNode
365    /// SVG filter semantics - no inputs, no linear
366    SVGFESourceGraphic,
367    /// Filter that copies the SourceAlpha image into the specified subregion,
368    /// This is intentionally the only way to get SourceAlpha into the graph,
369    /// as the filter region must be applied before it is used.
370    /// parameters: FilterOpGraphNode
371    /// SVG filter semantics - no inputs, no linear
372    SVGFESourceAlpha,
373    /// calculate lighting based on heightmap image with provided values for a
374    /// distant light source with specified direction
375    /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
376    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
377    /// SVG filter semantics - selectable input(s), selectable between linear
378    /// (default) and sRGB color space for calculations
379    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
380    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
381    SVGFESpecularLightingDistant{surface_scale: Au, specular_constant: Au,
382        specular_exponent: Au, kernel_unit_length_x: Au,
383        kernel_unit_length_y: Au, azimuth: Au, elevation: Au},
384    /// calculate lighting based on heightmap image with provided values for a
385    /// point light source at specified location
386    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
387    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
388    /// SVG filter semantics - selectable input(s), selectable between linear
389    /// (default) and sRGB color space for calculations
390    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
391    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
392    SVGFESpecularLightingPoint{surface_scale: Au, specular_constant: Au,
393        specular_exponent: Au, kernel_unit_length_x: Au,
394        kernel_unit_length_y: Au, x: Au, y: Au, z: Au},
395    /// calculate lighting based on heightmap image with provided values for a
396    /// spot light source at specified location pointing at specified target
397    /// location with specified hotspot sharpness and cone angle
398    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
399    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
400    ///  pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
401    /// SVG filter semantics - selectable input(s), selectable between linear
402    /// (default) and sRGB color space for calculations
403    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
404    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
405    SVGFESpecularLightingSpot{surface_scale: Au, specular_constant: Au,
406        specular_exponent: Au, kernel_unit_length_x: Au,
407        kernel_unit_length_y: Au, x: Au, y: Au, z: Au, points_at_x: Au,
408        points_at_y: Au, points_at_z: Au, cone_exponent: Au,
409        limiting_cone_angle: Au},
410    /// create a new image based on the input image, repeated throughout the
411    /// output rectangle
412    /// parameters: FilterOpGraphNode
413    /// SVG filter semantics - selectable input(s), selectable between linear
414    /// (default) and sRGB color space for calculations
415    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
416    SVGFETile,
417    /// convert a color image to an alpha channel - internal use; generated by
418    /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
419    SVGFEToAlpha,
420    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
421    /// stitching mode
422    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
423    ///  numOctaves, seed
424    /// SVG filter semantics - selectable input(s), selectable between linear
425    /// (default) and sRGB color space for calculations
426    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
427    SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x: Au,
428        base_frequency_y: Au, num_octaves: u32, seed: u32},
429    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
430    /// stitching mode
431    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
432    ///  numOctaves, seed
433    /// SVG filter semantics - selectable input(s), selectable between linear
434    /// (default) and sRGB color space for calculations
435    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
436    SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x: Au,
437        base_frequency_y: Au, num_octaves: u32, seed: u32},
438    /// synthesize a new image based on Turbulence Noise (offset vectors)
439    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
440    ///  numOctaves, seed
441    /// SVG filter semantics - selectable input(s), selectable between linear
442    /// (default) and sRGB color space for calculations
443    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
444    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x: Au,
445        base_frequency_y: Au, num_octaves: u32, seed: u32},
446    /// synthesize a new image based on Turbulence Noise (offset vectors)
447    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
448    ///  numOctaves, seed
449    /// SVG filter semantics - selectable input(s), selectable between linear
450    /// (default) and sRGB color space for calculations
451    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
452    SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x: Au,
453        base_frequency_y: Au, num_octaves: u32, seed: u32},
454}
455
456impl From<FilterGraphOp> for FilterGraphOpKey {
457    fn from(op: FilterGraphOp) -> Self {
458        match op {
459            FilterGraphOp::SVGFEBlendDarken => FilterGraphOpKey::SVGFEBlendDarken,
460            FilterGraphOp::SVGFEBlendLighten => FilterGraphOpKey::SVGFEBlendLighten,
461            FilterGraphOp::SVGFEBlendMultiply => FilterGraphOpKey::SVGFEBlendMultiply,
462            FilterGraphOp::SVGFEBlendNormal => FilterGraphOpKey::SVGFEBlendNormal,
463            FilterGraphOp::SVGFEBlendScreen => FilterGraphOpKey::SVGFEBlendScreen,
464            FilterGraphOp::SVGFEBlendOverlay => FilterGraphOpKey::SVGFEBlendOverlay,
465            FilterGraphOp::SVGFEBlendColorDodge => FilterGraphOpKey::SVGFEBlendColorDodge,
466            FilterGraphOp::SVGFEBlendColorBurn => FilterGraphOpKey::SVGFEBlendColorBurn,
467            FilterGraphOp::SVGFEBlendHardLight => FilterGraphOpKey::SVGFEBlendHardLight,
468            FilterGraphOp::SVGFEBlendSoftLight => FilterGraphOpKey::SVGFEBlendSoftLight,
469            FilterGraphOp::SVGFEBlendDifference => FilterGraphOpKey::SVGFEBlendDifference,
470            FilterGraphOp::SVGFEBlendExclusion => FilterGraphOpKey::SVGFEBlendExclusion,
471            FilterGraphOp::SVGFEBlendHue => FilterGraphOpKey::SVGFEBlendHue,
472            FilterGraphOp::SVGFEBlendSaturation => FilterGraphOpKey::SVGFEBlendSaturation,
473            FilterGraphOp::SVGFEBlendColor => FilterGraphOpKey::SVGFEBlendColor,
474            FilterGraphOp::SVGFEBlendLuminosity => FilterGraphOpKey::SVGFEBlendLuminosity,
475            FilterGraphOp::SVGFEColorMatrix { values: color_matrix } => {
476                let mut quantized_values: [Au; 20] = [Au(0); 20];
477                for (value, result) in color_matrix.iter().zip(quantized_values.iter_mut()) {
478                    *result = Au::from_f32_px(*value);
479                }
480                FilterGraphOpKey::SVGFEColorMatrix{values: quantized_values}
481            }
482            FilterGraphOp::SVGFEComponentTransfer => unreachable!(),
483            FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels } => FilterGraphOpKey::SVGFEComponentTransferInterned{
484                handle: handle.uid(),
485                creates_pixels,
486            },
487            FilterGraphOp::SVGFECompositeArithmetic { k1, k2, k3, k4 } => {
488                FilterGraphOpKey::SVGFECompositeArithmetic{
489                    k1: Au::from_f32_px(k1),
490                    k2: Au::from_f32_px(k2),
491                    k3: Au::from_f32_px(k3),
492                    k4: Au::from_f32_px(k4),
493                }
494            }
495            FilterGraphOp::SVGFECompositeATop => FilterGraphOpKey::SVGFECompositeATop,
496            FilterGraphOp::SVGFECompositeIn => FilterGraphOpKey::SVGFECompositeIn,
497            FilterGraphOp::SVGFECompositeLighter => FilterGraphOpKey::SVGFECompositeLighter,
498            FilterGraphOp::SVGFECompositeOut => FilterGraphOpKey::SVGFECompositeOut,
499            FilterGraphOp::SVGFECompositeOver => FilterGraphOpKey::SVGFECompositeOver,
500            FilterGraphOp::SVGFECompositeXOR => FilterGraphOpKey::SVGFECompositeXOR,
501            FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
502                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
503                for (value, result) in kernel.iter().zip(values.iter_mut()) {
504                    *result = Au::from_f32_px(*value)
505                }
506                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeDuplicate{
507                    order_x,
508                    order_y,
509                    kernel: values,
510                    divisor: Au::from_f32_px(divisor),
511                    bias: Au::from_f32_px(bias),
512                    target_x,
513                    target_y,
514                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
515                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
516                    preserve_alpha,
517                }
518            }
519            FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
520                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
521                for (value, result) in kernel.iter().zip(values.iter_mut()) {
522                    *result = Au::from_f32_px(*value)
523                }
524                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeNone{
525                    order_x,
526                    order_y,
527                    kernel: values,
528                    divisor: Au::from_f32_px(divisor),
529                    bias: Au::from_f32_px(bias),
530                    target_x,
531                    target_y,
532                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
533                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
534                    preserve_alpha,
535                }
536            }
537            FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
538                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
539                for (value, result) in kernel.iter().zip(values.iter_mut()) {
540                    *result = Au::from_f32_px(*value)
541                }
542                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeWrap{
543                    order_x,
544                    order_y,
545                    kernel: values,
546                    divisor: Au::from_f32_px(divisor),
547                    bias: Au::from_f32_px(bias),
548                    target_x,
549                    target_y,
550                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
551                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
552                    preserve_alpha,
553                }
554            }
555            FilterGraphOp::SVGFEDiffuseLightingDistant { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
556                FilterGraphOpKey::SVGFEDiffuseLightingDistant{
557                    surface_scale: Au::from_f32_px(surface_scale),
558                    diffuse_constant: Au::from_f32_px(diffuse_constant),
559                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
560                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
561                    azimuth: Au::from_f32_px(azimuth),
562                    elevation: Au::from_f32_px(elevation),
563                }
564            }
565            FilterGraphOp::SVGFEDiffuseLightingPoint { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
566                FilterGraphOpKey::SVGFEDiffuseLightingPoint{
567                    surface_scale: Au::from_f32_px(surface_scale),
568                    diffuse_constant: Au::from_f32_px(diffuse_constant),
569                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
570                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
571                    x: Au::from_f32_px(x),
572                    y: Au::from_f32_px(y),
573                    z: Au::from_f32_px(z),
574                }
575            }
576            FilterGraphOp::SVGFEDiffuseLightingSpot { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle } => {
577                FilterGraphOpKey::SVGFEDiffuseLightingSpot{
578                    surface_scale: Au::from_f32_px(surface_scale),
579                    diffuse_constant: Au::from_f32_px(diffuse_constant),
580                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
581                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
582                    x: Au::from_f32_px(x),
583                    y: Au::from_f32_px(y),
584                    z: Au::from_f32_px(z),
585                    points_at_x: Au::from_f32_px(points_at_x),
586                    points_at_y: Au::from_f32_px(points_at_y),
587                    points_at_z: Au::from_f32_px(points_at_z),
588                    cone_exponent: Au::from_f32_px(cone_exponent),
589                    limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
590                }
591            }
592            FilterGraphOp::SVGFEDisplacementMap { scale, x_channel_selector, y_channel_selector } => {
593                FilterGraphOpKey::SVGFEDisplacementMap{
594                    scale: Au::from_f32_px(scale),
595                    x_channel_selector,
596                    y_channel_selector,
597                }
598            }
599            FilterGraphOp::SVGFEDropShadow { color, dx, dy, std_deviation_x, std_deviation_y } => {
600                FilterGraphOpKey::SVGFEDropShadow{
601                    color: color.into(),
602                    dx: Au::from_f32_px(dx),
603                    dy: Au::from_f32_px(dy),
604                    std_deviation_x: Au::from_f32_px(std_deviation_x),
605                    std_deviation_y: Au::from_f32_px(std_deviation_y),
606                }
607            }
608            FilterGraphOp::SVGFEFlood { color } => FilterGraphOpKey::SVGFEFlood{color: color.into()},
609            FilterGraphOp::SVGFEGaussianBlur { std_deviation_x, std_deviation_y } => {
610                FilterGraphOpKey::SVGFEGaussianBlur{
611                    std_deviation_x: Au::from_f32_px(std_deviation_x),
612                    std_deviation_y: Au::from_f32_px(std_deviation_y),
613                }
614            }
615            FilterGraphOp::SVGFEIdentity => FilterGraphOpKey::SVGFEIdentity,
616            FilterGraphOp::SVGFEImage { sampling_filter, matrix } => {
617                let mut values: [Au; 6] = [Au(0); 6];
618                for (value, result) in matrix.iter().zip(values.iter_mut()) {
619                    *result = Au::from_f32_px(*value)
620                }
621                FilterGraphOpKey::SVGFEImage{
622                    sampling_filter,
623                    matrix: values,
624                }
625            }
626            FilterGraphOp::SVGFEMorphologyDilate { radius_x, radius_y } => {
627                FilterGraphOpKey::SVGFEMorphologyDilate{
628                    radius_x: Au::from_f32_px(radius_x),
629                    radius_y: Au::from_f32_px(radius_y),
630                }
631            }
632            FilterGraphOp::SVGFEMorphologyErode { radius_x, radius_y } => {
633                FilterGraphOpKey::SVGFEMorphologyErode{
634                    radius_x: Au::from_f32_px(radius_x),
635                    radius_y: Au::from_f32_px(radius_y),
636                }
637            }
638            FilterGraphOp::SVGFEOpacity{valuebinding: binding, value: _} => {
639                match binding {
640                    PropertyBinding::Value(value) => {
641                        FilterGraphOpKey::SVGFEOpacity{value: Au::from_f32_px(value)}
642                    }
643                    PropertyBinding::Binding(key, default) => {
644                        FilterGraphOpKey::SVGFEOpacityBinding{valuebindingid: key.id, value: Au::from_f32_px(default)}
645                    }
646                }
647            }
648            FilterGraphOp::SVGFESourceAlpha => FilterGraphOpKey::SVGFESourceAlpha,
649            FilterGraphOp::SVGFESourceGraphic => FilterGraphOpKey::SVGFESourceGraphic,
650            FilterGraphOp::SVGFESpecularLightingDistant { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
651                FilterGraphOpKey::SVGFESpecularLightingDistant{
652                    surface_scale: Au::from_f32_px(surface_scale),
653                    specular_constant: Au::from_f32_px(specular_constant),
654                    specular_exponent: Au::from_f32_px(specular_exponent),
655                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
656                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
657                    azimuth: Au::from_f32_px(azimuth),
658                    elevation: Au::from_f32_px(elevation),
659                }
660            }
661            FilterGraphOp::SVGFESpecularLightingPoint { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
662                FilterGraphOpKey::SVGFESpecularLightingPoint{
663                    surface_scale: Au::from_f32_px(surface_scale),
664                    specular_constant: Au::from_f32_px(specular_constant),
665                    specular_exponent: Au::from_f32_px(specular_exponent),
666                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
667                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
668                    x: Au::from_f32_px(x),
669                    y: Au::from_f32_px(y),
670                    z: Au::from_f32_px(z),
671                }
672            }
673            FilterGraphOp::SVGFESpecularLightingSpot { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z, points_at_x, points_at_y, points_at_z, cone_exponent, limiting_cone_angle } => {
674                FilterGraphOpKey::SVGFESpecularLightingSpot{
675                    surface_scale: Au::from_f32_px(surface_scale),
676                    specular_constant: Au::from_f32_px(specular_constant),
677                    specular_exponent: Au::from_f32_px(specular_exponent),
678                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
679                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
680                    x: Au::from_f32_px(x),
681                    y: Au::from_f32_px(y),
682                    z: Au::from_f32_px(z),
683                    points_at_x: Au::from_f32_px(points_at_x),
684                    points_at_y: Au::from_f32_px(points_at_y),
685                    points_at_z: Au::from_f32_px(points_at_z),
686                    cone_exponent: Au::from_f32_px(cone_exponent),
687                    limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
688                }
689            }
690            FilterGraphOp::SVGFETile => FilterGraphOpKey::SVGFETile,
691            FilterGraphOp::SVGFEToAlpha => FilterGraphOpKey::SVGFEToAlpha,
692            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
693                FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithNoStitching {
694                    base_frequency_x: Au::from_f32_px(base_frequency_x),
695                    base_frequency_y: Au::from_f32_px(base_frequency_y),
696                    num_octaves,
697                    seed,
698                }
699            }
700            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
701                FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithStitching {
702                    base_frequency_x: Au::from_f32_px(base_frequency_x),
703                    base_frequency_y: Au::from_f32_px(base_frequency_y),
704                    num_octaves,
705                    seed,
706                }
707            }
708            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
709                FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching {
710                    base_frequency_x: Au::from_f32_px(base_frequency_x),
711                    base_frequency_y: Au::from_f32_px(base_frequency_y),
712                    num_octaves,
713                    seed,
714                }
715            }
716            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
717                FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithStitching {
718                    base_frequency_x: Au::from_f32_px(base_frequency_x),
719                    base_frequency_y: Au::from_f32_px(base_frequency_y),
720                    num_octaves,
721                    seed,
722                }
723            }
724        }
725    }
726}
727
728#[cfg_attr(feature = "capture", derive(Serialize))]
729#[cfg_attr(feature = "replay", derive(Deserialize))]
730#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
731pub struct FilterGraphNodeKey {
732    /// Indicates this graph node was marked as unnecessary by the DAG optimizer
733    /// (for example SVGFEOffset can often be folded into downstream nodes)
734    pub kept_by_optimizer: bool,
735    /// True if color_interpolation_filter == LinearRgb; shader will convert
736    /// sRGB texture pixel colors on load and convert back on store, for correct
737    /// interpolation
738    pub linear: bool,
739    /// virtualized picture input binding 1 (i.e. texture source), typically
740    /// this is used, but certain filters do not use it
741    pub inputs: Vec<FilterGraphPictureReferenceKey>,
742    /// rect this node will render into, in filter space, does not account for
743    /// inflate or device_pixel_scale
744    pub subregion: [Au; 4],
745}
746
747impl From<FilterGraphNode> for FilterGraphNodeKey {
748    fn from(node: FilterGraphNode) -> Self {
749        FilterGraphNodeKey{
750            kept_by_optimizer: node.kept_by_optimizer,
751            linear: node.linear,
752            inputs: node.inputs.into_iter().map(|node| {node.into()}).collect(),
753            subregion: [
754                Au::from_f32_px(node.subregion.min.x),
755                Au::from_f32_px(node.subregion.min.y),
756                Au::from_f32_px(node.subregion.max.x),
757                Au::from_f32_px(node.subregion.max.y),
758            ],
759        }
760    }
761}
762
763#[derive(Clone, Copy, Debug)]
764#[cfg_attr(feature = "capture", derive(Serialize))]
765#[cfg_attr(feature = "replay", derive(Deserialize))]
766pub struct FilterGraphPictureReference {
767    /// Id of the picture in question in a namespace unique to this filter DAG,
768    /// some are special values like
769    /// FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic.
770    pub buffer_id: FilterOpGraphPictureBufferId,
771    /// Set by wrap_prim_with_filters to the subregion of the input node, may
772    /// also have been offset for feDropShadow or feOffset
773    pub subregion: LayoutRect,
774    /// During scene build this is the offset to apply to the input subregion
775    /// for feOffset, which can be optimized away by pushing its offset and
776    /// subregion crop to downstream nodes.  This is always zero in render tasks
777    /// where it has already been applied to subregion by that point.  Not used
778    /// in get_coverage_svgfe because source_padding/target_padding represent
779    /// the offset there.
780    pub offset: LayoutVector2D,
781    /// Equal to the inflate value of the referenced buffer, or 0
782    pub inflate: i16,
783    /// Padding on each side to represent how this input is read relative to the
784    /// node's output subregion, this represents what the operation needs to
785    /// read from ths input, which may be blurred or offset.
786    pub source_padding: LayoutRect,
787    /// Padding on each side to represent how this input affects the node's
788    /// subregion, this can be used to calculate target subregion based on
789    /// SourceGraphic subregion.  This is usually equal to source_padding except
790    /// offset in the opposite direction, inflates typically do the same thing
791    /// to both types of padding.
792    pub target_padding: LayoutRect,
793}
794
795impl From<FilterOpGraphPictureReference> for FilterGraphPictureReference {
796    fn from(pic: FilterOpGraphPictureReference) -> Self {
797        FilterGraphPictureReference{
798            buffer_id: pic.buffer_id,
799            // All of these are set by wrap_prim_with_filters
800            subregion: LayoutRect::zero(),
801            offset: LayoutVector2D::zero(),
802            inflate: 0,
803            source_padding: LayoutRect::zero(),
804            target_padding: LayoutRect::zero(),
805        }
806    }
807}
808
809pub const SVGFE_CONVOLVE_DIAMETER_LIMIT: usize = 5;
810pub const SVGFE_CONVOLVE_VALUES_LIMIT: usize = SVGFE_CONVOLVE_DIAMETER_LIMIT *
811    SVGFE_CONVOLVE_DIAMETER_LIMIT;
812
813#[derive(Clone, Debug)]
814#[cfg_attr(feature = "capture", derive(Serialize))]
815#[cfg_attr(feature = "replay", derive(Deserialize))]
816pub enum FilterGraphOp {
817    /// Filter that copies the SourceGraphic image into the specified subregion,
818    /// This is intentionally the only way to get SourceGraphic into the graph,
819    /// as the filter region must be applied before it is used.
820    /// parameters: FilterOpGraphNode
821    /// SVG filter semantics - no inputs, no linear
822    SVGFESourceGraphic,
823    /// Filter that copies the SourceAlpha image into the specified subregion,
824    /// This is intentionally the only way to get SourceAlpha into the graph,
825    /// as the filter region must be applied before it is used.
826    /// parameters: FilterOpGraphNode
827    /// SVG filter semantics - no inputs, no linear
828    SVGFESourceAlpha,
829    /// Filter that does no transformation of the colors, used to implement a
830    /// few things like SVGFEOffset, and this is the default value in
831    /// impl_default_for_enums.
832    /// parameters: FilterGraphNode
833    /// SVG filter semantics - selectable input with offset
834    SVGFEIdentity,
835    /// represents CSS opacity property as a graph node like the rest of the
836    /// SVGFE* filters
837    /// parameters: FilterGraphNode
838    /// SVG filter semantics - selectable input(s), selectable between linear
839    /// (default) and sRGB color space for calculations
840    SVGFEOpacity{valuebinding: api::PropertyBinding<f32>, value: f32},
841    /// convert a color image to an alpha channel - internal use; generated by
842    /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
843    SVGFEToAlpha,
844    /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
845    /// parameters: FilterGraphNode
846    /// SVG filter semantics - selectable input(s), selectable between linear
847    /// (default) and sRGB color space for calculations
848    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
849    SVGFEBlendDarken,
850    /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
851    /// parameters: FilterGraphNode
852    /// SVG filter semantics - selectable input(s), selectable between linear
853    /// (default) and sRGB color space for calculations
854    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
855    SVGFEBlendLighten,
856    /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
857    /// parameters: FilterGraphNode
858    /// SVG filter semantics - selectable input(s), selectable between linear
859    /// (default) and sRGB color space for calculations
860    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
861    SVGFEBlendMultiply,
862    /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
863    /// parameters: FilterGraphNode
864    /// SVG filter semantics - selectable input(s), selectable between linear
865    /// (default) and sRGB color space for calculations
866    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
867    SVGFEBlendNormal,
868    /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
869    /// parameters: FilterGraphNode
870    /// SVG filter semantics - selectable input(s), selectable between linear
871    /// (default) and sRGB color space for calculations
872    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
873    SVGFEBlendScreen,
874    /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
875    /// parameters: FilterOpGraphNode
876    /// SVG filter semantics - selectable input(s), selectable between linear
877    /// (default) and sRGB color space for calculations
878    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
879    SVGFEBlendOverlay,
880    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
881    /// parameters: FilterOpGraphNode
882    /// SVG filter semantics - selectable input(s), selectable between linear
883    /// (default) and sRGB color space for calculations
884    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
885    SVGFEBlendColorDodge,
886    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
887    /// parameters: FilterOpGraphNode
888    /// SVG filter semantics - selectable input(s), selectable between linear
889    /// (default) and sRGB color space for calculations
890    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
891    SVGFEBlendColorBurn,
892    /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
893    /// parameters: FilterOpGraphNode
894    /// SVG filter semantics - selectable input(s), selectable between linear
895    /// (default) and sRGB color space for calculations
896    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
897    SVGFEBlendHardLight,
898    /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
899    /// parameters: FilterOpGraphNode
900    /// SVG filter semantics - selectable input(s), selectable between linear
901    /// (default) and sRGB color space for calculations
902    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
903    SVGFEBlendSoftLight,
904    /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
905    /// parameters: FilterOpGraphNode
906    /// SVG filter semantics - selectable input(s), selectable between linear
907    /// (default) and sRGB color space for calculations
908    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
909    SVGFEBlendDifference,
910    /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
911    /// parameters: FilterOpGraphNode
912    /// SVG filter semantics - selectable input(s), selectable between linear
913    /// (default) and sRGB color space for calculations
914    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
915    SVGFEBlendExclusion,
916    /// combine 2 images with SVG_FEBLEND_MODE_HUE
917    /// parameters: FilterOpGraphNode
918    /// SVG filter semantics - selectable input(s), selectable between linear
919    /// (default) and sRGB color space for calculations
920    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
921    SVGFEBlendHue,
922    /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
923    /// parameters: FilterOpGraphNode
924    /// SVG filter semantics - selectable input(s), selectable between linear
925    /// (default) and sRGB color space for calculations
926    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
927    SVGFEBlendSaturation,
928    /// combine 2 images with SVG_FEBLEND_MODE_COLOR
929    /// parameters: FilterOpGraphNode
930    /// SVG filter semantics - selectable input(s), selectable between linear
931    /// (default) and sRGB color space for calculations
932    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
933    SVGFEBlendColor,
934    /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
935    /// parameters: FilterOpGraphNode
936    /// SVG filter semantics - selectable input(s), selectable between linear
937    /// (default) and sRGB color space for calculations
938    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
939    SVGFEBlendLuminosity,
940    /// transform colors of image through 5x4 color matrix (transposed for
941    /// efficiency)
942    /// parameters: FilterGraphNode, matrix[5][4]
943    /// SVG filter semantics - selectable input(s), selectable between linear
944    /// (default) and sRGB color space for calculations
945    /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
946    SVGFEColorMatrix{values: [f32; 20]},
947    /// transform colors of image through configurable gradients with component
948    /// swizzle
949    /// parameters: FilterGraphNode
950    /// SVG filter semantics - selectable input(s), selectable between linear
951    /// (default) and sRGB color space for calculations
952    /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
953    SVGFEComponentTransfer,
954    /// Processed version of SVGFEComponentTransfer with the FilterData
955    /// replaced by an interned handle, this is made in wrap_prim_with_filters.
956    /// Aside from the interned handle, creates_pixels indicates if the transfer
957    /// parameters will probably fill the entire subregion with non-zero alpha.
958    SVGFEComponentTransferInterned{handle: FilterDataHandle, creates_pixels: bool},
959    /// composite 2 images with chosen composite mode with parameters for that
960    /// mode
961    /// parameters: FilterGraphNode, k1, k2, k3, k4
962    /// SVG filter semantics - selectable input(s), selectable between linear
963    /// (default) and sRGB color space for calculations
964    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
965    SVGFECompositeArithmetic{k1: f32, k2: f32, k3: f32, k4: f32},
966    /// composite 2 images with chosen composite mode with parameters for that
967    /// mode
968    /// parameters: FilterGraphNode
969    /// SVG filter semantics - selectable input(s), selectable between linear
970    /// (default) and sRGB color space for calculations
971    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
972    SVGFECompositeATop,
973    /// composite 2 images with chosen composite mode with parameters for that
974    /// mode
975    /// parameters: FilterGraphNode
976    /// SVG filter semantics - selectable input(s), selectable between linear
977    /// (default) and sRGB color space for calculations
978    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
979    SVGFECompositeIn,
980    /// composite 2 images with chosen composite mode with parameters for that
981    /// mode
982    /// parameters: FilterOpGraphNode
983    /// SVG filter semantics - selectable input(s), selectable between linear
984    /// (default) and sRGB color space for calculations
985    /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
986    SVGFECompositeLighter,
987    /// composite 2 images with chosen composite mode with parameters for that
988    /// mode
989    /// parameters: FilterGraphNode
990    /// SVG filter semantics - selectable input(s), selectable between linear
991    /// (default) and sRGB color space for calculations
992    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
993    SVGFECompositeOut,
994    /// composite 2 images with chosen composite mode with parameters for that
995    /// mode
996    /// parameters: FilterGraphNode
997    /// SVG filter semantics - selectable input(s), selectable between linear
998    /// (default) and sRGB color space for calculations
999    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1000    SVGFECompositeOver,
1001    /// composite 2 images with chosen composite mode with parameters for that
1002    /// mode
1003    /// parameters: FilterGraphNode
1004    /// SVG filter semantics - selectable input(s), selectable between linear
1005    /// (default) and sRGB color space for calculations
1006    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1007    SVGFECompositeXOR,
1008    /// transform image through convolution matrix of up to 25 values (spec
1009    /// allows more but for performance reasons we do not)
1010    /// parameters: FilterGraphNode, orderX, orderY, kernelValues[25], divisor,
1011    ///  bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1012    ///  preserveAlpha
1013    /// SVG filter semantics - selectable input(s), selectable between linear
1014    /// (default) and sRGB color space for calculations
1015    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1016    SVGFEConvolveMatrixEdgeModeDuplicate{order_x: i32, order_y: i32,
1017        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
1018        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
1019        kernel_unit_length_y: f32, preserve_alpha: i32},
1020    /// transform image through convolution matrix of up to 25 values (spec
1021    /// allows more but for performance reasons we do not)
1022    /// parameters: FilterGraphNode, orderX, orderY, kernelValues[25], divisor,
1023    ///  bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1024    ///  preserveAlpha
1025    /// SVG filter semantics - selectable input(s), selectable between linear
1026    /// (default) and sRGB color space for calculations
1027    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1028    SVGFEConvolveMatrixEdgeModeNone{order_x: i32, order_y: i32,
1029        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
1030        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
1031        kernel_unit_length_y: f32, preserve_alpha: i32},
1032    /// transform image through convolution matrix of up to 25 values (spec
1033    /// allows more but for performance reasons we do not)
1034    /// parameters: FilterGraphNode, orderX, orderY, kernelValues[25], divisor,
1035    ///  bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1036    ///  preserveAlpha
1037    /// SVG filter semantics - selectable input(s), selectable between linear
1038    /// (default) and sRGB color space for calculations
1039    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1040    SVGFEConvolveMatrixEdgeModeWrap{order_x: i32, order_y: i32,
1041        kernel: [f32; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: f32, bias: f32,
1042        target_x: i32, target_y: i32, kernel_unit_length_x: f32,
1043        kernel_unit_length_y: f32, preserve_alpha: i32},
1044    /// calculate lighting based on heightmap image with provided values for a
1045    /// distant light source with specified direction
1046    /// parameters: FilterGraphNode, surfaceScale, diffuseConstant,
1047    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
1048    /// SVG filter semantics - selectable input(s), selectable between linear
1049    /// (default) and sRGB color space for calculations
1050    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1051    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
1052    SVGFEDiffuseLightingDistant{surface_scale: f32, diffuse_constant: f32,
1053        kernel_unit_length_x: f32, kernel_unit_length_y: f32, azimuth: f32,
1054        elevation: f32},
1055    /// calculate lighting based on heightmap image with provided values for a
1056    /// point light source at specified location
1057    /// parameters: FilterGraphNode, surfaceScale, diffuseConstant,
1058    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z
1059    /// SVG filter semantics - selectable input(s), selectable between linear
1060    /// (default) and sRGB color space for calculations
1061    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1062    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
1063    SVGFEDiffuseLightingPoint{surface_scale: f32, diffuse_constant: f32,
1064        kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1065        z: f32},
1066    /// calculate lighting based on heightmap image with provided values for a
1067    /// spot light source at specified location pointing at specified target
1068    /// location with specified hotspot sharpness and cone angle
1069    /// parameters: FilterGraphNode, surfaceScale, diffuseConstant,
1070    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
1071    ///  pointsAtZ, specularExponent, limitingConeAngle
1072    /// SVG filter semantics - selectable input(s), selectable between linear
1073    /// (default) and sRGB color space for calculations
1074    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1075    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
1076    SVGFEDiffuseLightingSpot{surface_scale: f32, diffuse_constant: f32,
1077        kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1078        z: f32, points_at_x: f32, points_at_y: f32, points_at_z: f32,
1079        cone_exponent: f32, limiting_cone_angle: f32},
1080    /// calculate a distorted version of first input image using offset values
1081    /// from second input image at specified intensity
1082    /// parameters: FilterGraphNode, scale, xChannelSelector, yChannelSelector
1083    /// SVG filter semantics - selectable input(s), selectable between linear
1084    /// (default) and sRGB color space for calculations
1085    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
1086    SVGFEDisplacementMap{scale: f32, x_channel_selector: u32,
1087        y_channel_selector: u32},
1088    /// create and merge a dropshadow version of the specified image's alpha
1089    /// channel with specified offset and blur radius
1090    /// parameters: FilterGraphNode, flood_color, flood_opacity, dx, dy,
1091    ///  stdDeviationX, stdDeviationY
1092    /// SVG filter semantics - selectable input(s), selectable between linear
1093    /// (default) and sRGB color space for calculations
1094    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
1095    SVGFEDropShadow{color: ColorF, dx: f32, dy: f32, std_deviation_x: f32,
1096        std_deviation_y: f32},
1097    /// synthesize a new image of specified size containing a solid color
1098    /// parameters: FilterGraphNode, color
1099    /// SVG filter semantics - selectable input(s), selectable between linear
1100    /// (default) and sRGB color space for calculations
1101    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
1102    SVGFEFlood{color: ColorF},
1103    /// create a blurred version of the input image
1104    /// parameters: FilterGraphNode, stdDeviationX, stdDeviationY
1105    /// SVG filter semantics - selectable input(s), selectable between linear
1106    /// (default) and sRGB color space for calculations
1107    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
1108    SVGFEGaussianBlur{std_deviation_x: f32, std_deviation_y: f32},
1109    /// synthesize a new image based on a url (i.e. blob image source)
1110    /// parameters: FilterGraphNode,
1111    ///  samplingFilter (see SamplingFilter in Types.h), transform
1112    /// SVG filter semantics - selectable input(s), selectable between linear
1113    /// (default) and sRGB color space for calculations
1114    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
1115    SVGFEImage{sampling_filter: u32, matrix: [f32; 6]},
1116    /// create a new image based on the input image with the contour stretched
1117    /// outward (dilate operator)
1118    /// parameters: FilterGraphNode, radiusX, radiusY
1119    /// SVG filter semantics - selectable input(s), selectable between linear
1120    /// (default) and sRGB color space for calculations
1121    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
1122    SVGFEMorphologyDilate{radius_x: f32, radius_y: f32},
1123    /// create a new image based on the input image with the contour shrunken
1124    /// inward (erode operator)
1125    /// parameters: FilterGraphNode, radiusX, radiusY
1126    /// SVG filter semantics - selectable input(s), selectable between linear
1127    /// (default) and sRGB color space for calculations
1128    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
1129    SVGFEMorphologyErode{radius_x: f32, radius_y: f32},
1130    /// calculate lighting based on heightmap image with provided values for a
1131    /// distant light source with specified direction
1132    /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
1133    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
1134    /// SVG filter semantics - selectable input(s), selectable between linear
1135    /// (default) and sRGB color space for calculations
1136    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1137    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
1138    SVGFESpecularLightingDistant{surface_scale: f32, specular_constant: f32,
1139        specular_exponent: f32, kernel_unit_length_x: f32,
1140        kernel_unit_length_y: f32, azimuth: f32, elevation: f32},
1141    /// calculate lighting based on heightmap image with provided values for a
1142    /// point light source at specified location
1143    /// parameters: FilterGraphNode, surfaceScale, specularConstant,
1144    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
1145    /// SVG filter semantics - selectable input(s), selectable between linear
1146    /// (default) and sRGB color space for calculations
1147    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1148    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
1149    SVGFESpecularLightingPoint{surface_scale: f32, specular_constant: f32,
1150        specular_exponent: f32, kernel_unit_length_x: f32,
1151        kernel_unit_length_y: f32, x: f32, y: f32, z: f32},
1152    /// calculate lighting based on heightmap image with provided values for a
1153    /// spot light source at specified location pointing at specified target
1154    /// location with specified hotspot sharpness and cone angle
1155    /// parameters: FilterGraphNode, surfaceScale, specularConstant,
1156    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
1157    ///  pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
1158    /// SVG filter semantics - selectable input(s), selectable between linear
1159    /// (default) and sRGB color space for calculations
1160    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1161    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
1162    SVGFESpecularLightingSpot{surface_scale: f32, specular_constant: f32,
1163        specular_exponent: f32, kernel_unit_length_x: f32,
1164        kernel_unit_length_y: f32, x: f32, y: f32, z: f32, points_at_x: f32,
1165        points_at_y: f32, points_at_z: f32, cone_exponent: f32,
1166        limiting_cone_angle: f32},
1167    /// create a new image based on the input image, repeated throughout the
1168    /// output rectangle
1169    /// parameters: FilterGraphNode
1170    /// SVG filter semantics - selectable input(s), selectable between linear
1171    /// (default) and sRGB color space for calculations
1172    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
1173    SVGFETile,
1174    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
1175    /// stitching mode
1176    /// parameters: FilterGraphNode, baseFrequencyX, baseFrequencyY, numOctaves,
1177    ///  seed
1178    /// SVG filter semantics - selectable input(s), selectable between linear
1179    /// (default) and sRGB color space for calculations
1180    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1181    SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x: f32,
1182        base_frequency_y: f32, num_octaves: u32, seed: u32},
1183    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
1184    /// stitching mode
1185    /// parameters: FilterGraphNode, baseFrequencyX, baseFrequencyY, numOctaves,
1186    ///  seed
1187    /// SVG filter semantics - selectable input(s), selectable between linear
1188    /// (default) and sRGB color space for calculations
1189    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1190    SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x: f32,
1191        base_frequency_y: f32, num_octaves: u32, seed: u32},
1192    /// synthesize a new image based on Turbulence Noise (offset vectors)
1193    /// parameters: FilterGraphNode, baseFrequencyX, baseFrequencyY, numOctaves,
1194    ///  seed
1195    /// SVG filter semantics - selectable input(s), selectable between linear
1196    /// (default) and sRGB color space for calculations
1197    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1198    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x: f32,
1199        base_frequency_y: f32, num_octaves: u32, seed: u32},
1200    /// synthesize a new image based on Turbulence Noise (offset vectors)
1201    /// parameters: FilterGraphNode, baseFrequencyX, baseFrequencyY, numOctaves,
1202    ///  seed
1203    /// SVG filter semantics - selectable input(s), selectable between linear
1204    /// (default) and sRGB color space for calculations
1205    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1206    SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x: f32,
1207        base_frequency_y: f32, num_octaves: u32, seed: u32},
1208}
1209
1210impl FilterGraphOp {
1211    pub fn kind(&self) -> &'static str {
1212        match *self {
1213            FilterGraphOp::SVGFEBlendColor => "SVGFEBlendColor",
1214            FilterGraphOp::SVGFEBlendColorBurn => "SVGFEBlendColorBurn",
1215            FilterGraphOp::SVGFEBlendColorDodge => "SVGFEBlendColorDodge",
1216            FilterGraphOp::SVGFEBlendDarken => "SVGFEBlendDarken",
1217            FilterGraphOp::SVGFEBlendDifference => "SVGFEBlendDifference",
1218            FilterGraphOp::SVGFEBlendExclusion => "SVGFEBlendExclusion",
1219            FilterGraphOp::SVGFEBlendHardLight => "SVGFEBlendHardLight",
1220            FilterGraphOp::SVGFEBlendHue => "SVGFEBlendHue",
1221            FilterGraphOp::SVGFEBlendLighten => "SVGFEBlendLighten",
1222            FilterGraphOp::SVGFEBlendLuminosity => "SVGFEBlendLuminosity",
1223            FilterGraphOp::SVGFEBlendMultiply => "SVGFEBlendMultiply",
1224            FilterGraphOp::SVGFEBlendNormal => "SVGFEBlendNormal",
1225            FilterGraphOp::SVGFEBlendOverlay => "SVGFEBlendOverlay",
1226            FilterGraphOp::SVGFEBlendSaturation => "SVGFEBlendSaturation",
1227            FilterGraphOp::SVGFEBlendScreen => "SVGFEBlendScreen",
1228            FilterGraphOp::SVGFEBlendSoftLight => "SVGFEBlendSoftLight",
1229            FilterGraphOp::SVGFEColorMatrix{..} => "SVGFEColorMatrix",
1230            FilterGraphOp::SVGFEComponentTransfer => "SVGFEComponentTransfer",
1231            FilterGraphOp::SVGFEComponentTransferInterned{..} => "SVGFEComponentTransferInterned",
1232            FilterGraphOp::SVGFECompositeArithmetic{..} => "SVGFECompositeArithmetic",
1233            FilterGraphOp::SVGFECompositeATop => "SVGFECompositeATop",
1234            FilterGraphOp::SVGFECompositeIn => "SVGFECompositeIn",
1235            FilterGraphOp::SVGFECompositeLighter => "SVGFECompositeLighter",
1236            FilterGraphOp::SVGFECompositeOut => "SVGFECompositeOut",
1237            FilterGraphOp::SVGFECompositeOver => "SVGFECompositeOver",
1238            FilterGraphOp::SVGFECompositeXOR => "SVGFECompositeXOR",
1239            FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{..} => "SVGFEConvolveMatrixEdgeModeDuplicate",
1240            FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{..} => "SVGFEConvolveMatrixEdgeModeNone",
1241            FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap{..} => "SVGFEConvolveMatrixEdgeModeWrap",
1242            FilterGraphOp::SVGFEDiffuseLightingDistant{..} => "SVGFEDiffuseLightingDistant",
1243            FilterGraphOp::SVGFEDiffuseLightingPoint{..} => "SVGFEDiffuseLightingPoint",
1244            FilterGraphOp::SVGFEDiffuseLightingSpot{..} => "SVGFEDiffuseLightingSpot",
1245            FilterGraphOp::SVGFEDisplacementMap{..} => "SVGFEDisplacementMap",
1246            FilterGraphOp::SVGFEDropShadow{..} => "SVGFEDropShadow",
1247            FilterGraphOp::SVGFEFlood{..} => "SVGFEFlood",
1248            FilterGraphOp::SVGFEGaussianBlur{..} => "SVGFEGaussianBlur",
1249            FilterGraphOp::SVGFEIdentity => "SVGFEIdentity",
1250            FilterGraphOp::SVGFEImage{..} => "SVGFEImage",
1251            FilterGraphOp::SVGFEMorphologyDilate{..} => "SVGFEMorphologyDilate",
1252            FilterGraphOp::SVGFEMorphologyErode{..} => "SVGFEMorphologyErode",
1253            FilterGraphOp::SVGFEOpacity{..} => "SVGFEOpacity",
1254            FilterGraphOp::SVGFESourceAlpha => "SVGFESourceAlpha",
1255            FilterGraphOp::SVGFESourceGraphic => "SVGFESourceGraphic",
1256            FilterGraphOp::SVGFESpecularLightingDistant{..} => "SVGFESpecularLightingDistant",
1257            FilterGraphOp::SVGFESpecularLightingPoint{..} => "SVGFESpecularLightingPoint",
1258            FilterGraphOp::SVGFESpecularLightingSpot{..} => "SVGFESpecularLightingSpot",
1259            FilterGraphOp::SVGFETile => "SVGFETile",
1260            FilterGraphOp::SVGFEToAlpha => "SVGFEToAlpha",
1261            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching{..} => "SVGFETurbulenceWithFractalNoiseWithNoStitching",
1262            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching{..} => "SVGFETurbulenceWithFractalNoiseWithStitching",
1263            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{..} => "SVGFETurbulenceWithTurbulenceNoiseWithNoStitching",
1264            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{..} => "SVGFETurbulenceWithTurbulenceNoiseWithStitching",
1265        }
1266    }
1267}
1268
1269#[derive(Clone, Debug)]
1270#[cfg_attr(feature = "capture", derive(Serialize))]
1271#[cfg_attr(feature = "replay", derive(Deserialize))]
1272pub struct FilterGraphNode {
1273    /// Indicates this graph node was marked as necessary by the DAG optimizer
1274    pub kept_by_optimizer: bool,
1275    /// true if color_interpolation_filter == LinearRgb; shader will convert
1276    /// sRGB texture pixel colors on load and convert back on store, for correct
1277    /// interpolation
1278    pub linear: bool,
1279    /// padding for output rect if we need a border to get correct clamping, or
1280    /// to account for larger final subregion than source rect (see bug 1869672)
1281    pub inflate: i16,
1282    /// virtualized picture input bindings, these refer to other filter outputs
1283    /// by number within the graph, usually there is one element
1284    pub inputs: Vec<FilterGraphPictureReference>,
1285    /// clipping rect for filter node output
1286    pub subregion: LayoutRect,
1287}
1288
1289impl From<FilterOpGraphNode> for FilterGraphNode {
1290    fn from(node: FilterOpGraphNode) -> Self {
1291        let mut inputs: Vec<FilterGraphPictureReference> = Vec::new();
1292        if node.input.buffer_id != FilterOpGraphPictureBufferId::None {
1293            inputs.push(node.input.into());
1294        }
1295        if node.input2.buffer_id != FilterOpGraphPictureBufferId::None {
1296            inputs.push(node.input2.into());
1297        }
1298        // If the op used by this node is a feMerge, it will add more inputs
1299        // after this invocation.
1300        FilterGraphNode{
1301            linear: node.linear,
1302            inputs,
1303            subregion: node.subregion,
1304            // These are computed later in scene_building
1305            kept_by_optimizer: true,
1306            inflate: 0,
1307        }
1308    }
1309}
1310
1311/// Here we transform source rect to target rect for SVGFEGraph by walking
1312/// the whole graph and propagating subregions based on the provided
1313/// invalidation rect, and we want it to be a tight fit so we don't waste
1314/// time applying multiple filters to pixels that do not contribute to the
1315/// invalidated rect.
1316///
1317/// The interesting parts of the handling of SVG filters are:
1318/// * scene_building.rs : wrap_prim_with_filters
1319/// * picture.rs : get_coverage_target_svgfe (you are here)
1320/// * picture.rs : get_coverage_source_svgfe
1321/// * render_task.rs : new_svg_filter_graph
1322/// * render_target.rs : add_svg_filter_node_instances
1323pub fn get_coverage_target_svgfe(
1324    filters: &[(FilterGraphNode, FilterGraphOp)],
1325    surface_rect: LayoutRect,
1326) -> LayoutRect {
1327
1328    // The value of BUFFER_LIMIT here must be the same as in
1329    // scene_building.rs, or we'll hit asserts here.
1330    const BUFFER_LIMIT: usize = SVGFE_GRAPH_MAX;
1331
1332    // We need to evaluate the subregions based on the proposed
1333    // SourceGraphic rect as it isn't known at scene build time.
1334    let mut subregion_by_buffer_id: [LayoutRect; BUFFER_LIMIT] = [LayoutRect::zero(); BUFFER_LIMIT];
1335    for (id, (node, op)) in filters.iter().enumerate() {
1336        let full_subregion = node.subregion;
1337        let mut used_subregion = LayoutRect::zero();
1338        for input in &node.inputs {
1339            match input.buffer_id {
1340                FilterOpGraphPictureBufferId::BufferId(id) => {
1341                    assert!((id as usize) < BUFFER_LIMIT, "BUFFER_LIMIT must be the same in frame building and scene building");
1342                    // This id lookup should always succeed.
1343                    let input_subregion = subregion_by_buffer_id[id as usize];
1344                    // Now add the padding that transforms from
1345                    // source to target, this was determined during
1346                    // scene build based on the operation.
1347                    let input_subregion =
1348                        LayoutRect::new(
1349                            LayoutPoint::new(
1350                                input_subregion.min.x + input.target_padding.min.x,
1351                                input_subregion.min.y + input.target_padding.min.y,
1352                            ),
1353                            LayoutPoint::new(
1354                                input_subregion.max.x + input.target_padding.max.x,
1355                                input_subregion.max.y + input.target_padding.max.y,
1356                            ),
1357                        );
1358                    used_subregion = used_subregion
1359                        .union(&input_subregion);
1360                }
1361                FilterOpGraphPictureBufferId::None => {
1362                    panic!("Unsupported BufferId type");
1363                }
1364            }
1365        }
1366        // We can clip the used subregion to the node subregion
1367        used_subregion = used_subregion
1368            .intersection(&full_subregion)
1369            .unwrap_or(LayoutRect::zero());
1370        match op {
1371            FilterGraphOp::SVGFEBlendColor => {}
1372            FilterGraphOp::SVGFEBlendColorBurn => {}
1373            FilterGraphOp::SVGFEBlendColorDodge => {}
1374            FilterGraphOp::SVGFEBlendDarken => {}
1375            FilterGraphOp::SVGFEBlendDifference => {}
1376            FilterGraphOp::SVGFEBlendExclusion => {}
1377            FilterGraphOp::SVGFEBlendHardLight => {}
1378            FilterGraphOp::SVGFEBlendHue => {}
1379            FilterGraphOp::SVGFEBlendLighten => {}
1380            FilterGraphOp::SVGFEBlendLuminosity => {}
1381            FilterGraphOp::SVGFEBlendMultiply => {}
1382            FilterGraphOp::SVGFEBlendNormal => {}
1383            FilterGraphOp::SVGFEBlendOverlay => {}
1384            FilterGraphOp::SVGFEBlendSaturation => {}
1385            FilterGraphOp::SVGFEBlendScreen => {}
1386            FilterGraphOp::SVGFEBlendSoftLight => {}
1387            FilterGraphOp::SVGFEColorMatrix { values } => {
1388                if values[19] > 0.0 {
1389                    // Manipulating alpha offset can easily create new
1390                    // pixels outside of input subregions
1391                    used_subregion = full_subregion;
1392                    add_text_marker(
1393                        "SVGFEColorMatrix",
1394                        "SVGFEColorMatrix with non-zero alpha offset, using full subregion",
1395                        Duration::from_millis(1));
1396                }
1397            }
1398            FilterGraphOp::SVGFEComponentTransfer => unreachable!(),
1399            FilterGraphOp::SVGFEComponentTransferInterned{handle: _, creates_pixels} => {
1400                // Check if the value of alpha[0] is modified, if so
1401                // the whole subregion is used because it will be
1402                // creating new pixels outside of input subregions
1403                if *creates_pixels {
1404                    used_subregion = full_subregion;
1405                    add_text_marker(
1406                        "SVGFEComponentTransfer",
1407                        "SVGFEComponentTransfer with non-zero minimum alpha, using full subregion",
1408                        Duration::from_millis(1));
1409                }
1410            }
1411            FilterGraphOp::SVGFECompositeArithmetic { k1, k2, k3, k4 } => {
1412                // Optimization opportunity - some inputs may be
1413                // smaller subregions due to the way the math works,
1414                // k1 is the intersection of the two inputs, k2 is
1415                // the first input only, k3 is the second input
1416                // only, and k4 changes the whole subregion.
1417                //
1418                // See logic for SVG_FECOMPOSITE_OPERATOR_ARITHMETIC
1419                // in FilterSupport.cpp
1420                //
1421                // We can at least ignore the entire node if
1422                // everything is zero.
1423                if *k1 <= 0.0 &&
1424                    *k2 <= 0.0 &&
1425                    *k3 <= 0.0 {
1426                    used_subregion = LayoutRect::zero();
1427                }
1428                // Check if alpha is added to pixels as it means it
1429                // can fill pixels outside input subregions
1430                if *k4 > 0.0 {
1431                    used_subregion = full_subregion;
1432                    add_text_marker(
1433                        "SVGFECompositeArithmetic",
1434                        "SVGFECompositeArithmetic with non-zero offset, using full subregion",
1435                        Duration::from_millis(1));
1436                }
1437            }
1438            FilterGraphOp::SVGFECompositeATop => {}
1439            FilterGraphOp::SVGFECompositeIn => {}
1440            FilterGraphOp::SVGFECompositeLighter => {}
1441            FilterGraphOp::SVGFECompositeOut => {}
1442            FilterGraphOp::SVGFECompositeOver => {}
1443            FilterGraphOp::SVGFECompositeXOR => {}
1444            FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{..} => {}
1445            FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{..} => {}
1446            FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap{..} => {}
1447            FilterGraphOp::SVGFEDiffuseLightingDistant{..} => {}
1448            FilterGraphOp::SVGFEDiffuseLightingPoint{..} => {}
1449            FilterGraphOp::SVGFEDiffuseLightingSpot{..} => {}
1450            FilterGraphOp::SVGFEDisplacementMap{..} => {}
1451            FilterGraphOp::SVGFEDropShadow{..} => {}
1452            FilterGraphOp::SVGFEFlood { color } => {
1453                // Subregion needs to be set to the full node
1454                // subregion for fills (unless the fill is a no-op)
1455                if color.a > 0.0 {
1456                    used_subregion = full_subregion;
1457                }
1458            }
1459            FilterGraphOp::SVGFEGaussianBlur{..} => {}
1460            FilterGraphOp::SVGFEIdentity => {}
1461            FilterGraphOp::SVGFEImage { sampling_filter: _sampling_filter, matrix: _matrix } => {
1462                // TODO: calculate the actual subregion
1463                used_subregion = full_subregion;
1464            }
1465            FilterGraphOp::SVGFEMorphologyDilate{..} => {}
1466            FilterGraphOp::SVGFEMorphologyErode{..} => {}
1467            FilterGraphOp::SVGFEOpacity { valuebinding: _valuebinding, value } => {
1468                // If fully transparent, we can ignore this node
1469                if *value <= 0.0 {
1470                    used_subregion = LayoutRect::zero();
1471                }
1472            }
1473            FilterGraphOp::SVGFESourceAlpha |
1474            FilterGraphOp::SVGFESourceGraphic => {
1475                used_subregion = surface_rect;
1476            }
1477            FilterGraphOp::SVGFESpecularLightingDistant{..} => {}
1478            FilterGraphOp::SVGFESpecularLightingPoint{..} => {}
1479            FilterGraphOp::SVGFESpecularLightingSpot{..} => {}
1480            FilterGraphOp::SVGFETile => {
1481                // feTile fills the entire output with
1482                // source pixels, so it's effectively a flood.
1483                used_subregion = full_subregion;
1484            }
1485            FilterGraphOp::SVGFEToAlpha => {}
1486            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching{..} |
1487            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching{..} |
1488            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{..} |
1489            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching{..} => {
1490                // Turbulence produces pixel values throughout the
1491                // node subregion.
1492                used_subregion = full_subregion;
1493            }
1494        }
1495        // Store the subregion so later nodes can refer back
1496        // to this and propagate rects properly
1497        assert!((id as usize) < BUFFER_LIMIT, "BUFFER_LIMIT must be the same in frame building and scene building");
1498        subregion_by_buffer_id[id] = used_subregion;
1499    }
1500    subregion_by_buffer_id[filters.len() - 1]
1501}
1502
1503/// Here we transform target rect to source rect for SVGFEGraph by walking
1504/// the whole graph and propagating subregions based on the provided
1505/// invalidation rect, and we want it to be a tight fit so we don't waste
1506/// time applying multiple filters to pixels that do not contribute to the
1507/// invalidated rect.
1508///
1509/// The interesting parts of the handling of SVG filters are:
1510/// * scene_building.rs : wrap_prim_with_filters
1511/// * picture.rs : get_coverage_target_svgfe
1512/// * picture.rs : get_coverage_source_svgfe (you are here)
1513/// * render_task.rs : new_svg_filter_graph
1514/// * render_target.rs : add_svg_filter_node_instances
1515pub fn get_coverage_source_svgfe(
1516    filters: &[(FilterGraphNode, FilterGraphOp)],
1517    surface_rect: LayoutRect,
1518) -> LayoutRect {
1519
1520    // The value of BUFFER_LIMIT here must be the same as in
1521    // scene_building.rs, or we'll hit asserts here.
1522    const BUFFER_LIMIT: usize = SVGFE_GRAPH_MAX;
1523
1524    // We're solving the source rect from target rect (e.g. due
1525    // to invalidation of a region, we need to know how much of
1526    // SourceGraphic is needed to draw that region accurately),
1527    // so we need to walk the DAG in reverse and accumulate the source
1528    // subregion for each input onto the referenced node, which can then
1529    // propagate that to its inputs when it is iterated.
1530    let mut source_subregion = LayoutRect::zero();
1531    let mut subregion_by_buffer_id: [LayoutRect; BUFFER_LIMIT] =
1532    [LayoutRect::zero(); BUFFER_LIMIT];
1533    let final_buffer_id = filters.len() - 1;
1534    assert!(final_buffer_id < BUFFER_LIMIT, "BUFFER_LIMIT must be the same in frame building and scene building");
1535    subregion_by_buffer_id[final_buffer_id] = surface_rect;
1536    for (node_buffer_id, (node, op)) in filters.iter().enumerate().rev() {
1537        // This is the subregion this node outputs, we can clip
1538        // the inputs based on source_padding relative to this,
1539        // and accumulate a new subregion for them.
1540        assert!(node_buffer_id < BUFFER_LIMIT, "BUFFER_LIMIT must be the same in frame building and scene building");
1541        let full_subregion = node.subregion;
1542        let mut used_subregion =
1543            subregion_by_buffer_id[node_buffer_id];
1544        // We can clip the propagated subregion to the node subregion before
1545        // we add source_padding for each input and propogate to them
1546        used_subregion = used_subregion
1547            .intersection(&full_subregion)
1548            .unwrap_or(LayoutRect::zero());
1549        if !used_subregion.is_empty() {
1550            for input in &node.inputs {
1551                let input_subregion = LayoutRect::new(
1552                    LayoutPoint::new(
1553                        used_subregion.min.x + input.source_padding.min.x,
1554                        used_subregion.min.y + input.source_padding.min.y,
1555                    ),
1556                    LayoutPoint::new(
1557                        used_subregion.max.x + input.source_padding.max.x,
1558                        used_subregion.max.y + input.source_padding.max.y,
1559                    ),
1560                );
1561                match input.buffer_id {
1562                    FilterOpGraphPictureBufferId::BufferId(id) => {
1563                        // Add the used area to the input, later when
1564                        // the referneced node is iterated as a node it
1565                        // will propagate the used bounds.
1566                        subregion_by_buffer_id[id as usize] =
1567                            subregion_by_buffer_id[id as usize]
1568                            .union(&input_subregion);
1569                    }
1570                    FilterOpGraphPictureBufferId::None => {}
1571                }
1572            }
1573        }
1574        // If this is the SourceGraphic or SourceAlpha, we now have the
1575        // source subregion we're looking for.  If both exist in the
1576        // same graph, we need to combine them, so don't merely replace.
1577        match op {
1578            FilterGraphOp::SVGFESourceAlpha |
1579            FilterGraphOp::SVGFESourceGraphic => {
1580                source_subregion = source_subregion.union(&used_subregion);
1581            }
1582            _ => {}
1583        }
1584    }
1585
1586    // Note that this can be zero if SourceGraphic/SourceAlpha is not used
1587    // in this graph.
1588    source_subregion
1589}