use euclid::{SideOffsets2D, TypedRect};
use std::ops::Not;
use font;
use api::{PipelineId, PropertyBinding};
use color::ColorF;
use image::{ColorDepth, ImageKey};
use units::*;
pub const MAX_BLUR_RADIUS: f32 = 300.;
pub type ItemTag = (u64, u16);
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct GenericDisplayItem<T> {
pub item: T,
pub layout: LayoutPrimitiveInfo,
pub space_and_clip: SpaceAndClipInfo,
}
pub type DisplayItem = GenericDisplayItem<SpecificDisplayItem>;
#[derive(Serialize)]
pub struct SerializedDisplayItem<'a> {
pub item: &'a SpecificDisplayItem,
pub layout: &'a LayoutPrimitiveInfo,
pub space_and_clip: &'a SpaceAndClipInfo,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct PrimitiveInfo<T> {
pub rect: TypedRect<f32, T>,
pub clip_rect: TypedRect<f32, T>,
pub is_backface_visible: bool,
pub tag: Option<ItemTag>,
}
impl LayoutPrimitiveInfo {
pub fn new(rect: TypedRect<f32, LayoutPixel>) -> Self {
Self::with_clip_rect(rect, rect)
}
pub fn with_clip_rect(
rect: TypedRect<f32, LayoutPixel>,
clip_rect: TypedRect<f32, LayoutPixel>,
) -> Self {
PrimitiveInfo {
rect,
clip_rect,
is_backface_visible: true,
tag: None,
}
}
}
pub type LayoutPrimitiveInfo = PrimitiveInfo<LayoutPixel>;
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct SpaceAndClipInfo {
pub spatial_id: SpatialId,
pub clip_id: ClipId,
}
impl SpaceAndClipInfo {
pub fn root_scroll(pipeline_id: PipelineId) -> Self {
SpaceAndClipInfo {
spatial_id: SpatialId::root_scroll_node(pipeline_id),
clip_id: ClipId::root(pipeline_id),
}
}
}
#[repr(u64)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum SpecificDisplayItem {
Clip(ClipDisplayItem),
ScrollFrame(ScrollFrameDisplayItem),
StickyFrame(StickyFrameDisplayItem),
Rectangle(RectangleDisplayItem),
ClearRectangle,
Line(LineDisplayItem),
Text(TextDisplayItem),
Image(ImageDisplayItem),
YuvImage(YuvImageDisplayItem),
Border(BorderDisplayItem),
BoxShadow(BoxShadowDisplayItem),
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
ClipChain(ClipChainItem),
Iframe(IframeDisplayItem),
PushReferenceFrame(ReferenceFrameDisplayListItem),
PopReferenceFrame,
PushStackingContext(PushStackingContextDisplayItem),
PopStackingContext,
SetGradientStops,
PushShadow(Shadow),
PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
}
#[cfg(any(feature = "serialize", feature = "deserialize"))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum CompletelySpecificDisplayItem {
Clip(ClipDisplayItem, Vec<ComplexClipRegion>),
ClipChain(ClipChainItem, Vec<ClipId>),
ScrollFrame(ScrollFrameDisplayItem, Vec<ComplexClipRegion>),
StickyFrame(StickyFrameDisplayItem),
Rectangle(RectangleDisplayItem),
ClearRectangle,
Line(LineDisplayItem),
Text(TextDisplayItem, Vec<font::GlyphInstance>),
Image(ImageDisplayItem),
YuvImage(YuvImageDisplayItem),
Border(BorderDisplayItem),
BoxShadow(BoxShadowDisplayItem),
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
Iframe(IframeDisplayItem),
PushReferenceFrame(ReferenceFrameDisplayListItem),
PopReferenceFrame,
PushStackingContext(PushStackingContextDisplayItem, Vec<FilterOp>),
PopStackingContext,
SetGradientStops(Vec<GradientStop>),
PushShadow(Shadow),
PopAllShadows,
PushCacheMarker(CacheMarkerDisplayItem),
PopCacheMarker,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClipDisplayItem {
pub id: ClipId,
pub image_mask: Option<ImageMask>,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct StickyOffsetBounds {
pub min: f32,
pub max: f32,
}
impl StickyOffsetBounds {
pub fn new(min: f32, max: f32) -> StickyOffsetBounds {
StickyOffsetBounds { min, max }
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct StickyFrameDisplayItem {
pub id: SpatialId,
pub margins: SideOffsets2D<Option<f32>>,
pub vertical_offset_bounds: StickyOffsetBounds,
pub horizontal_offset_bounds: StickyOffsetBounds,
pub previously_applied_offset: LayoutVector2D,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum ScrollSensitivity {
ScriptAndInputEvents,
Script,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ScrollFrameDisplayItem {
pub clip_id: ClipId,
pub scroll_frame_id: SpatialId,
pub external_id: Option<ExternalScrollId>,
pub image_mask: Option<ImageMask>,
pub scroll_sensitivity: ScrollSensitivity,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RectangleDisplayItem {
pub color: ColorF,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct LineDisplayItem {
pub orientation: LineOrientation,
pub wavy_line_thickness: f32,
pub color: ColorF,
pub style: LineStyle,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
pub enum LineOrientation {
Vertical,
Horizontal,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
pub enum LineStyle {
Solid,
Dotted,
Dashed,
Wavy,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct TextDisplayItem {
pub font_key: font::FontInstanceKey,
pub color: ColorF,
pub glyph_options: Option<font::GlyphOptions>,
}
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct NormalBorder {
pub left: BorderSide,
pub right: BorderSide,
pub top: BorderSide,
pub bottom: BorderSide,
pub radius: BorderRadius,
pub do_aa: bool,
}
impl NormalBorder {
fn can_disable_antialiasing(&self) -> bool {
fn is_valid(style: BorderStyle) -> bool {
style == BorderStyle::Solid || style == BorderStyle::None
}
self.radius.is_zero() &&
is_valid(self.top.style) &&
is_valid(self.left.style) &&
is_valid(self.bottom.style) &&
is_valid(self.right.style)
}
#[inline]
pub fn normalize(&mut self, widths: &LayoutSideOffsets) {
debug_assert!(
self.do_aa || self.can_disable_antialiasing(),
"Unexpected disabled-antialiasing in a border, likely won't work or will be ignored"
);
#[inline]
fn renders_small_border_solid(style: BorderStyle) -> bool {
match style {
BorderStyle::Groove |
BorderStyle::Ridge => true,
_ => false,
}
}
let normalize_side = |side: &mut BorderSide, width: f32| {
if renders_small_border_solid(side.style) && width < 2. {
side.style = BorderStyle::Solid;
}
};
normalize_side(&mut self.left, widths.left);
normalize_side(&mut self.right, widths.right);
normalize_side(&mut self.top, widths.top);
normalize_side(&mut self.bottom, widths.bottom);
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub enum RepeatMode {
Stretch,
Repeat,
Round,
Space,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum NinePatchBorderSource {
Image(ImageKey),
Gradient(Gradient),
RadialGradient(RadialGradient),
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct NinePatchBorder {
pub source: NinePatchBorderSource,
pub width: i32,
pub height: i32,
pub slice: SideOffsets2D<i32>,
pub fill: bool,
pub repeat_horizontal: RepeatMode,
pub repeat_vertical: RepeatMode,
pub outset: SideOffsets2D<f32>,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum BorderDetails {
Normal(NormalBorder),
NinePatch(NinePatchBorder),
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct BorderDisplayItem {
pub widths: LayoutSideOffsets,
pub details: BorderDetails,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum BorderRadiusKind {
Uniform,
NonUniform,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct BorderRadius {
pub top_left: LayoutSize,
pub top_right: LayoutSize,
pub bottom_left: LayoutSize,
pub bottom_right: LayoutSize,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct BorderSide {
pub color: ColorF,
pub style: BorderStyle,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq)]
pub enum BorderStyle {
None = 0,
Solid = 1,
Double = 2,
Dotted = 3,
Dashed = 4,
Hidden = 5,
Groove = 6,
Ridge = 7,
Inset = 8,
Outset = 9,
}
impl BorderStyle {
pub fn is_hidden(&self) -> bool {
*self == BorderStyle::Hidden || *self == BorderStyle::None
}
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum BoxShadowClipMode {
Outset = 0,
Inset = 1,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct BoxShadowDisplayItem {
pub box_bounds: LayoutRect,
pub offset: LayoutVector2D,
pub color: ColorF,
pub blur_radius: f32,
pub spread_radius: f32,
pub border_radius: BorderRadius,
pub clip_mode: BoxShadowClipMode,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct Shadow {
pub offset: LayoutVector2D,
pub color: ColorF,
pub blur_radius: f32,
pub should_inflate: bool,
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum ExtendMode {
Clamp,
Repeat,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct Gradient {
pub start_point: LayoutPoint,
pub end_point: LayoutPoint,
pub extend_mode: ExtendMode,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct GradientDisplayItem {
pub gradient: Gradient,
pub tile_size: LayoutSize,
pub tile_spacing: LayoutSize,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct GradientStop {
pub offset: f32,
pub color: ColorF,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradient {
pub center: LayoutPoint,
pub radius: LayoutSize,
pub start_offset: f32,
pub end_offset: f32,
pub extend_mode: ExtendMode,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClipChainItem {
pub id: ClipChainId,
pub parent: Option<ClipChainId>,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct RadialGradientDisplayItem {
pub gradient: RadialGradient,
pub tile_size: LayoutSize,
pub tile_spacing: LayoutSize,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ReferenceFrameDisplayListItem {
pub reference_frame: ReferenceFrame,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct CacheMarkerDisplayItem {
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub enum ReferenceFrameKind {
Transform,
Perspective {
scrolling_relative_to: Option<ExternalScrollId>,
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ReferenceFrame {
pub kind: ReferenceFrameKind,
pub transform_style: TransformStyle,
pub transform: PropertyBinding<LayoutTransform>,
pub id: SpatialId,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct PushStackingContextDisplayItem {
pub stacking_context: StackingContext,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct StackingContext {
pub transform_style: TransformStyle,
pub mix_blend_mode: MixBlendMode,
pub clip_id: Option<ClipId>,
pub raster_space: RasterSpace,
pub cache_tiles: bool,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum TransformStyle {
Flat = 0,
Preserve3D = 1,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
#[repr(u32)]
pub enum RasterSpace {
Local(f32),
Screen,
}
impl RasterSpace {
pub fn local_scale(&self) -> Option<f32> {
match *self {
RasterSpace::Local(scale) => Some(scale),
RasterSpace::Screen => None,
}
}
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum MixBlendMode {
Normal = 0,
Multiply = 1,
Screen = 2,
Overlay = 3,
Darken = 4,
Lighten = 5,
ColorDodge = 6,
ColorBurn = 7,
HardLight = 8,
SoftLight = 9,
Difference = 10,
Exclusion = 11,
Hue = 12,
Saturation = 13,
Color = 14,
Luminosity = 15,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
pub enum FilterOp {
Identity,
Blur(f32),
Brightness(f32),
Contrast(f32),
Grayscale(f32),
HueRotate(f32),
Invert(f32),
Opacity(PropertyBinding<f32>, f32),
Saturate(f32),
Sepia(f32),
DropShadow(LayoutVector2D, f32, ColorF),
ColorMatrix([f32; 20]),
SrgbToLinear,
LinearToSrgb,
}
impl FilterOp {
pub fn sanitize(self) -> FilterOp {
match self {
FilterOp::Blur(radius) => {
let radius = radius.min(MAX_BLUR_RADIUS);
FilterOp::Blur(radius)
}
FilterOp::DropShadow(offset, radius, color) => {
let radius = radius.min(MAX_BLUR_RADIUS);
FilterOp::DropShadow(offset, radius, color)
}
filter => filter,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct IframeDisplayItem {
pub pipeline_id: PipelineId,
pub ignore_missing_pipeline: bool,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageDisplayItem {
pub image_key: ImageKey,
pub stretch_size: LayoutSize,
pub tile_spacing: LayoutSize,
pub image_rendering: ImageRendering,
pub alpha_type: AlphaType,
pub color: ColorF,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum ImageRendering {
Auto = 0,
CrispEdges = 1,
Pixelated = 2,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum AlphaType {
Alpha = 0,
PremultipliedAlpha = 1,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct YuvImageDisplayItem {
pub yuv_data: YuvData,
pub color_depth: ColorDepth,
pub color_space: YuvColorSpace,
pub image_rendering: ImageRendering,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum YuvColorSpace {
Rec601 = 0,
Rec709 = 1,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum YuvData {
NV12(ImageKey, ImageKey),
PlanarYCbCr(ImageKey, ImageKey, ImageKey),
InterleavedYCbCr(ImageKey),
}
impl YuvData {
pub fn get_format(&self) -> YuvFormat {
match *self {
YuvData::NV12(..) => YuvFormat::NV12,
YuvData::PlanarYCbCr(..) => YuvFormat::PlanarYCbCr,
YuvData::InterleavedYCbCr(..) => YuvFormat::InterleavedYCbCr,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub enum YuvFormat {
NV12 = 0,
PlanarYCbCr = 1,
InterleavedYCbCr = 2,
}
impl YuvFormat {
pub fn get_plane_num(&self) -> usize {
match *self {
YuvFormat::NV12 => 2,
YuvFormat::PlanarYCbCr => 3,
YuvFormat::InterleavedYCbCr => 1,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ImageMask {
pub image: ImageKey,
pub rect: LayoutRect,
pub repeat: bool,
}
impl ImageMask {
pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
if self.repeat {
None
} else {
Some(self.rect)
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub enum ClipMode {
Clip,
ClipOut,
}
impl Not for ClipMode {
type Output = ClipMode;
fn not(self) -> ClipMode {
match self {
ClipMode::Clip => ClipMode::ClipOut,
ClipMode::ClipOut => ClipMode::Clip,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ComplexClipRegion {
pub rect: LayoutRect,
pub radii: BorderRadius,
pub mode: ClipMode,
}
impl BorderRadius {
pub fn zero() -> BorderRadius {
BorderRadius {
top_left: LayoutSize::new(0.0, 0.0),
top_right: LayoutSize::new(0.0, 0.0),
bottom_left: LayoutSize::new(0.0, 0.0),
bottom_right: LayoutSize::new(0.0, 0.0),
}
}
pub fn uniform(radius: f32) -> BorderRadius {
BorderRadius {
top_left: LayoutSize::new(radius, radius),
top_right: LayoutSize::new(radius, radius),
bottom_left: LayoutSize::new(radius, radius),
bottom_right: LayoutSize::new(radius, radius),
}
}
pub fn uniform_size(radius: LayoutSize) -> BorderRadius {
BorderRadius {
top_left: radius,
top_right: radius,
bottom_left: radius,
bottom_right: radius,
}
}
pub fn is_uniform(&self) -> Option<f32> {
match self.is_uniform_size() {
Some(radius) if radius.width == radius.height => Some(radius.width),
_ => None,
}
}
pub fn is_uniform_size(&self) -> Option<LayoutSize> {
let uniform_radius = self.top_left;
if self.top_right == uniform_radius && self.bottom_left == uniform_radius &&
self.bottom_right == uniform_radius
{
Some(uniform_radius)
} else {
None
}
}
pub fn is_zero(&self) -> bool {
if let Some(radius) = self.is_uniform() {
radius == 0.0
} else {
false
}
}
}
impl ComplexClipRegion {
pub fn new(
rect: LayoutRect,
radii: BorderRadius,
mode: ClipMode,
) -> Self {
ComplexClipRegion { rect, radii, mode }
}
}
impl ComplexClipRegion {
pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
match self.mode {
ClipMode::Clip => {
Some(self.rect)
}
ClipMode::ClipOut => {
None
}
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ClipChainId(pub u64, pub PipelineId);
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub enum ClipId {
Clip(usize, PipelineId),
ClipChain(ClipChainId),
}
const ROOT_CLIP_ID: usize = 0;
impl ClipId {
pub fn root(pipeline_id: PipelineId) -> Self {
ClipId::Clip(ROOT_CLIP_ID, pipeline_id)
}
pub fn invalid() -> Self {
ClipId::Clip(!0, PipelineId::dummy())
}
pub fn pipeline_id(&self) -> PipelineId {
match *self {
ClipId::Clip(_, pipeline_id) |
ClipId::ClipChain(ClipChainId(_, pipeline_id)) => pipeline_id,
}
}
pub fn is_root(&self) -> bool {
match *self {
ClipId::Clip(id, _) => id == ROOT_CLIP_ID,
ClipId::ClipChain(_) => false,
}
}
pub fn is_valid(&self) -> bool {
match *self {
ClipId::Clip(id, _) => id != !0,
_ => true,
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct SpatialId(pub usize, PipelineId);
const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
const ROOT_SCROLL_NODE_SPATIAL_ID: usize = 1;
impl SpatialId {
pub fn new(spatial_node_index: usize, pipeline_id: PipelineId) -> Self {
SpatialId(spatial_node_index, pipeline_id)
}
pub fn root_reference_frame(pipeline_id: PipelineId) -> Self {
SpatialId(ROOT_REFERENCE_FRAME_SPATIAL_ID, pipeline_id)
}
pub fn root_scroll_node(pipeline_id: PipelineId) -> Self {
SpatialId(ROOT_SCROLL_NODE_SPATIAL_ID, pipeline_id)
}
pub fn pipeline_id(&self) -> PipelineId {
self.1
}
pub fn is_root_reference_frame(&self) -> bool {
self.0 == ROOT_REFERENCE_FRAME_SPATIAL_ID
}
pub fn is_root_scroll_node(&self) -> bool {
self.0 == ROOT_SCROLL_NODE_SPATIAL_ID
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[repr(C)]
pub struct ExternalScrollId(pub u64, pub PipelineId);
impl ExternalScrollId {
pub fn pipeline_id(&self) -> PipelineId {
self.1
}
pub fn is_root(&self) -> bool {
self.0 == 0
}
}