1use euclid::{SideOffsets2D, Angle};
6use peek_poke::PeekPoke;
7use std::ops::Not;
8use 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
17pub type ItemTag = (u64, u16);
33
34pub type ItemKey = u16;
37
38#[repr(C)]
39#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
40pub struct PrimitiveFlags(u8);
41
42bitflags! {
43 impl PrimitiveFlags: u8 {
44 const IS_BACKFACE_VISIBLE = 1 << 0;
46 const IS_SCROLLBAR_CONTAINER = 1 << 1;
48 const PREFER_COMPOSITOR_SURFACE = 1 << 2;
52 const SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE = 1 << 3;
56 const ANTIALISED = 1 << 4;
58 const CHECKERBOARD_BACKGROUND = 1 << 5;
60 }
61}
62
63impl core::fmt::Debug for PrimitiveFlags {
64 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
65 if self.is_empty() {
66 write!(f, "{:#x}", Self::empty().bits())
67 } else {
68 bitflags::parser::to_writer(self, f)
69 }
70 }
71}
72
73impl Default for PrimitiveFlags {
74 fn default() -> Self {
75 PrimitiveFlags::IS_BACKFACE_VISIBLE
76 }
77}
78
79#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
82pub struct CommonItemProperties {
83 pub clip_rect: LayoutRect,
87 pub clip_chain_id: ClipChainId,
89 pub spatial_id: SpatialId,
91 pub flags: PrimitiveFlags,
93}
94
95impl CommonItemProperties {
96 pub fn new(
98 clip_rect: LayoutRect,
99 space_and_clip: SpaceAndClipInfo,
100 ) -> Self {
101 Self {
102 clip_rect,
103 spatial_id: space_and_clip.spatial_id,
104 clip_chain_id: space_and_clip.clip_chain_id,
105 flags: PrimitiveFlags::default(),
106 }
107 }
108}
109
110#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
117pub struct SpaceAndClipInfo {
118 pub spatial_id: SpatialId,
119 pub clip_chain_id: ClipChainId,
120}
121
122impl SpaceAndClipInfo {
123 pub fn root_scroll(pipeline_id: PipelineId) -> Self {
126 SpaceAndClipInfo {
127 spatial_id: SpatialId::root_scroll_node(pipeline_id),
128 clip_chain_id: ClipChainId::INVALID,
129 }
130 }
131}
132
133#[repr(C)]
138#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke, Default, Eq, Hash)]
139pub struct SpatialTreeItemKey {
140 key0: u64,
141 key1: u64,
142}
143
144impl SpatialTreeItemKey {
145 pub fn new(key0: u64, key1: u64) -> Self {
146 SpatialTreeItemKey {
147 key0,
148 key1,
149 }
150 }
151}
152
153#[repr(u8)]
154#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
155pub enum SpatialTreeItem {
156 ScrollFrame(ScrollFrameDescriptor),
157 ReferenceFrame(ReferenceFrameDescriptor),
158 StickyFrame(StickyFrameDescriptor),
159 Invalid,
160}
161
162#[repr(u8)]
163#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
164pub enum DisplayItem {
165 Rectangle(RectangleDisplayItem),
167 ClearRectangle(ClearRectangleDisplayItem),
168 HitTest(HitTestDisplayItem),
169 Text(TextDisplayItem),
170 Line(LineDisplayItem),
171 Border(BorderDisplayItem),
172 BoxShadow(BoxShadowDisplayItem),
173 PushShadow(PushShadowDisplayItem),
174 Gradient(GradientDisplayItem),
175 RadialGradient(RadialGradientDisplayItem),
176 ConicGradient(ConicGradientDisplayItem),
177 Image(ImageDisplayItem),
178 RepeatingImage(RepeatingImageDisplayItem),
179 YuvImage(YuvImageDisplayItem),
180 BackdropFilter(BackdropFilterDisplayItem),
181
182 RectClip(RectClipDisplayItem),
184 RoundedRectClip(RoundedRectClipDisplayItem),
185 ImageMaskClip(ImageMaskClipDisplayItem),
186 ClipChain(ClipChainItem),
187
188 Iframe(IframeDisplayItem),
190 PushReferenceFrame(ReferenceFrameDisplayListItem),
191 PushStackingContext(PushStackingContextDisplayItem),
192
193 SetGradientStops,
196 SetFilterOps,
197 SetFilterData,
198 SetFilterPrimitives,
199 SetPoints,
200
201 PopReferenceFrame,
203 PopStackingContext,
204 PopAllShadows,
205
206 ReuseItems(ItemKey),
207 RetainedItems(ItemKey),
208
209 DebugMarker(u32),
211}
212
213#[cfg(any(feature = "serialize", feature = "deserialize"))]
216#[cfg_attr(feature = "serialize", derive(Serialize))]
217#[cfg_attr(feature = "deserialize", derive(Deserialize))]
218pub enum DebugDisplayItem {
219 Rectangle(RectangleDisplayItem),
220 ClearRectangle(ClearRectangleDisplayItem),
221 HitTest(HitTestDisplayItem),
222 Text(TextDisplayItem, Vec<font::GlyphInstance>),
223 Line(LineDisplayItem),
224 Border(BorderDisplayItem),
225 BoxShadow(BoxShadowDisplayItem),
226 PushShadow(PushShadowDisplayItem),
227 Gradient(GradientDisplayItem),
228 RadialGradient(RadialGradientDisplayItem),
229 ConicGradient(ConicGradientDisplayItem),
230 Image(ImageDisplayItem),
231 RepeatingImage(RepeatingImageDisplayItem),
232 YuvImage(YuvImageDisplayItem),
233 BackdropFilter(BackdropFilterDisplayItem),
234
235 ImageMaskClip(ImageMaskClipDisplayItem),
236 RoundedRectClip(RoundedRectClipDisplayItem),
237 RectClip(RectClipDisplayItem),
238 ClipChain(ClipChainItem, Vec<ClipId>),
239
240 Iframe(IframeDisplayItem),
241 PushReferenceFrame(ReferenceFrameDisplayListItem),
242 PushStackingContext(PushStackingContextDisplayItem),
243
244 SetGradientStops(Vec<GradientStop>),
245 SetFilterOps(Vec<FilterOp>),
246 SetFilterData(FilterData),
247 SetFilterPrimitives(Vec<FilterPrimitive>),
248 SetPoints(Vec<LayoutPoint>),
249
250 PopReferenceFrame,
251 PopStackingContext,
252 PopAllShadows,
253
254 DebugMarker(u32)
255}
256
257#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
258pub struct ImageMaskClipDisplayItem {
259 pub id: ClipId,
260 pub spatial_id: SpatialId,
261 pub image_mask: ImageMask,
262 pub fill_rule: FillRule,
263} #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
266pub struct RectClipDisplayItem {
267 pub id: ClipId,
268 pub spatial_id: SpatialId,
269 pub clip_rect: LayoutRect,
270}
271
272#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
273pub struct RoundedRectClipDisplayItem {
274 pub id: ClipId,
275 pub spatial_id: SpatialId,
276 pub clip: ComplexClipRegion,
277}
278
279#[repr(C)]
281#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
282pub struct StickyOffsetBounds {
283 pub min: f32,
287
288 pub max: f32,
292}
293
294impl StickyOffsetBounds {
295 pub fn new(min: f32, max: f32) -> StickyOffsetBounds {
296 StickyOffsetBounds { min, max }
297 }
298}
299
300#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
301pub struct StickyFrameDescriptor {
302 pub id: SpatialId,
303 pub parent_spatial_id: SpatialId,
304 pub bounds: LayoutRect,
305
306 pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
310
311 pub vertical_offset_bounds: StickyOffsetBounds,
316
317 pub horizontal_offset_bounds: StickyOffsetBounds,
322
323 pub previously_applied_offset: LayoutVector2D,
329
330 pub key: SpatialTreeItemKey,
332
333 pub transform: Option<PropertyBinding<LayoutTransform>>,
335}
336
337#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
338pub struct ScrollFrameDescriptor {
339 pub scroll_frame_id: SpatialId,
341 pub content_rect: LayoutRect,
344 pub frame_rect: LayoutRect,
345 pub parent_space: SpatialId,
346 pub external_id: ExternalScrollId,
347 pub external_scroll_offset: LayoutVector2D,
353 pub scroll_offset_generation: APZScrollGeneration,
355 pub has_scroll_linked_effect: HasScrollLinkedEffect,
357 pub key: SpatialTreeItemKey,
359}
360
361#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
363pub struct RectangleDisplayItem {
364 pub common: CommonItemProperties,
365 pub bounds: LayoutRect,
366 pub color: PropertyBinding<ColorF>,
367}
368
369#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
372pub struct ClearRectangleDisplayItem {
373 pub common: CommonItemProperties,
374 pub bounds: LayoutRect,
375}
376
377#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
381pub struct HitTestDisplayItem {
382 pub rect: LayoutRect,
383 pub clip_chain_id: ClipChainId,
384 pub spatial_id: SpatialId,
385 pub flags: PrimitiveFlags,
386 pub tag: ItemTag,
387}
388
389#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
390pub struct LineDisplayItem {
391 pub common: CommonItemProperties,
392 pub area: LayoutRect,
398 pub orientation: LineOrientation,
400 pub wavy_line_thickness: f32,
406 pub color: ColorF,
407 pub style: LineStyle,
408}
409
410#[repr(u8)]
411#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
412pub enum LineOrientation {
413 Vertical,
414 Horizontal,
415}
416
417#[repr(u8)]
418#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
419pub enum LineStyle {
420 Solid,
421 Dotted,
422 Dashed,
423 Wavy,
424}
425
426#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
427pub struct TextDisplayItem {
428 pub common: CommonItemProperties,
429 pub bounds: LayoutRect,
437 pub font_key: font::FontInstanceKey,
438 pub color: ColorF,
439 pub glyph_options: Option<font::GlyphOptions>,
440 pub ref_frame_offset: LayoutVector2D,
441} #[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
444pub struct NormalBorder {
445 pub left: BorderSide,
446 pub right: BorderSide,
447 pub top: BorderSide,
448 pub bottom: BorderSide,
449 pub radius: BorderRadius,
450 pub do_aa: bool,
455}
456
457impl NormalBorder {
458 fn can_disable_antialiasing(&self) -> bool {
459 fn is_valid(style: BorderStyle) -> bool {
460 style == BorderStyle::Solid || style == BorderStyle::None
461 }
462
463 self.radius.is_zero() &&
464 is_valid(self.top.style) &&
465 is_valid(self.left.style) &&
466 is_valid(self.bottom.style) &&
467 is_valid(self.right.style)
468 }
469
470 #[inline]
473 pub fn normalize(&mut self, widths: &LayoutSideOffsets) {
474 debug_assert!(
475 self.do_aa || self.can_disable_antialiasing(),
476 "Unexpected disabled-antialiasing in a border, likely won't work or will be ignored"
477 );
478
479 #[inline]
480 fn renders_small_border_solid(style: BorderStyle) -> bool {
481 match style {
482 BorderStyle::Groove |
483 BorderStyle::Ridge => true,
484 _ => false,
485 }
486 }
487
488 let normalize_side = |side: &mut BorderSide, width: f32| {
489 if renders_small_border_solid(side.style) && width < 2. {
490 side.style = BorderStyle::Solid;
491 }
492 };
493
494 normalize_side(&mut self.left, widths.left);
495 normalize_side(&mut self.right, widths.right);
496 normalize_side(&mut self.top, widths.top);
497 normalize_side(&mut self.bottom, widths.bottom);
498 }
499}
500
501#[repr(u8)]
502#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
503pub enum RepeatMode {
504 Stretch,
505 Repeat,
506 Round,
507 Space,
508}
509
510#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
511pub enum NinePatchBorderSource {
512 Image(ImageKey, ImageRendering),
513 Gradient(Gradient),
514 RadialGradient(RadialGradient),
515 ConicGradient(ConicGradient),
516}
517
518#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
519pub struct NinePatchBorder {
520 pub source: NinePatchBorderSource,
523
524 pub width: i32,
526
527 pub height: i32,
529
530 pub slice: DeviceIntSideOffsets,
538
539 pub fill: bool,
542
543 pub repeat_horizontal: RepeatMode,
546
547 pub repeat_vertical: RepeatMode,
550}
551
552#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
553pub enum BorderDetails {
554 Normal(NormalBorder),
555 NinePatch(NinePatchBorder),
556}
557
558#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
559pub struct BorderDisplayItem {
560 pub common: CommonItemProperties,
561 pub bounds: LayoutRect,
562 pub widths: LayoutSideOffsets,
563 pub details: BorderDetails,
564}
565
566#[repr(C)]
567#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
568pub enum BorderRadiusKind {
569 Uniform,
570 NonUniform,
571}
572
573#[repr(C)]
574#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
575pub struct BorderRadius {
576 pub top_left: LayoutSize,
577 pub top_right: LayoutSize,
578 pub bottom_left: LayoutSize,
579 pub bottom_right: LayoutSize,
580}
581
582impl Default for BorderRadius {
583 fn default() -> Self {
584 BorderRadius {
585 top_left: LayoutSize::zero(),
586 top_right: LayoutSize::zero(),
587 bottom_left: LayoutSize::zero(),
588 bottom_right: LayoutSize::zero(),
589 }
590 }
591}
592
593#[repr(C)]
594#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
595pub struct BorderSide {
596 pub color: ColorF,
597 pub style: BorderStyle,
598}
599
600#[repr(u32)]
601#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq, PeekPoke)]
602pub enum BorderStyle {
603 None = 0,
604 Solid = 1,
605 Double = 2,
606 Dotted = 3,
607 Dashed = 4,
608 Hidden = 5,
609 Groove = 6,
610 Ridge = 7,
611 Inset = 8,
612 Outset = 9,
613}
614
615impl BorderStyle {
616 pub fn is_hidden(self) -> bool {
617 self == BorderStyle::Hidden || self == BorderStyle::None
618 }
619}
620
621#[repr(u8)]
622#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
623pub enum BoxShadowClipMode {
624 Outset = 0,
625 Inset = 1,
626}
627
628#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
629pub struct BoxShadowDisplayItem {
630 pub common: CommonItemProperties,
631 pub box_bounds: LayoutRect,
632 pub offset: LayoutVector2D,
633 pub color: ColorF,
634 pub blur_radius: f32,
635 pub spread_radius: f32,
636 pub border_radius: BorderRadius,
637 pub clip_mode: BoxShadowClipMode,
638}
639
640#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
641pub struct PushShadowDisplayItem {
642 pub space_and_clip: SpaceAndClipInfo,
643 pub shadow: Shadow,
644 pub should_inflate: bool,
645}
646
647#[repr(C)]
648#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
649pub struct Shadow {
650 pub offset: LayoutVector2D,
651 pub color: ColorF,
652 pub blur_radius: f32,
653}
654
655#[repr(u8)]
656#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
657pub enum ExtendMode {
658 Clamp,
659 Repeat,
660}
661
662#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
663pub struct Gradient {
664 pub start_point: LayoutPoint,
665 pub end_point: LayoutPoint,
666 pub extend_mode: ExtendMode,
667} impl Gradient {
670 pub fn is_valid(&self) -> bool {
671 self.start_point.x.is_finite() &&
672 self.start_point.y.is_finite() &&
673 self.end_point.x.is_finite() &&
674 self.end_point.y.is_finite()
675 }
676}
677
678#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
680pub struct GradientDisplayItem {
681 pub common: CommonItemProperties,
683 pub bounds: LayoutRect,
687 pub tile_size: LayoutSize,
689 pub tile_spacing: LayoutSize,
691 pub gradient: Gradient,
692}
693
694#[repr(C)]
695#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
696pub struct GradientStop {
697 pub offset: f32,
698 pub color: ColorF,
699}
700
701#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
702pub struct RadialGradient {
703 pub center: LayoutPoint,
704 pub radius: LayoutSize,
705 pub start_offset: f32,
706 pub end_offset: f32,
707 pub extend_mode: ExtendMode,
708} impl RadialGradient {
711 pub fn is_valid(&self) -> bool {
712 self.center.x.is_finite() &&
713 self.center.y.is_finite() &&
714 self.start_offset.is_finite() &&
715 self.end_offset.is_finite()
716 }
717}
718
719#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
720pub struct ConicGradient {
721 pub center: LayoutPoint,
722 pub angle: f32,
723 pub start_offset: f32,
724 pub end_offset: f32,
725 pub extend_mode: ExtendMode,
726} impl ConicGradient {
729 pub fn is_valid(&self) -> bool {
730 self.center.x.is_finite() &&
731 self.center.y.is_finite() &&
732 self.angle.is_finite() &&
733 self.start_offset.is_finite() &&
734 self.end_offset.is_finite()
735 }
736}
737
738#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
740pub struct ClipChainItem {
741 pub id: ClipChainId,
742 pub parent: Option<ClipChainId>,
743} #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
746pub struct RadialGradientDisplayItem {
747 pub common: CommonItemProperties,
748 pub bounds: LayoutRect,
752 pub gradient: RadialGradient,
753 pub tile_size: LayoutSize,
754 pub tile_spacing: LayoutSize,
755}
756
757#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
758pub struct ConicGradientDisplayItem {
759 pub common: CommonItemProperties,
760 pub bounds: LayoutRect,
764 pub gradient: ConicGradient,
765 pub tile_size: LayoutSize,
766 pub tile_spacing: LayoutSize,
767}
768
769#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
771pub struct BackdropFilterDisplayItem {
772 pub common: CommonItemProperties,
773}
774#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
777pub struct ReferenceFrameDisplayListItem {
778}
779
780#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
781pub struct ReferenceFrameDescriptor {
782 pub origin: LayoutPoint,
783 pub parent_spatial_id: SpatialId,
784 pub reference_frame: ReferenceFrame,
785}
786
787#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
788pub enum ReferenceFrameKind {
789 Transform {
791 is_2d_scale_translation: bool,
794 should_snap: bool,
797 paired_with_perspective: bool,
801 },
802 Perspective {
804 scrolling_relative_to: Option<ExternalScrollId>,
805 }
806}
807
808#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
809pub enum Rotation {
810 Degree0,
811 Degree90,
812 Degree180,
813 Degree270,
814}
815
816impl Rotation {
817 pub fn to_matrix(
818 &self,
819 size: LayoutSize,
820 ) -> LayoutTransform {
821 let (shift_center_to_origin, angle) = match self {
822 Rotation::Degree0 => {
823 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(0.))
824 },
825 Rotation::Degree90 => {
826 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(90.))
827 },
828 Rotation::Degree180 => {
829 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(180.))
830 },
831 Rotation::Degree270 => {
832 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(270.))
833 },
834 };
835 let shift_origin_to_center = LayoutTransform::translation(size.width / 2., size.height / 2., 0.);
836
837 shift_center_to_origin
838 .then(&LayoutTransform::rotation(0., 0., 1.0, angle))
839 .then(&shift_origin_to_center)
840 }
841}
842
843#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
844pub enum ReferenceTransformBinding {
845 Static {
847 binding: PropertyBinding<LayoutTransform>,
848 },
849 Computed {
858 scale_from: Option<LayoutSize>,
859 vertical_flip: bool,
860 rotation: Rotation,
861 },
862}
863
864impl Default for ReferenceTransformBinding {
865 fn default() -> Self {
866 ReferenceTransformBinding::Static {
867 binding: Default::default(),
868 }
869 }
870}
871
872#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
873pub struct ReferenceFrame {
874 pub kind: ReferenceFrameKind,
875 pub transform_style: TransformStyle,
876 pub transform: ReferenceTransformBinding,
879 pub id: SpatialId,
880 pub key: SpatialTreeItemKey,
882}
883
884#[repr(C)]
897#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
898pub struct SnapshotInfo {
899 pub key: SnapshotImageKey,
901 pub area: LayoutRect,
906 pub detached: bool,
911}
912
913#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
914pub struct PushStackingContextDisplayItem {
915 pub origin: LayoutPoint,
916 pub spatial_id: SpatialId,
917 pub snapshot: Option<SnapshotInfo>,
918 pub prim_flags: PrimitiveFlags,
919 pub ref_frame_offset: LayoutVector2D,
920 pub stacking_context: StackingContext,
921}
922
923#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
924pub struct StackingContext {
925 pub transform_style: TransformStyle,
926 pub mix_blend_mode: MixBlendMode,
927 pub clip_chain_id: Option<ClipChainId>,
928 pub raster_space: RasterSpace,
929 pub flags: StackingContextFlags,
930}
931#[repr(u8)]
934#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
935pub enum TransformStyle {
936 Flat = 0,
937 Preserve3D = 1,
938}
939
940#[derive(Clone, Copy, Debug, Deserialize, PartialEq, MallocSizeOf, Serialize, PeekPoke)]
947#[repr(u8)]
948pub enum RasterSpace {
949 Local(f32),
952
953 Screen,
958}
959
960impl RasterSpace {
961 pub fn local_scale(self) -> Option<f32> {
962 match self {
963 RasterSpace::Local(scale) => Some(scale),
964 RasterSpace::Screen => None,
965 }
966 }
967}
968
969impl Eq for RasterSpace {}
970
971impl Hash for RasterSpace {
972 fn hash<H: Hasher>(&self, state: &mut H) {
973 match self {
974 RasterSpace::Screen => {
975 0.hash(state);
976 }
977 RasterSpace::Local(scale) => {
978 1.hash(state);
980 scale.to_bits().hash(state);
981 }
982 }
983 }
984}
985
986#[repr(C)]
987#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
988pub struct StackingContextFlags(u8);
989
990bitflags! {
991 impl StackingContextFlags: u8 {
992 const IS_BLEND_CONTAINER = 1 << 0;
995 const WRAPS_BACKDROP_FILTER = 1 << 1;
999 }
1000}
1001
1002impl core::fmt::Debug for StackingContextFlags {
1003 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1004 if self.is_empty() {
1005 write!(f, "{:#x}", Self::empty().bits())
1006 } else {
1007 bitflags::parser::to_writer(self, f)
1008 }
1009 }
1010}
1011
1012impl Default for StackingContextFlags {
1013 fn default() -> Self {
1014 StackingContextFlags::empty()
1015 }
1016}
1017
1018#[repr(u8)]
1019#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1020pub enum MixBlendMode {
1021 Normal = 0,
1022 Multiply = 1,
1023 Screen = 2,
1024 Overlay = 3,
1025 Darken = 4,
1026 Lighten = 5,
1027 ColorDodge = 6,
1028 ColorBurn = 7,
1029 HardLight = 8,
1030 SoftLight = 9,
1031 Difference = 10,
1032 Exclusion = 11,
1033 Hue = 12,
1034 Saturation = 13,
1035 Color = 14,
1036 Luminosity = 15,
1037 PlusLighter = 16,
1038}
1039
1040#[repr(C)]
1041#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1042pub enum ColorSpace {
1043 Srgb,
1044 LinearRgb,
1045}
1046
1047#[repr(C)]
1049#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1050pub enum CompositeOperator {
1051 Over,
1052 In,
1053 Atop,
1054 Out,
1055 Xor,
1056 Lighter,
1057 Arithmetic([f32; 4]),
1058}
1059
1060impl CompositeOperator {
1061 pub fn as_int(&self) -> u32 {
1063 match self {
1064 CompositeOperator::Over => 0,
1065 CompositeOperator::In => 1,
1066 CompositeOperator::Out => 2,
1067 CompositeOperator::Atop => 3,
1068 CompositeOperator::Xor => 4,
1069 CompositeOperator::Lighter => 5,
1070 CompositeOperator::Arithmetic(..) => 6,
1071 }
1072 }
1073}
1074
1075#[repr(C)]
1077#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1078pub enum FilterPrimitiveInput {
1079 Original,
1081 Previous,
1083 OutputOfPrimitiveIndex(usize),
1085}
1086
1087impl FilterPrimitiveInput {
1088 pub fn to_index(self, cur_index: usize) -> Option<usize> {
1091 match self {
1092 FilterPrimitiveInput::Previous if cur_index > 0 => Some(cur_index - 1),
1093 FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => Some(index),
1094 _ => None,
1095 }
1096 }
1097}
1098
1099#[repr(C)]
1100#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1101pub struct BlendPrimitive {
1102 pub input1: FilterPrimitiveInput,
1103 pub input2: FilterPrimitiveInput,
1104 pub mode: MixBlendMode,
1105}
1106
1107#[repr(C)]
1108#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1109pub struct FloodPrimitive {
1110 pub color: ColorF,
1111}
1112
1113impl FloodPrimitive {
1114 pub fn sanitize(&mut self) {
1115 self.color.r = self.color.r.clamp(0.0, 1.0);
1116 self.color.g = self.color.g.clamp(0.0, 1.0);
1117 self.color.b = self.color.b.clamp(0.0, 1.0);
1118 self.color.a = self.color.a.clamp(0.0, 1.0);
1119 }
1120}
1121
1122#[repr(C)]
1123#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1124pub struct BlurPrimitive {
1125 pub input: FilterPrimitiveInput,
1126 pub width: f32,
1127 pub height: f32,
1128}
1129
1130#[repr(C)]
1131#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1132pub struct OpacityPrimitive {
1133 pub input: FilterPrimitiveInput,
1134 pub opacity: f32,
1135}
1136
1137impl OpacityPrimitive {
1138 pub fn sanitize(&mut self) {
1139 self.opacity = self.opacity.clamp(0.0, 1.0);
1140 }
1141}
1142
1143#[repr(C)]
1145#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1146pub struct ColorMatrixPrimitive {
1147 pub input: FilterPrimitiveInput,
1148 pub matrix: [f32; 20],
1149}
1150
1151#[repr(C)]
1152#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1153pub struct DropShadowPrimitive {
1154 pub input: FilterPrimitiveInput,
1155 pub shadow: Shadow,
1156}
1157
1158#[repr(C)]
1159#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1160pub struct ComponentTransferPrimitive {
1161 pub input: FilterPrimitiveInput,
1162 }
1164
1165#[repr(C)]
1166#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1167pub struct IdentityPrimitive {
1168 pub input: FilterPrimitiveInput,
1169}
1170
1171#[repr(C)]
1172#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1173pub struct OffsetPrimitive {
1174 pub input: FilterPrimitiveInput,
1175 pub offset: LayoutVector2D,
1176}
1177
1178#[repr(C)]
1179#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1180pub struct CompositePrimitive {
1181 pub input1: FilterPrimitiveInput,
1182 pub input2: FilterPrimitiveInput,
1183 pub operator: CompositeOperator,
1184}
1185
1186#[repr(C)]
1189#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
1190pub enum FilterPrimitiveKind {
1191 Identity(IdentityPrimitive),
1192 Blend(BlendPrimitive),
1193 Flood(FloodPrimitive),
1194 Blur(BlurPrimitive),
1195 Opacity(OpacityPrimitive),
1197 ColorMatrix(ColorMatrixPrimitive),
1199 DropShadow(DropShadowPrimitive),
1200 ComponentTransfer(ComponentTransferPrimitive),
1201 Offset(OffsetPrimitive),
1202 Composite(CompositePrimitive),
1203}
1204
1205impl Default for FilterPrimitiveKind {
1206 fn default() -> Self {
1207 FilterPrimitiveKind::Identity(IdentityPrimitive::default())
1208 }
1209}
1210
1211impl FilterPrimitiveKind {
1212 pub fn sanitize(&mut self) {
1213 match self {
1214 FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
1215 FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
1216
1217 FilterPrimitiveKind::Identity(..) |
1219 FilterPrimitiveKind::Blend(..) |
1220 FilterPrimitiveKind::ColorMatrix(..) |
1221 FilterPrimitiveKind::Offset(..) |
1222 FilterPrimitiveKind::Composite(..) |
1223 FilterPrimitiveKind::Blur(..) |
1224 FilterPrimitiveKind::DropShadow(..) |
1225 FilterPrimitiveKind::ComponentTransfer(..) => {}
1227 }
1228 }
1229}
1230
1231#[repr(C)]
1235#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1236pub struct FilterPrimitive {
1237 pub kind: FilterPrimitiveKind,
1238 pub color_space: ColorSpace,
1239}
1240
1241impl FilterPrimitive {
1242 pub fn sanitize(&mut self) {
1243 self.kind.sanitize();
1244 }
1245}
1246
1247#[repr(C)]
1248#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, PeekPoke)]
1249pub enum FilterOpGraphPictureBufferId {
1250 #[default]
1251 None,
1253 BufferId(i16),
1255}
1256
1257#[repr(C)]
1258#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
1259pub struct FilterOpGraphPictureReference {
1260 pub buffer_id: FilterOpGraphPictureBufferId,
1262}
1263
1264#[repr(C)]
1265#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
1266pub struct FilterOpGraphNode {
1267 pub linear: bool,
1271 pub input: FilterOpGraphPictureReference,
1274 pub input2: FilterOpGraphPictureReference,
1277 pub subregion: LayoutRect,
1279}
1280
1281pub const SVGFE_GRAPH_MAX: usize = 256;
1286
1287#[repr(C)]
1288#[derive(Clone, Copy, Debug, Deserialize, Serialize, PeekPoke)]
1289pub enum FilterOp {
1290 Identity,
1295 Blur(f32, f32),
1299 Brightness(f32),
1303 Contrast(f32),
1307 Grayscale(f32),
1311 HueRotate(f32),
1315 Invert(f32),
1319 Opacity(PropertyBinding<f32>, f32),
1323 Saturate(f32),
1327 Sepia(f32),
1331 DropShadow(Shadow),
1335 ColorMatrix([f32; 20]),
1339 SrgbToLinear,
1343 LinearToSrgb,
1347 ComponentTransfer,
1351 Flood(ColorF),
1356 SVGFESourceGraphic{node: FilterOpGraphNode},
1362 SVGFESourceAlpha{node: FilterOpGraphNode},
1368 SVGFEIdentity{node: FilterOpGraphNode},
1371 SVGFEOpacity{node: FilterOpGraphNode, valuebinding: PropertyBinding<f32>, value: f32},
1376 SVGFEToAlpha{node: FilterOpGraphNode},
1379 SVGFEBlendDarken{node: FilterOpGraphNode},
1385 SVGFEBlendLighten{node: FilterOpGraphNode},
1391 SVGFEBlendMultiply{node: FilterOpGraphNode},
1397 SVGFEBlendNormal{node: FilterOpGraphNode},
1403 SVGFEBlendScreen{node: FilterOpGraphNode},
1409 SVGFEBlendOverlay{node: FilterOpGraphNode},
1415 SVGFEBlendColorDodge{node: FilterOpGraphNode},
1421 SVGFEBlendColorBurn{node: FilterOpGraphNode},
1427 SVGFEBlendHardLight{node: FilterOpGraphNode},
1433 SVGFEBlendSoftLight{node: FilterOpGraphNode},
1439 SVGFEBlendDifference{node: FilterOpGraphNode},
1445 SVGFEBlendExclusion{node: FilterOpGraphNode},
1451 SVGFEBlendHue{node: FilterOpGraphNode},
1457 SVGFEBlendSaturation{node: FilterOpGraphNode},
1463 SVGFEBlendColor{node: FilterOpGraphNode},
1469 SVGFEBlendLuminosity{node: FilterOpGraphNode},
1475 SVGFEColorMatrix{node: FilterOpGraphNode, values: [f32; 20]},
1481 SVGFEComponentTransfer{node: FilterOpGraphNode},
1487 SVGFECompositeArithmetic{node: FilterOpGraphNode, k1: f32, k2: f32, k3: f32,
1493 k4: f32},
1494 SVGFECompositeATop{node: FilterOpGraphNode},
1500 SVGFECompositeIn{node: FilterOpGraphNode},
1506 SVGFECompositeLighter{node: FilterOpGraphNode},
1512 SVGFECompositeOut{node: FilterOpGraphNode},
1518 SVGFECompositeOver{node: FilterOpGraphNode},
1524 SVGFECompositeXOR{node: FilterOpGraphNode},
1530 SVGFEConvolveMatrixEdgeModeDuplicate{node: FilterOpGraphNode, order_x: i32,
1539 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1540 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1541 preserve_alpha: i32},
1542 SVGFEConvolveMatrixEdgeModeNone{node: FilterOpGraphNode, order_x: i32,
1551 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1552 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1553 preserve_alpha: i32},
1554 SVGFEConvolveMatrixEdgeModeWrap{node: FilterOpGraphNode, order_x: i32,
1563 order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
1564 target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
1565 preserve_alpha: i32},
1566 SVGFEDiffuseLightingDistant{node: FilterOpGraphNode, surface_scale: f32,
1575 diffuse_constant: f32, kernel_unit_length_x: f32,
1576 kernel_unit_length_y: f32, azimuth: f32, elevation: f32},
1577 SVGFEDiffuseLightingPoint{node: FilterOpGraphNode, surface_scale: f32,
1586 diffuse_constant: f32, kernel_unit_length_x: f32,
1587 kernel_unit_length_y: f32, x: f32, y: f32, z: f32},
1588 SVGFEDiffuseLightingSpot{node: FilterOpGraphNode, surface_scale: f32,
1599 diffuse_constant: f32, kernel_unit_length_x: f32,
1600 kernel_unit_length_y: f32, x: f32, y: f32, z: f32, points_at_x: f32,
1601 points_at_y: f32, points_at_z: f32, cone_exponent: f32,
1602 limiting_cone_angle: f32},
1603 SVGFEDisplacementMap{node: FilterOpGraphNode, scale: f32,
1610 x_channel_selector: u32, y_channel_selector: u32},
1611 SVGFEDropShadow{node: FilterOpGraphNode, color: ColorF, dx: f32, dy: f32,
1619 std_deviation_x: f32, std_deviation_y: f32},
1620 SVGFEFlood{node: FilterOpGraphNode, color: ColorF},
1626 SVGFEGaussianBlur{node: FilterOpGraphNode, std_deviation_x: f32, std_deviation_y: f32},
1632 SVGFEImage{node: FilterOpGraphNode, sampling_filter: u32, matrix: [f32; 6]},
1638 SVGFEMorphologyDilate{node: FilterOpGraphNode, radius_x: f32, radius_y: f32},
1645 SVGFEMorphologyErode{node: FilterOpGraphNode, radius_x: f32, radius_y: f32},
1652 SVGFEOffset{node: FilterOpGraphNode, offset_x: f32, offset_y: f32},
1659 SVGFESpecularLightingDistant{node: FilterOpGraphNode, surface_scale: f32,
1668 specular_constant: f32, specular_exponent: f32,
1669 kernel_unit_length_x: f32, kernel_unit_length_y: f32, azimuth: f32,
1670 elevation: f32},
1671 SVGFESpecularLightingPoint{node: FilterOpGraphNode, surface_scale: f32,
1680 specular_constant: f32, specular_exponent: f32,
1681 kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1682 z: f32},
1683 SVGFESpecularLightingSpot{node: FilterOpGraphNode, surface_scale: f32,
1694 specular_constant: f32, specular_exponent: f32,
1695 kernel_unit_length_x: f32, kernel_unit_length_y: f32, x: f32, y: f32,
1696 z: f32, points_at_x: f32, points_at_y: f32, points_at_z: f32,
1697 cone_exponent: f32, limiting_cone_angle: f32},
1698 SVGFETile{node: FilterOpGraphNode},
1705 SVGFETurbulenceWithFractalNoiseWithNoStitching{node: FilterOpGraphNode,
1713 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1714 seed: u32},
1715 SVGFETurbulenceWithFractalNoiseWithStitching{node: FilterOpGraphNode,
1723 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1724 seed: u32},
1725 SVGFETurbulenceWithTurbulenceNoiseWithNoStitching{node: FilterOpGraphNode,
1732 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32,
1733 seed: u32},
1734 SVGFETurbulenceWithTurbulenceNoiseWithStitching{node: FilterOpGraphNode,
1741 base_frequency_x: f32, base_frequency_y: f32, num_octaves: u32, seed: u32},
1742}
1743
1744#[repr(u8)]
1745#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
1746pub enum ComponentTransferFuncType {
1747 Identity = 0,
1748 Table = 1,
1749 Discrete = 2,
1750 Linear = 3,
1751 Gamma = 4,
1752}
1753
1754#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
1755pub struct FilterData {
1756 pub func_r_type: ComponentTransferFuncType,
1758 pub r_values: Vec<f32>,
1759 pub func_g_type: ComponentTransferFuncType,
1760 pub g_values: Vec<f32>,
1761 pub func_b_type: ComponentTransferFuncType,
1762 pub b_values: Vec<f32>,
1763 pub func_a_type: ComponentTransferFuncType,
1764 pub a_values: Vec<f32>,
1765}
1766
1767fn sanitize_func_type(
1768 func_type: ComponentTransferFuncType,
1769 values: &[f32],
1770) -> ComponentTransferFuncType {
1771 if values.is_empty() {
1772 return ComponentTransferFuncType::Identity;
1773 }
1774 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1775 return ComponentTransferFuncType::Identity;
1776 }
1777 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1778 return ComponentTransferFuncType::Identity;
1779 }
1780 func_type
1781}
1782
1783fn sanitize_values(
1784 func_type: ComponentTransferFuncType,
1785 values: &[f32],
1786) -> bool {
1787 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1788 return false;
1789 }
1790 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1791 return false;
1792 }
1793 true
1794}
1795
1796impl FilterData {
1797 pub fn sanitize(&self) -> FilterData {
1799 FilterData {
1800 func_r_type: sanitize_func_type(self.func_r_type, &self.r_values),
1801 r_values:
1802 if sanitize_values(self.func_r_type, &self.r_values) {
1803 self.r_values.clone()
1804 } else {
1805 Vec::new()
1806 },
1807 func_g_type: sanitize_func_type(self.func_g_type, &self.g_values),
1808 g_values:
1809 if sanitize_values(self.func_g_type, &self.g_values) {
1810 self.g_values.clone()
1811 } else {
1812 Vec::new()
1813 },
1814
1815 func_b_type: sanitize_func_type(self.func_b_type, &self.b_values),
1816 b_values:
1817 if sanitize_values(self.func_b_type, &self.b_values) {
1818 self.b_values.clone()
1819 } else {
1820 Vec::new()
1821 },
1822
1823 func_a_type: sanitize_func_type(self.func_a_type, &self.a_values),
1824 a_values:
1825 if sanitize_values(self.func_a_type, &self.a_values) {
1826 self.a_values.clone()
1827 } else {
1828 Vec::new()
1829 },
1830
1831 }
1832 }
1833
1834 pub fn is_identity(&self) -> bool {
1835 self.func_r_type == ComponentTransferFuncType::Identity &&
1836 self.func_g_type == ComponentTransferFuncType::Identity &&
1837 self.func_b_type == ComponentTransferFuncType::Identity &&
1838 self.func_a_type == ComponentTransferFuncType::Identity
1839 }
1840}
1841
1842#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1843pub struct IframeDisplayItem {
1844 pub bounds: LayoutRect,
1845 pub clip_rect: LayoutRect,
1846 pub space_and_clip: SpaceAndClipInfo,
1847 pub pipeline_id: PipelineId,
1848 pub ignore_missing_pipeline: bool,
1849}
1850
1851#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1856pub struct ImageDisplayItem {
1857 pub common: CommonItemProperties,
1858 pub bounds: LayoutRect,
1862 pub image_key: ImageKey,
1863 pub image_rendering: ImageRendering,
1864 pub alpha_type: AlphaType,
1865 pub color: ColorF,
1867}
1868
1869#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1872pub struct RepeatingImageDisplayItem {
1873 pub common: CommonItemProperties,
1874 pub bounds: LayoutRect,
1878 pub stretch_size: LayoutSize,
1880 pub tile_spacing: LayoutSize,
1882 pub image_key: ImageKey,
1883 pub image_rendering: ImageRendering,
1884 pub alpha_type: AlphaType,
1885 pub color: ColorF,
1887}
1888
1889#[repr(u8)]
1890#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1891pub enum ImageRendering {
1892 Auto = 0,
1893 CrispEdges = 1,
1894 Pixelated = 2,
1895}
1896
1897#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1898pub enum AlphaType {
1899 Alpha = 0,
1900 PremultipliedAlpha = 1,
1901}
1902
1903#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1904pub struct YuvImageDisplayItem {
1905 pub common: CommonItemProperties,
1906 pub bounds: LayoutRect,
1907 pub yuv_data: YuvData,
1908 pub color_depth: ColorDepth,
1909 pub color_space: YuvColorSpace,
1910 pub color_range: ColorRange,
1911 pub image_rendering: ImageRendering,
1912}
1913
1914#[repr(u8)]
1915#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1916pub enum YuvColorSpace {
1917 Rec601 = 0,
1918 Rec709 = 1,
1919 Rec2020 = 2,
1920 Identity = 3, }
1922
1923#[repr(u8)]
1924#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1925pub enum ColorRange {
1926 Limited = 0,
1927 Full = 1,
1928}
1929
1930#[repr(u8)]
1931#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1932pub enum YuvRangedColorSpace {
1933 Rec601Narrow = 0,
1934 Rec601Full = 1,
1935 Rec709Narrow = 2,
1936 Rec709Full = 3,
1937 Rec2020Narrow = 4,
1938 Rec2020Full = 5,
1939 GbrIdentity = 6,
1940}
1941
1942impl YuvColorSpace {
1943 pub fn with_range(self, range: ColorRange) -> YuvRangedColorSpace {
1944 match self {
1945 YuvColorSpace::Identity => YuvRangedColorSpace::GbrIdentity,
1946 YuvColorSpace::Rec601 => {
1947 match range {
1948 ColorRange::Limited => YuvRangedColorSpace::Rec601Narrow,
1949 ColorRange::Full => YuvRangedColorSpace::Rec601Full,
1950 }
1951 }
1952 YuvColorSpace::Rec709 => {
1953 match range {
1954 ColorRange::Limited => YuvRangedColorSpace::Rec709Narrow,
1955 ColorRange::Full => YuvRangedColorSpace::Rec709Full,
1956 }
1957 }
1958 YuvColorSpace::Rec2020 => {
1959 match range {
1960 ColorRange::Limited => YuvRangedColorSpace::Rec2020Narrow,
1961 ColorRange::Full => YuvRangedColorSpace::Rec2020Full,
1962 }
1963 }
1964 }
1965 }
1966}
1967
1968#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1969pub enum YuvData {
1970 NV12(ImageKey, ImageKey), P010(ImageKey, ImageKey), NV16(ImageKey, ImageKey), PlanarYCbCr(ImageKey, ImageKey, ImageKey), InterleavedYCbCr(ImageKey), }
1976
1977impl YuvData {
1978 pub fn get_format(&self) -> YuvFormat {
1979 match *self {
1980 YuvData::NV12(..) => YuvFormat::NV12,
1981 YuvData::P010(..) => YuvFormat::P010,
1982 YuvData::NV16(..) => YuvFormat::NV16,
1983 YuvData::PlanarYCbCr(..) => YuvFormat::PlanarYCbCr,
1984 YuvData::InterleavedYCbCr(..) => YuvFormat::InterleavedYCbCr,
1985 }
1986 }
1987}
1988
1989#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1990pub enum YuvFormat {
1991 NV12 = 0,
1993 P010 = 1,
1994 NV16 = 2,
1995 PlanarYCbCr = 3,
1996 InterleavedYCbCr = 4,
1997}
1998
1999impl YuvFormat {
2000 pub fn get_plane_num(self) -> usize {
2001 match self {
2002 YuvFormat::NV12 | YuvFormat::P010 | YuvFormat::NV16 => 2,
2003 YuvFormat::PlanarYCbCr => 3,
2004 YuvFormat::InterleavedYCbCr => 1,
2005 }
2006 }
2007}
2008
2009#[repr(C)]
2010#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
2011pub struct ImageMask {
2012 pub image: ImageKey,
2013 pub rect: LayoutRect,
2014}
2015
2016impl ImageMask {
2017 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
2019 Some(self.rect)
2020 }
2021}
2022
2023#[repr(C)]
2024#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
2025pub enum ClipMode {
2026 Clip, ClipOut, }
2029
2030impl Not for ClipMode {
2031 type Output = ClipMode;
2032
2033 fn not(self) -> ClipMode {
2034 match self {
2035 ClipMode::Clip => ClipMode::ClipOut,
2036 ClipMode::ClipOut => ClipMode::Clip,
2037 }
2038 }
2039}
2040
2041#[repr(C)]
2042#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
2043pub struct ComplexClipRegion {
2044 pub rect: LayoutRect,
2046 pub radii: BorderRadius,
2048 pub mode: ClipMode,
2051}
2052
2053impl BorderRadius {
2054 pub fn zero() -> BorderRadius {
2055 BorderRadius {
2056 top_left: LayoutSize::new(0.0, 0.0),
2057 top_right: LayoutSize::new(0.0, 0.0),
2058 bottom_left: LayoutSize::new(0.0, 0.0),
2059 bottom_right: LayoutSize::new(0.0, 0.0),
2060 }
2061 }
2062
2063 pub fn uniform(radius: f32) -> BorderRadius {
2064 BorderRadius {
2065 top_left: LayoutSize::new(radius, radius),
2066 top_right: LayoutSize::new(radius, radius),
2067 bottom_left: LayoutSize::new(radius, radius),
2068 bottom_right: LayoutSize::new(radius, radius),
2069 }
2070 }
2071
2072 pub fn uniform_size(radius: LayoutSize) -> BorderRadius {
2073 BorderRadius {
2074 top_left: radius,
2075 top_right: radius,
2076 bottom_left: radius,
2077 bottom_right: radius,
2078 }
2079 }
2080
2081 pub fn all_sides_uniform(&self) -> bool {
2082 let corner_is_uniform = |corner: &LayoutSize| corner.width == corner.height;
2083 corner_is_uniform(&self.top_left) &&
2084 corner_is_uniform(&self.top_right) &&
2085 corner_is_uniform(&self.bottom_right) &&
2086 corner_is_uniform(&self.bottom_left)
2087 }
2088
2089 pub fn can_use_fast_path_in(&self, rect: &LayoutRect) -> bool {
2090 if !self.all_sides_uniform() {
2091 return false;
2093 }
2094 let tl = self.top_left.width;
2099 if tl == self.bottom_right.width && tl == self.top_right.width && tl == self.bottom_left.width {
2100 return true;
2101 }
2102 let half_size = rect.size() * 0.5;
2103 let fits = |v: f32| v <= half_size.width && v <= half_size.height;
2104 fits(tl) && fits(self.bottom_right.width) && fits(self.top_right.width) && fits(self.bottom_left.width)
2105 }
2106
2107 pub fn is_zero(&self) -> bool {
2110 let corner_is_zero = |corner: &LayoutSize| corner.width == 0.0 || corner.height == 0.0;
2111 corner_is_zero(&self.top_left) &&
2112 corner_is_zero(&self.top_right) &&
2113 corner_is_zero(&self.bottom_right) &&
2114 corner_is_zero(&self.bottom_left)
2115 }
2116}
2117
2118impl ComplexClipRegion {
2119 pub fn new(
2121 rect: LayoutRect,
2122 radii: BorderRadius,
2123 mode: ClipMode,
2124 ) -> Self {
2125 ComplexClipRegion { rect, radii, mode }
2126 }
2127}
2128
2129impl ComplexClipRegion {
2130 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
2132 match self.mode {
2133 ClipMode::Clip => {
2134 Some(self.rect)
2135 }
2136 ClipMode::ClipOut => {
2137 None
2138 }
2139 }
2140 }
2141}
2142
2143pub const POLYGON_CLIP_VERTEX_MAX: usize = 32;
2144
2145#[repr(u8)]
2146#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
2147pub enum FillRule {
2148 Nonzero = 0x1, Evenodd = 0x2, }
2151
2152impl From<u8> for FillRule {
2153 fn from(fill_rule: u8) -> Self {
2154 match fill_rule {
2155 0x1 => FillRule::Nonzero,
2156 0x2 => FillRule::Evenodd,
2157 _ => panic!("Unexpected FillRule value."),
2158 }
2159 }
2160}
2161
2162impl From<FillRule> for u8 {
2163 fn from(fill_rule: FillRule) -> Self {
2164 match fill_rule {
2165 FillRule::Nonzero => 0x1,
2166 FillRule::Evenodd => 0x2,
2167 }
2168 }
2169}
2170
2171#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
2172pub struct ClipChainId(pub u64, pub PipelineId);
2173
2174impl ClipChainId {
2175 pub const INVALID: Self = ClipChainId(!0, PipelineId::INVALID);
2176}
2177
2178#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
2180pub struct ClipId(pub usize, pub PipelineId);
2181
2182impl Default for ClipId {
2183 fn default() -> Self {
2184 ClipId::invalid()
2185 }
2186}
2187
2188const ROOT_CLIP_ID: usize = 0;
2189
2190impl ClipId {
2191 pub fn root(pipeline_id: PipelineId) -> Self {
2193 ClipId(ROOT_CLIP_ID, pipeline_id)
2194 }
2195
2196 pub fn invalid() -> Self {
2199 ClipId(!0, PipelineId::dummy())
2200 }
2201
2202 pub fn pipeline_id(&self) -> PipelineId {
2203 match *self {
2204 ClipId(_, pipeline_id) => pipeline_id,
2205 }
2206 }
2207
2208 pub fn is_root(&self) -> bool {
2209 match *self {
2210 ClipId(id, _) => id == ROOT_CLIP_ID,
2211 }
2212 }
2213
2214 pub fn is_valid(&self) -> bool {
2215 match *self {
2216 ClipId(id, _) => id != !0,
2217 }
2218 }
2219}
2220
2221#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
2223pub struct SpatialId(pub usize, PipelineId);
2224
2225const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
2226const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
2227
2228impl SpatialId {
2229 pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
2230 SpatialId(spatial_node_index, pipeline_id)
2231 }
2232
2233 pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
2234 SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
2235 }
2236
2237 pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
2238 SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
2239 }
2240
2241 pub fn pipeline_id(&self) -> PipelineId {
2242 self.1
2243 }
2244}
2245
2246#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
2254#[repr(C)]
2255pub struct ExternalScrollId(pub u64, pub PipelineId);
2256
2257impl ExternalScrollId {
2258 pub fn pipeline_id(&self) -> PipelineId {
2259 self.1
2260 }
2261
2262 pub fn is_root(&self) -> bool {
2263 self.0 == 0
2264 }
2265}
2266
2267impl DisplayItem {
2268 pub fn debug_name(&self) -> &'static str {
2269 match *self {
2270 DisplayItem::Border(..) => "border",
2271 DisplayItem::BoxShadow(..) => "box_shadow",
2272 DisplayItem::ClearRectangle(..) => "clear_rectangle",
2273 DisplayItem::HitTest(..) => "hit_test",
2274 DisplayItem::RectClip(..) => "rect_clip",
2275 DisplayItem::RoundedRectClip(..) => "rounded_rect_clip",
2276 DisplayItem::ImageMaskClip(..) => "image_mask_clip",
2277 DisplayItem::ClipChain(..) => "clip_chain",
2278 DisplayItem::ConicGradient(..) => "conic_gradient",
2279 DisplayItem::Gradient(..) => "gradient",
2280 DisplayItem::Iframe(..) => "iframe",
2281 DisplayItem::Image(..) => "image",
2282 DisplayItem::RepeatingImage(..) => "repeating_image",
2283 DisplayItem::Line(..) => "line",
2284 DisplayItem::PopAllShadows => "pop_all_shadows",
2285 DisplayItem::PopReferenceFrame => "pop_reference_frame",
2286 DisplayItem::PopStackingContext => "pop_stacking_context",
2287 DisplayItem::PushShadow(..) => "push_shadow",
2288 DisplayItem::PushReferenceFrame(..) => "push_reference_frame",
2289 DisplayItem::PushStackingContext(..) => "push_stacking_context",
2290 DisplayItem::SetFilterOps => "set_filter_ops",
2291 DisplayItem::SetFilterData => "set_filter_data",
2292 DisplayItem::SetFilterPrimitives => "set_filter_primitives",
2293 DisplayItem::SetPoints => "set_points",
2294 DisplayItem::RadialGradient(..) => "radial_gradient",
2295 DisplayItem::Rectangle(..) => "rectangle",
2296 DisplayItem::SetGradientStops => "set_gradient_stops",
2297 DisplayItem::ReuseItems(..) => "reuse_item",
2298 DisplayItem::RetainedItems(..) => "retained_items",
2299 DisplayItem::Text(..) => "text",
2300 DisplayItem::YuvImage(..) => "yuv_image",
2301 DisplayItem::BackdropFilter(..) => "backdrop_filter",
2302 DisplayItem::DebugMarker(..) => "debug",
2303 }
2304 }
2305}
2306
2307macro_rules! impl_default_for_enums {
2308 ($($enum:ident => $init:expr ),+) => {
2309 $(impl Default for $enum {
2310 #[allow(unused_imports)]
2311 fn default() -> Self {
2312 use $enum::*;
2313 $init
2314 }
2315 })*
2316 }
2317}
2318
2319impl_default_for_enums! {
2320 DisplayItem => PopStackingContext,
2321 LineOrientation => Vertical,
2322 LineStyle => Solid,
2323 RepeatMode => Stretch,
2324 NinePatchBorderSource => Image(ImageKey::default(), ImageRendering::Auto),
2325 BorderDetails => Normal(NormalBorder::default()),
2326 BorderRadiusKind => Uniform,
2327 BorderStyle => None,
2328 BoxShadowClipMode => Outset,
2329 ExtendMode => Clamp,
2330 FilterOp => Identity,
2331 ComponentTransferFuncType => Identity,
2332 ClipMode => Clip,
2333 FillRule => Nonzero,
2334 ReferenceFrameKind => Transform {
2335 is_2d_scale_translation: false,
2336 should_snap: false,
2337 paired_with_perspective: false,
2338 },
2339 Rotation => Degree0,
2340 TransformStyle => Flat,
2341 RasterSpace => Local(f32::default()),
2342 MixBlendMode => Normal,
2343 ImageRendering => Auto,
2344 AlphaType => Alpha,
2345 YuvColorSpace => Rec601,
2346 YuvRangedColorSpace => Rec601Narrow,
2347 ColorRange => Limited,
2348 YuvData => NV12(ImageKey::default(), ImageKey::default()),
2349 YuvFormat => NV12,
2350 FilterPrimitiveInput => Original,
2351 ColorSpace => Srgb,
2352 CompositeOperator => Over
2353}