1use euclid::{SideOffsets2D, Angle};
6use peek_poke::PeekPoke;
7use std::ops::Not;
8use crate::font;
10use crate::{PipelineId, PropertyBinding};
11use crate::color::ColorF;
12use crate::image::{ColorDepth, ImageKey};
13use crate::units::*;
14use std::hash::{Hash, Hasher};
15
16pub type ItemTag = (u64, u16);
32
33pub type ItemKey = u16;
36
37bitflags! {
38 #[repr(C)]
39 #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
40 pub struct PrimitiveFlags: u8 {
41 const IS_BACKFACE_VISIBLE = 1 << 0;
43 const IS_SCROLLBAR_CONTAINER = 1 << 1;
45 const IS_SCROLLBAR_THUMB = 1 << 2;
47 const PREFER_COMPOSITOR_SURFACE = 1 << 3;
51 const SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE = 1 << 4;
55 }
56}
57
58impl Default for PrimitiveFlags {
59 fn default() -> Self {
60 PrimitiveFlags::IS_BACKFACE_VISIBLE
61 }
62}
63
64#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
67pub struct CommonItemProperties {
68 pub clip_rect: LayoutRect,
72 pub clip_id: ClipId,
74 pub spatial_id: SpatialId,
76 pub flags: PrimitiveFlags,
78}
79
80impl CommonItemProperties {
81 pub fn new(
83 clip_rect: LayoutRect,
84 space_and_clip: SpaceAndClipInfo,
85 ) -> Self {
86 Self {
87 clip_rect,
88 spatial_id: space_and_clip.spatial_id,
89 clip_id: space_and_clip.clip_id,
90 flags: PrimitiveFlags::default(),
91 }
92 }
93}
94
95#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
102pub struct SpaceAndClipInfo {
103 pub spatial_id: SpatialId,
104 pub clip_id: ClipId,
105}
106
107impl SpaceAndClipInfo {
108 pub fn root_scroll(pipeline_id: PipelineId) -> Self {
111 SpaceAndClipInfo {
112 spatial_id: SpatialId::root_scroll_node(pipeline_id),
113 clip_id: ClipId::root(pipeline_id),
114 }
115 }
116}
117
118#[repr(u8)]
119#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
120pub enum DisplayItem {
121 Rectangle(RectangleDisplayItem),
123 ClearRectangle(ClearRectangleDisplayItem),
124 HitTest(HitTestDisplayItem),
125 Text(TextDisplayItem),
126 Line(LineDisplayItem),
127 Border(BorderDisplayItem),
128 BoxShadow(BoxShadowDisplayItem),
129 PushShadow(PushShadowDisplayItem),
130 Gradient(GradientDisplayItem),
131 RadialGradient(RadialGradientDisplayItem),
132 ConicGradient(ConicGradientDisplayItem),
133 Image(ImageDisplayItem),
134 RepeatingImage(RepeatingImageDisplayItem),
135 YuvImage(YuvImageDisplayItem),
136 BackdropFilter(BackdropFilterDisplayItem),
137
138 RectClip(RectClipDisplayItem),
140 RoundedRectClip(RoundedRectClipDisplayItem),
141 ImageMaskClip(ImageMaskClipDisplayItem),
142 ClipChain(ClipChainItem),
143
144 ScrollFrame(ScrollFrameDisplayItem),
146 StickyFrame(StickyFrameDisplayItem),
147 Iframe(IframeDisplayItem),
148 PushReferenceFrame(ReferenceFrameDisplayListItem),
149 PushStackingContext(PushStackingContextDisplayItem),
150
151 SetGradientStops,
154 SetFilterOps,
155 SetFilterData,
156 SetFilterPrimitives,
157 SetPoints,
158
159 PopReferenceFrame,
161 PopStackingContext,
162 PopAllShadows,
163
164 ReuseItems(ItemKey),
165 RetainedItems(ItemKey),
166}
167
168#[cfg(any(feature = "serialize", feature = "deserialize"))]
171#[cfg_attr(feature = "serialize", derive(Serialize))]
172#[cfg_attr(feature = "deserialize", derive(Deserialize))]
173pub enum DebugDisplayItem {
174 Rectangle(RectangleDisplayItem),
175 ClearRectangle(ClearRectangleDisplayItem),
176 HitTest(HitTestDisplayItem),
177 Text(TextDisplayItem, Vec<font::GlyphInstance>),
178 Line(LineDisplayItem),
179 Border(BorderDisplayItem),
180 BoxShadow(BoxShadowDisplayItem),
181 PushShadow(PushShadowDisplayItem),
182 Gradient(GradientDisplayItem),
183 RadialGradient(RadialGradientDisplayItem),
184 ConicGradient(ConicGradientDisplayItem),
185 Image(ImageDisplayItem),
186 RepeatingImage(RepeatingImageDisplayItem),
187 YuvImage(YuvImageDisplayItem),
188 BackdropFilter(BackdropFilterDisplayItem),
189
190 ImageMaskClip(ImageMaskClipDisplayItem),
191 RoundedRectClip(RoundedRectClipDisplayItem),
192 RectClip(RectClipDisplayItem),
193 ClipChain(ClipChainItem, Vec<ClipId>),
194
195 ScrollFrame(ScrollFrameDisplayItem),
196 StickyFrame(StickyFrameDisplayItem),
197 Iframe(IframeDisplayItem),
198 PushReferenceFrame(ReferenceFrameDisplayListItem),
199 PushStackingContext(PushStackingContextDisplayItem),
200
201 SetGradientStops(Vec<GradientStop>),
202 SetFilterOps(Vec<FilterOp>),
203 SetFilterData(FilterData),
204 SetFilterPrimitives(Vec<FilterPrimitive>),
205 SetPoints(Vec<LayoutPoint>),
206
207 PopReferenceFrame,
208 PopStackingContext,
209 PopAllShadows,
210}
211
212#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
213pub struct ImageMaskClipDisplayItem {
214 pub id: ClipId,
215 pub parent_space_and_clip: SpaceAndClipInfo,
216 pub image_mask: ImageMask,
217 pub fill_rule: FillRule,
218} #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
221pub struct RectClipDisplayItem {
222 pub id: ClipId,
223 pub parent_space_and_clip: SpaceAndClipInfo,
224 pub clip_rect: LayoutRect,
225}
226
227#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
228pub struct RoundedRectClipDisplayItem {
229 pub id: ClipId,
230 pub parent_space_and_clip: SpaceAndClipInfo,
231 pub clip: ComplexClipRegion,
232}
233
234#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
235pub struct ClipDisplayItem {
236 pub id: ClipId,
237 pub parent_space_and_clip: SpaceAndClipInfo,
238 pub clip_rect: LayoutRect,
239} #[repr(C)]
243#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
244pub struct StickyOffsetBounds {
245 pub min: f32,
249
250 pub max: f32,
254}
255
256impl StickyOffsetBounds {
257 pub fn new(min: f32, max: f32) -> StickyOffsetBounds {
258 StickyOffsetBounds { min, max }
259 }
260}
261
262#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
263pub struct StickyFrameDisplayItem {
264 pub id: SpatialId,
265 pub parent_spatial_id: SpatialId,
266 pub bounds: LayoutRect,
267
268 pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
272
273 pub vertical_offset_bounds: StickyOffsetBounds,
278
279 pub horizontal_offset_bounds: StickyOffsetBounds,
284
285 pub previously_applied_offset: LayoutVector2D,
291}
292
293#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
294pub enum ScrollSensitivity {
295 ScriptAndInputEvents,
296 Script,
297}
298
299#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
300pub struct ScrollFrameDisplayItem {
301 pub clip_id: ClipId,
303 pub scroll_frame_id: SpatialId,
305 pub content_rect: LayoutRect,
308 pub clip_rect: LayoutRect,
309 pub parent_space_and_clip: SpaceAndClipInfo,
310 pub external_id: ExternalScrollId,
311 pub scroll_sensitivity: ScrollSensitivity,
312 pub external_scroll_offset: LayoutVector2D,
318}
319
320#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
322pub struct RectangleDisplayItem {
323 pub common: CommonItemProperties,
324 pub bounds: LayoutRect,
325 pub color: PropertyBinding<ColorF>,
326}
327
328#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
331pub struct ClearRectangleDisplayItem {
332 pub common: CommonItemProperties,
333 pub bounds: LayoutRect,
334}
335
336#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
340pub struct HitTestDisplayItem {
341 pub common: CommonItemProperties,
342 pub tag: ItemTag,
343}
344
345#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
346pub struct LineDisplayItem {
347 pub common: CommonItemProperties,
348 pub area: LayoutRect,
354 pub orientation: LineOrientation,
356 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 pub bounds: LayoutRect,
393 pub font_key: font::FontInstanceKey,
394 pub color: ColorF,
395 pub glyph_options: Option<font::GlyphOptions>,
396} #[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 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 #[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),
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 pub source: NinePatchBorderSource,
478
479 pub width: i32,
481
482 pub height: i32,
484
485 pub slice: DeviceIntSideOffsets,
493
494 pub fill: bool,
497
498 pub repeat_horizontal: RepeatMode,
501
502 pub repeat_vertical: RepeatMode,
505
506 pub outset: LayoutSideOffsets, }
510
511#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
512pub enum BorderDetails {
513 Normal(NormalBorder),
514 NinePatch(NinePatchBorder),
515}
516
517#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
518pub struct BorderDisplayItem {
519 pub common: CommonItemProperties,
520 pub bounds: LayoutRect,
521 pub widths: LayoutSideOffsets,
522 pub details: BorderDetails,
523}
524
525#[repr(C)]
526#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
527pub enum BorderRadiusKind {
528 Uniform,
529 NonUniform,
530}
531
532#[repr(C)]
533#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
534pub struct BorderRadius {
535 pub top_left: LayoutSize,
536 pub top_right: LayoutSize,
537 pub bottom_left: LayoutSize,
538 pub bottom_right: LayoutSize,
539}
540
541impl Default for BorderRadius {
542 fn default() -> Self {
543 BorderRadius {
544 top_left: LayoutSize::zero(),
545 top_right: LayoutSize::zero(),
546 bottom_left: LayoutSize::zero(),
547 bottom_right: LayoutSize::zero(),
548 }
549 }
550}
551
552#[repr(C)]
553#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
554pub struct BorderSide {
555 pub color: ColorF,
556 pub style: BorderStyle,
557}
558
559#[repr(u32)]
560#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq, PeekPoke)]
561pub enum BorderStyle {
562 None = 0,
563 Solid = 1,
564 Double = 2,
565 Dotted = 3,
566 Dashed = 4,
567 Hidden = 5,
568 Groove = 6,
569 Ridge = 7,
570 Inset = 8,
571 Outset = 9,
572}
573
574impl BorderStyle {
575 pub fn is_hidden(self) -> bool {
576 self == BorderStyle::Hidden || self == BorderStyle::None
577 }
578}
579
580#[repr(u8)]
581#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
582pub enum BoxShadowClipMode {
583 Outset = 0,
584 Inset = 1,
585}
586
587#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
588pub struct BoxShadowDisplayItem {
589 pub common: CommonItemProperties,
590 pub box_bounds: LayoutRect,
591 pub offset: LayoutVector2D,
592 pub color: ColorF,
593 pub blur_radius: f32,
594 pub spread_radius: f32,
595 pub border_radius: BorderRadius,
596 pub clip_mode: BoxShadowClipMode,
597}
598
599#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
600pub struct PushShadowDisplayItem {
601 pub space_and_clip: SpaceAndClipInfo,
602 pub shadow: Shadow,
603 pub should_inflate: bool,
604}
605
606#[repr(C)]
607#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
608pub struct Shadow {
609 pub offset: LayoutVector2D,
610 pub color: ColorF,
611 pub blur_radius: f32,
612}
613
614#[repr(u8)]
615#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
616pub enum ExtendMode {
617 Clamp,
618 Repeat,
619}
620
621#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
622pub struct Gradient {
623 pub start_point: LayoutPoint,
624 pub end_point: LayoutPoint,
625 pub extend_mode: ExtendMode,
626} impl Gradient {
629 pub fn is_valid(&self) -> bool {
630 self.start_point.x.is_finite() &&
631 self.start_point.y.is_finite() &&
632 self.end_point.x.is_finite() &&
633 self.end_point.y.is_finite()
634 }
635}
636
637#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
639pub struct GradientDisplayItem {
640 pub common: CommonItemProperties,
642 pub bounds: LayoutRect,
646 pub tile_size: LayoutSize,
648 pub tile_spacing: LayoutSize,
650 pub gradient: Gradient,
651}
652
653#[repr(C)]
654#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
655pub struct GradientStop {
656 pub offset: f32,
657 pub color: ColorF,
658}
659
660#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
661pub struct RadialGradient {
662 pub center: LayoutPoint,
663 pub radius: LayoutSize,
664 pub start_offset: f32,
665 pub end_offset: f32,
666 pub extend_mode: ExtendMode,
667} impl RadialGradient {
670 pub fn is_valid(&self) -> bool {
671 self.center.x.is_finite() &&
672 self.center.y.is_finite() &&
673 self.start_offset.is_finite() &&
674 self.end_offset.is_finite()
675 }
676}
677
678#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
679pub struct ConicGradient {
680 pub center: LayoutPoint,
681 pub angle: f32,
682 pub start_offset: f32,
683 pub end_offset: f32,
684 pub extend_mode: ExtendMode,
685} impl ConicGradient {
688 pub fn is_valid(&self) -> bool {
689 self.center.x.is_finite() &&
690 self.center.y.is_finite() &&
691 self.angle.is_finite() &&
692 self.start_offset.is_finite() &&
693 self.end_offset.is_finite()
694 }
695}
696
697#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
699pub struct ClipChainItem {
700 pub id: ClipChainId,
701 pub parent: Option<ClipChainId>,
702} #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
705pub struct RadialGradientDisplayItem {
706 pub common: CommonItemProperties,
707 pub bounds: LayoutRect,
711 pub gradient: RadialGradient,
712 pub tile_size: LayoutSize,
713 pub tile_spacing: LayoutSize,
714}
715
716#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
717pub struct ConicGradientDisplayItem {
718 pub common: CommonItemProperties,
719 pub bounds: LayoutRect,
723 pub gradient: ConicGradient,
724 pub tile_size: LayoutSize,
725 pub tile_spacing: LayoutSize,
726}
727
728#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
730pub struct BackdropFilterDisplayItem {
731 pub common: CommonItemProperties,
732}
733#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
736pub struct ReferenceFrameDisplayListItem {
737 pub origin: LayoutPoint,
738 pub parent_spatial_id: SpatialId,
739 pub reference_frame: ReferenceFrame,
740}
741
742#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
743pub enum ReferenceFrameKind {
744 Transform {
746 is_2d_scale_translation: bool,
749 should_snap: bool,
752 },
753 Perspective {
755 scrolling_relative_to: Option<ExternalScrollId>,
756 }
757}
758
759#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
760pub enum Rotation {
761 Degree0,
762 Degree90,
763 Degree180,
764 Degree270,
765}
766
767impl Rotation {
768 pub fn to_matrix(
769 &self,
770 size: LayoutSize,
771 ) -> LayoutTransform {
772 let (shift_center_to_origin, angle) = match self {
773 Rotation::Degree0 => {
774 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(0.))
775 },
776 Rotation::Degree90 => {
777 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(90.))
778 },
779 Rotation::Degree180 => {
780 (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(180.))
781 },
782 Rotation::Degree270 => {
783 (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(270.))
784 },
785 };
786 let shift_origin_to_center = LayoutTransform::translation(size.width / 2., size.height / 2., 0.);
787
788 shift_center_to_origin
789 .then(&LayoutTransform::rotation(0., 0., 1.0, angle))
790 .then(&shift_origin_to_center)
791 }
792}
793
794#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
795pub enum ReferenceTransformBinding {
796 Static {
798 binding: PropertyBinding<LayoutTransform>,
799 },
800 Computed {
804 scale_from: Option<LayoutSize>,
805 vertical_flip: bool,
806 rotation: Rotation,
807 },
808}
809
810impl Default for ReferenceTransformBinding {
811 fn default() -> Self {
812 ReferenceTransformBinding::Static {
813 binding: Default::default(),
814 }
815 }
816}
817
818#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
819pub struct ReferenceFrame {
820 pub kind: ReferenceFrameKind,
821 pub transform_style: TransformStyle,
822 pub transform: ReferenceTransformBinding,
825 pub id: SpatialId,
826}
827
828#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
829pub struct PushStackingContextDisplayItem {
830 pub origin: LayoutPoint,
831 pub spatial_id: SpatialId,
832 pub prim_flags: PrimitiveFlags,
833 pub stacking_context: StackingContext,
834}
835
836#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
837pub struct StackingContext {
838 pub transform_style: TransformStyle,
839 pub mix_blend_mode: MixBlendMode,
840 pub clip_id: Option<ClipId>,
841 pub raster_space: RasterSpace,
842 pub flags: StackingContextFlags,
843}
844#[repr(u8)]
847#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
848pub enum TransformStyle {
849 Flat = 0,
850 Preserve3D = 1,
851}
852
853#[derive(Clone, Copy, Debug, Deserialize, PartialEq, MallocSizeOf, Serialize, PeekPoke)]
860#[repr(u8)]
861pub enum RasterSpace {
862 Local(f32),
865
866 Screen,
871}
872
873impl RasterSpace {
874 pub fn local_scale(self) -> Option<f32> {
875 match self {
876 RasterSpace::Local(scale) => Some(scale),
877 RasterSpace::Screen => None,
878 }
879 }
880}
881
882impl Eq for RasterSpace {}
883
884impl Hash for RasterSpace {
885 fn hash<H: Hasher>(&self, state: &mut H) {
886 match self {
887 RasterSpace::Screen => {
888 0.hash(state);
889 }
890 RasterSpace::Local(scale) => {
891 1.hash(state);
893 scale.to_bits().hash(state);
894 }
895 }
896 }
897}
898
899bitflags! {
900 #[repr(C)]
901 #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
902 pub struct StackingContextFlags: u8 {
903 const IS_BACKDROP_ROOT = 1 << 0;
906 const IS_BLEND_CONTAINER = 1 << 1;
909 }
910}
911
912impl Default for StackingContextFlags {
913 fn default() -> Self {
914 StackingContextFlags::empty()
915 }
916}
917
918#[repr(u8)]
919#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
920pub enum MixBlendMode {
921 Normal = 0,
922 Multiply = 1,
923 Screen = 2,
924 Overlay = 3,
925 Darken = 4,
926 Lighten = 5,
927 ColorDodge = 6,
928 ColorBurn = 7,
929 HardLight = 8,
930 SoftLight = 9,
931 Difference = 10,
932 Exclusion = 11,
933 Hue = 12,
934 Saturation = 13,
935 Color = 14,
936 Luminosity = 15,
937}
938
939#[repr(C)]
940#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
941pub enum ColorSpace {
942 Srgb,
943 LinearRgb,
944}
945
946#[repr(C)]
948#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
949pub enum CompositeOperator {
950 Over,
951 In,
952 Atop,
953 Out,
954 Xor,
955 Lighter,
956 Arithmetic([f32; 4]),
957}
958
959impl CompositeOperator {
960 pub fn as_int(&self) -> u32 {
962 match self {
963 CompositeOperator::Over => 0,
964 CompositeOperator::In => 1,
965 CompositeOperator::Out => 2,
966 CompositeOperator::Atop => 3,
967 CompositeOperator::Xor => 4,
968 CompositeOperator::Lighter => 5,
969 CompositeOperator::Arithmetic(..) => 6,
970 }
971 }
972}
973
974#[repr(C)]
976#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
977pub enum FilterPrimitiveInput {
978 Original,
980 Previous,
982 OutputOfPrimitiveIndex(usize),
984}
985
986impl FilterPrimitiveInput {
987 pub fn to_index(self, cur_index: usize) -> Option<usize> {
990 match self {
991 FilterPrimitiveInput::Previous if cur_index > 0 => Some(cur_index - 1),
992 FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => Some(index),
993 _ => None,
994 }
995 }
996}
997
998#[repr(C)]
999#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1000pub struct BlendPrimitive {
1001 pub input1: FilterPrimitiveInput,
1002 pub input2: FilterPrimitiveInput,
1003 pub mode: MixBlendMode,
1004}
1005
1006#[repr(C)]
1007#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1008pub struct FloodPrimitive {
1009 pub color: ColorF,
1010}
1011
1012impl FloodPrimitive {
1013 pub fn sanitize(&mut self) {
1014 self.color.r = self.color.r.min(1.0).max(0.0);
1015 self.color.g = self.color.g.min(1.0).max(0.0);
1016 self.color.b = self.color.b.min(1.0).max(0.0);
1017 self.color.a = self.color.a.min(1.0).max(0.0);
1018 }
1019}
1020
1021#[repr(C)]
1022#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1023pub struct BlurPrimitive {
1024 pub input: FilterPrimitiveInput,
1025 pub width: f32,
1026 pub height: f32,
1027}
1028
1029#[repr(C)]
1030#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1031pub struct OpacityPrimitive {
1032 pub input: FilterPrimitiveInput,
1033 pub opacity: f32,
1034}
1035
1036impl OpacityPrimitive {
1037 pub fn sanitize(&mut self) {
1038 self.opacity = self.opacity.min(1.0).max(0.0);
1039 }
1040}
1041
1042#[repr(C)]
1044#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1045pub struct ColorMatrixPrimitive {
1046 pub input: FilterPrimitiveInput,
1047 pub matrix: [f32; 20],
1048}
1049
1050#[repr(C)]
1051#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1052pub struct DropShadowPrimitive {
1053 pub input: FilterPrimitiveInput,
1054 pub shadow: Shadow,
1055}
1056
1057#[repr(C)]
1058#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1059pub struct ComponentTransferPrimitive {
1060 pub input: FilterPrimitiveInput,
1061 }
1063
1064#[repr(C)]
1065#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1066pub struct IdentityPrimitive {
1067 pub input: FilterPrimitiveInput,
1068}
1069
1070#[repr(C)]
1071#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1072pub struct OffsetPrimitive {
1073 pub input: FilterPrimitiveInput,
1074 pub offset: LayoutVector2D,
1075}
1076
1077#[repr(C)]
1078#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1079pub struct CompositePrimitive {
1080 pub input1: FilterPrimitiveInput,
1081 pub input2: FilterPrimitiveInput,
1082 pub operator: CompositeOperator,
1083}
1084
1085#[repr(C)]
1088#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
1089pub enum FilterPrimitiveKind {
1090 Identity(IdentityPrimitive),
1091 Blend(BlendPrimitive),
1092 Flood(FloodPrimitive),
1093 Blur(BlurPrimitive),
1094 Opacity(OpacityPrimitive),
1096 ColorMatrix(ColorMatrixPrimitive),
1098 DropShadow(DropShadowPrimitive),
1099 ComponentTransfer(ComponentTransferPrimitive),
1100 Offset(OffsetPrimitive),
1101 Composite(CompositePrimitive),
1102}
1103
1104impl Default for FilterPrimitiveKind {
1105 fn default() -> Self {
1106 FilterPrimitiveKind::Identity(IdentityPrimitive::default())
1107 }
1108}
1109
1110impl FilterPrimitiveKind {
1111 pub fn sanitize(&mut self) {
1112 match self {
1113 FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
1114 FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),
1115
1116 FilterPrimitiveKind::Identity(..) |
1118 FilterPrimitiveKind::Blend(..) |
1119 FilterPrimitiveKind::ColorMatrix(..) |
1120 FilterPrimitiveKind::Offset(..) |
1121 FilterPrimitiveKind::Composite(..) |
1122 FilterPrimitiveKind::Blur(..) |
1123 FilterPrimitiveKind::DropShadow(..) |
1124 FilterPrimitiveKind::ComponentTransfer(..) => {}
1126 }
1127 }
1128}
1129
1130#[repr(C)]
1134#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1135pub struct FilterPrimitive {
1136 pub kind: FilterPrimitiveKind,
1137 pub color_space: ColorSpace,
1138}
1139
1140impl FilterPrimitive {
1141 pub fn sanitize(&mut self) {
1142 self.kind.sanitize();
1143 }
1144}
1145
1146#[repr(C)]
1148#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
1149pub enum FilterOp {
1150 Identity,
1153 Blur(f32, f32),
1154 Brightness(f32),
1155 Contrast(f32),
1156 Grayscale(f32),
1157 HueRotate(f32),
1158 Invert(f32),
1159 Opacity(PropertyBinding<f32>, f32),
1160 Saturate(f32),
1161 Sepia(f32),
1162 DropShadow(Shadow),
1163 ColorMatrix([f32; 20]),
1164 SrgbToLinear,
1165 LinearToSrgb,
1166 ComponentTransfer,
1167 Flood(ColorF),
1168}
1169
1170#[repr(u8)]
1171#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
1172pub enum ComponentTransferFuncType {
1173 Identity = 0,
1174 Table = 1,
1175 Discrete = 2,
1176 Linear = 3,
1177 Gamma = 4,
1178}
1179
1180#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
1181pub struct FilterData {
1182 pub func_r_type: ComponentTransferFuncType,
1183 pub r_values: Vec<f32>,
1184 pub func_g_type: ComponentTransferFuncType,
1185 pub g_values: Vec<f32>,
1186 pub func_b_type: ComponentTransferFuncType,
1187 pub b_values: Vec<f32>,
1188 pub func_a_type: ComponentTransferFuncType,
1189 pub a_values: Vec<f32>,
1190}
1191
1192fn sanitize_func_type(
1193 func_type: ComponentTransferFuncType,
1194 values: &[f32],
1195) -> ComponentTransferFuncType {
1196 if values.is_empty() {
1197 return ComponentTransferFuncType::Identity;
1198 }
1199 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1200 return ComponentTransferFuncType::Identity;
1201 }
1202 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1203 return ComponentTransferFuncType::Identity;
1204 }
1205 func_type
1206}
1207
1208fn sanitize_values(
1209 func_type: ComponentTransferFuncType,
1210 values: &[f32],
1211) -> bool {
1212 if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
1213 return false;
1214 }
1215 if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
1216 return false;
1217 }
1218 true
1219}
1220
1221impl FilterData {
1222 pub fn sanitize(&self) -> FilterData {
1224 FilterData {
1225 func_r_type: sanitize_func_type(self.func_r_type, &self.r_values),
1226 r_values:
1227 if sanitize_values(self.func_r_type, &self.r_values) {
1228 self.r_values.clone()
1229 } else {
1230 Vec::new()
1231 },
1232 func_g_type: sanitize_func_type(self.func_g_type, &self.g_values),
1233 g_values:
1234 if sanitize_values(self.func_g_type, &self.g_values) {
1235 self.g_values.clone()
1236 } else {
1237 Vec::new()
1238 },
1239
1240 func_b_type: sanitize_func_type(self.func_b_type, &self.b_values),
1241 b_values:
1242 if sanitize_values(self.func_b_type, &self.b_values) {
1243 self.b_values.clone()
1244 } else {
1245 Vec::new()
1246 },
1247
1248 func_a_type: sanitize_func_type(self.func_a_type, &self.a_values),
1249 a_values:
1250 if sanitize_values(self.func_a_type, &self.a_values) {
1251 self.a_values.clone()
1252 } else {
1253 Vec::new()
1254 },
1255
1256 }
1257 }
1258
1259 pub fn is_identity(&self) -> bool {
1260 self.func_r_type == ComponentTransferFuncType::Identity &&
1261 self.func_g_type == ComponentTransferFuncType::Identity &&
1262 self.func_b_type == ComponentTransferFuncType::Identity &&
1263 self.func_a_type == ComponentTransferFuncType::Identity
1264 }
1265}
1266
1267#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1268pub struct IframeDisplayItem {
1269 pub bounds: LayoutRect,
1270 pub clip_rect: LayoutRect,
1271 pub space_and_clip: SpaceAndClipInfo,
1272 pub pipeline_id: PipelineId,
1273 pub ignore_missing_pipeline: bool,
1274}
1275
1276#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1281pub struct ImageDisplayItem {
1282 pub common: CommonItemProperties,
1283 pub bounds: LayoutRect,
1287 pub image_key: ImageKey,
1288 pub image_rendering: ImageRendering,
1289 pub alpha_type: AlphaType,
1290 pub color: ColorF,
1292}
1293
1294#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1297pub struct RepeatingImageDisplayItem {
1298 pub common: CommonItemProperties,
1299 pub bounds: LayoutRect,
1303 pub stretch_size: LayoutSize,
1305 pub tile_spacing: LayoutSize,
1307 pub image_key: ImageKey,
1308 pub image_rendering: ImageRendering,
1309 pub alpha_type: AlphaType,
1310 pub color: ColorF,
1312}
1313
1314#[repr(u8)]
1315#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1316pub enum ImageRendering {
1317 Auto = 0,
1318 CrispEdges = 1,
1319 Pixelated = 2,
1320}
1321
1322#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1323pub enum AlphaType {
1324 Alpha = 0,
1325 PremultipliedAlpha = 1,
1326}
1327
1328#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1329pub struct YuvImageDisplayItem {
1330 pub common: CommonItemProperties,
1331 pub bounds: LayoutRect,
1332 pub yuv_data: YuvData,
1333 pub color_depth: ColorDepth,
1334 pub color_space: YuvColorSpace,
1335 pub color_range: ColorRange,
1336 pub image_rendering: ImageRendering,
1337}
1338
1339#[repr(u8)]
1340#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1341pub enum YuvColorSpace {
1342 Rec601 = 0,
1343 Rec709 = 1,
1344 Rec2020 = 2,
1345 Identity = 3, }
1347
1348#[repr(u8)]
1349#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1350pub enum ColorRange {
1351 Limited = 0,
1352 Full = 1,
1353}
1354
1355#[repr(u8)]
1356#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1357pub enum YuvRangedColorSpace {
1358 Rec601Narrow = 0,
1359 Rec601Full = 1,
1360 Rec709Narrow = 2,
1361 Rec709Full = 3,
1362 Rec2020Narrow = 4,
1363 Rec2020Full = 5,
1364 GbrIdentity = 6,
1365}
1366
1367impl YuvColorSpace {
1368 pub fn with_range(self, range: ColorRange) -> YuvRangedColorSpace {
1369 match self {
1370 YuvColorSpace::Identity => YuvRangedColorSpace::GbrIdentity,
1371 YuvColorSpace::Rec601 => {
1372 match range {
1373 ColorRange::Limited => YuvRangedColorSpace::Rec601Narrow,
1374 ColorRange::Full => YuvRangedColorSpace::Rec601Full,
1375 }
1376 }
1377 YuvColorSpace::Rec709 => {
1378 match range {
1379 ColorRange::Limited => YuvRangedColorSpace::Rec709Narrow,
1380 ColorRange::Full => YuvRangedColorSpace::Rec709Full,
1381 }
1382 }
1383 YuvColorSpace::Rec2020 => {
1384 match range {
1385 ColorRange::Limited => YuvRangedColorSpace::Rec2020Narrow,
1386 ColorRange::Full => YuvRangedColorSpace::Rec2020Full,
1387 }
1388 }
1389 }
1390 }
1391}
1392
1393#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1394pub enum YuvData {
1395 NV12(ImageKey, ImageKey), PlanarYCbCr(ImageKey, ImageKey, ImageKey), InterleavedYCbCr(ImageKey), }
1399
1400impl YuvData {
1401 pub fn get_format(&self) -> YuvFormat {
1402 match *self {
1403 YuvData::NV12(..) => YuvFormat::NV12,
1404 YuvData::PlanarYCbCr(..) => YuvFormat::PlanarYCbCr,
1405 YuvData::InterleavedYCbCr(..) => YuvFormat::InterleavedYCbCr,
1406 }
1407 }
1408}
1409
1410#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1411pub enum YuvFormat {
1412 NV12 = 0,
1413 PlanarYCbCr = 1,
1414 InterleavedYCbCr = 2,
1415}
1416
1417impl YuvFormat {
1418 pub fn get_plane_num(self) -> usize {
1419 match self {
1420 YuvFormat::NV12 => 2,
1421 YuvFormat::PlanarYCbCr => 3,
1422 YuvFormat::InterleavedYCbCr => 1,
1423 }
1424 }
1425}
1426
1427#[repr(C)]
1428#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1429pub struct ImageMask {
1430 pub image: ImageKey,
1431 pub rect: LayoutRect,
1432 pub repeat: bool,
1433}
1434
1435impl ImageMask {
1436 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
1438 if self.repeat {
1439 None
1440 } else {
1441 Some(self.rect)
1442 }
1443 }
1444}
1445
1446#[repr(C)]
1447#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
1448pub enum ClipMode {
1449 Clip, ClipOut, }
1452
1453impl Not for ClipMode {
1454 type Output = ClipMode;
1455
1456 fn not(self) -> ClipMode {
1457 match self {
1458 ClipMode::Clip => ClipMode::ClipOut,
1459 ClipMode::ClipOut => ClipMode::Clip,
1460 }
1461 }
1462}
1463
1464#[repr(C)]
1465#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1466pub struct ComplexClipRegion {
1467 pub rect: LayoutRect,
1469 pub radii: BorderRadius,
1471 pub mode: ClipMode,
1474}
1475
1476impl BorderRadius {
1477 pub fn zero() -> BorderRadius {
1478 BorderRadius {
1479 top_left: LayoutSize::new(0.0, 0.0),
1480 top_right: LayoutSize::new(0.0, 0.0),
1481 bottom_left: LayoutSize::new(0.0, 0.0),
1482 bottom_right: LayoutSize::new(0.0, 0.0),
1483 }
1484 }
1485
1486 pub fn uniform(radius: f32) -> BorderRadius {
1487 BorderRadius {
1488 top_left: LayoutSize::new(radius, radius),
1489 top_right: LayoutSize::new(radius, radius),
1490 bottom_left: LayoutSize::new(radius, radius),
1491 bottom_right: LayoutSize::new(radius, radius),
1492 }
1493 }
1494
1495 pub fn uniform_size(radius: LayoutSize) -> BorderRadius {
1496 BorderRadius {
1497 top_left: radius,
1498 top_right: radius,
1499 bottom_left: radius,
1500 bottom_right: radius,
1501 }
1502 }
1503
1504 pub fn is_uniform(&self) -> Option<f32> {
1505 match self.is_uniform_size() {
1506 Some(radius) if radius.width == radius.height => Some(radius.width),
1507 _ => None,
1508 }
1509 }
1510
1511 pub fn is_uniform_size(&self) -> Option<LayoutSize> {
1512 let uniform_radius = self.top_left;
1513 if self.top_right == uniform_radius && self.bottom_left == uniform_radius &&
1514 self.bottom_right == uniform_radius
1515 {
1516 Some(uniform_radius)
1517 } else {
1518 None
1519 }
1520 }
1521
1522 pub fn is_zero(&self) -> bool {
1525 let corner_is_zero = |corner: &LayoutSize| corner.width == 0.0 || corner.height == 0.0;
1526 corner_is_zero(&self.top_left) &&
1527 corner_is_zero(&self.top_right) &&
1528 corner_is_zero(&self.bottom_right) &&
1529 corner_is_zero(&self.bottom_left)
1530 }
1531}
1532
1533impl ComplexClipRegion {
1534 pub fn new(
1536 rect: LayoutRect,
1537 radii: BorderRadius,
1538 mode: ClipMode,
1539 ) -> Self {
1540 ComplexClipRegion { rect, radii, mode }
1541 }
1542}
1543
1544impl ComplexClipRegion {
1545 pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
1547 match self.mode {
1548 ClipMode::Clip => {
1549 Some(self.rect)
1550 }
1551 ClipMode::ClipOut => {
1552 None
1553 }
1554 }
1555 }
1556}
1557
1558pub const POLYGON_CLIP_VERTEX_MAX: usize = 16;
1559
1560#[repr(u8)]
1561#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
1562pub enum FillRule {
1563 Nonzero = 0x1, Evenodd = 0x2, }
1566
1567impl From<u8> for FillRule {
1568 fn from(fill_rule: u8) -> Self {
1569 match fill_rule {
1570 0x1 => FillRule::Nonzero,
1571 0x2 => FillRule::Evenodd,
1572 _ => panic!("Unexpected FillRule value."),
1573 }
1574 }
1575}
1576
1577impl From<FillRule> for u8 {
1578 fn from(fill_rule: FillRule) -> Self {
1579 match fill_rule {
1580 FillRule::Nonzero => 0x1,
1581 FillRule::Evenodd => 0x2,
1582 }
1583 }
1584}
1585
1586#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1587pub struct ClipChainId(pub u64, pub PipelineId);
1588
1589#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1591pub enum ClipId {
1592 Clip(usize, PipelineId),
1593 ClipChain(ClipChainId),
1594}
1595
1596const ROOT_CLIP_ID: usize = 0;
1597
1598impl ClipId {
1599 pub fn root(pipeline_id: PipelineId) -> Self {
1601 ClipId::Clip(ROOT_CLIP_ID, pipeline_id)
1602 }
1603
1604 pub fn invalid() -> Self {
1607 ClipId::Clip(!0, PipelineId::dummy())
1608 }
1609
1610 pub fn pipeline_id(&self) -> PipelineId {
1611 match *self {
1612 ClipId::Clip(_, pipeline_id) |
1613 ClipId::ClipChain(ClipChainId(_, pipeline_id)) => pipeline_id,
1614 }
1615 }
1616
1617 pub fn is_root(&self) -> bool {
1618 match *self {
1619 ClipId::Clip(id, _) => id == ROOT_CLIP_ID,
1620 ClipId::ClipChain(_) => false,
1621 }
1622 }
1623
1624 pub fn is_valid(&self) -> bool {
1625 match *self {
1626 ClipId::Clip(id, _) => id != !0,
1627 _ => true,
1628 }
1629 }
1630}
1631
1632#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1634pub struct SpatialId(pub usize, PipelineId);
1635
1636const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
1637const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
1638
1639impl SpatialId {
1640 pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
1641 SpatialId(spatial_node_index, pipeline_id)
1642 }
1643
1644 pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
1645 SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
1646 }
1647
1648 pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
1649 SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
1650 }
1651
1652 pub fn pipeline_id(&self) -> PipelineId {
1653 self.1
1654 }
1655
1656 pub fn is_root_reference_frame(&self) -> bool {
1657 self.0 == ROOT_REFERENCE_FRAME_SPATIAL_ID
1658 }
1659
1660 pub fn is_root_scroll_node(&self) -> bool {
1661 self.0 == ROOT_SCROLL_NODE_SPATIAL_ID
1662 }
1663}
1664
1665#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
1673#[repr(C)]
1674pub struct ExternalScrollId(pub u64, pub PipelineId);
1675
1676impl ExternalScrollId {
1677 pub fn pipeline_id(&self) -> PipelineId {
1678 self.1
1679 }
1680
1681 pub fn is_root(&self) -> bool {
1682 self.0 == 0
1683 }
1684}
1685
1686impl DisplayItem {
1687 pub fn debug_name(&self) -> &'static str {
1688 match *self {
1689 DisplayItem::Border(..) => "border",
1690 DisplayItem::BoxShadow(..) => "box_shadow",
1691 DisplayItem::ClearRectangle(..) => "clear_rectangle",
1692 DisplayItem::HitTest(..) => "hit_test",
1693 DisplayItem::RectClip(..) => "rect_clip",
1694 DisplayItem::RoundedRectClip(..) => "rounded_rect_clip",
1695 DisplayItem::ImageMaskClip(..) => "image_mask_clip",
1696 DisplayItem::ClipChain(..) => "clip_chain",
1697 DisplayItem::ConicGradient(..) => "conic_gradient",
1698 DisplayItem::Gradient(..) => "gradient",
1699 DisplayItem::Iframe(..) => "iframe",
1700 DisplayItem::Image(..) => "image",
1701 DisplayItem::RepeatingImage(..) => "repeating_image",
1702 DisplayItem::Line(..) => "line",
1703 DisplayItem::PopAllShadows => "pop_all_shadows",
1704 DisplayItem::PopReferenceFrame => "pop_reference_frame",
1705 DisplayItem::PopStackingContext => "pop_stacking_context",
1706 DisplayItem::PushShadow(..) => "push_shadow",
1707 DisplayItem::PushReferenceFrame(..) => "push_reference_frame",
1708 DisplayItem::PushStackingContext(..) => "push_stacking_context",
1709 DisplayItem::SetFilterOps => "set_filter_ops",
1710 DisplayItem::SetFilterData => "set_filter_data",
1711 DisplayItem::SetFilterPrimitives => "set_filter_primitives",
1712 DisplayItem::SetPoints => "set_points",
1713 DisplayItem::RadialGradient(..) => "radial_gradient",
1714 DisplayItem::Rectangle(..) => "rectangle",
1715 DisplayItem::ScrollFrame(..) => "scroll_frame",
1716 DisplayItem::SetGradientStops => "set_gradient_stops",
1717 DisplayItem::ReuseItems(..) => "reuse_item",
1718 DisplayItem::RetainedItems(..) => "retained_items",
1719 DisplayItem::StickyFrame(..) => "sticky_frame",
1720 DisplayItem::Text(..) => "text",
1721 DisplayItem::YuvImage(..) => "yuv_image",
1722 DisplayItem::BackdropFilter(..) => "backdrop_filter",
1723 }
1724 }
1725}
1726
1727macro_rules! impl_default_for_enums {
1728 ($($enum:ident => $init:expr ),+) => {
1729 $(impl Default for $enum {
1730 #[allow(unused_imports)]
1731 fn default() -> Self {
1732 use $enum::*;
1733 $init
1734 }
1735 })*
1736 }
1737}
1738
1739impl_default_for_enums! {
1740 DisplayItem => PopStackingContext,
1741 ScrollSensitivity => ScriptAndInputEvents,
1742 LineOrientation => Vertical,
1743 LineStyle => Solid,
1744 RepeatMode => Stretch,
1745 NinePatchBorderSource => Image(ImageKey::default()),
1746 BorderDetails => Normal(NormalBorder::default()),
1747 BorderRadiusKind => Uniform,
1748 BorderStyle => None,
1749 BoxShadowClipMode => Outset,
1750 ExtendMode => Clamp,
1751 FilterOp => Identity,
1752 ComponentTransferFuncType => Identity,
1753 ClipMode => Clip,
1754 FillRule => Nonzero,
1755 ClipId => ClipId::invalid(),
1756 ReferenceFrameKind => Transform {
1757 is_2d_scale_translation: false,
1758 should_snap: false,
1759 },
1760 Rotation => Degree0,
1761 TransformStyle => Flat,
1762 RasterSpace => Local(f32::default()),
1763 MixBlendMode => Normal,
1764 ImageRendering => Auto,
1765 AlphaType => Alpha,
1766 YuvColorSpace => Rec601,
1767 YuvRangedColorSpace => Rec601Narrow,
1768 ColorRange => Limited,
1769 YuvData => NV12(ImageKey::default(), ImageKey::default()),
1770 YuvFormat => NV12,
1771 FilterPrimitiveInput => Original,
1772 ColorSpace => Srgb,
1773 CompositeOperator => Over
1774}