webrender_api/display_item.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 euclid::{SideOffsets2D, Angle};
6use peek_poke::PeekPoke;
7use std::ops::Not;
8// local imports
9use crate::{font, SnapshotImageKey};
10use crate::{APZScrollGeneration, HasScrollLinkedEffect, PipelineId, PropertyBinding};
11use crate::serde::{Serialize, Deserialize};
12use crate::color::ColorF;
13use crate::image::{ColorDepth, ImageKey};
14use crate::units::*;
15use std::hash::{Hash, Hasher};
16
17// ******************************************************************
18// * NOTE: some of these structs have an "IMPLICIT" comment. *
19// * This indicates that the BuiltDisplayList will have serialized *
20// * a list of values nearby that this item consumes. The traversal *
21// * iterator should handle finding these. DebugDisplayItem should *
22// * make them explicit. *
23// ******************************************************************
24
25/// A tag that can be used to identify items during hit testing. If the tag
26/// is missing then the item doesn't take part in hit testing at all. This
27/// is composed of two numbers. In Servo, the first is an identifier while the
28/// second is used to select the cursor that should be used during mouse
29/// movement. In Gecko, the first is a scrollframe identifier, while the second
30/// is used to store various flags that APZ needs to properly process input
31/// events.
32pub type ItemTag = (u64, u16);
33
34#[repr(C)]
35#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
36pub struct PrimitiveFlags(u8);
37
38bitflags! {
39 impl PrimitiveFlags: u8 {
40 /// The CSS backface-visibility property (yes, it can be really granular)
41 const IS_BACKFACE_VISIBLE = 1 << 0;
42 /// If set, this primitive represents a scroll bar container
43 const IS_SCROLLBAR_CONTAINER = 1 << 1;
44 /// This is used as a performance hint - this primitive may be promoted to a native
45 /// compositor surface under certain (implementation specific) conditions. This
46 /// is typically used for large videos, and canvas elements.
47 const PREFER_COMPOSITOR_SURFACE = 1 << 2;
48 /// If set, this primitive can be passed directly to the compositor via its
49 /// ExternalImageId, and the compositor will use the native image directly.
50 /// Used as a further extension on top of PREFER_COMPOSITOR_SURFACE.
51 const SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE = 1 << 3;
52 /// This flags disables snapping and forces anti-aliasing even if the primitive is axis-aligned.
53 const ANTIALISED = 1 << 4;
54 /// If true, this primitive is used as a background for checkerboarding
55 const CHECKERBOARD_BACKGROUND = 1 << 5;
56 }
57}
58
59impl core::fmt::Debug for PrimitiveFlags {
60 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
61 if self.is_empty() {
62 write!(f, "{:#x}", Self::empty().bits())
63 } else {
64 bitflags::parser::to_writer(self, f)
65 }
66 }
67}
68
69impl Default for PrimitiveFlags {
70 fn default() -> Self {
71 PrimitiveFlags::IS_BACKFACE_VISIBLE
72 }
73}
74
75/// A grouping of fields a lot of display items need, just to avoid
76/// repeating these over and over in this file.
77#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
78pub struct CommonItemProperties {
79 /// Bounds of the display item to clip to. Many items are logically
80 /// infinite, and rely on this clip_rect to define their bounds
81 /// (solid colors, background-images, gradients, etc).
82 pub clip_rect: LayoutRect,
83 /// Additional clips
84 pub clip_chain_id: ClipChainId,
85 /// The coordinate-space the item is in (yes, it can be really granular)
86 pub spatial_id: SpatialId,
87 /// Various flags describing properties of this primitive.
88 pub flags: PrimitiveFlags,
89}
90
91impl CommonItemProperties {
92 /// Convenience for tests.
93 pub fn new(
94 clip_rect: LayoutRect,
95 space_and_clip: SpaceAndClipInfo,
96 ) -> Self {
97 Self {
98 clip_rect,
99 spatial_id: space_and_clip.spatial_id,
100 clip_chain_id: space_and_clip.clip_chain_id,
101 flags: PrimitiveFlags::default(),
102 }
103 }
104}
105
106/// Per-primitive information about the nodes in the clip tree and
107/// the spatial tree that the primitive belongs to.
108///
109/// Note: this is a separate struct from `PrimitiveInfo` because
110/// it needs indirectional mapping during the DL flattening phase,
111/// turning into `ScrollNodeAndClipChain`.
112#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
113pub struct SpaceAndClipInfo {
114 pub spatial_id: SpatialId,
115 pub clip_chain_id: ClipChainId,
116}
117
118impl SpaceAndClipInfo {
119 /// Create a new space/clip info associated with the root
120 /// scroll frame.
121 pub fn root_scroll(pipeline_id: PipelineId) -> Self {
122 SpaceAndClipInfo {
123 spatial_id: SpatialId::root_scroll_node(pipeline_id),
124 clip_chain_id: ClipChainId::INVALID,
125 }
126 }
127}
128
129#[repr(u8)]
130#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
131pub enum SpatialTreeItem {
132 ScrollFrame(ScrollFrameDescriptor),
133 ReferenceFrame(ReferenceFrameDescriptor),
134 StickyFrame(StickyFrameDescriptor),
135 Invalid,
136}
137
138#[repr(u8)]
139#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
140pub enum DisplayItem {
141 // These are the "real content" display items
142 Rectangle(RectangleDisplayItem),
143 HitTest(HitTestDisplayItem),
144 Text(TextDisplayItem),
145 Line(LineDisplayItem),
146 Border(BorderDisplayItem),
147 BoxShadow(BoxShadowDisplayItem),
148 PushShadow(PushShadowDisplayItem),
149 Gradient(GradientDisplayItem),
150 RadialGradient(RadialGradientDisplayItem),
151 ConicGradient(ConicGradientDisplayItem),
152 Image(ImageDisplayItem),
153 RepeatingImage(RepeatingImageDisplayItem),
154 YuvImage(YuvImageDisplayItem),
155 BackdropFilter(BackdropFilterDisplayItem),
156
157 // Clips
158 RectClip(RectClipDisplayItem),
159 RoundedRectClip(RoundedRectClipDisplayItem),
160 ImageMaskClip(ImageMaskClipDisplayItem),
161 ClipChain(ClipChainItem),
162
163 // Spaces and Frames that content can be scoped under.
164 Iframe(IframeDisplayItem),
165 PushReferenceFrame(ReferenceFrameDisplayListItem),
166 PushStackingContext(PushStackingContextDisplayItem),
167
168 // These marker items indicate an array of data follows, to be used for the
169 // next non-marker item.
170 SetGradientStops,
171 SetFilterOps,
172 SetFilterData,
173 SetPoints,
174
175 // These marker items terminate a scope introduced by a previous item.
176 PopReferenceFrame,
177 PopStackingContext,
178 PopAllShadows,
179
180 // For debugging purposes.
181 DebugMarker(u32),
182}
183
184/// This is a "complete" version of the DisplayItem, with all implicit trailing
185/// arrays included, for debug serialization (captures).
186#[cfg(any(feature = "serialize", feature = "deserialize"))]
187#[cfg_attr(feature = "serialize", derive(Serialize))]
188#[cfg_attr(feature = "deserialize", derive(Deserialize))]
189pub enum DebugDisplayItem {
190 Rectangle(RectangleDisplayItem),
191 HitTest(HitTestDisplayItem),
192 Text(TextDisplayItem, Vec<font::GlyphInstance>),
193 Line(LineDisplayItem),
194 Border(BorderDisplayItem),
195 BoxShadow(BoxShadowDisplayItem),
196 PushShadow(PushShadowDisplayItem),
197 Gradient(GradientDisplayItem),
198 RadialGradient(RadialGradientDisplayItem),
199 ConicGradient(ConicGradientDisplayItem),
200 Image(ImageDisplayItem),
201 RepeatingImage(RepeatingImageDisplayItem),
202 YuvImage(YuvImageDisplayItem),
203 BackdropFilter(BackdropFilterDisplayItem),
204
205 ImageMaskClip(ImageMaskClipDisplayItem),
206 RoundedRectClip(RoundedRectClipDisplayItem),
207 RectClip(RectClipDisplayItem),
208 ClipChain(ClipChainItem, Vec<ClipId>),
209
210 Iframe(IframeDisplayItem),
211 PushReferenceFrame(ReferenceFrameDisplayListItem),
212 PushStackingContext(PushStackingContextDisplayItem),
213
214 SetGradientStops(Vec<GradientStop>),
215 SetFilterOps(Vec<FilterOp>),
216 SetFilterData(FilterData),
217 SetPoints(Vec<LayoutPoint>),
218
219 PopReferenceFrame,
220 PopStackingContext,
221 PopAllShadows,
222
223 DebugMarker(u32)
224}
225
226#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
227pub struct ImageMaskClipDisplayItem {
228 pub id: ClipId,
229 pub spatial_id: SpatialId,
230 pub image_mask: ImageMask,
231 pub fill_rule: FillRule,
232} // IMPLICIT points: Vec<LayoutPoint>
233
234#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
235pub struct RectClipDisplayItem {
236 pub id: ClipId,
237 pub spatial_id: SpatialId,
238 pub clip_rect: LayoutRect,
239}
240
241#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
242pub struct RoundedRectClipDisplayItem {
243 pub id: ClipId,
244 pub spatial_id: SpatialId,
245 pub clip: ComplexClipRegion,
246}
247
248/// The minimum and maximum allowable offset for a sticky frame in a single dimension.
249#[repr(C)]
250#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
251pub struct StickyOffsetBounds {
252 /// The minimum offset for this frame, typically a negative value, which specifies how
253 /// far in the negative direction the sticky frame can offset its contents in this
254 /// dimension.
255 pub min: f32,
256
257 /// The maximum offset for this frame, typically a positive value, which specifies how
258 /// far in the positive direction the sticky frame can offset its contents in this
259 /// dimension.
260 pub max: f32,
261}
262
263impl StickyOffsetBounds {
264 pub fn new(min: f32, max: f32) -> StickyOffsetBounds {
265 StickyOffsetBounds { min, max }
266 }
267}
268
269#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
270pub struct StickyFrameDescriptor {
271 pub id: SpatialId,
272 pub parent_spatial_id: SpatialId,
273 pub bounds: LayoutRect,
274
275 /// The margins that should be maintained between the edge of the parent viewport and this
276 /// sticky frame. A margin of None indicates that the sticky frame should not stick at all
277 /// to that particular edge of the viewport.
278 pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
279
280 /// The minimum and maximum vertical offsets for this sticky frame. Ignoring these constraints,
281 /// the sticky frame will continue to stick to the edge of the viewport as its original
282 /// position is scrolled out of view. Constraints specify a maximum and minimum offset from the
283 /// original position relative to non-sticky content within the same scrolling frame.
284 pub vertical_offset_bounds: StickyOffsetBounds,
285
286 /// The minimum and maximum horizontal offsets for this sticky frame. Ignoring these constraints,
287 /// the sticky frame will continue to stick to the edge of the viewport as its original
288 /// position is scrolled out of view. Constraints specify a maximum and minimum offset from the
289 /// original position relative to non-sticky content within the same scrolling frame.
290 pub horizontal_offset_bounds: StickyOffsetBounds,
291
292 /// The amount of offset that has already been applied to the sticky frame. A positive y
293 /// component this field means that a top-sticky item was in a scrollframe that has been
294 /// scrolled down, such that the sticky item's position needed to be offset downwards by
295 /// `previously_applied_offset.y`. A negative y component corresponds to the upward offset
296 /// applied due to bottom-stickiness. The x-axis works analogously.
297 pub previously_applied_offset: LayoutVector2D,
298
299 /// A property binding that we use to store an animation ID for APZ
300 pub transform: Option<PropertyBinding<LayoutTransform>>,
301}
302
303#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
304pub struct ScrollFrameDescriptor {
305 /// The id of the space this scroll frame creates
306 pub scroll_frame_id: SpatialId,
307 /// The size of the contents this contains (so the backend knows how far it can scroll).
308 // FIXME: this can *probably* just be a size? Origin seems to just get thrown out.
309 pub content_rect: LayoutRect,
310 pub frame_rect: LayoutRect,
311 pub parent_space: SpatialId,
312 pub external_id: ExternalScrollId,
313 /// The amount this scrollframe has already been scrolled by, in the caller.
314 /// This means that all the display items that are inside the scrollframe
315 /// will have their coordinates shifted by this amount, and this offset
316 /// should be added to those display item coordinates in order to get a
317 /// normalized value that is consistent across display lists.
318 pub external_scroll_offset: LayoutVector2D,
319 /// The generation of the external_scroll_offset.
320 pub scroll_offset_generation: APZScrollGeneration,
321 /// Whether this scrollframe document has any scroll-linked effect or not.
322 pub has_scroll_linked_effect: HasScrollLinkedEffect,
323}
324
325/// A solid or an animating color to draw (may not actually be a rectangle due to complex clips)
326#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
327pub struct RectangleDisplayItem {
328 pub common: CommonItemProperties,
329 pub bounds: LayoutRect,
330 pub color: PropertyBinding<ColorF>,
331}
332
333/// A minimal hit-testable item for the parent browser's convenience, and is
334/// slimmer than a RectangleDisplayItem (no color). The existence of this as a
335/// distinct item also makes it easier to inspect/debug display items.
336#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
337pub struct HitTestDisplayItem {
338 pub rect: LayoutRect,
339 pub clip_chain_id: ClipChainId,
340 pub spatial_id: SpatialId,
341 pub flags: PrimitiveFlags,
342 pub tag: ItemTag,
343}
344
345#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
346pub struct LineDisplayItem {
347 pub common: CommonItemProperties,
348 /// We need a separate rect from common.clip_rect to encode cute
349 /// tricks that firefox does to make a series of text-decorations seamlessly
350 /// line up -- snapping the decorations to a multiple of their period, and
351 /// then clipping them to their "proper" area. This rect is that "logical"
352 /// snapped area that may be clipped to the right size by the clip_rect.
353 pub area: LayoutRect,
354 /// Whether the rect is interpretted as vertical or horizontal
355 pub orientation: LineOrientation,
356 /// This could potentially be implied from area, but we currently prefer
357 /// that this is the responsibility of the layout engine. Value irrelevant
358 /// for non-wavy lines.
359 // FIXME: this was done before we could use tagged unions in enums, but now
360 // it should just be part of LineStyle::Wavy.
361 pub wavy_line_thickness: f32,
362 pub color: ColorF,
363 pub style: LineStyle,
364}
365
366#[repr(u8)]
367#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
368pub enum LineOrientation {
369 Vertical,
370 Horizontal,
371}
372
373#[repr(u8)]
374#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
375pub enum LineStyle {
376 Solid,
377 Dotted,
378 Dashed,
379 Wavy,
380}
381
382#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
383pub struct TextDisplayItem {
384 pub common: CommonItemProperties,
385 /// The area all the glyphs should be found in. Strictly speaking this isn't
386 /// necessarily needed, but layout engines should already "know" this, and we
387 /// use it cull and size things quickly before glyph layout is done. Currently
388 /// the glyphs *can* be outside these bounds, but that should imply they
389 /// can be cut off.
390 // FIXME: these are currently sometimes ignored to keep some old wrench tests
391 // working, but we should really just fix the tests!
392 pub bounds: LayoutRect,
393 pub font_key: font::FontInstanceKey,
394 pub color: ColorF,
395 pub glyph_options: Option<font::GlyphOptions>,
396} // IMPLICIT: glyphs: Vec<font::GlyphInstance>
397
398#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
399pub struct NormalBorder {
400 pub left: BorderSide,
401 pub right: BorderSide,
402 pub top: BorderSide,
403 pub bottom: BorderSide,
404 pub radius: BorderRadius,
405 /// Whether to apply anti-aliasing on the border corners.
406 ///
407 /// Note that for this to be `false` and work, this requires the borders to
408 /// be solid, and no border-radius.
409 pub do_aa: bool,
410}
411
412impl NormalBorder {
413 fn can_disable_antialiasing(&self) -> bool {
414 fn is_valid(style: BorderStyle) -> bool {
415 style == BorderStyle::Solid || style == BorderStyle::None
416 }
417
418 self.radius.is_zero() &&
419 is_valid(self.top.style) &&
420 is_valid(self.left.style) &&
421 is_valid(self.bottom.style) &&
422 is_valid(self.right.style)
423 }
424
425 /// Normalizes a border so that we don't render disallowed stuff, like inset
426 /// borders that are less than two pixels wide.
427 #[inline]
428 pub fn normalize(&mut self, widths: &LayoutSideOffsets) {
429 debug_assert!(
430 self.do_aa || self.can_disable_antialiasing(),
431 "Unexpected disabled-antialiasing in a border, likely won't work or will be ignored"
432 );
433
434 #[inline]
435 fn renders_small_border_solid(style: BorderStyle) -> bool {
436 match style {
437 BorderStyle::Groove |
438 BorderStyle::Ridge => true,
439 _ => false,
440 }
441 }
442
443 let normalize_side = |side: &mut BorderSide, width: f32| {
444 if renders_small_border_solid(side.style) && width < 2. {
445 side.style = BorderStyle::Solid;
446 }
447 };
448
449 normalize_side(&mut self.left, widths.left);
450 normalize_side(&mut self.right, widths.right);
451 normalize_side(&mut self.top, widths.top);
452 normalize_side(&mut self.bottom, widths.bottom);
453 }
454}
455
456#[repr(u8)]
457#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
458pub enum RepeatMode {
459 Stretch,
460 Repeat,
461 Round,
462 Space,
463}
464
465#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
466pub enum NinePatchBorderSource {
467 Image(ImageKey, ImageRendering),
468 Gradient(Gradient),
469 RadialGradient(RadialGradient),
470 ConicGradient(ConicGradient),
471}
472
473#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
474pub struct NinePatchBorder {
475 /// Describes what to use as the 9-patch source image. If this is an image,
476 /// it will be stretched to fill the size given by width x height.
477 pub source: NinePatchBorderSource,
478
479 /// The width of the 9-part image.
480 pub width: i32,
481
482 /// The height of the 9-part image.
483 pub height: i32,
484
485 /// Distances from each edge where the image should be sliced up. These
486 /// values are in 9-part-image space (the same space as width and height),
487 /// and the resulting image parts will be used to fill the corresponding
488 /// parts of the border as given by the border widths. This can lead to
489 /// stretching.
490 /// Slices can be overlapping. In that case, the same pixels from the
491 /// 9-part image will show up in multiple parts of the resulting border.
492 pub slice: DeviceIntSideOffsets,
493
494 /// Controls whether the center of the 9 patch image is rendered or
495 /// ignored. The center is never rendered if the slices are overlapping.
496 pub fill: bool,
497
498 /// Determines what happens if the horizontal side parts of the 9-part
499 /// image have a different size than the horizontal parts of the border.
500 pub repeat_horizontal: RepeatMode,
501
502 /// Determines what happens if the vertical side parts of the 9-part
503 /// image have a different size than the vertical parts of the border.
504 pub repeat_vertical: RepeatMode,
505}
506
507#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
508pub enum BorderDetails {
509 Normal(NormalBorder),
510 NinePatch(NinePatchBorder),
511}
512
513#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
514pub struct BorderDisplayItem {
515 pub common: CommonItemProperties,
516 pub bounds: LayoutRect,
517 pub widths: LayoutSideOffsets,
518 pub details: BorderDetails,
519}
520
521#[repr(C)]
522#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
523pub enum BorderRadiusKind {
524 Uniform,
525 NonUniform,
526}
527
528#[repr(C)]
529#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
530pub struct BorderRadius {
531 pub top_left: LayoutSize,
532 pub top_right: LayoutSize,
533 pub bottom_left: LayoutSize,
534 pub bottom_right: LayoutSize,
535}
536
537impl Default for BorderRadius {
538 fn default() -> Self {
539 BorderRadius {
540 top_left: LayoutSize::zero(),
541 top_right: LayoutSize::zero(),
542 bottom_left: LayoutSize::zero(),
543 bottom_right: LayoutSize::zero(),
544 }
545 }
546}
547
548#[repr(C)]
549#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
550pub struct BorderSide {
551 pub color: ColorF,
552 pub style: BorderStyle,
553}
554
555#[repr(u32)]
556#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq, PeekPoke)]
557pub enum BorderStyle {
558 None = 0,
559 Solid = 1,
560 Double = 2,
561 Dotted = 3,
562 Dashed = 4,
563 Hidden = 5,
564 Groove = 6,
565 Ridge = 7,
566 Inset = 8,
567 Outset = 9,
568}
569
570impl BorderStyle {
571 pub fn is_hidden(self) -> bool {
572 self == BorderStyle::Hidden || self == BorderStyle::None
573 }
574}
575
576#[repr(u8)]
577#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
578pub enum BoxShadowClipMode {
579 Outset = 0,
580 Inset = 1,
581}
582
583#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
584pub struct BoxShadowDisplayItem {
585 pub common: CommonItemProperties,
586 pub box_bounds: LayoutRect,
587 pub offset: LayoutVector2D,
588 pub color: ColorF,
589 pub blur_radius: f32,
590 pub spread_radius: f32,
591 pub border_radius: BorderRadius,
592 pub shadow_radius: BorderRadius,
593 pub clip_mode: BoxShadowClipMode,
594}
595
596#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
597pub struct PushShadowDisplayItem {
598 pub space_and_clip: SpaceAndClipInfo,
599 pub shadow: Shadow,
600 pub should_inflate: bool,
601}
602
603#[repr(C)]
604#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
605pub struct Shadow {
606 pub offset: LayoutVector2D,
607 pub color: ColorF,
608 pub blur_radius: f32,
609}
610
611#[repr(u8)]
612#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
613pub enum ExtendMode {
614 Clamp,
615 Repeat,
616}
617
618#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
619pub struct Gradient {
620 pub start_point: LayoutPoint,
621 pub end_point: LayoutPoint,
622 pub extend_mode: ExtendMode,
623} // IMPLICIT: stops: Vec<GradientStop>
624
625impl Gradient {
626 pub fn is_valid(&self) -> bool {
627 self.start_point.x.is_finite() &&
628 self.start_point.y.is_finite() &&
629 self.end_point.x.is_finite() &&
630 self.end_point.y.is_finite()
631 }
632}
633
634/// The area
635#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
636pub struct GradientDisplayItem {
637 /// NOTE: common.clip_rect is the area the gradient covers
638 pub common: CommonItemProperties,
639 /// The area to tile the gradient over (first tile starts at origin of this rect)
640 // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
641 // defining the bounds of the item. Needs non-trivial backend changes.
642 pub bounds: LayoutRect,
643 /// How big a tile of the of the gradient should be (common case: bounds.size)
644 pub tile_size: LayoutSize,
645 /// The space between tiles of the gradient (common case: 0)
646 pub tile_spacing: LayoutSize,
647 pub gradient: Gradient,
648}
649
650#[repr(C)]
651#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
652pub struct GradientStop {
653 pub offset: f32,
654 pub color: ColorF,
655}
656
657#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
658pub struct RadialGradient {
659 pub center: LayoutPoint,
660 pub radius: LayoutSize,
661 pub start_offset: f32,
662 pub end_offset: f32,
663 pub extend_mode: ExtendMode,
664} // IMPLICIT stops: Vec<GradientStop>
665
666impl RadialGradient {
667 pub fn is_valid(&self) -> bool {
668 self.center.x.is_finite() &&
669 self.center.y.is_finite() &&
670 self.start_offset.is_finite() &&
671 self.end_offset.is_finite()
672 }
673}
674
675#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
676pub struct ConicGradient {
677 pub center: LayoutPoint,
678 pub angle: f32,
679 pub start_offset: f32,
680 pub end_offset: f32,
681 pub extend_mode: ExtendMode,
682} // IMPLICIT stops: Vec<GradientStop>
683
684impl ConicGradient {
685 pub fn is_valid(&self) -> bool {
686 self.center.x.is_finite() &&
687 self.center.y.is_finite() &&
688 self.angle.is_finite() &&
689 self.start_offset.is_finite() &&
690 self.end_offset.is_finite()
691 }
692}
693
694/// Just an abstraction for bundling up a bunch of clips into a "super clip".
695#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
696pub struct ClipChainItem {
697 pub id: ClipChainId,
698 pub parent: Option<ClipChainId>,
699} // IMPLICIT clip_ids: Vec<ClipId>
700
701#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
702pub struct RadialGradientDisplayItem {
703 pub common: CommonItemProperties,
704 /// The area to tile the gradient over (first tile starts at origin of this rect)
705 // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
706 // defining the bounds of the item. Needs non-trivial backend changes.
707 pub bounds: LayoutRect,
708 pub gradient: RadialGradient,
709 pub tile_size: LayoutSize,
710 pub tile_spacing: LayoutSize,
711}
712
713#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
714pub struct ConicGradientDisplayItem {
715 pub common: CommonItemProperties,
716 /// The area to tile the gradient over (first tile starts at origin of this rect)
717 // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
718 // defining the bounds of the item. Needs non-trivial backend changes.
719 pub bounds: LayoutRect,
720 pub gradient: ConicGradient,
721 pub tile_size: LayoutSize,
722 pub tile_spacing: LayoutSize,
723}
724
725/// Renders a filtered region of its backdrop
726#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
727pub struct BackdropFilterDisplayItem {
728 pub common: CommonItemProperties,
729}
730// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>
731
732#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
733pub struct ReferenceFrameDisplayListItem {
734}
735
736#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
737pub struct ReferenceFrameDescriptor {
738 pub origin: LayoutPoint,
739 pub parent_spatial_id: SpatialId,
740 pub reference_frame: ReferenceFrame,
741}
742
743#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
744pub enum ReferenceFrameKind {
745 /// A normal transform matrix, may contain perspective (the CSS transform property)
746 Transform {
747 /// Optionally marks the transform as only ever having a simple 2D scale or translation,
748 /// allowing for optimizations.
749 is_2d_scale_translation: bool,
750 /// Marks that the transform should be snapped. Used for transforms which animate in
751 /// response to scrolling, eg for zooming or dynamic toolbar fixed-positioning.
752 should_snap: bool,
753 /// Marks the transform being a part of the CSS stacking context that also has
754 /// a perspective. In this case, backface visibility takes this perspective into
755 /// account.
756 paired_with_perspective: bool,
757 },
758 /// A perspective transform, that optionally scrolls relative to a specific scroll node
759 Perspective {
760 scrolling_relative_to: Option<ExternalScrollId>,
761 }
762}
763
764#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
765pub enum Rotation {
766 Degree0,
767 Degree90,
768 Degree180,
769 Degree270,
770}
771
772impl Rotation {
773 pub fn to_matrix(
774 &self,
775 size: LayoutSize,
776 ) -> LayoutTransform {
777 let (shift_center_to_origin, angle) = match self {
778 Rotation::Degree0 => {
779 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(0.))
780 },
781 Rotation::Degree90 => {
782 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(90.))
783 },
784 Rotation::Degree180 => {
785 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(180.))
786 },
787 Rotation::Degree270 => {
788 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(270.))
789 },
790 };
791 let shift_origin_to_center = LayoutTransform::translation(size.width / 2., size.height / 2., 0.);
792
793 shift_center_to_origin
794 .then(&LayoutTransform::rotation(0., 0., 1.0, angle))
795 .then(&shift_origin_to_center)
796 }
797}
798
799#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
800pub enum ReferenceTransformBinding {
801 /// Standard reference frame which contains a precomputed transform.
802 Static {
803 binding: PropertyBinding<LayoutTransform>,
804 },
805 /// Computed reference frame which dynamically calculates the transform
806 /// based on the given parameters. The reference is the content size of
807 /// the parent iframe, which is affected by snapping.
808 ///
809 /// This is used when a transform depends on the layout size of an
810 /// element, otherwise the difference between the unsnapped size
811 /// used in the transform, and the snapped size calculated during scene
812 /// building can cause seaming.
813 Computed {
814 scale_from: Option<LayoutSize>,
815 vertical_flip: bool,
816 rotation: Rotation,
817 },
818}
819
820impl Default for ReferenceTransformBinding {
821 fn default() -> Self {
822 ReferenceTransformBinding::Static {
823 binding: Default::default(),
824 }
825 }
826}
827
828#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
829pub struct ReferenceFrame {
830 pub kind: ReferenceFrameKind,
831 pub transform_style: TransformStyle,
832 /// The transform matrix, either the perspective matrix or the transform
833 /// matrix.
834 pub transform: ReferenceTransformBinding,
835 pub id: SpatialId,
836}
837
838/// If passed in a stacking context display item, inform WebRender that
839/// the contents of the stacking context should be retained into a texture
840/// and associated to an image key.
841///
842/// Image display items can then display the cached snapshot using the
843/// same image key.
844///
845/// The flow for creating/using/deleting snapshots is the same as with
846/// regular images:
847/// - The image key must have been created with `Transaction::add_snapshot_image`.
848/// - The current scene must not contain references to the snapshot when
849/// `Transaction::delete_snapshot_image` is called.
850#[repr(C)]
851#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
852pub struct SnapshotInfo {
853 /// The image key to associate the snapshot with.
854 pub key: SnapshotImageKey,
855 /// The bounds of the snapshot in local space.
856 ///
857 /// This rectangle is relative to the same coordinate space as the
858 /// child items of the stacking context.
859 pub area: LayoutRect,
860 /// If true, detach the stacking context from the scene and only
861 /// render it into the snapshot.
862 /// If false, the stacking context rendered in the frame normally
863 /// in addition to being cached into the snapshot.
864 pub detached: bool,
865}
866
867#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
868pub struct PushStackingContextDisplayItem {
869 pub spatial_id: SpatialId,
870 pub snapshot: Option<SnapshotInfo>,
871 pub prim_flags: PrimitiveFlags,
872 pub stacking_context: StackingContext,
873}
874
875#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
876pub struct StackingContext {
877 pub transform_style: TransformStyle,
878 pub mix_blend_mode: MixBlendMode,
879 pub clip_chain_id: Option<ClipChainId>,
880 pub raster_space: RasterSpace,
881 pub flags: StackingContextFlags,
882}
883// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>
884
885#[repr(u8)]
886#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
887pub enum TransformStyle {
888 Flat = 0,
889 Preserve3D = 1,
890}
891
892/// Configure whether the contents of a stacking context
893/// should be rasterized in local space or screen space.
894/// Local space rasterized pictures are typically used
895/// when we want to cache the output, and performance is
896/// important. Note that this is a performance hint only,
897/// which WR may choose to ignore.
898#[derive(Clone, Copy, Debug, Deserialize, PartialEq, MallocSizeOf, Serialize, PeekPoke)]
899#[repr(u8)]
900pub enum RasterSpace {
901 // Rasterize in local-space, applying supplied scale to primitives.
902 // Best performance, but lower quality.
903 Local(f32),
904
905 // Rasterize the picture in screen-space, including rotation / skew etc in
906 // the rasterized element. Best quality, but slower performance. Note that
907 // any stacking context with a perspective transform will be rasterized
908 // in local-space, even if this is set.
909 Screen,
910}
911
912impl RasterSpace {
913 pub fn local_scale(self) -> Option<f32> {
914 match self {
915 RasterSpace::Local(scale) => Some(scale),
916 RasterSpace::Screen => None,
917 }
918 }
919}
920
921impl Eq for RasterSpace {}
922
923impl Hash for RasterSpace {
924 fn hash<H: Hasher>(&self, state: &mut H) {
925 match self {
926 RasterSpace::Screen => {
927 0.hash(state);
928 }
929 RasterSpace::Local(scale) => {
930 // Note: this is inconsistent with the Eq impl for -0.0 (don't care).
931 1.hash(state);
932 scale.to_bits().hash(state);
933 }
934 }
935 }
936}
937
938#[repr(C)]
939#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
940pub struct StackingContextFlags(u8);
941
942bitflags! {
943 impl StackingContextFlags: u8 {
944 /// If true, this stacking context is a blend container than contains
945 /// mix-blend-mode children (and should thus be isolated).
946 const IS_BLEND_CONTAINER = 1 << 0;
947 /// If true, this stacking context is a wrapper around a backdrop-filter (e.g. for
948 /// a clip-mask). This is needed to allow the correct selection of a backdrop root
949 /// since a clip-mask stacking context creates a parent surface.
950 const WRAPS_BACKDROP_FILTER = 1 << 1;
951 /// If true, this stacking context must be isolated from parent by a surface.
952 const FORCED_ISOLATION = 1 << 2;
953 }
954}
955
956impl core::fmt::Debug for StackingContextFlags {
957 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
958 if self.is_empty() {
959 write!(f, "{:#x}", Self::empty().bits())
960 } else {
961 bitflags::parser::to_writer(self, f)
962 }
963 }
964}
965
966impl Default for StackingContextFlags {
967 fn default() -> Self {
968 StackingContextFlags::empty()
969 }
970}
971
972#[repr(u8)]
973#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
974pub enum MixBlendMode {
975 Normal = 0,
976 Multiply = 1,
977 Screen = 2,
978 Overlay = 3,
979 Darken = 4,
980 Lighten = 5,
981 ColorDodge = 6,
982 ColorBurn = 7,
983 HardLight = 8,
984 SoftLight = 9,
985 Difference = 10,
986 Exclusion = 11,
987 Hue = 12,
988 Saturation = 13,
989 Color = 14,
990 Luminosity = 15,
991 PlusLighter = 16,
992}
993
994#[repr(C)]
995#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
996pub enum ColorSpace {
997 Srgb,
998 LinearRgb,
999}
1000
1001/// Available composite operoations for the composite filter primitive
1002#[repr(C)]
1003#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1004pub enum CompositeOperator {
1005 Over,
1006 In,
1007 Atop,
1008 Out,
1009 Xor,
1010 Lighter,
1011 Arithmetic([f32; 4]),
1012}
1013
1014impl CompositeOperator {
1015 // This must stay in sync with the composite operator defines in cs_svg_filter.glsl
1016 pub fn as_int(&self) -> u32 {
1017 match self {
1018 CompositeOperator::Over => 0,
1019 CompositeOperator::In => 1,
1020 CompositeOperator::Out => 2,
1021 CompositeOperator::Atop => 3,
1022 CompositeOperator::Xor => 4,
1023 CompositeOperator::Lighter => 5,
1024 CompositeOperator::Arithmetic(..) => 6,
1025 }
1026 }
1027}
1028
1029/// An input to a SVG filter primitive.
1030#[repr(C)]
1031#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1032pub enum FilterPrimitiveInput {
1033 /// The input is the original graphic that the filter is being applied to.
1034 Original,
1035 /// The input is the output of the previous filter primitive in the filter primitive chain.
1036 Previous,
1037 /// The input is the output of the filter primitive at the given index in the filter primitive chain.
1038 OutputOfPrimitiveIndex(usize),
1039}
1040
1041impl FilterPrimitiveInput {
1042 /// Gets the index of the input.
1043 /// Returns `None` if the source graphic is the input.
1044 pub fn to_index(self, cur_index: usize) -> Option<usize> {
1045 match self {
1046 FilterPrimitiveInput::Previous if cur_index > 0 => Some(cur_index - 1),
1047 FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => Some(index),
1048 _ => None,
1049 }
1050 }
1051}
1052
1053#[repr(C)]
1054#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1055pub struct BlendPrimitive {
1056 pub input1: FilterPrimitiveInput,
1057 pub input2: FilterPrimitiveInput,
1058 pub mode: MixBlendMode,
1059}
1060
1061#[repr(C)]
1062#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1063pub struct FloodPrimitive {
1064 pub color: ColorF,
1065}
1066
1067impl FloodPrimitive {
1068 pub fn sanitize(&mut self) {
1069 self.color.r = self.color.r.clamp(0.0, 1.0);
1070 self.color.g = self.color.g.clamp(0.0, 1.0);
1071 self.color.b = self.color.b.clamp(0.0, 1.0);
1072 self.color.a = self.color.a.clamp(0.0, 1.0);
1073 }
1074}
1075
1076#[repr(C)]
1077#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1078pub struct BlurPrimitive {
1079 pub input: FilterPrimitiveInput,
1080 pub width: f32,
1081 pub height: f32,
1082}
1083
1084#[repr(C)]
1085#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1086pub struct OpacityPrimitive {
1087 pub input: FilterPrimitiveInput,
1088 pub opacity: f32,
1089}
1090
1091impl OpacityPrimitive {
1092 pub fn sanitize(&mut self) {
1093 self.opacity = self.opacity.clamp(0.0, 1.0);
1094 }
1095}
1096
1097/// cbindgen:derive-eq=false
1098#[repr(C)]
1099#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1100pub struct ColorMatrixPrimitive {
1101 pub input: FilterPrimitiveInput,
1102 pub matrix: [f32; 20],
1103}
1104
1105#[repr(C)]
1106#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1107pub struct DropShadowPrimitive {
1108 pub input: FilterPrimitiveInput,
1109 pub shadow: Shadow,
1110}
1111
1112#[repr(C)]
1113#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1114pub struct ComponentTransferPrimitive {
1115 pub input: FilterPrimitiveInput,
1116 // Component transfer data is stored in FilterData.
1117}
1118
1119#[repr(C)]
1120#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1121pub struct IdentityPrimitive {
1122 pub input: FilterPrimitiveInput,
1123}
1124
1125#[repr(C)]
1126#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1127pub struct OffsetPrimitive {
1128 pub input: FilterPrimitiveInput,
1129 pub offset: LayoutVector2D,
1130}
1131
1132#[repr(C)]
1133#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1134pub struct CompositePrimitive {
1135 pub input1: FilterPrimitiveInput,
1136 pub input2: FilterPrimitiveInput,
1137 pub operator: CompositeOperator,
1138}
1139
1140/// See: https://github.com/eqrion/cbindgen/issues/9
1141/// cbindgen:derive-eq=false
1142#[repr(C)]
1143#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
1144pub enum FilterPrimitiveKind {
1145 Identity(IdentityPrimitive),
1146 Blend(BlendPrimitive),
1147 Flood(FloodPrimitive),
1148 Blur(BlurPrimitive),
1149 // TODO: Support animated opacity?
1150 Opacity(OpacityPrimitive),
1151 /// cbindgen:derive-eq=false
1152 ColorMatrix(ColorMatrixPrimitive),
1153 DropShadow(DropShadowPrimitive),
1154 ComponentTransfer(ComponentTransferPrimitive),
1155 Offset(OffsetPrimitive),
1156 Composite(CompositePrimitive),
1157}
1158
1159impl Default for FilterPrimitiveKind {
1160 fn default() -> Self {
1161 FilterPrimitiveKind::Identity(IdentityPrimitive::default())
1162 }
1163}
1164
1165impl FilterPrimitiveKind {
1166 pub fn sanitize(&mut self) {
1167 match self {
1168 FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
1169 FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
1170
1171 // No sanitization needed.
1172 FilterPrimitiveKind::Identity(..) |
1173 FilterPrimitiveKind::Blend(..) |
1174 FilterPrimitiveKind::ColorMatrix(..) |
1175 FilterPrimitiveKind::Offset(..) |
1176 FilterPrimitiveKind::Composite(..) |
1177 FilterPrimitiveKind::Blur(..) |
1178 FilterPrimitiveKind::DropShadow(..) |
1179 // Component transfer's filter data is sanitized separately.
1180 FilterPrimitiveKind::ComponentTransfer(..) => {}
1181 }
1182 }
1183}
1184
1185/// SVG Filter Primitive.
1186/// See: https://github.com/eqrion/cbindgen/issues/9
1187/// cbindgen:derive-eq=false
1188#[repr(C)]
1189#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1190pub struct FilterPrimitive {
1191 pub kind: FilterPrimitiveKind,
1192 pub color_space: ColorSpace,
1193}
1194
1195impl FilterPrimitive {
1196 pub fn sanitize(&mut self) {
1197 self.kind.sanitize();
1198 }
1199}
1200
1201#[repr(C)]
1202#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, PeekPoke)]
1203pub enum FilterOpGraphPictureBufferId {
1204 #[default]
1205 /// empty slot in feMerge inputs
1206 None,
1207 /// reference to another (earlier) node in filter graph
1208 BufferId(i16),
1209}
1210
1211#[repr(C)]
1212#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
1213pub struct FilterOpGraphPictureReference {
1214 /// Id of the picture in question in a namespace unique to this filter DAG
1215 pub buffer_id: FilterOpGraphPictureBufferId,
1216}
1217
1218#[repr(C)]
1219#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
1220pub struct FilterOpGraphNode {
1221 /// True if color_interpolation_filter == LinearRgb; shader will convert
1222 /// sRGB texture pixel colors on load and convert back on store, for correct
1223 /// interpolation
1224 pub linear: bool,
1225 /// virtualized picture input binding 1 (i.e. texture source), typically
1226 /// this is used, but certain filters do not use it
1227 pub input: FilterOpGraphPictureReference,
1228 /// virtualized picture input binding 2 (i.e. texture sources), only certain
1229 /// filters use this
1230 pub input2: FilterOpGraphPictureReference,
1231 /// rect this node will render into, in filter space
1232 pub subregion: LayoutRect,
1233}
1234
1235/// Maximum number of SVGFE filters in one graph, this is constant size to avoid
1236/// allocating anything, and the SVG spec allows us to drop all filters on an
1237/// item if the graph is excessively complex - a graph this large will never be
1238/// a good user experience, performance-wise.
1239pub const SVGFE_GRAPH_MAX: usize = 256;
1240
1241#[repr(C)]
1242#[derive(Clone, Copy, Debug, Deserialize, Serialize, PeekPoke)]
1243pub enum FilterOp {
1244 /// Filter that does no transformation of the colors, needed for
1245 /// debug purposes, and is the default value in impl_default_for_enums.
1246 /// parameters: none
1247 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1248 Identity,
1249 /// apply blur effect
1250 /// parameters: stdDeviationX, stdDeviationY
1251 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1252 Blur(f32, f32),
1253 /// apply brightness effect
1254 /// parameters: amount
1255 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1256 Brightness(f32),
1257 /// apply contrast effect
1258 /// parameters: amount
1259 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1260 Contrast(f32),
1261 /// fade image toward greyscale version of image
1262 /// parameters: amount
1263 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1264 Grayscale(f32),
1265 /// fade image toward hue-rotated version of image (rotate RGB around color wheel)
1266 /// parameters: angle
1267 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1268 HueRotate(f32),
1269 /// fade image toward inverted image (1 - RGB)
1270 /// parameters: amount
1271 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1272 Invert(f32),
1273 /// multiplies color and alpha by opacity
1274 /// parameters: amount
1275 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1276 Opacity(PropertyBinding<f32>, f32),
1277 /// multiply saturation of colors
1278 /// parameters: amount
1279 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1280 Saturate(f32),
1281 /// fade image toward sepia tone version of image
1282 /// parameters: amount
1283 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1284 Sepia(f32),
1285 /// add drop shadow version of image to the image
1286 /// parameters: shadow
1287 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1288 DropShadow(Shadow),
1289 /// transform color and alpha in image through 4x5 color matrix (transposed for efficiency)
1290 /// parameters: matrix[5][4]
1291 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1292 ColorMatrix([f32; 20]),
1293 /// internal use - convert sRGB input to linear output
1294 /// parameters: none
1295 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1296 SrgbToLinear,
1297 /// internal use - convert linear input to sRGB output
1298 /// parameters: none
1299 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1300 LinearToSrgb,
1301 /// remap RGBA with color gradients and component swizzle
1302 /// parameters: FilterData
1303 /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
1304 ComponentTransfer,
1305 /// replace image with a solid color
1306 /// NOTE: UNUSED; Gecko never produces this filter
1307 /// parameters: color
1308 /// CSS filter semantics - operates on previous picture,uses sRGB space (non-linear)
1309 Flood(ColorF),
1310 /// Filter that copies the SourceGraphic image into the specified subregion,
1311 /// This is intentionally the only way to get SourceGraphic into the graph,
1312 /// as the filter region must be applied before it is used.
1313 /// parameters: FilterOpGraphNode
1314 /// SVG filter semantics - no inputs, no linear
1315 SVGFESourceGraphic{node: FilterOpGraphNode},
1316 /// Filter that copies the SourceAlpha image into the specified subregion,
1317 /// This is intentionally the only way to get SourceGraphic into the graph,
1318 /// as the filter region must be applied before it is used.
1319 /// parameters: FilterOpGraphNode
1320 /// SVG filter semantics - no inputs, no linear
1321 SVGFESourceAlpha{node: FilterOpGraphNode},
1322 /// Filter that does no transformation of the colors, used for subregion
1323 /// cropping only.
1324 SVGFEIdentity{node: FilterOpGraphNode},
1325 /// represents CSS opacity property as a graph node like the rest of the SVGFE* filters
1326 /// parameters: FilterOpGraphNode
1327 /// SVG filter semantics - selectable input(s), selectable between linear
1328 /// (default) and sRGB color space for calculations
1329 SVGFEOpacity{node: FilterOpGraphNode, valuebinding: PropertyBinding<f32>, value: f32},
1330 /// convert a color image to an alpha channel - internal use; generated by
1331 /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
1332 SVGFEToAlpha{node: FilterOpGraphNode},
1333 /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
1334 /// parameters: FilterOpGraphNode
1335 /// SVG filter semantics - selectable input(s), selectable between linear
1336 /// (default) and sRGB color space for calculations
1337 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
1338 SVGFEBlendDarken{node: FilterOpGraphNode},
1339 /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
1340 /// parameters: FilterOpGraphNode
1341 /// SVG filter semantics - selectable input(s), selectable between linear
1342 /// (default) and sRGB color space for calculations
1343 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
1344 SVGFEBlendLighten{node: FilterOpGraphNode},
1345 /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
1346 /// parameters: FilterOpGraphNode
1347 /// SVG filter semantics - selectable input(s), selectable between linear
1348 /// (default) and sRGB color space for calculations
1349 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
1350 SVGFEBlendMultiply{node: FilterOpGraphNode},
1351 /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
1352 /// parameters: FilterOpGraphNode
1353 /// SVG filter semantics - selectable input(s), selectable between linear
1354 /// (default) and sRGB color space for calculations
1355 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
1356 SVGFEBlendNormal{node: FilterOpGraphNode},
1357 /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
1358 /// parameters: FilterOpGraphNode
1359 /// SVG filter semantics - selectable input(s), selectable between linear
1360 /// (default) and sRGB color space for calculations
1361 /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
1362 SVGFEBlendScreen{node: FilterOpGraphNode},
1363 /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
1364 /// parameters: FilterOpGraphNode
1365 /// SVG filter semantics - selectable input(s), selectable between linear
1366 /// (default) and sRGB color space for calculations
1367 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1368 SVGFEBlendOverlay{node: FilterOpGraphNode},
1369 /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
1370 /// parameters: FilterOpGraphNode
1371 /// SVG filter semantics - selectable input(s), selectable between linear
1372 /// (default) and sRGB color space for calculations
1373 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1374 SVGFEBlendColorDodge{node: FilterOpGraphNode},
1375 /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
1376 /// parameters: FilterOpGraphNode
1377 /// SVG filter semantics - selectable input(s), selectable between linear
1378 /// (default) and sRGB color space for calculations
1379 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1380 SVGFEBlendColorBurn{node: FilterOpGraphNode},
1381 /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
1382 /// parameters: FilterOpGraphNode
1383 /// SVG filter semantics - selectable input(s), selectable between linear
1384 /// (default) and sRGB color space for calculations
1385 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1386 SVGFEBlendHardLight{node: FilterOpGraphNode},
1387 /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
1388 /// parameters: FilterOpGraphNode
1389 /// SVG filter semantics - selectable input(s), selectable between linear
1390 /// (default) and sRGB color space for calculations
1391 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1392 SVGFEBlendSoftLight{node: FilterOpGraphNode},
1393 /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
1394 /// parameters: FilterOpGraphNode
1395 /// SVG filter semantics - selectable input(s), selectable between linear
1396 /// (default) and sRGB color space for calculations
1397 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1398 SVGFEBlendDifference{node: FilterOpGraphNode},
1399 /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
1400 /// parameters: FilterOpGraphNode
1401 /// SVG filter semantics - selectable input(s), selectable between linear
1402 /// (default) and sRGB color space for calculations
1403 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1404 SVGFEBlendExclusion{node: FilterOpGraphNode},
1405 /// combine 2 images with SVG_FEBLEND_MODE_HUE
1406 /// parameters: FilterOpGraphNode
1407 /// SVG filter semantics - selectable input(s), selectable between linear
1408 /// (default) and sRGB color space for calculations
1409 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1410 SVGFEBlendHue{node: FilterOpGraphNode},
1411 /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
1412 /// parameters: FilterOpGraphNode
1413 /// SVG filter semantics - selectable input(s), selectable between linear
1414 /// (default) and sRGB color space for calculations
1415 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1416 SVGFEBlendSaturation{node: FilterOpGraphNode},
1417 /// combine 2 images with SVG_FEBLEND_MODE_COLOR
1418 /// parameters: FilterOpGraphNode
1419 /// SVG filter semantics - selectable input(s), selectable between linear
1420 /// (default) and sRGB color space for calculations
1421 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1422 SVGFEBlendColor{node: FilterOpGraphNode},
1423 /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
1424 /// parameters: FilterOpGraphNode
1425 /// SVG filter semantics - selectable input(s), selectable between linear
1426 /// (default) and sRGB color space for calculations
1427 /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
1428 SVGFEBlendLuminosity{node: FilterOpGraphNode},
1429 /// transform colors of image through 5x4 color matrix (transposed for efficiency)
1430 /// parameters: FilterOpGraphNode, matrix[5][4]
1431 /// SVG filter semantics - selectable input(s), selectable between linear
1432 /// (default) and sRGB color space for calculations
1433 /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
1434 SVGFEColorMatrix{node: FilterOpGraphNode, values: [f32; 20]},
1435 /// transform colors of image through configurable gradients with component swizzle
1436 /// parameters: FilterOpGraphNode, FilterData
1437 /// SVG filter semantics - selectable input(s), selectable between linear
1438 /// (default) and sRGB color space for calculations
1439 /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
1440 SVGFEComponentTransfer{node: FilterOpGraphNode},
1441 /// composite 2 images with chosen composite mode with parameters for that mode
1442 /// parameters: FilterOpGraphNode, k1, k2, k3, k4
1443 /// SVG filter semantics - selectable input(s), selectable between linear
1444 /// (default) and sRGB color space for calculations
1445 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1446 SVGFECompositeArithmetic{node: FilterOpGraphNode, k1: f32, k2: f32, k3: f32,
1447 k4: f32},
1448 /// composite 2 images with chosen composite mode with parameters for that mode
1449 /// parameters: FilterOpGraphNode
1450 /// SVG filter semantics - selectable input(s), selectable between linear
1451 /// (default) and sRGB color space for calculations
1452 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1453 SVGFECompositeATop{node: FilterOpGraphNode},
1454 /// composite 2 images with chosen composite mode with parameters for that mode
1455 /// parameters: FilterOpGraphNode
1456 /// SVG filter semantics - selectable input(s), selectable between linear
1457 /// (default) and sRGB color space for calculations
1458 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1459 SVGFECompositeIn{node: FilterOpGraphNode},
1460 /// composite 2 images with chosen composite mode with parameters for that mode
1461 /// parameters: FilterOpGraphNode
1462 /// SVG filter semantics - selectable input(s), selectable between linear
1463 /// (default) and sRGB color space for calculations
1464 /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
1465 SVGFECompositeLighter{node: FilterOpGraphNode},
1466 /// composite 2 images with chosen composite mode with parameters for that mode
1467 /// parameters: FilterOpGraphNode
1468 /// SVG filter semantics - selectable input(s), selectable between linear
1469 /// (default) and sRGB color space for calculations
1470 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1471 SVGFECompositeOut{node: FilterOpGraphNode},
1472 /// composite 2 images with chosen composite mode with parameters for that mode
1473 /// parameters: FilterOpGraphNode
1474 /// SVG filter semantics - selectable input(s), selectable between linear
1475 /// (default) and sRGB color space for calculations
1476 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1477 SVGFECompositeOver{node: FilterOpGraphNode},
1478 /// composite 2 images with chosen composite mode with parameters for that mode
1479 /// parameters: FilterOpGraphNode
1480 /// SVG filter semantics - selectable input(s), selectable between linear
1481 /// (default) and sRGB color space for calculations
1482 /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
1483 SVGFECompositeXOR{node: FilterOpGraphNode},
1484 /// transform image through convolution matrix of up to 25 values (spec
1485 /// allows more but for performance reasons we do not)
1486 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
1487 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1488 /// preserveAlpha
1489 /// SVG filter semantics - selectable input(s), selectable between linear
1490 /// (default) and sRGB color space for calculations
1491 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1492 SVGFEConvolveMatrixEdgeModeDuplicate{node: FilterOpGraphNode, order_x: i32,
1493 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1494 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1495 preserve_alpha: i32},
1496 /// transform image through convolution matrix of up to 25 values (spec
1497 /// allows more but for performance reasons we do not)
1498 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
1499 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1500 /// preserveAlpha
1501 /// SVG filter semantics - selectable input(s), selectable between linear
1502 /// (default) and sRGB color space for calculations
1503 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1504 SVGFEConvolveMatrixEdgeModeNone{node: FilterOpGraphNode, order_x: i32,
1505 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1506 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1507 preserve_alpha: i32},
1508 /// transform image through convolution matrix of up to 25 values (spec
1509 /// allows more but for performance reasons we do not)
1510 /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
1511 /// divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
1512 /// preserveAlpha
1513 /// SVG filter semantics - selectable input(s), selectable between linear
1514 /// (default) and sRGB color space for calculations
1515 /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
1516 SVGFEConvolveMatrixEdgeModeWrap{node: FilterOpGraphNode, order_x: i32,
1517 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1518 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1519 preserve_alpha: i32},
1520 /// calculate lighting based on heightmap image with provided values for a
1521 /// distant light source with specified direction
1522 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
1523 /// kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
1524 /// SVG filter semantics - selectable input(s), selectable between linear
1525 /// (default) and sRGB color space for calculations
1526 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1527 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
1528 SVGFEDiffuseLightingDistant{node: FilterOpGraphNode, surface_scale: f32,
1529 diffuse_constant: f32, kernel_unit_length_x: f32,
1530 kernel_unit_length_y: f32, azimuth: f32, elevation: f32},
1531 /// calculate lighting based on heightmap image with provided values for a
1532 /// point light source at specified location
1533 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
1534 /// kernelUnitLengthX, kernelUnitLengthY, x, y, z
1535 /// SVG filter semantics - selectable input(s), selectable between linear
1536 /// (default) and sRGB color space for calculations
1537 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1538 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
1539 SVGFEDiffuseLightingPoint{node: FilterOpGraphNode, surface_scale: f32,
1540 diffuse_constant: f32, kernel_unit_length_x: f32,
1541 kernel_unit_length_y: f32, x: f32, y: f32, z: f32},
1542 /// calculate lighting based on heightmap image with provided values for a
1543 /// spot light source at specified location pointing at specified target
1544 /// location with specified hotspot sharpness and cone angle
1545 /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
1546 /// kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
1547 /// pointsAtZ, specularExponent, limitingConeAngle
1548 /// SVG filter semantics - selectable input(s), selectable between linear
1549 /// (default) and sRGB color space for calculations
1550 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
1551 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
1552 SVGFEDiffuseLightingSpot{node: FilterOpGraphNode, surface_scale: f32,
1553 diffuse_constant: f32, kernel_unit_length_x: f32,
1554 kernel_unit_length_y: f32, x: f32, y: f32, z: f32, points_at_x: f32,
1555 points_at_y: f32, points_at_z: f32, cone_exponent: f32,
1556 limiting_cone_angle: f32},
1557 /// calculate a distorted version of first input image using offset values
1558 /// from second input image at specified intensity
1559 /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
1560 /// SVG filter semantics - selectable input(s), selectable between linear
1561 /// (default) and sRGB color space for calculations
1562 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
1563 SVGFEDisplacementMap{node: FilterOpGraphNode, scale: f32,
1564 x_channel_selector: u32, y_channel_selector: u32},
1565 /// create and merge a dropshadow version of the specified image's alpha
1566 /// channel with specified offset and blur radius
1567 /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
1568 /// stdDeviationX, stdDeviationY
1569 /// SVG filter semantics - selectable input(s), selectable between linear
1570 /// (default) and sRGB color space for calculations
1571 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDropShadowElement
1572 SVGFEDropShadow{node: FilterOpGraphNode, color: ColorF, dx: f32, dy: f32,
1573 std_deviation_x: f32, std_deviation_y: f32},
1574 /// synthesize a new image of specified size containing a solid color
1575 /// parameters: FilterOpGraphNode, color
1576 /// SVG filter semantics - selectable input(s), selectable between linear
1577 /// (default) and sRGB color space for calculations
1578 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEFloodElement
1579 SVGFEFlood{node: FilterOpGraphNode, color: ColorF},
1580 /// create a blurred version of the input image
1581 /// parameters: FilterOpGraphNode, stdDeviationX, stdDeviationY
1582 /// SVG filter semantics - selectable input(s), selectable between linear
1583 /// (default) and sRGB color space for calculations
1584 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEGaussianBlurElement
1585 SVGFEGaussianBlur{node: FilterOpGraphNode, std_deviation_x: f32, std_deviation_y: f32},
1586 /// synthesize a new image based on a url (i.e. blob image source)
1587 /// parameters: FilterOpGraphNode, sampling_filter (see SamplingFilter in Types.h), transform
1588 /// SVG filter semantics - selectable input(s), selectable between linear
1589 /// (default) and sRGB color space for calculations
1590 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEImageElement
1591 SVGFEImage{node: FilterOpGraphNode, sampling_filter: u32, matrix: [f32; 6]},
1592 /// create a new image based on the input image with the contour stretched
1593 /// outward (dilate operator)
1594 /// parameters: FilterOpGraphNode, radiusX, radiusY
1595 /// SVG filter semantics - selectable input(s), selectable between linear
1596 /// (default) and sRGB color space for calculations
1597 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
1598 SVGFEMorphologyDilate{node: FilterOpGraphNode, radius_x: f32, radius_y: f32},
1599 /// create a new image based on the input image with the contour shrunken
1600 /// inward (erode operator)
1601 /// parameters: FilterOpGraphNode, radiusX, radiusY
1602 /// SVG filter semantics - selectable input(s), selectable between linear
1603 /// (default) and sRGB color space for calculations
1604 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEMorphologyElement
1605 SVGFEMorphologyErode{node: FilterOpGraphNode, radius_x: f32, radius_y: f32},
1606 /// create a new image that is a scrolled version of the input image, this
1607 /// is basically a no-op as we support offset in the graph node
1608 /// parameters: FilterOpGraphNode
1609 /// SVG filter semantics - selectable input(s), selectable between linear
1610 /// (default) and sRGB color space for calculations
1611 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEOffsetElement
1612 SVGFEOffset{node: FilterOpGraphNode, offset_x: f32, offset_y: f32},
1613 /// calculate lighting based on heightmap image with provided values for a
1614 /// distant light source with specified direction
1615 /// parameters: FilerData, surfaceScale, specularConstant, specularExponent,
1616 /// kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
1617 /// SVG filter semantics - selectable input(s), selectable between linear
1618 /// (default) and sRGB color space for calculations
1619 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1620 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
1621 SVGFESpecularLightingDistant{node: FilterOpGraphNode, surface_scale: f32,
1622 specular_constant: f32, specular_exponent: f32,
1623 kernel_unit_length_x: f32, kernel_unit_length_y: f32, azimuth: f32,
1624 elevation: f32},
1625 /// calculate lighting based on heightmap image with provided values for a
1626 /// point light source at specified location
1627 /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
1628 /// specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z
1629 /// SVG filter semantics - selectable input(s), selectable between linear
1630 /// (default) and sRGB color space for calculations
1631 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1632 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
1633 SVGFESpecularLightingPoint{node: FilterOpGraphNode, surface_scale: f32,
1634 specular_constant: f32, specular_exponent: f32,
1635 kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1636 z: f32},
1637 /// calculate lighting based on heightmap image with provided values for a
1638 /// spot light source at specified location pointing at specified target
1639 /// location with specified hotspot sharpness and cone angle
1640 /// parameters: FilterOpGraphNode, surfaceScale, specularConstant,
1641 /// specularExponent, kernelUnitLengthX, kernelUnitLengthY, x, y, z,
1642 /// pointsAtX, pointsAtY, pointsAtZ, specularExponent, limitingConeAngle
1643 /// SVG filter semantics - selectable input(s), selectable between linear
1644 /// (default) and sRGB color space for calculations
1645 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpecularLightingElement
1646 /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
1647 SVGFESpecularLightingSpot{node: FilterOpGraphNode, surface_scale: f32,
1648 specular_constant: f32, specular_exponent: f32,
1649 kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1650 z: f32, points_at_x: f32, points_at_y: f32, points_at_z: f32,
1651 cone_exponent: f32, limiting_cone_angle: f32},
1652 /// create a new image based on the input image, repeated throughout the
1653 /// output rectangle
1654 /// parameters: FilterOpGraphNode
1655 /// SVG filter semantics - selectable input(s), selectable between linear
1656 /// (default) and sRGB color space for calculations
1657 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETileElement
1658 SVGFETile{node: FilterOpGraphNode},
1659 /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
1660 /// stitching mode
1661 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
1662 /// numOctaves, seed
1663 /// SVG filter semantics - selectable input(s), selectable between linear
1664 /// (default) and sRGB color space for calculations
1665 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1666 SVGFETurbulenceWithFractalNoiseWithNoStitching{node: FilterOpGraphNode,
1667 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1668 seed: u32},
1669 /// synthesize a new image based on Fractal Noise (Perlin) with the chosen
1670 /// stitching mode
1671 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
1672 /// numOctaves, seed
1673 /// SVG filter semantics - selectable input(s), selectable between linear
1674 /// (default) and sRGB color space for calculations
1675 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1676 SVGFETurbulenceWithFractalNoiseWithStitching{node: FilterOpGraphNode,
1677 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1678 seed: u32},
1679 /// synthesize a new image based on Turbulence Noise (offset vectors)
1680 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
1681 /// numOctaves, seed
1682 /// SVG filter semantics - selectable input(s), selectable between linear
1683 /// (default) and sRGB color space for calculations
1684 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1685 SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{node: FilterOpGraphNode,
1686 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1687 seed: u32},
1688 /// synthesize a new image based on Turbulence Noise (offset vectors)
1689 /// parameters: FilterOpGraphNode, baseFrequencyX, baseFrequencyY,
1690 /// numOctaves, seed
1691 /// SVG filter semantics - selectable input(s), selectable between linear
1692 /// (default) and sRGB color space for calculations
1693 /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFETurbulenceElement
1694 SVGFETurbulenceWithTurbulenceNoiseWithStitching{node: FilterOpGraphNode,
1695 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32, seed: u32},
1696}
1697
1698#[repr(u8)]
1699#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
1700pub enum ComponentTransferFuncType {
1701 Identity = 0,
1702 Table = 1,
1703 Discrete = 2,
1704 Linear = 3,
1705 Gamma = 4,
1706}
1707
1708#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
1709pub struct FilterData {
1710 /// ComponentTransfer / SVGFEComponentTransfer
1711 pub func_r_type: ComponentTransferFuncType,
1712 pub r_values: Vec<f32>,
1713 pub func_g_type: ComponentTransferFuncType,
1714 pub g_values: Vec<f32>,
1715 pub func_b_type: ComponentTransferFuncType,
1716 pub b_values: Vec<f32>,
1717 pub func_a_type: ComponentTransferFuncType,
1718 pub a_values: Vec<f32>,
1719}
1720
1721fn sanitize_func_type(
1722 func_type: ComponentTransferFuncType,
1723 values: &[f32],
1724) -> ComponentTransferFuncType {
1725 if values.is_empty() {
1726 return ComponentTransferFuncType::Identity;
1727 }
1728 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1729 return ComponentTransferFuncType::Identity;
1730 }
1731 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1732 return ComponentTransferFuncType::Identity;
1733 }
1734 func_type
1735}
1736
1737fn sanitize_values(
1738 func_type: ComponentTransferFuncType,
1739 values: &[f32],
1740) -> bool {
1741 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1742 return false;
1743 }
1744 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1745 return false;
1746 }
1747 true
1748}
1749
1750impl FilterData {
1751 /// Ensure that the number of values matches up with the function type.
1752 pub fn sanitize(&self) -> FilterData {
1753 FilterData {
1754 func_r_type: sanitize_func_type(self.func_r_type, &self.r_values),
1755 r_values:
1756 if sanitize_values(self.func_r_type, &self.r_values) {
1757 self.r_values.clone()
1758 } else {
1759 Vec::new()
1760 },
1761 func_g_type: sanitize_func_type(self.func_g_type, &self.g_values),
1762 g_values:
1763 if sanitize_values(self.func_g_type, &self.g_values) {
1764 self.g_values.clone()
1765 } else {
1766 Vec::new()
1767 },
1768
1769 func_b_type: sanitize_func_type(self.func_b_type, &self.b_values),
1770 b_values:
1771 if sanitize_values(self.func_b_type, &self.b_values) {
1772 self.b_values.clone()
1773 } else {
1774 Vec::new()
1775 },
1776
1777 func_a_type: sanitize_func_type(self.func_a_type, &self.a_values),
1778 a_values:
1779 if sanitize_values(self.func_a_type, &self.a_values) {
1780 self.a_values.clone()
1781 } else {
1782 Vec::new()
1783 },
1784
1785 }
1786 }
1787
1788 pub fn is_identity(&self) -> bool {
1789 self.func_r_type == ComponentTransferFuncType::Identity &&
1790 self.func_g_type == ComponentTransferFuncType::Identity &&
1791 self.func_b_type == ComponentTransferFuncType::Identity &&
1792 self.func_a_type == ComponentTransferFuncType::Identity
1793 }
1794}
1795
1796#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1797pub struct IframeDisplayItem {
1798 pub bounds: LayoutRect,
1799 pub clip_rect: LayoutRect,
1800 pub space_and_clip: SpaceAndClipInfo,
1801 pub pipeline_id: PipelineId,
1802 pub ignore_missing_pipeline: bool,
1803}
1804
1805/// This describes an image that fills the specified area. It stretches or shrinks
1806/// the image as necessary. While RepeatingImageDisplayItem could otherwise provide
1807/// a superset of the functionality, it has been problematic inferring the desired
1808/// repetition properties when snapping changes the size of the primitive.
1809#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1810pub struct ImageDisplayItem {
1811 pub common: CommonItemProperties,
1812 /// The area to tile the image over (first tile starts at origin of this rect)
1813 // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
1814 // defining the bounds of the item. Needs non-trivial backend changes.
1815 pub bounds: LayoutRect,
1816 pub image_key: ImageKey,
1817 pub image_rendering: ImageRendering,
1818 pub alpha_type: AlphaType,
1819 /// A hack used by gecko to color a simple bitmap font used for tofu glyphs
1820 pub color: ColorF,
1821}
1822
1823/// This describes a background-image and its tiling. It repeats in a grid to fill
1824/// the specified area.
1825#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1826pub struct RepeatingImageDisplayItem {
1827 pub common: CommonItemProperties,
1828 /// The area to tile the image over (first tile starts at origin of this rect)
1829 // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
1830 // defining the bounds of the item. Needs non-trivial backend changes.
1831 pub bounds: LayoutRect,
1832 /// How large to make a single tile of the image (common case: bounds.size)
1833 pub stretch_size: LayoutSize,
1834 /// The space between tiles (common case: 0)
1835 pub tile_spacing: LayoutSize,
1836 pub image_key: ImageKey,
1837 pub image_rendering: ImageRendering,
1838 pub alpha_type: AlphaType,
1839 /// A hack used by gecko to color a simple bitmap font used for tofu glyphs
1840 pub color: ColorF,
1841}
1842
1843#[repr(u8)]
1844#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1845pub enum ImageRendering {
1846 Auto = 0,
1847 CrispEdges = 1,
1848 Pixelated = 2,
1849}
1850
1851#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1852pub enum AlphaType {
1853 Alpha = 0,
1854 PremultipliedAlpha = 1,
1855}
1856
1857#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1858pub struct YuvImageDisplayItem {
1859 pub common: CommonItemProperties,
1860 pub bounds: LayoutRect,
1861 pub yuv_data: YuvData,
1862 pub color_depth: ColorDepth,
1863 pub color_space: YuvColorSpace,
1864 pub color_range: ColorRange,
1865 pub image_rendering: ImageRendering,
1866}
1867
1868#[repr(u8)]
1869#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1870pub enum YuvColorSpace {
1871 Rec601 = 0,
1872 Rec709 = 1,
1873 Rec2020 = 2,
1874 Identity = 3, // aka GBR as per ISO/IEC 23091-2:2019
1875}
1876
1877#[repr(u8)]
1878#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1879pub enum ColorRange {
1880 Limited = 0,
1881 Full = 1,
1882}
1883
1884#[repr(u8)]
1885#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1886pub enum YuvRangedColorSpace {
1887 Rec601Narrow = 0,
1888 Rec601Full = 1,
1889 Rec709Narrow = 2,
1890 Rec709Full = 3,
1891 Rec2020Narrow = 4,
1892 Rec2020Full = 5,
1893 GbrIdentity = 6,
1894}
1895
1896impl YuvColorSpace {
1897 pub fn with_range(self, range: ColorRange) -> YuvRangedColorSpace {
1898 match self {
1899 YuvColorSpace::Identity => YuvRangedColorSpace::GbrIdentity,
1900 YuvColorSpace::Rec601 => {
1901 match range {
1902 ColorRange::Limited => YuvRangedColorSpace::Rec601Narrow,
1903 ColorRange::Full => YuvRangedColorSpace::Rec601Full,
1904 }
1905 }
1906 YuvColorSpace::Rec709 => {
1907 match range {
1908 ColorRange::Limited => YuvRangedColorSpace::Rec709Narrow,
1909 ColorRange::Full => YuvRangedColorSpace::Rec709Full,
1910 }
1911 }
1912 YuvColorSpace::Rec2020 => {
1913 match range {
1914 ColorRange::Limited => YuvRangedColorSpace::Rec2020Narrow,
1915 ColorRange::Full => YuvRangedColorSpace::Rec2020Full,
1916 }
1917 }
1918 }
1919 }
1920}
1921
1922#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1923pub enum YuvData {
1924 NV12(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
1925 P010(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
1926 NV16(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
1927 PlanarYCbCr(ImageKey, ImageKey, ImageKey), // (Y channel, Cb channel, Cr Channel)
1928 InterleavedYCbCr(ImageKey), // (YCbCr interleaved channel)
1929}
1930
1931impl YuvData {
1932 pub fn get_format(&self) -> YuvFormat {
1933 match *self {
1934 YuvData::NV12(..) => YuvFormat::NV12,
1935 YuvData::P010(..) => YuvFormat::P010,
1936 YuvData::NV16(..) => YuvFormat::NV16,
1937 YuvData::PlanarYCbCr(..) => YuvFormat::PlanarYCbCr,
1938 YuvData::InterleavedYCbCr(..) => YuvFormat::InterleavedYCbCr,
1939 }
1940 }
1941}
1942
1943#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1944pub enum YuvFormat {
1945 // These enum values need to be kept in sync with yuv.glsl.
1946 NV12 = 0,
1947 P010 = 1,
1948 NV16 = 2,
1949 PlanarYCbCr = 3,
1950 InterleavedYCbCr = 4,
1951}
1952
1953impl YuvFormat {
1954 pub fn get_plane_num(self) -> usize {
1955 match self {
1956 YuvFormat::NV12 | YuvFormat::P010 | YuvFormat::NV16 => 2,
1957 YuvFormat::PlanarYCbCr => 3,
1958 YuvFormat::InterleavedYCbCr => 1,
1959 }
1960 }
1961}
1962
1963#[repr(C)]
1964#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1965pub struct ImageMask {
1966 pub image: ImageKey,
1967 pub rect: LayoutRect,
1968}
1969
1970impl ImageMask {
1971 /// Get a local clipping rect contributed by this mask.
1972 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
1973 Some(self.rect)
1974 }
1975}
1976
1977#[repr(C)]
1978#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
1979pub enum ClipMode {
1980 Clip, // Pixels inside the region are visible.
1981 ClipOut, // Pixels outside the region are visible.
1982}
1983
1984impl Not for ClipMode {
1985 type Output = ClipMode;
1986
1987 fn not(self) -> ClipMode {
1988 match self {
1989 ClipMode::Clip => ClipMode::ClipOut,
1990 ClipMode::ClipOut => ClipMode::Clip,
1991 }
1992 }
1993}
1994
1995#[repr(C)]
1996#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1997pub struct ComplexClipRegion {
1998 /// The boundaries of the rectangle.
1999 pub rect: LayoutRect,
2000 /// Border radii of this rectangle.
2001 pub radii: BorderRadius,
2002 /// Whether we are clipping inside or outside
2003 /// the region.
2004 pub mode: ClipMode,
2005}
2006
2007impl BorderRadius {
2008 pub fn zero() -> BorderRadius {
2009 BorderRadius {
2010 top_left: LayoutSize::new(0.0, 0.0),
2011 top_right: LayoutSize::new(0.0, 0.0),
2012 bottom_left: LayoutSize::new(0.0, 0.0),
2013 bottom_right: LayoutSize::new(0.0, 0.0),
2014 }
2015 }
2016
2017 pub fn uniform(radius: f32) -> BorderRadius {
2018 BorderRadius {
2019 top_left: LayoutSize::new(radius, radius),
2020 top_right: LayoutSize::new(radius, radius),
2021 bottom_left: LayoutSize::new(radius, radius),
2022 bottom_right: LayoutSize::new(radius, radius),
2023 }
2024 }
2025
2026 pub fn uniform_size(radius: LayoutSize) -> BorderRadius {
2027 BorderRadius {
2028 top_left: radius,
2029 top_right: radius,
2030 bottom_left: radius,
2031 bottom_right: radius,
2032 }
2033 }
2034
2035 pub fn all_sides_uniform(&self) -> bool {
2036 let corner_is_uniform = |corner: &LayoutSize| corner.width == corner.height;
2037 corner_is_uniform(&self.top_left) &&
2038 corner_is_uniform(&self.top_right) &&
2039 corner_is_uniform(&self.bottom_right) &&
2040 corner_is_uniform(&self.bottom_left)
2041 }
2042
2043 pub fn can_use_fast_path_in(&self, rect: &LayoutRect) -> bool {
2044 if !self.all_sides_uniform() {
2045 // The fast path needs uniform sides.
2046 return false;
2047 }
2048 // The shader code that evaluates the rounded corners in the fast path relies on each
2049 // corner fitting into their quadrant of the quad. In other words the radius cannot
2050 // exceed half of the length of the sides they are on. That necessarily holds if all the
2051 // radii are the same.
2052 let tl = self.top_left.width;
2053 if tl == self.bottom_right.width && tl == self.top_right.width && tl == self.bottom_left.width {
2054 return true;
2055 }
2056 let half_size = rect.size() * 0.5;
2057 let fits = |v: f32| v <= half_size.width && v <= half_size.height;
2058 fits(tl) && fits(self.bottom_right.width) && fits(self.top_right.width) && fits(self.bottom_left.width)
2059 }
2060
2061 /// Return whether, in each corner, the radius in *either* direction is zero.
2062 /// This means that none of the corners are rounded.
2063 pub fn is_zero(&self) -> bool {
2064 let corner_is_zero = |corner: &LayoutSize| corner.width == 0.0 || corner.height == 0.0;
2065 corner_is_zero(&self.top_left) &&
2066 corner_is_zero(&self.top_right) &&
2067 corner_is_zero(&self.bottom_right) &&
2068 corner_is_zero(&self.bottom_left)
2069 }
2070}
2071
2072impl ComplexClipRegion {
2073 /// Create a new complex clip region.
2074 pub fn new(
2075 rect: LayoutRect,
2076 radii: BorderRadius,
2077 mode: ClipMode,
2078 ) -> Self {
2079 ComplexClipRegion { rect, radii, mode }
2080 }
2081}
2082
2083impl ComplexClipRegion {
2084 /// Get a local clipping rect contributed by this clip region.
2085 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
2086 match self.mode {
2087 ClipMode::Clip => {
2088 Some(self.rect)
2089 }
2090 ClipMode::ClipOut => {
2091 None
2092 }
2093 }
2094 }
2095}
2096
2097pub const POLYGON_CLIP_VERTEX_MAX: usize = 32;
2098
2099#[repr(u8)]
2100#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
2101pub enum FillRule {
2102 Nonzero = 0x1, // Behaves as the SVG fill-rule definition for nonzero.
2103 Evenodd = 0x2, // Behaves as the SVG fill-rule definition for evenodd.
2104}
2105
2106impl From<u8> for FillRule {
2107 fn from(fill_rule: u8) -> Self {
2108 match fill_rule {
2109 0x1 => FillRule::Nonzero,
2110 0x2 => FillRule::Evenodd,
2111 _ => panic!("Unexpected FillRule value."),
2112 }
2113 }
2114}
2115
2116impl From<FillRule> for u8 {
2117 fn from(fill_rule: FillRule) -> Self {
2118 match fill_rule {
2119 FillRule::Nonzero => 0x1,
2120 FillRule::Evenodd => 0x2,
2121 }
2122 }
2123}
2124
2125#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
2126pub struct ClipChainId(pub u64, pub PipelineId);
2127
2128impl ClipChainId {
2129 pub const INVALID: Self = ClipChainId(!0, PipelineId::INVALID);
2130}
2131
2132/// A reference to a clipping node defining how an item is clipped.
2133#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
2134pub struct ClipId(pub usize, pub PipelineId);
2135
2136impl Default for ClipId {
2137 fn default() -> Self {
2138 ClipId::invalid()
2139 }
2140}
2141
2142const ROOT_CLIP_ID: usize = 0;
2143
2144impl ClipId {
2145 /// Return the root clip ID - effectively doing no clipping.
2146 pub fn root(pipeline_id: PipelineId) -> Self {
2147 ClipId(ROOT_CLIP_ID, pipeline_id)
2148 }
2149
2150 /// Return an invalid clip ID - needed in places where we carry
2151 /// one but need to not attempt to use it.
2152 pub fn invalid() -> Self {
2153 ClipId(!0, PipelineId::dummy())
2154 }
2155
2156 pub fn pipeline_id(&self) -> PipelineId {
2157 match *self {
2158 ClipId(_, pipeline_id) => pipeline_id,
2159 }
2160 }
2161
2162 pub fn is_root(&self) -> bool {
2163 match *self {
2164 ClipId(id, _) => id == ROOT_CLIP_ID,
2165 }
2166 }
2167
2168 pub fn is_valid(&self) -> bool {
2169 match *self {
2170 ClipId(id, _) => id != !0,
2171 }
2172 }
2173}
2174
2175/// A reference to a spatial node defining item positioning.
2176#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
2177pub struct SpatialId(pub usize, PipelineId);
2178
2179const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
2180const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
2181
2182impl SpatialId {
2183 pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
2184 SpatialId(spatial_node_index, pipeline_id)
2185 }
2186
2187 pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
2188 SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
2189 }
2190
2191 pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
2192 SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
2193 }
2194
2195 pub fn pipeline_id(&self) -> PipelineId {
2196 self.1
2197 }
2198}
2199
2200/// An external identifier that uniquely identifies a scroll frame independent of its ClipId, which
2201/// may change from frame to frame. This should be unique within a pipeline. WebRender makes no
2202/// attempt to ensure uniqueness. The zero value is reserved for use by the root scroll node of
2203/// every pipeline, which always has an external id.
2204///
2205/// When setting display lists with the `preserve_frame_state` this id is used to preserve scroll
2206/// offsets between different sets of SpatialNodes which are ScrollFrames.
2207#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
2208#[repr(C)]
2209pub struct ExternalScrollId(pub u64, pub PipelineId);
2210
2211impl ExternalScrollId {
2212 pub fn pipeline_id(&self) -> PipelineId {
2213 self.1
2214 }
2215
2216 pub fn is_root(&self) -> bool {
2217 self.0 == 0
2218 }
2219}
2220
2221impl DisplayItem {
2222 pub fn debug_name(&self) -> &'static str {
2223 match *self {
2224 DisplayItem::Border(..) => "border",
2225 DisplayItem::BoxShadow(..) => "box_shadow",
2226 DisplayItem::HitTest(..) => "hit_test",
2227 DisplayItem::RectClip(..) => "rect_clip",
2228 DisplayItem::RoundedRectClip(..) => "rounded_rect_clip",
2229 DisplayItem::ImageMaskClip(..) => "image_mask_clip",
2230 DisplayItem::ClipChain(..) => "clip_chain",
2231 DisplayItem::ConicGradient(..) => "conic_gradient",
2232 DisplayItem::Gradient(..) => "gradient",
2233 DisplayItem::Iframe(..) => "iframe",
2234 DisplayItem::Image(..) => "image",
2235 DisplayItem::RepeatingImage(..) => "repeating_image",
2236 DisplayItem::Line(..) => "line",
2237 DisplayItem::PopAllShadows => "pop_all_shadows",
2238 DisplayItem::PopReferenceFrame => "pop_reference_frame",
2239 DisplayItem::PopStackingContext => "pop_stacking_context",
2240 DisplayItem::PushShadow(..) => "push_shadow",
2241 DisplayItem::PushReferenceFrame(..) => "push_reference_frame",
2242 DisplayItem::PushStackingContext(..) => "push_stacking_context",
2243 DisplayItem::SetFilterOps => "set_filter_ops",
2244 DisplayItem::SetFilterData => "set_filter_data",
2245 DisplayItem::SetPoints => "set_points",
2246 DisplayItem::RadialGradient(..) => "radial_gradient",
2247 DisplayItem::Rectangle(..) => "rectangle",
2248 DisplayItem::SetGradientStops => "set_gradient_stops",
2249 DisplayItem::Text(..) => "text",
2250 DisplayItem::YuvImage(..) => "yuv_image",
2251 DisplayItem::BackdropFilter(..) => "backdrop_filter",
2252 DisplayItem::DebugMarker(..) => "debug",
2253 }
2254 }
2255}
2256
2257macro_rules! impl_default_for_enums {
2258 ($($enum:ident => $init:expr ),+) => {
2259 $(impl Default for $enum {
2260 #[allow(unused_imports)]
2261 fn default() -> Self {
2262 use $enum::*;
2263 $init
2264 }
2265 })*
2266 }
2267}
2268
2269impl_default_for_enums! {
2270 DisplayItem => PopStackingContext,
2271 LineOrientation => Vertical,
2272 LineStyle => Solid,
2273 RepeatMode => Stretch,
2274 NinePatchBorderSource => Image(ImageKey::default(), ImageRendering::Auto),
2275 BorderDetails => Normal(NormalBorder::default()),
2276 BorderRadiusKind => Uniform,
2277 BorderStyle => None,
2278 BoxShadowClipMode => Outset,
2279 ExtendMode => Clamp,
2280 FilterOp => Identity,
2281 ComponentTransferFuncType => Identity,
2282 ClipMode => Clip,
2283 FillRule => Nonzero,
2284 ReferenceFrameKind => Transform {
2285 is_2d_scale_translation: false,
2286 should_snap: false,
2287 paired_with_perspective: false,
2288 },
2289 Rotation => Degree0,
2290 TransformStyle => Flat,
2291 RasterSpace => Local(f32::default()),
2292 MixBlendMode => Normal,
2293 ImageRendering => Auto,
2294 AlphaType => Alpha,
2295 YuvColorSpace => Rec601,
2296 YuvRangedColorSpace => Rec601Narrow,
2297 ColorRange => Limited,
2298 YuvData => NV12(ImageKey::default(), ImageKey::default()),
2299 YuvFormat => NV12,
2300 FilterPrimitiveInput => Original,
2301 ColorSpace => Srgb,
2302 CompositeOperator => Over
2303}