webrender/prim_store/
picture.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::{
6    ColorU, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveKind,
7    ColorSpace, PropertyBinding, PropertyBindingId, CompositeOperator,
8    RasterSpace, FilterOpGraphPictureBufferId,
9};
10use api::units::Au;
11use crate::scene_building::IsVisible;
12use crate::filterdata::SFilterData;
13use crate::gpu_types::BlurEdgeMode;
14use crate::intern::ItemUid;
15use crate::intern::{Internable, InternDebug, Handle as InternHandle};
16use crate::internal_types::{LayoutPrimitiveInfo, FilterGraphPictureReference,
17    FilterGraphOp, FilterGraphNode, SVGFE_CONVOLVE_VALUES_LIMIT, Filter};
18use crate::picture::PictureCompositeMode;
19use crate::prim_store::{
20    PrimitiveInstanceKind, PrimitiveStore, VectorKey,
21    InternablePrimitive,
22};
23
24#[cfg_attr(feature = "capture", derive(Serialize))]
25#[cfg_attr(feature = "replay", derive(Deserialize))]
26#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
27pub enum CompositeOperatorKey {
28    Over,
29    In,
30    Out,
31    Atop,
32    Xor,
33    Lighter,
34    Arithmetic([Au; 4]),
35}
36
37impl From<CompositeOperator> for CompositeOperatorKey {
38    fn from(operator: CompositeOperator) -> Self {
39        match operator {
40            CompositeOperator::Over => CompositeOperatorKey::Over,
41            CompositeOperator::In => CompositeOperatorKey::In,
42            CompositeOperator::Out => CompositeOperatorKey::Out,
43            CompositeOperator::Atop => CompositeOperatorKey::Atop,
44            CompositeOperator::Xor => CompositeOperatorKey::Xor,
45            CompositeOperator::Lighter => CompositeOperatorKey::Lighter,
46            CompositeOperator::Arithmetic(k_vals) => {
47                let k_vals = [
48                    Au::from_f32_px(k_vals[0]),
49                    Au::from_f32_px(k_vals[1]),
50                    Au::from_f32_px(k_vals[2]),
51                    Au::from_f32_px(k_vals[3]),
52                ];
53                CompositeOperatorKey::Arithmetic(k_vals)
54            }
55        }
56    }
57}
58
59#[cfg_attr(feature = "capture", derive(Serialize))]
60#[cfg_attr(feature = "replay", derive(Deserialize))]
61#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
62pub enum FilterPrimitiveKey {
63    Identity(ColorSpace, FilterPrimitiveInput),
64    Flood(ColorSpace, ColorU),
65    Blend(ColorSpace, MixBlendMode, FilterPrimitiveInput, FilterPrimitiveInput),
66    Blur(ColorSpace, Au, Au, FilterPrimitiveInput),
67    Opacity(ColorSpace, Au, FilterPrimitiveInput),
68    ColorMatrix(ColorSpace, [Au; 20], FilterPrimitiveInput),
69    DropShadow(ColorSpace, (VectorKey, Au, ColorU), FilterPrimitiveInput),
70    ComponentTransfer(ColorSpace, FilterPrimitiveInput, Vec<SFilterData>),
71    Offset(ColorSpace, FilterPrimitiveInput, VectorKey),
72    Composite(ColorSpace, FilterPrimitiveInput, FilterPrimitiveInput, CompositeOperatorKey),
73}
74
75#[cfg_attr(feature = "capture", derive(Serialize))]
76#[cfg_attr(feature = "replay", derive(Deserialize))]
77#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
78pub enum FilterGraphPictureBufferIdKey {
79    #[default]
80    /// empty slot in feMerge inputs
81    None,
82    /// reference to another (earlier) node in filter graph
83    BufferId(i16),
84}
85
86#[cfg_attr(feature = "capture", derive(Serialize))]
87#[cfg_attr(feature = "replay", derive(Deserialize))]
88#[derive(Debug, Clone, Copy, Default, MallocSizeOf, PartialEq, Hash, Eq)]
89pub struct FilterGraphPictureReferenceKey {
90    /// Id of the picture in question in a namespace unique to this filter DAG,
91    /// some are special values like
92    /// FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic.
93    pub buffer_id: FilterGraphPictureBufferIdKey,
94    /// Place the input image here in Layout space (like node.subregion)
95    pub subregion: [Au; 4],
96    /// Translate the subregion by this amount
97    pub offset: [Au; 2],
98}
99
100impl From<FilterGraphPictureReference> for FilterGraphPictureReferenceKey {
101    fn from(pic: FilterGraphPictureReference) -> Self {
102        FilterGraphPictureReferenceKey{
103            buffer_id: match pic.buffer_id {
104                FilterOpGraphPictureBufferId::None => FilterGraphPictureBufferIdKey::None,
105                FilterOpGraphPictureBufferId::BufferId(id) => FilterGraphPictureBufferIdKey::BufferId(id),
106            },
107            subregion: [
108                Au::from_f32_px(pic.subregion.min.x),
109                Au::from_f32_px(pic.subregion.min.y),
110                Au::from_f32_px(pic.subregion.max.x),
111                Au::from_f32_px(pic.subregion.max.y),
112            ],
113            offset: [
114                Au::from_f32_px(pic.offset.x),
115                Au::from_f32_px(pic.offset.y),
116            ],
117        }
118    }
119}
120
121#[cfg_attr(feature = "capture", derive(Serialize))]
122#[cfg_attr(feature = "replay", derive(Deserialize))]
123#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
124pub enum FilterGraphOpKey {
125    /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
126    /// parameters: FilterOpGraphNode
127    /// SVG filter semantics - selectable input(s), selectable between linear
128    /// (default) and sRGB color space for calculations
129    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
130    SVGFEBlendDarken,
131    /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
132    /// parameters: FilterOpGraphNode
133    /// SVG filter semantics - selectable input(s), selectable between linear
134    /// (default) and sRGB color space for calculations
135    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
136    SVGFEBlendLighten,
137    /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
138    /// parameters: FilterOpGraphNode
139    /// SVG filter semantics - selectable input(s), selectable between linear
140    /// (default) and sRGB color space for calculations
141    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
142    SVGFEBlendMultiply,
143    /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
144    /// parameters: FilterOpGraphNode
145    /// SVG filter semantics - selectable input(s), selectable between linear
146    /// (default) and sRGB color space for calculations
147    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
148    SVGFEBlendNormal,
149    /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
150    /// parameters: FilterOpGraphNode
151    /// SVG filter semantics - selectable input(s), selectable between linear
152    /// (default) and sRGB color space for calculations
153    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
154    SVGFEBlendScreen,
155    /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
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    SVGFEBlendOverlay,
161    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
162    /// parameters: FilterOpGraphNode
163    /// SVG filter semantics - selectable input(s), selectable between linear
164    /// (default) and sRGB color space for calculations
165    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
166    SVGFEBlendColorDodge,
167    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
168    /// parameters: FilterOpGraphNode
169    /// SVG filter semantics - selectable input(s), selectable between linear
170    /// (default) and sRGB color space for calculations
171    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
172    SVGFEBlendColorBurn,
173    /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
174    /// parameters: FilterOpGraphNode
175    /// SVG filter semantics - selectable input(s), selectable between linear
176    /// (default) and sRGB color space for calculations
177    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
178    SVGFEBlendHardLight,
179    /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
180    /// parameters: FilterOpGraphNode
181    /// SVG filter semantics - selectable input(s), selectable between linear
182    /// (default) and sRGB color space for calculations
183    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
184    SVGFEBlendSoftLight,
185    /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
186    /// parameters: FilterOpGraphNode
187    /// SVG filter semantics - selectable input(s), selectable between linear
188    /// (default) and sRGB color space for calculations
189    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
190    SVGFEBlendDifference,
191    /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
192    /// parameters: FilterOpGraphNode
193    /// SVG filter semantics - selectable input(s), selectable between linear
194    /// (default) and sRGB color space for calculations
195    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
196    SVGFEBlendExclusion,
197    /// combine 2 images with SVG_FEBLEND_MODE_HUE
198    /// parameters: FilterOpGraphNode
199    /// SVG filter semantics - selectable input(s), selectable between linear
200    /// (default) and sRGB color space for calculations
201    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
202    SVGFEBlendHue,
203    /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
204    /// parameters: FilterOpGraphNode
205    /// SVG filter semantics - selectable input(s), selectable between linear
206    /// (default) and sRGB color space for calculations
207    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
208    SVGFEBlendSaturation,
209    /// combine 2 images with SVG_FEBLEND_MODE_COLOR
210    /// parameters: FilterOpGraphNode
211    /// SVG filter semantics - selectable input(s), selectable between linear
212    /// (default) and sRGB color space for calculations
213    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
214    SVGFEBlendColor,
215    /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
216    /// parameters: FilterOpGraphNode
217    /// SVG filter semantics - selectable input(s), selectable between linear
218    /// (default) and sRGB color space for calculations
219    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
220    SVGFEBlendLuminosity,
221    /// transform colors of image through 5x4 color matrix (transposed for
222    /// efficiency)
223    /// parameters: FilterOpGraphNode, matrix[5][4]
224    /// SVG filter semantics - selectable input(s), selectable between linear
225    /// (default) and sRGB color space for calculations
226    /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
227    SVGFEColorMatrix{values: [Au; 20]},
228    /// transform colors of image through configurable gradients with component
229    /// swizzle
230    /// parameters: FilterOpGraphNode, FilterData
231    /// SVG filter semantics - selectable input(s), selectable between linear
232    /// (default) and sRGB color space for calculations
233    /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
234    SVGFEComponentTransferInterned{handle: ItemUid, creates_pixels: bool},
235    /// composite 2 images with chosen composite mode with parameters for that
236    /// mode
237    /// parameters: FilterOpGraphNode, k1, k2, k3, k4
238    /// SVG filter semantics - selectable input(s), selectable between linear
239    /// (default) and sRGB color space for calculations
240    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
241    SVGFECompositeArithmetic{k1: Au, k2: Au, k3: Au, k4: Au},
242    /// composite 2 images with chosen composite mode with parameters for that
243    /// mode
244    /// parameters: FilterOpGraphNode
245    /// SVG filter semantics - selectable input(s), selectable between linear
246    /// (default) and sRGB color space for calculations
247    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
248    SVGFECompositeATop,
249    /// composite 2 images with chosen composite mode with parameters for that
250    /// mode
251    /// parameters: FilterOpGraphNode
252    /// SVG filter semantics - selectable input(s), selectable between linear
253    /// (default) and sRGB color space for calculations
254    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
255    SVGFECompositeIn,
256    /// composite 2 images with chosen composite mode with parameters for that
257    /// mode
258    /// parameters: FilterOpGraphNode
259    /// SVG filter semantics - selectable input(s), selectable between linear
260    /// (default) and sRGB color space for calculations
261    /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
262    SVGFECompositeLighter,
263    /// composite 2 images with chosen composite mode with parameters for that
264    /// mode
265    /// parameters: FilterOpGraphNode
266    /// SVG filter semantics - selectable input(s), selectable between linear
267    /// (default) and sRGB color space for calculations
268    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
269    SVGFECompositeOut,
270    /// composite 2 images with chosen composite mode with parameters for that
271    /// mode
272    /// parameters: FilterOpGraphNode
273    /// SVG filter semantics - selectable input(s), selectable between linear
274    /// (default) and sRGB color space for calculations
275    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
276    SVGFECompositeOver,
277    /// composite 2 images with chosen composite mode with parameters for that
278    /// mode
279    /// parameters: FilterOpGraphNode
280    /// SVG filter semantics - selectable input(s), selectable between linear
281    /// (default) and sRGB color space for calculations
282    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
283    SVGFECompositeXOR,
284    /// transform image through convolution matrix of up to 25 values (spec
285    /// allows more but for performance reasons we do not)
286    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
287    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
288    ///  preserveAlpha
289    /// SVG filter semantics - selectable input(s), selectable between linear
290    /// (default) and sRGB color space for calculations
291    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
292    SVGFEConvolveMatrixEdgeModeDuplicate{order_x: i32, order_y: i32,
293        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
294        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
295        kernel_unit_length_y: Au, preserve_alpha: i32},
296    /// transform image through convolution matrix of up to 25 values (spec
297    /// allows more but for performance reasons we do not)
298    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
299    /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
300    /// preserveAlpha
301    /// SVG filter semantics - selectable input(s), selectable between linear
302    /// (default) and sRGB color space for calculations
303    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
304    SVGFEConvolveMatrixEdgeModeNone{order_x: i32, order_y: i32,
305        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
306        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
307        kernel_unit_length_y: Au, preserve_alpha: i32},
308    /// transform image through convolution matrix of up to 25 values (spec
309    /// allows more but for performance reasons we do not)
310    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
311    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
312    ///  preserveAlpha
313    /// SVG filter semantics - selectable input(s), selectable between linear
314    /// (default) and sRGB color space for calculations
315    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
316    SVGFEConvolveMatrixEdgeModeWrap{order_x: i32, order_y: i32,
317        kernel: [Au; SVGFE_CONVOLVE_VALUES_LIMIT], divisor: Au, bias: Au,
318        target_x: i32, target_y: i32, kernel_unit_length_x: Au,
319        kernel_unit_length_y: Au, preserve_alpha: i32},
320    /// calculate lighting based on heightmap image with provided values for a
321    /// distant light source with specified direction
322    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
323    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
324    /// SVG filter semantics - selectable input(s), selectable between linear
325    /// (default) and sRGB color space for calculations
326    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
327    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
328    SVGFEDiffuseLightingDistant{surface_scale: Au, diffuse_constant: Au,
329        kernel_unit_length_x: Au, kernel_unit_length_y: Au, azimuth: Au,
330        elevation: Au},
331    /// calculate lighting based on heightmap image with provided values for a
332    /// point light source at specified location
333    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
334    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z
335    /// SVG filter semantics - selectable input(s), selectable between linear
336    /// (default) and sRGB color space for calculations
337    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
338    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
339    SVGFEDiffuseLightingPoint{surface_scale: Au, diffuse_constant: Au,
340        kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au,
341        z: Au},
342    /// calculate lighting based on heightmap image with provided values for a
343    /// spot light source at specified location pointing at specified target
344    /// location with specified hotspot sharpness and cone angle
345    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
346    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
347    ///  pointsAtZ, specularExponent, limitingConeAngle
348    /// SVG filter semantics - selectable input(s), selectable between linear
349    /// (default) and sRGB color space for calculations
350    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
351    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
352    SVGFEDiffuseLightingSpot{surface_scale: Au, diffuse_constant: Au,
353        kernel_unit_length_x: Au, kernel_unit_length_y: Au, x: Au, y: Au, z: Au,
354        points_at_x: Au, points_at_y: Au, points_at_z: Au, cone_exponent: Au,
355        limiting_cone_angle: Au},
356    /// calculate a distorted version of first input image using offset values
357    /// from second input image at specified intensity
358    /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
359    /// SVG filter semantics - selectable input(s), selectable between linear
360    /// (default) and sRGB color space for calculations
361    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
362    SVGFEDisplacementMap{scale: Au, x_channel_selector: u32,
363        y_channel_selector: u32},
364    /// create and merge a dropshadow version of the specified image's alpha
365    /// channel with specified offset and blur radius
366    /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
367    ///  stdDeviationX, stdDeviationY
368    /// SVG filter semantics - selectable input(s), selectable between linear
369    /// (default) and sRGB color space for calculations
370    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
371    SVGFEDropShadow{color: ColorU, dx: Au, dy: Au, std_deviation_x: Au,
372        std_deviation_y: Au},
373    /// synthesize a new image of specified size containing a solid color
374    /// parameters: FilterOpGraphNode, color
375    /// SVG filter semantics - selectable input(s), selectable between linear
376    /// (default) and sRGB color space for calculations
377    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
378    SVGFEFlood{color: ColorU},
379    /// create a blurred version of the input image
380    /// parameters: FilterOpGraphNode, stdDeviationX, stdDeviationY
381    /// SVG filter semantics - selectable input(s), selectable between linear
382    /// (default) and sRGB color space for calculations
383    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
384    SVGFEGaussianBlur{std_deviation_x: Au, std_deviation_y: Au},
385    /// Filter that does no transformation of the colors, needed for
386    /// debug purposes, and is the default value in impl_default_for_enums.
387    SVGFEIdentity,
388    /// synthesize a new image based on a url (i.e. blob image source)
389    /// parameters: FilterOpGraphNode, sampling_filter (see SamplingFilter in
390    /// Types.h), transform
391    /// SVG filter semantics - selectable input(s), selectable between linear
392    /// (default) and sRGB color space for calculations
393    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
394    SVGFEImage{sampling_filter: u32, matrix: [Au; 6]},
395    /// create a new image based on the input image with the contour stretched
396    /// outward (dilate operator)
397    /// parameters: FilterOpGraphNode, radiusX, radiusY
398    /// SVG filter semantics - selectable input(s), selectable between linear
399    /// (default) and sRGB color space for calculations
400    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
401    SVGFEMorphologyDilate{radius_x: Au, radius_y: Au},
402    /// create a new image based on the input image with the contour shrunken
403    /// inward (erode operator)
404    /// parameters: FilterOpGraphNode, radiusX, radiusY
405    /// SVG filter semantics - selectable input(s), selectable between linear
406    /// (default) and sRGB color space for calculations
407    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
408    SVGFEMorphologyErode{radius_x: Au, radius_y: Au},
409    /// represents CSS opacity property as a graph node like the rest of the
410    /// SVGFE* filters
411    /// parameters: FilterOpGraphNode
412    /// SVG filter semantics - selectable input(s), selectable between linear
413    /// (default) and sRGB color space for calculations
414    SVGFEOpacity{value: Au},
415    /// represents CSS opacity property as a graph node like the rest of the
416    /// SVGFE* filters
417    /// parameters: FilterOpGraphNode
418    /// SVG filter semantics - selectable input(s), selectable between linear
419    /// (default) and sRGB color space for calculations
420    SVGFEOpacityBinding{valuebindingid: PropertyBindingId, value: Au},
421    /// Filter that copies the SourceGraphic image into the specified subregion,
422    /// This is intentionally the only way to get SourceGraphic into the graph,
423    /// as the filter region must be applied before it is used.
424    /// parameters: FilterOpGraphNode
425    /// SVG filter semantics - no inputs, no linear
426    SVGFESourceGraphic,
427    /// Filter that copies the SourceAlpha image into the specified subregion,
428    /// This is intentionally the only way to get SourceAlpha into the graph,
429    /// as the filter region must be applied before it is used.
430    /// parameters: FilterOpGraphNode
431    /// SVG filter semantics - no inputs, no linear
432    SVGFESourceAlpha,
433    /// calculate lighting based on heightmap image with provided values for a
434    /// distant light source with specified direction
435    /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
436    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
437    /// SVG filter semantics - selectable input(s), selectable between linear
438    /// (default) and sRGB color space for calculations
439    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
440    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
441    SVGFESpecularLightingDistant{surface_scale: Au, specular_constant: Au,
442        specular_exponent: Au, kernel_unit_length_x: Au,
443        kernel_unit_length_y: Au, azimuth: Au, elevation: Au},
444    /// calculate lighting based on heightmap image with provided values for a
445    /// point light source at specified location
446    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
447    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
448    /// SVG filter semantics - selectable input(s), selectable between linear
449    /// (default) and sRGB color space for calculations
450    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
451    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
452    SVGFESpecularLightingPoint{surface_scale: Au, specular_constant: Au,
453        specular_exponent: Au, kernel_unit_length_x: Au,
454        kernel_unit_length_y: Au, x: Au, y: Au, z: Au},
455    /// calculate lighting based on heightmap image with provided values for a
456    /// spot light source at specified location pointing at specified target
457    /// location with specified hotspot sharpness and cone angle
458    /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
459    ///  specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
460    ///  pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
461    /// SVG filter semantics - selectable input(s), selectable between linear
462    /// (default) and sRGB color space for calculations
463    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
464    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
465    SVGFESpecularLightingSpot{surface_scale: Au, specular_constant: Au,
466        specular_exponent: Au, kernel_unit_length_x: Au,
467        kernel_unit_length_y: Au, x: Au, y: Au, z: Au, points_at_x: Au,
468        points_at_y: Au, points_at_z: Au, cone_exponent: Au,
469        limiting_cone_angle: Au},
470    /// create a new image based on the input image, repeated throughout the
471    /// output rectangle
472    /// parameters: FilterOpGraphNode
473    /// SVG filter semantics - selectable input(s), selectable between linear
474    /// (default) and sRGB color space for calculations
475    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
476    SVGFETile,
477    /// convert a color image to an alpha channel - internal use; generated by
478    /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
479    SVGFEToAlpha,
480    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
481    /// stitching mode
482    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
483    ///  numOctaves, seed
484    /// SVG filter semantics - selectable input(s), selectable between linear
485    /// (default) and sRGB color space for calculations
486    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
487    SVGFETurbulenceWithFractalNoiseWithNoStitching{base_frequency_x: Au,
488        base_frequency_y: Au, num_octaves: u32, seed: u32},
489    /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
490    /// stitching mode
491    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
492    ///  numOctaves, seed
493    /// SVG filter semantics - selectable input(s), selectable between linear
494    /// (default) and sRGB color space for calculations
495    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
496    SVGFETurbulenceWithFractalNoiseWithStitching{base_frequency_x: Au,
497        base_frequency_y: Au, num_octaves: u32, seed: u32},
498    /// synthesize a new image based on Turbulence Noise (offset vectors)
499    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
500    ///  numOctaves, seed
501    /// SVG filter semantics - selectable input(s), selectable between linear
502    /// (default) and sRGB color space for calculations
503    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
504    SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{base_frequency_x: Au,
505        base_frequency_y: Au, num_octaves: u32, seed: u32},
506    /// synthesize a new image based on Turbulence Noise (offset vectors)
507    /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
508    ///  numOctaves, seed
509    /// SVG filter semantics - selectable input(s), selectable between linear
510    /// (default) and sRGB color space for calculations
511    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
512    SVGFETurbulenceWithTurbulenceNoiseWithStitching{base_frequency_x: Au,
513        base_frequency_y: Au, num_octaves: u32, seed: u32},
514}
515
516impl From<FilterGraphOp> for FilterGraphOpKey {
517    fn from(op: FilterGraphOp) -> Self {
518        match op {
519            FilterGraphOp::SVGFEBlendDarken => FilterGraphOpKey::SVGFEBlendDarken,
520            FilterGraphOp::SVGFEBlendLighten => FilterGraphOpKey::SVGFEBlendLighten,
521            FilterGraphOp::SVGFEBlendMultiply => FilterGraphOpKey::SVGFEBlendMultiply,
522            FilterGraphOp::SVGFEBlendNormal => FilterGraphOpKey::SVGFEBlendNormal,
523            FilterGraphOp::SVGFEBlendScreen => FilterGraphOpKey::SVGFEBlendScreen,
524            FilterGraphOp::SVGFEBlendOverlay => FilterGraphOpKey::SVGFEBlendOverlay,
525            FilterGraphOp::SVGFEBlendColorDodge => FilterGraphOpKey::SVGFEBlendColorDodge,
526            FilterGraphOp::SVGFEBlendColorBurn => FilterGraphOpKey::SVGFEBlendColorBurn,
527            FilterGraphOp::SVGFEBlendHardLight => FilterGraphOpKey::SVGFEBlendHardLight,
528            FilterGraphOp::SVGFEBlendSoftLight => FilterGraphOpKey::SVGFEBlendSoftLight,
529            FilterGraphOp::SVGFEBlendDifference => FilterGraphOpKey::SVGFEBlendDifference,
530            FilterGraphOp::SVGFEBlendExclusion => FilterGraphOpKey::SVGFEBlendExclusion,
531            FilterGraphOp::SVGFEBlendHue => FilterGraphOpKey::SVGFEBlendHue,
532            FilterGraphOp::SVGFEBlendSaturation => FilterGraphOpKey::SVGFEBlendSaturation,
533            FilterGraphOp::SVGFEBlendColor => FilterGraphOpKey::SVGFEBlendColor,
534            FilterGraphOp::SVGFEBlendLuminosity => FilterGraphOpKey::SVGFEBlendLuminosity,
535            FilterGraphOp::SVGFEColorMatrix { values: color_matrix } => {
536                let mut quantized_values: [Au; 20] = [Au(0); 20];
537                for (value, result) in color_matrix.iter().zip(quantized_values.iter_mut()) {
538                    *result = Au::from_f32_px(*value);
539                }
540                FilterGraphOpKey::SVGFEColorMatrix{values: quantized_values}
541            }
542            FilterGraphOp::SVGFEComponentTransfer => unreachable!(),
543            FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels } => FilterGraphOpKey::SVGFEComponentTransferInterned{
544                handle: handle.uid(),
545                creates_pixels,
546            },
547            FilterGraphOp::SVGFECompositeArithmetic { k1, k2, k3, k4 } => {
548                FilterGraphOpKey::SVGFECompositeArithmetic{
549                    k1: Au::from_f32_px(k1),
550                    k2: Au::from_f32_px(k2),
551                    k3: Au::from_f32_px(k3),
552                    k4: Au::from_f32_px(k4),
553                }
554            }
555            FilterGraphOp::SVGFECompositeATop => FilterGraphOpKey::SVGFECompositeATop,
556            FilterGraphOp::SVGFECompositeIn => FilterGraphOpKey::SVGFECompositeIn,
557            FilterGraphOp::SVGFECompositeLighter => FilterGraphOpKey::SVGFECompositeLighter,
558            FilterGraphOp::SVGFECompositeOut => FilterGraphOpKey::SVGFECompositeOut,
559            FilterGraphOp::SVGFECompositeOver => FilterGraphOpKey::SVGFECompositeOver,
560            FilterGraphOp::SVGFECompositeXOR => FilterGraphOpKey::SVGFECompositeXOR,
561            FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
562                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
563                for (value, result) in kernel.iter().zip(values.iter_mut()) {
564                    *result = Au::from_f32_px(*value)
565                }
566                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeDuplicate{
567                    order_x,
568                    order_y,
569                    kernel: values,
570                    divisor: Au::from_f32_px(divisor),
571                    bias: Au::from_f32_px(bias),
572                    target_x,
573                    target_y,
574                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
575                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
576                    preserve_alpha,
577                }
578            }
579            FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
580                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
581                for (value, result) in kernel.iter().zip(values.iter_mut()) {
582                    *result = Au::from_f32_px(*value)
583                }
584                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeNone{
585                    order_x,
586                    order_y,
587                    kernel: values,
588                    divisor: Au::from_f32_px(divisor),
589                    bias: Au::from_f32_px(bias),
590                    target_x,
591                    target_y,
592                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
593                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
594                    preserve_alpha,
595                }
596            }
597            FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap { order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha } => {
598                let mut values: [Au; SVGFE_CONVOLVE_VALUES_LIMIT] = [Au(0); SVGFE_CONVOLVE_VALUES_LIMIT];
599                for (value, result) in kernel.iter().zip(values.iter_mut()) {
600                    *result = Au::from_f32_px(*value)
601                }
602                FilterGraphOpKey::SVGFEConvolveMatrixEdgeModeWrap{
603                    order_x,
604                    order_y,
605                    kernel: values,
606                    divisor: Au::from_f32_px(divisor),
607                    bias: Au::from_f32_px(bias),
608                    target_x,
609                    target_y,
610                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
611                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
612                    preserve_alpha,
613                }
614            }
615            FilterGraphOp::SVGFEDiffuseLightingDistant { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
616                FilterGraphOpKey::SVGFEDiffuseLightingDistant{
617                    surface_scale: Au::from_f32_px(surface_scale),
618                    diffuse_constant: Au::from_f32_px(diffuse_constant),
619                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
620                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
621                    azimuth: Au::from_f32_px(azimuth),
622                    elevation: Au::from_f32_px(elevation),
623                }
624            }
625            FilterGraphOp::SVGFEDiffuseLightingPoint { surface_scale, diffuse_constant, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
626                FilterGraphOpKey::SVGFEDiffuseLightingPoint{
627                    surface_scale: Au::from_f32_px(surface_scale),
628                    diffuse_constant: Au::from_f32_px(diffuse_constant),
629                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
630                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
631                    x: Au::from_f32_px(x),
632                    y: Au::from_f32_px(y),
633                    z: Au::from_f32_px(z),
634                }
635            }
636            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 } => {
637                FilterGraphOpKey::SVGFEDiffuseLightingSpot{
638                    surface_scale: Au::from_f32_px(surface_scale),
639                    diffuse_constant: Au::from_f32_px(diffuse_constant),
640                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
641                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
642                    x: Au::from_f32_px(x),
643                    y: Au::from_f32_px(y),
644                    z: Au::from_f32_px(z),
645                    points_at_x: Au::from_f32_px(points_at_x),
646                    points_at_y: Au::from_f32_px(points_at_y),
647                    points_at_z: Au::from_f32_px(points_at_z),
648                    cone_exponent: Au::from_f32_px(cone_exponent),
649                    limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
650                }
651            }
652            FilterGraphOp::SVGFEDisplacementMap { scale, x_channel_selector, y_channel_selector } => {
653                FilterGraphOpKey::SVGFEDisplacementMap{
654                    scale: Au::from_f32_px(scale),
655                    x_channel_selector,
656                    y_channel_selector,
657                }
658            }
659            FilterGraphOp::SVGFEDropShadow { color, dx, dy, std_deviation_x, std_deviation_y } => {
660                FilterGraphOpKey::SVGFEDropShadow{
661                    color: color.into(),
662                    dx: Au::from_f32_px(dx),
663                    dy: Au::from_f32_px(dy),
664                    std_deviation_x: Au::from_f32_px(std_deviation_x),
665                    std_deviation_y: Au::from_f32_px(std_deviation_y),
666                }
667            }
668            FilterGraphOp::SVGFEFlood { color } => FilterGraphOpKey::SVGFEFlood{color: color.into()},
669            FilterGraphOp::SVGFEGaussianBlur { std_deviation_x, std_deviation_y } => {
670                FilterGraphOpKey::SVGFEGaussianBlur{
671                    std_deviation_x: Au::from_f32_px(std_deviation_x),
672                    std_deviation_y: Au::from_f32_px(std_deviation_y),
673                }
674            }
675            FilterGraphOp::SVGFEIdentity => FilterGraphOpKey::SVGFEIdentity,
676            FilterGraphOp::SVGFEImage { sampling_filter, matrix } => {
677                let mut values: [Au; 6] = [Au(0); 6];
678                for (value, result) in matrix.iter().zip(values.iter_mut()) {
679                    *result = Au::from_f32_px(*value)
680                }
681                FilterGraphOpKey::SVGFEImage{
682                    sampling_filter,
683                    matrix: values,
684                }
685            }
686            FilterGraphOp::SVGFEMorphologyDilate { radius_x, radius_y } => {
687                FilterGraphOpKey::SVGFEMorphologyDilate{
688                    radius_x: Au::from_f32_px(radius_x),
689                    radius_y: Au::from_f32_px(radius_y),
690                }
691            }
692            FilterGraphOp::SVGFEMorphologyErode { radius_x, radius_y } => {
693                FilterGraphOpKey::SVGFEMorphologyErode{
694                    radius_x: Au::from_f32_px(radius_x),
695                    radius_y: Au::from_f32_px(radius_y),
696                }
697            }
698            FilterGraphOp::SVGFEOpacity{valuebinding: binding, value: _} => {
699                match binding {
700                    PropertyBinding::Value(value) => {
701                        FilterGraphOpKey::SVGFEOpacity{value: Au::from_f32_px(value)}
702                    }
703                    PropertyBinding::Binding(key, default) => {
704                        FilterGraphOpKey::SVGFEOpacityBinding{valuebindingid: key.id, value: Au::from_f32_px(default)}
705                    }
706                }
707            }
708            FilterGraphOp::SVGFESourceAlpha => FilterGraphOpKey::SVGFESourceAlpha,
709            FilterGraphOp::SVGFESourceGraphic => FilterGraphOpKey::SVGFESourceGraphic,
710            FilterGraphOp::SVGFESpecularLightingDistant { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, azimuth, elevation } => {
711                FilterGraphOpKey::SVGFESpecularLightingDistant{
712                    surface_scale: Au::from_f32_px(surface_scale),
713                    specular_constant: Au::from_f32_px(specular_constant),
714                    specular_exponent: Au::from_f32_px(specular_exponent),
715                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
716                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
717                    azimuth: Au::from_f32_px(azimuth),
718                    elevation: Au::from_f32_px(elevation),
719                }
720            }
721            FilterGraphOp::SVGFESpecularLightingPoint { surface_scale, specular_constant, specular_exponent, kernel_unit_length_x, kernel_unit_length_y, x, y, z } => {
722                FilterGraphOpKey::SVGFESpecularLightingPoint{
723                    surface_scale: Au::from_f32_px(surface_scale),
724                    specular_constant: Au::from_f32_px(specular_constant),
725                    specular_exponent: Au::from_f32_px(specular_exponent),
726                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
727                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
728                    x: Au::from_f32_px(x),
729                    y: Au::from_f32_px(y),
730                    z: Au::from_f32_px(z),
731                }
732            }
733            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 } => {
734                FilterGraphOpKey::SVGFESpecularLightingSpot{
735                    surface_scale: Au::from_f32_px(surface_scale),
736                    specular_constant: Au::from_f32_px(specular_constant),
737                    specular_exponent: Au::from_f32_px(specular_exponent),
738                    kernel_unit_length_x: Au::from_f32_px(kernel_unit_length_x),
739                    kernel_unit_length_y: Au::from_f32_px(kernel_unit_length_y),
740                    x: Au::from_f32_px(x),
741                    y: Au::from_f32_px(y),
742                    z: Au::from_f32_px(z),
743                    points_at_x: Au::from_f32_px(points_at_x),
744                    points_at_y: Au::from_f32_px(points_at_y),
745                    points_at_z: Au::from_f32_px(points_at_z),
746                    cone_exponent: Au::from_f32_px(cone_exponent),
747                    limiting_cone_angle: Au::from_f32_px(limiting_cone_angle),
748                }
749            }
750            FilterGraphOp::SVGFETile => FilterGraphOpKey::SVGFETile,
751            FilterGraphOp::SVGFEToAlpha => FilterGraphOpKey::SVGFEToAlpha,
752            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
753                FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithNoStitching {
754                    base_frequency_x: Au::from_f32_px(base_frequency_x),
755                    base_frequency_y: Au::from_f32_px(base_frequency_y),
756                    num_octaves,
757                    seed,
758                }
759            }
760            FilterGraphOp::SVGFETurbulenceWithFractalNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
761                FilterGraphOpKey::SVGFETurbulenceWithFractalNoiseWithStitching {
762                    base_frequency_x: Au::from_f32_px(base_frequency_x),
763                    base_frequency_y: Au::from_f32_px(base_frequency_y),
764                    num_octaves,
765                    seed,
766                }
767            }
768            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
769                FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithNoStitching {
770                    base_frequency_x: Au::from_f32_px(base_frequency_x),
771                    base_frequency_y: Au::from_f32_px(base_frequency_y),
772                    num_octaves,
773                    seed,
774                }
775            }
776            FilterGraphOp::SVGFETurbulenceWithTurbulenceNoiseWithStitching { base_frequency_x, base_frequency_y, num_octaves, seed } => {
777                FilterGraphOpKey::SVGFETurbulenceWithTurbulenceNoiseWithStitching {
778                    base_frequency_x: Au::from_f32_px(base_frequency_x),
779                    base_frequency_y: Au::from_f32_px(base_frequency_y),
780                    num_octaves,
781                    seed,
782                }
783            }
784        }
785    }
786}
787
788#[cfg_attr(feature = "capture", derive(Serialize))]
789#[cfg_attr(feature = "replay", derive(Deserialize))]
790#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
791pub struct FilterGraphNodeKey {
792    /// Indicates this graph node was marked as unnecessary by the DAG optimizer
793    /// (for example SVGFEOffset can often be folded into downstream nodes)
794    pub kept_by_optimizer: bool,
795    /// True if color_interpolation_filter == LinearRgb; shader will convert
796    /// sRGB texture pixel colors on load and convert back on store, for correct
797    /// interpolation
798    pub linear: bool,
799    /// virtualized picture input binding 1 (i.e. texture source), typically
800    /// this is used, but certain filters do not use it
801    pub inputs: Vec<FilterGraphPictureReferenceKey>,
802    /// rect this node will render into, in filter space, does not account for
803    /// inflate or device_pixel_scale
804    pub subregion: [Au; 4],
805}
806
807impl From<FilterGraphNode> for FilterGraphNodeKey {
808    fn from(node: FilterGraphNode) -> Self {
809        FilterGraphNodeKey{
810            kept_by_optimizer: node.kept_by_optimizer,
811            linear: node.linear,
812            inputs: node.inputs.into_iter().map(|node| {node.into()}).collect(),
813            subregion: [
814                Au::from_f32_px(node.subregion.min.x),
815                Au::from_f32_px(node.subregion.min.y),
816                Au::from_f32_px(node.subregion.max.x),
817                Au::from_f32_px(node.subregion.max.y),
818            ],
819        }
820    }
821}
822
823/// Represents a hashable description of how a picture primitive
824/// will be composited into its parent.
825#[cfg_attr(feature = "capture", derive(Serialize))]
826#[cfg_attr(feature = "replay", derive(Deserialize))]
827#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
828pub enum PictureCompositeKey {
829    // No visual compositing effect
830    Identity,
831
832    // FilterOp
833    Blur(Au, Au, bool, BlurEdgeMode),
834    Brightness(Au),
835    Contrast(Au),
836    Grayscale(Au),
837    HueRotate(Au),
838    Invert(Au),
839    Opacity(Au),
840    OpacityBinding(PropertyBindingId, Au),
841    Saturate(Au),
842    Sepia(Au),
843    DropShadows(Vec<(VectorKey, Au, ColorU)>),
844    ColorMatrix([Au; 20]),
845    SrgbToLinear,
846    LinearToSrgb,
847    ComponentTransfer(ItemUid),
848    Flood(ColorU),
849    SvgFilter(Vec<FilterPrimitiveKey>),
850    SVGFEGraph(Vec<(FilterGraphNodeKey, FilterGraphOpKey)>),
851
852    // MixBlendMode
853    Multiply,
854    Screen,
855    Overlay,
856    Darken,
857    Lighten,
858    ColorDodge,
859    ColorBurn,
860    HardLight,
861    SoftLight,
862    Difference,
863    Exclusion,
864    Hue,
865    Saturation,
866    Color,
867    Luminosity,
868    PlusLighter,
869}
870
871impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
872    fn from(mode: Option<PictureCompositeMode>) -> Self {
873        match mode {
874            Some(PictureCompositeMode::MixBlend(mode)) => {
875                match mode {
876                    MixBlendMode::Normal => PictureCompositeKey::Identity,
877                    MixBlendMode::Multiply => PictureCompositeKey::Multiply,
878                    MixBlendMode::Screen => PictureCompositeKey::Screen,
879                    MixBlendMode::Overlay => PictureCompositeKey::Overlay,
880                    MixBlendMode::Darken => PictureCompositeKey::Darken,
881                    MixBlendMode::Lighten => PictureCompositeKey::Lighten,
882                    MixBlendMode::ColorDodge => PictureCompositeKey::ColorDodge,
883                    MixBlendMode::ColorBurn => PictureCompositeKey::ColorBurn,
884                    MixBlendMode::HardLight => PictureCompositeKey::HardLight,
885                    MixBlendMode::SoftLight => PictureCompositeKey::SoftLight,
886                    MixBlendMode::Difference => PictureCompositeKey::Difference,
887                    MixBlendMode::Exclusion => PictureCompositeKey::Exclusion,
888                    MixBlendMode::Hue => PictureCompositeKey::Hue,
889                    MixBlendMode::Saturation => PictureCompositeKey::Saturation,
890                    MixBlendMode::Color => PictureCompositeKey::Color,
891                    MixBlendMode::Luminosity => PictureCompositeKey::Luminosity,
892                    MixBlendMode::PlusLighter => PictureCompositeKey::PlusLighter,
893                }
894            }
895            Some(PictureCompositeMode::Filter(op)) => {
896                match op {
897                    Filter::Blur { width, height, should_inflate, edge_mode } => {
898                        PictureCompositeKey::Blur(
899                            Au::from_f32_px(width),
900                            Au::from_f32_px(height),
901                            should_inflate,
902                            edge_mode,
903                        )
904                    }
905                    Filter::Brightness(value) => PictureCompositeKey::Brightness(Au::from_f32_px(value)),
906                    Filter::Contrast(value) => PictureCompositeKey::Contrast(Au::from_f32_px(value)),
907                    Filter::Grayscale(value) => PictureCompositeKey::Grayscale(Au::from_f32_px(value)),
908                    Filter::HueRotate(value) => PictureCompositeKey::HueRotate(Au::from_f32_px(value)),
909                    Filter::Invert(value) => PictureCompositeKey::Invert(Au::from_f32_px(value)),
910                    Filter::Saturate(value) => PictureCompositeKey::Saturate(Au::from_f32_px(value)),
911                    Filter::Sepia(value) => PictureCompositeKey::Sepia(Au::from_f32_px(value)),
912                    Filter::SrgbToLinear => PictureCompositeKey::SrgbToLinear,
913                    Filter::LinearToSrgb => PictureCompositeKey::LinearToSrgb,
914                    Filter::Identity => PictureCompositeKey::Identity,
915                    Filter::DropShadows(ref shadows) => {
916                        PictureCompositeKey::DropShadows(
917                            shadows.iter().map(|shadow| {
918                                (shadow.offset.into(), Au::from_f32_px(shadow.blur_radius), shadow.color.into())
919                            }).collect()
920                        )
921                    }
922                    Filter::Opacity(binding, _) => {
923                        match binding {
924                            PropertyBinding::Value(value) => {
925                                PictureCompositeKey::Opacity(Au::from_f32_px(value))
926                            }
927                            PropertyBinding::Binding(key, default) => {
928                                PictureCompositeKey::OpacityBinding(key.id, Au::from_f32_px(default))
929                            }
930                        }
931                    }
932                    Filter::ColorMatrix(values) => {
933                        let mut quantized_values: [Au; 20] = [Au(0); 20];
934                        for (value, result) in values.iter().zip(quantized_values.iter_mut()) {
935                            *result = Au::from_f32_px(*value);
936                        }
937                        PictureCompositeKey::ColorMatrix(quantized_values)
938                    }
939                    Filter::ComponentTransfer => unreachable!(),
940                    Filter::Flood(color) => PictureCompositeKey::Flood(color.into()),
941                    Filter::SVGGraphNode(_node, _op) => unreachable!(),
942                }
943            }
944            Some(PictureCompositeMode::ComponentTransferFilter(handle)) => {
945                PictureCompositeKey::ComponentTransfer(handle.uid())
946            }
947            Some(PictureCompositeMode::SvgFilter(filter_primitives, filter_data)) => {
948                PictureCompositeKey::SvgFilter(filter_primitives.into_iter().map(|primitive| {
949                    match primitive.kind {
950                        FilterPrimitiveKind::Identity(identity) => FilterPrimitiveKey::Identity(primitive.color_space, identity.input),
951                        FilterPrimitiveKind::Blend(blend) => FilterPrimitiveKey::Blend(primitive.color_space, blend.mode, blend.input1, blend.input2),
952                        FilterPrimitiveKind::Flood(flood) => FilterPrimitiveKey::Flood(primitive.color_space, flood.color.into()),
953                        FilterPrimitiveKind::Blur(blur) =>
954                            FilterPrimitiveKey::Blur(primitive.color_space, Au::from_f32_px(blur.width), Au::from_f32_px(blur.height), blur.input),
955                        FilterPrimitiveKind::Opacity(opacity) =>
956                            FilterPrimitiveKey::Opacity(primitive.color_space, Au::from_f32_px(opacity.opacity), opacity.input),
957                        FilterPrimitiveKind::ColorMatrix(color_matrix) => {
958                            let mut quantized_values: [Au; 20] = [Au(0); 20];
959                            for (value, result) in color_matrix.matrix.iter().zip(quantized_values.iter_mut()) {
960                                *result = Au::from_f32_px(*value);
961                            }
962                            FilterPrimitiveKey::ColorMatrix(primitive.color_space, quantized_values, color_matrix.input)
963                        }
964                        FilterPrimitiveKind::DropShadow(drop_shadow) => {
965                            FilterPrimitiveKey::DropShadow(
966                                primitive.color_space,
967                                (
968                                    drop_shadow.shadow.offset.into(),
969                                    Au::from_f32_px(drop_shadow.shadow.blur_radius),
970                                    drop_shadow.shadow.color.into(),
971                                ),
972                                drop_shadow.input,
973                            )
974                        }
975                        FilterPrimitiveKind::ComponentTransfer(component_transfer) =>
976                            FilterPrimitiveKey::ComponentTransfer(primitive.color_space, component_transfer.input, filter_data.clone()),
977                        FilterPrimitiveKind::Offset(info) =>
978                            FilterPrimitiveKey::Offset(primitive.color_space, info.input, info.offset.into()),
979                        FilterPrimitiveKind::Composite(info) =>
980                            FilterPrimitiveKey::Composite(primitive.color_space, info.input1, info.input2, info.operator.into()),
981                    }
982                }).collect())
983            }
984            Some(PictureCompositeMode::SVGFEGraph(filter_nodes)) => {
985                PictureCompositeKey::SVGFEGraph(
986                    filter_nodes.into_iter().map(|(node, op)| {
987                        (node.into(), op.into())
988                    }).collect())
989            }
990            Some(PictureCompositeMode::Blit(_)) |
991            Some(PictureCompositeMode::TileCache { .. }) |
992            Some(PictureCompositeMode::IntermediateSurface) |
993            None => {
994                PictureCompositeKey::Identity
995            }
996        }
997    }
998}
999
1000#[cfg_attr(feature = "capture", derive(Serialize))]
1001#[cfg_attr(feature = "replay", derive(Deserialize))]
1002#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
1003pub struct Picture {
1004    pub composite_mode_key: PictureCompositeKey,
1005    pub raster_space: RasterSpace,
1006}
1007
1008#[cfg_attr(feature = "capture", derive(Serialize))]
1009#[cfg_attr(feature = "replay", derive(Deserialize))]
1010#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
1011pub struct PictureKey {
1012    pub composite_mode_key: PictureCompositeKey,
1013    pub raster_space: RasterSpace,
1014}
1015
1016impl PictureKey {
1017    pub fn new(
1018        pic: Picture,
1019    ) -> Self {
1020        PictureKey {
1021            composite_mode_key: pic.composite_mode_key,
1022            raster_space: pic.raster_space,
1023        }
1024    }
1025}
1026
1027impl InternDebug for PictureKey {}
1028
1029#[cfg_attr(feature = "capture", derive(Serialize))]
1030#[cfg_attr(feature = "replay", derive(Deserialize))]
1031#[derive(MallocSizeOf)]
1032pub struct PictureTemplate;
1033
1034impl From<PictureKey> for PictureTemplate {
1035    fn from(_: PictureKey) -> Self {
1036        PictureTemplate
1037    }
1038}
1039
1040pub type PictureDataHandle = InternHandle<Picture>;
1041
1042impl Internable for Picture {
1043    type Key = PictureKey;
1044    type StoreData = PictureTemplate;
1045    type InternData = ();
1046    const PROFILE_COUNTER: usize = crate::profiler::INTERNED_PICTURES;
1047}
1048
1049impl InternablePrimitive for Picture {
1050    fn into_key(
1051        self,
1052        _: &LayoutPrimitiveInfo,
1053    ) -> PictureKey {
1054        PictureKey::new(self)
1055    }
1056
1057    fn make_instance_kind(
1058        _key: PictureKey,
1059        _: PictureDataHandle,
1060        _: &mut PrimitiveStore,
1061    ) -> PrimitiveInstanceKind {
1062        // Should never be hit as this method should not be
1063        // called for pictures.
1064        unreachable!();
1065    }
1066}
1067
1068impl IsVisible for Picture {
1069    fn is_visible(&self) -> bool {
1070        true
1071    }
1072}
1073
1074#[test]
1075#[cfg(target_pointer_width = "64")]
1076fn test_struct_sizes() {
1077    use std::mem;
1078    // The sizes of these structures are critical for performance on a number of
1079    // talos stress tests. If you get a failure here on CI, there's two possibilities:
1080    // (a) You made a structure smaller than it currently is. Great work! Update the
1081    //     test expectations and move on.
1082    // (b) You made a structure larger. This is not necessarily a problem, but should only
1083    //     be done with care, and after checking if talos performance regresses badly.
1084    assert_eq!(mem::size_of::<Picture>(), 96, "Picture size changed");
1085    assert_eq!(mem::size_of::<PictureTemplate>(), 0, "PictureTemplate size changed");
1086    assert_eq!(mem::size_of::<PictureKey>(), 96, "PictureKey size changed");
1087}