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