Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  display_item.rs   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::{SideOffsets2D, Angle};
use peek_poke::PeekPoke;
use std::ops::Not;
// local imports
use crate::{font, SnapshotImageKey};
use crate::{APZScrollGeneration, HasScrollLinkedEffect, PipelineId, PropertyBinding};
use crate::serde::{Serialize, Deserialize};
use crate::color::ColorF;
use crate::image::{ColorDepth, ImageKey};
use crate::units::*;
use std::hash::{Hash, Hasher};

// ******************************************************************
// * NOTE: some of these structs have an "IMPLICIT" comment.        *
// * This indicates that the BuiltDisplayList will have serialized  *
// * a list of values nearby that this item consumes. The traversal *
// * iterator should handle finding these. DebugDisplayItem should  *
// * make them explicit.                                            *
// ******************************************************************

/// A tag that can be used to identify items during hit testing. If the tag
/// is missing then the item doesn't take part in hit testing at all. This
/// is composed of two numbers. In Servo, the first is an identifier while the
/// second is used to select the cursor that should be used during mouse
/// movement. In Gecko, the first is a scrollframe identifier, while the second
/// is used to store various flags that APZ needs to properly process input
/// events.
pub type ItemTag = (u64, u16);

/// An identifier used to refer to previously sent display items. Currently it
/// refers to individual display items, but this may change later.
pub type ItemKey = u16;

#[repr(C)]
#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
pub struct PrimitiveFlags(u8);

bitflags! {
    impl PrimitiveFlags: u8 {
        /// The CSS backface-visibility property (yes, it can be really granular)
        const IS_BACKFACE_VISIBLE = 1 << 0;
        /// If set, this primitive represents a scroll bar container
        const IS_SCROLLBAR_CONTAINER = 1 << 1;
        /// This is used as a performance hint - this primitive may be promoted to a native
        /// compositor surface under certain (implementation specific) conditions. This
        /// is typically used for large videos, and canvas elements.
        const PREFER_COMPOSITOR_SURFACE = 1 << 2;
        /// If set, this primitive can be passed directly to the compositor via its
        /// ExternalImageId, and the compositor will use the native image directly.
        /// Used as a further extension on top of PREFER_COMPOSITOR_SURFACE.
        const SUPPORTS_EXTERNAL_COMPOSITOR_SURFACE = 1 << 3;
        /// This flags disables snapping and forces anti-aliasing even if the primitive is axis-aligned.
        const ANTIALISED = 1 << 4;
        /// If true, this primitive is used as a background for checkerboarding
        const CHECKERBOARD_BACKGROUND = 1 << 5;
    }
}

impl core::fmt::Debug for PrimitiveFlags {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        if self.is_empty() {
            write!(f, "{:#x}", Self::empty().bits())
        } else {
            bitflags::parser::to_writer(self, f)
        }
    }
}

impl Default for PrimitiveFlags {
    fn default() -> Self {
        PrimitiveFlags::IS_BACKFACE_VISIBLE
    }
}

/// A grouping of fields a lot of display items need, just to avoid
/// repeating these over and over in this file.
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct CommonItemProperties {
    /// Bounds of the display item to clip to. Many items are logically
    /// infinite, and rely on this clip_rect to define their bounds
    /// (solid colors, background-images, gradients, etc).
    pub clip_rect: LayoutRect,
    /// Additional clips
    pub clip_chain_id: ClipChainId,
    /// The coordinate-space the item is in (yes, it can be really granular)
    pub spatial_id: SpatialId,
    /// Various flags describing properties of this primitive.
    pub flags: PrimitiveFlags,
}

impl CommonItemProperties {
    /// Convenience for tests.
    pub fn new(
        clip_rect: LayoutRect,
        space_and_clip: SpaceAndClipInfo,
    ) -> Self {
        Self {
            clip_rect,
            spatial_id: space_and_clip.spatial_id,
            clip_chain_id: space_and_clip.clip_chain_id,
            flags: PrimitiveFlags::default(),
        }
    }
}

/// Per-primitive information about the nodes in the clip tree and
/// the spatial tree that the primitive belongs to.
///
/// Note: this is a separate struct from `PrimitiveInfo` because
/// it needs indirectional mapping during the DL flattening phase,
/// turning into `ScrollNodeAndClipChain`.
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct SpaceAndClipInfo {
    pub spatial_id: SpatialId,
    pub clip_chain_id: ClipChainId,
}

impl SpaceAndClipInfo {
    /// Create a new space/clip info associated with the root
    /// scroll frame.
    pub fn root_scroll(pipeline_id: PipelineId) -> Self {
        SpaceAndClipInfo {
            spatial_id: SpatialId::root_scroll_node(pipeline_id),
            clip_chain_id: ClipChainId::INVALID,
        }
    }
}

/// Defines a caller provided key that is unique for a given spatial node, and is stable across
/// display lists. WR uses this to determine which spatial nodes are added / removed for a new
/// display list. The content itself is arbitrary and opaque to WR, the only thing that matters
/// is that it's unique and stable between display lists.
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke, Default, Eq, Hash)]
pub struct SpatialTreeItemKey {
    key0: u64,
    key1: u64,
}

impl SpatialTreeItemKey {
    pub fn new(key0: u64, key1: u64) -> Self {
        SpatialTreeItemKey {
            key0,
            key1,
        }
    }
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum SpatialTreeItem {
    ScrollFrame(ScrollFrameDescriptor),
    ReferenceFrame(ReferenceFrameDescriptor),
    StickyFrame(StickyFrameDescriptor),
    Invalid,
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum DisplayItem {
    // These are the "real content" display items
    Rectangle(RectangleDisplayItem),
    ClearRectangle(ClearRectangleDisplayItem),
    HitTest(HitTestDisplayItem),
    Text(TextDisplayItem),
    Line(LineDisplayItem),
    Border(BorderDisplayItem),
    BoxShadow(BoxShadowDisplayItem),
    PushShadow(PushShadowDisplayItem),
    Gradient(GradientDisplayItem),
    RadialGradient(RadialGradientDisplayItem),
    ConicGradient(ConicGradientDisplayItem),
    Image(ImageDisplayItem),
    RepeatingImage(RepeatingImageDisplayItem),
    YuvImage(YuvImageDisplayItem),
    BackdropFilter(BackdropFilterDisplayItem),

    // Clips
    RectClip(RectClipDisplayItem),
    RoundedRectClip(RoundedRectClipDisplayItem),
    ImageMaskClip(ImageMaskClipDisplayItem),
    ClipChain(ClipChainItem),

    // Spaces and Frames that content can be scoped under.
    Iframe(IframeDisplayItem),
    PushReferenceFrame(ReferenceFrameDisplayListItem),
    PushStackingContext(PushStackingContextDisplayItem),

    // These marker items indicate an array of data follows, to be used for the
    // next non-marker item.
    SetGradientStops,
    SetFilterOps,
    SetFilterData,
    SetFilterPrimitives,
    SetPoints,

    // These marker items terminate a scope introduced by a previous item.
    PopReferenceFrame,
    PopStackingContext,
    PopAllShadows,

    ReuseItems(ItemKey),
    RetainedItems(ItemKey),
}

/// This is a "complete" version of the DisplayItem, with all implicit trailing
/// arrays included, for debug serialization (captures).
#[cfg(any(feature = "serialize", feature = "deserialize"))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum DebugDisplayItem {
    Rectangle(RectangleDisplayItem),
    ClearRectangle(ClearRectangleDisplayItem),
    HitTest(HitTestDisplayItem),
    Text(TextDisplayItem, Vec<font::GlyphInstance>),
    Line(LineDisplayItem),
    Border(BorderDisplayItem),
    BoxShadow(BoxShadowDisplayItem),
    PushShadow(PushShadowDisplayItem),
    Gradient(GradientDisplayItem),
    RadialGradient(RadialGradientDisplayItem),
    ConicGradient(ConicGradientDisplayItem),
    Image(ImageDisplayItem),
    RepeatingImage(RepeatingImageDisplayItem),
    YuvImage(YuvImageDisplayItem),
    BackdropFilter(BackdropFilterDisplayItem),

    ImageMaskClip(ImageMaskClipDisplayItem),
    RoundedRectClip(RoundedRectClipDisplayItem),
    RectClip(RectClipDisplayItem),
    ClipChain(ClipChainItem, Vec<ClipId>),

    Iframe(IframeDisplayItem),
    PushReferenceFrame(ReferenceFrameDisplayListItem),
    PushStackingContext(PushStackingContextDisplayItem),

    SetGradientStops(Vec<GradientStop>),
    SetFilterOps(Vec<FilterOp>),
    SetFilterData(FilterData),
    SetFilterPrimitives(Vec<FilterPrimitive>),
    SetPoints(Vec<LayoutPoint>),

    PopReferenceFrame,
    PopStackingContext,
    PopAllShadows,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ImageMaskClipDisplayItem {
    pub id: ClipId,
    pub spatial_id: SpatialId,
    pub image_mask: ImageMask,
    pub fill_rule: FillRule,
} // IMPLICIT points: Vec<LayoutPoint>

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RectClipDisplayItem {
    pub id: ClipId,
    pub spatial_id: SpatialId,
    pub clip_rect: LayoutRect,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RoundedRectClipDisplayItem {
    pub id: ClipId,
    pub spatial_id: SpatialId,
    pub clip: ComplexClipRegion,
}

/// The minimum and maximum allowable offset for a sticky frame in a single dimension.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct StickyOffsetBounds {
    /// The minimum offset for this frame, typically a negative value, which specifies how
    /// far in the negative direction the sticky frame can offset its contents in this
    /// dimension.
    pub min: f32,

    /// The maximum offset for this frame, typically a positive value, which specifies how
    /// far in the positive direction the sticky frame can offset its contents in this
    /// dimension.
    pub max: f32,
}

impl StickyOffsetBounds {
    pub fn new(min: f32, max: f32) -> StickyOffsetBounds {
        StickyOffsetBounds { min, max }
    }
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct StickyFrameDescriptor {
    pub id: SpatialId,
    pub parent_spatial_id: SpatialId,
    pub bounds: LayoutRect,

    /// The margins that should be maintained between the edge of the parent viewport and this
    /// sticky frame. A margin of None indicates that the sticky frame should not stick at all
    /// to that particular edge of the viewport.
    pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,

    /// The minimum and maximum vertical offsets for this sticky frame. Ignoring these constraints,
    /// the sticky frame will continue to stick to the edge of the viewport as its original
    /// position is scrolled out of view. Constraints specify a maximum and minimum offset from the
    /// original position relative to non-sticky content within the same scrolling frame.
    pub vertical_offset_bounds: StickyOffsetBounds,

    /// The minimum and maximum horizontal offsets for this sticky frame. Ignoring these constraints,
    /// the sticky frame will continue to stick to the edge of the viewport as its original
    /// position is scrolled out of view. Constraints specify a maximum and minimum offset from the
    /// original position relative to non-sticky content within the same scrolling frame.
    pub horizontal_offset_bounds: StickyOffsetBounds,

    /// The amount of offset that has already been applied to the sticky frame. A positive y
    /// component this field means that a top-sticky item was in a scrollframe that has been
    /// scrolled down, such that the sticky item's position needed to be offset downwards by
    /// `previously_applied_offset.y`. A negative y component corresponds to the upward offset
    /// applied due to bottom-stickiness. The x-axis works analogously.
    pub previously_applied_offset: LayoutVector2D,

    /// A unique (per-pipeline) key for this spatial that is stable across display lists.
    pub key: SpatialTreeItemKey,

    /// A property binding that we use to store an animation ID for APZ
    pub transform: Option<PropertyBinding<LayoutTransform>>,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ScrollFrameDescriptor {
    /// The id of the space this scroll frame creates
    pub scroll_frame_id: SpatialId,
    /// The size of the contents this contains (so the backend knows how far it can scroll).
    // FIXME: this can *probably* just be a size? Origin seems to just get thrown out.
    pub content_rect: LayoutRect,
    pub frame_rect: LayoutRect,
    pub parent_space: SpatialId,
    pub external_id: ExternalScrollId,
    /// The amount this scrollframe has already been scrolled by, in the caller.
    /// This means that all the display items that are inside the scrollframe
    /// will have their coordinates shifted by this amount, and this offset
    /// should be added to those display item coordinates in order to get a
    /// normalized value that is consistent across display lists.
    pub external_scroll_offset: LayoutVector2D,
    /// The generation of the external_scroll_offset.
    pub scroll_offset_generation: APZScrollGeneration,
    /// Whether this scrollframe document has any scroll-linked effect or not.
    pub has_scroll_linked_effect: HasScrollLinkedEffect,
    /// A unique (per-pipeline) key for this spatial that is stable across display lists.
    pub key: SpatialTreeItemKey,
}

/// A solid or an animating color to draw (may not actually be a rectangle due to complex clips)
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RectangleDisplayItem {
    pub common: CommonItemProperties,
    pub bounds: LayoutRect,
    pub color: PropertyBinding<ColorF>,
}

/// Clears all colors from the area, making it possible to cut holes in the window.
/// (useful for things like the macos frosted-glass effect).
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ClearRectangleDisplayItem {
    pub common: CommonItemProperties,
    pub bounds: LayoutRect,
}

/// A minimal hit-testable item for the parent browser's convenience, and is
/// slimmer than a RectangleDisplayItem (no color). The existence of this as a
/// distinct item also makes it easier to inspect/debug display items.
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct HitTestDisplayItem {
    pub rect: LayoutRect,
    pub clip_chain_id: ClipChainId,
    pub spatial_id: SpatialId,
    pub flags: PrimitiveFlags,
    pub tag: ItemTag,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct LineDisplayItem {
    pub common: CommonItemProperties,
    /// We need a separate rect from common.clip_rect to encode cute
    /// tricks that firefox does to make a series of text-decorations seamlessly
    /// line up -- snapping the decorations to a multiple of their period, and
    /// then clipping them to their "proper" area. This rect is that "logical"
    /// snapped area that may be clipped to the right size by the clip_rect.
    pub area: LayoutRect,
    /// Whether the rect is interpretted as vertical or horizontal
    pub orientation: LineOrientation,
    /// This could potentially be implied from area, but we currently prefer
    /// that this is the responsibility of the layout engine. Value irrelevant
    /// for non-wavy lines.
    // FIXME: this was done before we could use tagged unions in enums, but now
    // it should just be part of LineStyle::Wavy.
    pub wavy_line_thickness: f32,
    pub color: ColorF,
    pub style: LineStyle,
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
pub enum LineOrientation {
    Vertical,
    Horizontal,
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
pub enum LineStyle {
    Solid,
    Dotted,
    Dashed,
    Wavy,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct TextDisplayItem {
    pub common: CommonItemProperties,
    /// The area all the glyphs should be found in. Strictly speaking this isn't
    /// necessarily needed, but layout engines should already "know" this, and we
    /// use it cull and size things quickly before glyph layout is done. Currently
    /// the glyphs *can* be outside these bounds, but that should imply they
    /// can be cut off.
    // FIXME: these are currently sometimes ignored to keep some old wrench tests
    // working, but we should really just fix the tests!
    pub bounds: LayoutRect,
    pub font_key: font::FontInstanceKey,
    pub color: ColorF,
    pub glyph_options: Option<font::GlyphOptions>,
    pub ref_frame_offset: LayoutVector2D,
} // IMPLICIT: glyphs: Vec<font::GlyphInstance>

#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub struct NormalBorder {
    pub left: BorderSide,
    pub right: BorderSide,
    pub top: BorderSide,
    pub bottom: BorderSide,
    pub radius: BorderRadius,
    /// Whether to apply anti-aliasing on the border corners.
    ///
    /// Note that for this to be `false` and work, this requires the borders to
    /// be solid, and no border-radius.
    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)
    }

    /// Normalizes a border so that we don't render disallowed stuff, like inset
    /// borders that are less than two pixels wide.
    #[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(u8)]
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
pub enum RepeatMode {
    Stretch,
    Repeat,
    Round,
    Space,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum NinePatchBorderSource {
    Image(ImageKey, ImageRendering),
    Gradient(Gradient),
    RadialGradient(RadialGradient),
    ConicGradient(ConicGradient),
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct NinePatchBorder {
    /// Describes what to use as the 9-patch source image. If this is an image,
    /// it will be stretched to fill the size given by width x height.
    pub source: NinePatchBorderSource,

    /// The width of the 9-part image.
    pub width: i32,

    /// The height of the 9-part image.
    pub height: i32,

    /// Distances from each edge where the image should be sliced up. These
    /// values are in 9-part-image space (the same space as width and height),
    /// and the resulting image parts will be used to fill the corresponding
    /// parts of the border as given by the border widths. This can lead to
    /// stretching.
    /// Slices can be overlapping. In that case, the same pixels from the
    /// 9-part image will show up in multiple parts of the resulting border.
    pub slice: DeviceIntSideOffsets,

    /// Controls whether the center of the 9 patch image is rendered or
    /// ignored. The center is never rendered if the slices are overlapping.
    pub fill: bool,

    /// Determines what happens if the horizontal side parts of the 9-part
    /// image have a different size than the horizontal parts of the border.
    pub repeat_horizontal: RepeatMode,

    /// Determines what happens if the vertical side parts of the 9-part
    /// image have a different size than the vertical parts of the border.
    pub repeat_vertical: RepeatMode,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum BorderDetails {
    Normal(NormalBorder),
    NinePatch(NinePatchBorder),
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct BorderDisplayItem {
    pub common: CommonItemProperties,
    pub bounds: LayoutRect,
    pub widths: LayoutSideOffsets,
    pub details: BorderDetails,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum BorderRadiusKind {
    Uniform,
    NonUniform,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub struct BorderRadius {
    pub top_left: LayoutSize,
    pub top_right: LayoutSize,
    pub bottom_left: LayoutSize,
    pub bottom_right: LayoutSize,
}

impl Default for BorderRadius {
    fn default() -> Self {
        BorderRadius {
            top_left: LayoutSize::zero(),
            top_right: LayoutSize::zero(),
            bottom_left: LayoutSize::zero(),
            bottom_right: LayoutSize::zero(),
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub struct BorderSide {
    pub color: ColorF,
    pub style: BorderStyle,
}

#[repr(u32)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq, PeekPoke)]
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(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum BoxShadowClipMode {
    Outset = 0,
    Inset = 1,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct BoxShadowDisplayItem {
    pub common: CommonItemProperties,
    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,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct PushShadowDisplayItem {
    pub space_and_clip: SpaceAndClipInfo,
    pub shadow: Shadow,
    pub should_inflate: bool,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct Shadow {
    pub offset: LayoutVector2D,
    pub color: ColorF,
    pub blur_radius: f32,
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
pub enum ExtendMode {
    Clamp,
    Repeat,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct Gradient {
    pub start_point: LayoutPoint,
    pub end_point: LayoutPoint,
    pub extend_mode: ExtendMode,
} // IMPLICIT: stops: Vec<GradientStop>

impl Gradient {
    pub fn is_valid(&self) -> bool {
        self.start_point.x.is_finite() &&
            self.start_point.y.is_finite() &&
            self.end_point.x.is_finite() &&
            self.end_point.y.is_finite()
    }
}

/// The area
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct GradientDisplayItem {
    /// NOTE: common.clip_rect is the area the gradient covers
    pub common: CommonItemProperties,
    /// The area to tile the gradient over (first tile starts at origin of this rect)
    // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
    // defining the bounds of the item. Needs non-trivial backend changes.
    pub bounds: LayoutRect,
    /// How big a tile of the of the gradient should be (common case: bounds.size)
    pub tile_size: LayoutSize,
    /// The space between tiles of the gradient (common case: 0)
    pub tile_spacing: LayoutSize,
    pub gradient: Gradient,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub struct GradientStop {
    pub offset: f32,
    pub color: ColorF,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RadialGradient {
    pub center: LayoutPoint,
    pub radius: LayoutSize,
    pub start_offset: f32,
    pub end_offset: f32,
    pub extend_mode: ExtendMode,
} // IMPLICIT stops: Vec<GradientStop>

impl RadialGradient {
    pub fn is_valid(&self) -> bool {
        self.center.x.is_finite() &&
            self.center.y.is_finite() &&
            self.start_offset.is_finite() &&
            self.end_offset.is_finite()
    }
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ConicGradient {
    pub center: LayoutPoint,
    pub angle: f32,
    pub start_offset: f32,
    pub end_offset: f32,
    pub extend_mode: ExtendMode,
} // IMPLICIT stops: Vec<GradientStop>

impl ConicGradient {
    pub fn is_valid(&self) -> bool {
        self.center.x.is_finite() &&
            self.center.y.is_finite() &&
            self.angle.is_finite() &&
            self.start_offset.is_finite() &&
            self.end_offset.is_finite()
    }
}

/// Just an abstraction for bundling up a bunch of clips into a "super clip".
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ClipChainItem {
    pub id: ClipChainId,
    pub parent: Option<ClipChainId>,
} // IMPLICIT clip_ids: Vec<ClipId>

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct RadialGradientDisplayItem {
    pub common: CommonItemProperties,
    /// The area to tile the gradient over (first tile starts at origin of this rect)
    // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
    // defining the bounds of the item. Needs non-trivial backend changes.
    pub bounds: LayoutRect,
    pub gradient: RadialGradient,
    pub tile_size: LayoutSize,
    pub tile_spacing: LayoutSize,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ConicGradientDisplayItem {
    pub common: CommonItemProperties,
    /// The area to tile the gradient over (first tile starts at origin of this rect)
    // FIXME: this should ideally just be `tile_origin` here, with the clip_rect
    // defining the bounds of the item. Needs non-trivial backend changes.
    pub bounds: LayoutRect,
    pub gradient: ConicGradient,
    pub tile_size: LayoutSize,
    pub tile_spacing: LayoutSize,
}

/// Renders a filtered region of its backdrop
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct BackdropFilterDisplayItem {
    pub common: CommonItemProperties,
}
// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ReferenceFrameDisplayListItem {
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ReferenceFrameDescriptor {
    pub origin: LayoutPoint,
    pub parent_spatial_id: SpatialId,
    pub reference_frame: ReferenceFrame,
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum ReferenceFrameKind {
    /// A normal transform matrix, may contain perspective (the CSS transform property)
    Transform {
        /// Optionally marks the transform as only ever having a simple 2D scale or translation,
        /// allowing for optimizations.
        is_2d_scale_translation: bool,
        /// Marks that the transform should be snapped. Used for transforms which animate in
        /// response to scrolling, eg for zooming or dynamic toolbar fixed-positioning.
        should_snap: bool,
        /// Marks the transform being a part of the CSS stacking context that also has
        /// a perspective. In this case, backface visibility takes this perspective into
        /// account.
        paired_with_perspective: bool,
    },
    /// A perspective transform, that optionally scrolls relative to a specific scroll node
    Perspective {
        scrolling_relative_to: Option<ExternalScrollId>,
    }
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum Rotation {
    Degree0,
    Degree90,
    Degree180,
    Degree270,
}

impl Rotation {
    pub fn to_matrix(
        &self,
        size: LayoutSize,
    ) -> LayoutTransform {
        let (shift_center_to_origin, angle) = match self {
            Rotation::Degree0 => {
              (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(0.))
            },
            Rotation::Degree90 => {
              (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(90.))
            },
            Rotation::Degree180 => {
              (LayoutTransform::translation(-size.width / 2., -size.height / 2., 0.), Angle::degrees(180.))
            },
            Rotation::Degree270 => {
              (LayoutTransform::translation(-size.height / 2., -size.width / 2., 0.), Angle::degrees(270.))
            },
        };
        let shift_origin_to_center = LayoutTransform::translation(size.width / 2., size.height / 2., 0.);

        shift_center_to_origin
            .then(&LayoutTransform::rotation(0., 0., 1.0, angle))
            .then(&shift_origin_to_center)
    }
}

#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum ReferenceTransformBinding {
    /// Standard reference frame which contains a precomputed transform.
    Static {
        binding: PropertyBinding<LayoutTransform>,
    },
    /// Computed reference frame which dynamically calculates the transform
    /// based on the given parameters. The reference is the content size of
    /// the parent iframe, which is affected by snapping.
    ///
    /// This is used when a transform depends on the layout size of an
    /// element, otherwise the difference between the unsnapped size
    /// used in the transform, and the snapped size calculated during scene
    /// building can cause seaming.
    Computed {
        scale_from: Option<LayoutSize>,
        vertical_flip: bool,
        rotation: Rotation,
    },
}

impl Default for ReferenceTransformBinding {
    fn default() -> Self {
        ReferenceTransformBinding::Static {
            binding: Default::default(),
        }
    }
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ReferenceFrame {
    pub kind: ReferenceFrameKind,
    pub transform_style: TransformStyle,
    /// The transform matrix, either the perspective matrix or the transform
    /// matrix.
    pub transform: ReferenceTransformBinding,
    pub id: SpatialId,
    /// A unique (per-pipeline) key for this spatial that is stable across display lists.
    pub key: SpatialTreeItemKey,
}

/// If passed in a stacking context display item, inform WebRender that
/// the contents of the stacking context should be retained into a texture
/// and associated to an image key.
///
/// Image display items can then display the cached snapshot using the
/// same image key.
///
/// The flow for creating/using/deleting snapshots is the same as with
/// regular images:
///  - The image key must have been created with `Transaction::add_snapshot_image`.
///  - The current scene must not contain references to the snapshot when
///    `Transaction::delete_snapshot_image` is called.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct SnapshotInfo {
    /// The image key to associate the snapshot with.
    pub key: SnapshotImageKey,
    /// The bounds of the snapshot in local space.
    ///
    /// This rectangle is relative to the same coordinate space as the
    /// child items of the stacking context.
    pub area: LayoutRect,
    /// If true, detach the stacking context from the scene and only
    /// render it into the snapshot.
    /// If false, the stacking context rendered in the frame normally
    /// in addition to being cached into the snapshot.
    pub detached: bool,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct PushStackingContextDisplayItem {
    pub origin: LayoutPoint,
    pub spatial_id: SpatialId,
    pub snapshot: Option<SnapshotInfo>,
    pub prim_flags: PrimitiveFlags,
    pub ref_frame_offset: LayoutVector2D,
    pub stacking_context: StackingContext,
}

#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct StackingContext {
    pub transform_style: TransformStyle,
    pub mix_blend_mode: MixBlendMode,
    pub clip_chain_id: Option<ClipChainId>,
    pub raster_space: RasterSpace,
    pub flags: StackingContextFlags,
}
// IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
pub enum TransformStyle {
    Flat = 0,
    Preserve3D = 1,
}

/// Configure whether the contents of a stacking context
/// should be rasterized in local space or screen space.
/// Local space rasterized pictures are typically used
/// when we want to cache the output, and performance is
/// important. Note that this is a performance hint only,
/// which WR may choose to ignore.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, MallocSizeOf, Serialize, PeekPoke)]
#[repr(u8)]
pub enum RasterSpace {
    // Rasterize in local-space, applying supplied scale to primitives.
    // Best performance, but lower quality.
    Local(f32),

    // Rasterize the picture in screen-space, including rotation / skew etc in
    // the rasterized element. Best quality, but slower performance. Note that
    // any stacking context with a perspective transform will be rasterized
    // in local-space, even if this is set.
    Screen,
}

impl RasterSpace {
    pub fn local_scale(self) -> Option<f32> {
        match self {
            RasterSpace::Local(scale) => Some(scale),
            RasterSpace::Screen => None,
        }
    }
}

impl Eq for RasterSpace {}

impl Hash for RasterSpace {
    fn hash<H: Hasher>(&self, state: &mut H) {
        match self {
            RasterSpace::Screen => {
                0.hash(state);
            }
            RasterSpace::Local(scale) => {
                // Note: this is inconsistent with the Eq impl for -0.0 (don't care).
                1.hash(state);
                scale.to_bits().hash(state);
            }
        }
    }
}

#[repr(C)]
#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, Deserialize, MallocSizeOf, Serialize, PeekPoke)]
pub struct StackingContextFlags(u8);

bitflags! {
    impl StackingContextFlags: u8 {
        /// If true, this stacking context is a blend container than contains
        /// mix-blend-mode children (and should thus be isolated).
        const IS_BLEND_CONTAINER = 1 << 0;
        /// If true, this stacking context is a wrapper around a backdrop-filter (e.g. for
        /// a clip-mask). This is needed to allow the correct selection of a backdrop root
        /// since a clip-mask stacking context creates a parent surface.
        const WRAPS_BACKDROP_FILTER = 1 << 1;
    }
}

impl core::fmt::Debug for StackingContextFlags {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        if self.is_empty() {
            write!(f, "{:#x}", Self::empty().bits())
        } else {
            bitflags::parser::to_writer(self, f)
        }
    }
}

impl Default for StackingContextFlags {
    fn default() -> Self {
        StackingContextFlags::empty()
    }
}

#[repr(u8)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
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,
    PlusLighter = 16,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum ColorSpace {
    Srgb,
    LinearRgb,
}

/// Available composite operoations for the composite filter primitive
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum CompositeOperator {
    Over,
    In,
    Atop,
    Out,
    Xor,
    Lighter,
    Arithmetic([f32; 4]),
}

impl CompositeOperator {
    // This must stay in sync with the composite operator defines in cs_svg_filter.glsl
    pub fn as_int(&self) -> u32 {
        match self {
            CompositeOperator::Over => 0,
            CompositeOperator::In => 1,
            CompositeOperator::Out => 2,
            CompositeOperator::Atop => 3,
            CompositeOperator::Xor => 4,
            CompositeOperator::Lighter => 5,
            CompositeOperator::Arithmetic(..) => 6,
        }
    }
}

/// An input to a SVG filter primitive.
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
pub enum FilterPrimitiveInput {
    /// The input is the original graphic that the filter is being applied to.
    Original,
    /// The input is the output of the previous filter primitive in the filter primitive chain.
    Previous,
    /// The input is the output of the filter primitive at the given index in the filter primitive chain.
    OutputOfPrimitiveIndex(usize),
}

impl FilterPrimitiveInput {
    /// Gets the index of the input.
    /// Returns `None` if the source graphic is the input.
    pub fn to_index(self, cur_index: usize) -> Option<usize> {
        match self {
            FilterPrimitiveInput::Previous if cur_index > 0 => Some(cur_index - 1),
            FilterPrimitiveInput::OutputOfPrimitiveIndex(index) => Some(index),
            _ => None,
        }
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct BlendPrimitive {
    pub input1: FilterPrimitiveInput,
    pub input2: FilterPrimitiveInput,
    pub mode: MixBlendMode,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct FloodPrimitive {
    pub color: ColorF,
}

impl FloodPrimitive {
    pub fn sanitize(&mut self) {
        self.color.r = self.color.r.clamp(0.0, 1.0);
        self.color.g = self.color.g.clamp(0.0, 1.0);
        self.color.b = self.color.b.clamp(0.0, 1.0);
        self.color.a = self.color.a.clamp(0.0, 1.0);
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct BlurPrimitive {
    pub input: FilterPrimitiveInput,
    pub width: f32,
    pub height: f32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct OpacityPrimitive {
    pub input: FilterPrimitiveInput,
    pub opacity: f32,
}

impl OpacityPrimitive {
    pub fn sanitize(&mut self) {
        self.opacity = self.opacity.clamp(0.0, 1.0);
    }
}

/// cbindgen:derive-eq=false
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ColorMatrixPrimitive {
    pub input: FilterPrimitiveInput,
    pub matrix: [f32; 20],
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct DropShadowPrimitive {
    pub input: FilterPrimitiveInput,
    pub shadow: Shadow,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct ComponentTransferPrimitive {
    pub input: FilterPrimitiveInput,
    // Component transfer data is stored in FilterData.
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct IdentityPrimitive {
    pub input: FilterPrimitiveInput,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct OffsetPrimitive {
    pub input: FilterPrimitiveInput,
    pub offset: LayoutVector2D,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct CompositePrimitive {
    pub input1: FilterPrimitiveInput,
    pub input2: FilterPrimitiveInput,
    pub operator: CompositeOperator,
}

/// See: https://github.com/eqrion/cbindgen/issues/9
/// cbindgen:derive-eq=false
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
pub enum FilterPrimitiveKind {
    Identity(IdentityPrimitive),
    Blend(BlendPrimitive),
    Flood(FloodPrimitive),
    Blur(BlurPrimitive),
    // TODO: Support animated opacity?
    Opacity(OpacityPrimitive),
    /// cbindgen:derive-eq=false
    ColorMatrix(ColorMatrixPrimitive),
    DropShadow(DropShadowPrimitive),
    ComponentTransfer(ComponentTransferPrimitive),
    Offset(OffsetPrimitive),
    Composite(CompositePrimitive),
}

impl Default for FilterPrimitiveKind {
    fn default() -> Self {
        FilterPrimitiveKind::Identity(IdentityPrimitive::default())
    }
}

impl FilterPrimitiveKind {
    pub fn sanitize(&mut self) {
        match self {
            FilterPrimitiveKind::Flood(flood) => flood.sanitize(),
            FilterPrimitiveKind::Opacity(opacity) => opacity.sanitize(),

            // No sanitization needed.
            FilterPrimitiveKind::Identity(..) |
            FilterPrimitiveKind::Blend(..) |
            FilterPrimitiveKind::ColorMatrix(..) |
            FilterPrimitiveKind::Offset(..) |
            FilterPrimitiveKind::Composite(..) |
            FilterPrimitiveKind::Blur(..) |
            FilterPrimitiveKind::DropShadow(..) |
            // Component transfer's filter data is sanitized separately.
            FilterPrimitiveKind::ComponentTransfer(..) => {}
        }
    }
}

/// SVG Filter Primitive.
/// See: https://github.com/eqrion/cbindgen/issues/9
/// cbindgen:derive-eq=false
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
pub struct FilterPrimitive {
    pub kind: FilterPrimitiveKind,
    pub color_space: ColorSpace,
}

impl FilterPrimitive {
    pub fn sanitize(&mut self) {
        self.kind.sanitize();
    }
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, PeekPoke)]
pub enum FilterOpGraphPictureBufferId {
    #[default]
    /// empty slot in feMerge inputs
    None,
    /// reference to another (earlier) node in filter graph
    BufferId(i16),
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
pub struct FilterOpGraphPictureReference {
    /// Id of the picture in question in a namespace unique to this filter DAG
    pub buffer_id: FilterOpGraphPictureBufferId,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PeekPoke)]
pub struct FilterOpGraphNode {
    /// True if color_interpolation_filter == LinearRgb; shader will convert
    /// sRGB texture pixel colors on load and convert back on store, for correct
    /// interpolation
    pub linear: bool,
    /// virtualized picture input binding 1 (i.e. texture source), typically
    /// this is used, but certain filters do not use it
    pub input: FilterOpGraphPictureReference,
    /// virtualized picture input binding 2 (i.e. texture sources), only certain
    /// filters use this
    pub input2: FilterOpGraphPictureReference,
    /// rect this node will render into, in filter space
    pub subregion: LayoutRect,
}

/// Maximum number of SVGFE filters in one graph, this is constant size to avoid
/// allocating anything, and the SVG spec allows us to drop all filters on an
/// item if the graph is excessively complex - a graph this large will never be
/// a good user experience, performance-wise.
pub const SVGFE_GRAPH_MAX: usize = 256;

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PeekPoke)]
pub enum FilterOp {
    /// Filter that does no transformation of the colors, needed for
    /// debug purposes, and is the default value in impl_default_for_enums.
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Identity,
    /// apply blur effect
    /// parameters: stdDeviationX, stdDeviationY
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Blur(f32, f32),
    /// apply brightness effect
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Brightness(f32),
    /// apply contrast effect
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Contrast(f32),
    /// fade image toward greyscale version of image
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Grayscale(f32),
    /// fade image toward hue-rotated version of image (rotate RGB around color wheel)
    /// parameters: angle
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    HueRotate(f32),
    /// fade image toward inverted image (1 - RGB)
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Invert(f32),
    /// multiplies color and alpha by opacity
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Opacity(PropertyBinding<f32>, f32),
    /// multiply saturation of colors
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Saturate(f32),
    /// fade image toward sepia tone version of image
    /// parameters: amount
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    Sepia(f32),
    /// add drop shadow version of image to the image
    /// parameters: shadow
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    DropShadow(Shadow),
    /// transform color and alpha in image through 4x5 color matrix (transposed for efficiency)
    /// parameters: matrix[5][4]
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    ColorMatrix([f32; 20]),
    /// internal use - convert sRGB input to linear output
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    SrgbToLinear,
    /// internal use - convert linear input to sRGB output
    /// parameters: none
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    LinearToSrgb,
    /// remap RGBA with color gradients and component swizzle
    /// parameters: FilterData
    /// CSS filter semantics - operates on previous picture, uses sRGB space (non-linear)
    ComponentTransfer,
    /// replace image with a solid color
    /// NOTE: UNUSED; Gecko never produces this filter
    /// parameters: color
    /// CSS filter semantics - operates on previous picture,uses sRGB space (non-linear)
    Flood(ColorF),
    /// Filter that copies the SourceGraphic image into the specified subregion,
    /// This is intentionally the only way to get SourceGraphic into the graph,
    /// as the filter region must be applied before it is used.
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - no inputs, no linear
    SVGFESourceGraphic{node: FilterOpGraphNode},
    /// Filter that copies the SourceAlpha image into the specified subregion,
    /// This is intentionally the only way to get SourceGraphic into the graph,
    /// as the filter region must be applied before it is used.
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - no inputs, no linear
    SVGFESourceAlpha{node: FilterOpGraphNode},
    /// Filter that does no transformation of the colors, used for subregion
    /// cropping only.
    SVGFEIdentity{node: FilterOpGraphNode},
    /// represents CSS opacity property as a graph node like the rest of the SVGFE* filters
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    SVGFEOpacity{node: FilterOpGraphNode, valuebinding: PropertyBinding<f32>, value: f32},
    /// convert a color image to an alpha channel - internal use; generated by
    /// SVGFilterInstance::GetOrCreateSourceAlphaIndex().
    SVGFEToAlpha{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_DARKEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendDarken{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_LIGHTEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendLighten{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_MULTIPLY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendMultiply{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_NORMAL
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendNormal{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_SCREEN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feBlendElement
    SVGFEBlendScreen{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_OVERLAY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendOverlay{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_DODGE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColorDodge{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR_BURN
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColorBurn{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_HARD_LIGHT
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendHardLight{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_SOFT_LIGHT
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendSoftLight{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_DIFFERENCE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendDifference{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_EXCLUSION
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendExclusion{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_HUE
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendHue{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_SATURATION
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendSaturation{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_COLOR
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendColor{node: FilterOpGraphNode},
    /// combine 2 images with SVG_FEBLEND_MODE_LUMINOSITY
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Source: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
    SVGFEBlendLuminosity{node: FilterOpGraphNode},
    /// transform colors of image through 5x4 color matrix (transposed for efficiency)
    /// parameters: FilterOpGraphNode, matrix[5][4]
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement
    SVGFEColorMatrix{node: FilterOpGraphNode, values: [f32; 20]},
    /// transform colors of image through configurable gradients with component swizzle
    /// parameters: FilterOpGraphNode, FilterData
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feComponentTransferElement
    SVGFEComponentTransfer{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode, k1, k2, k3, k4
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeArithmetic{node: FilterOpGraphNode, k1: f32, k2: f32, k3: f32,
        k4: f32},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeATop{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeIn{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feComposite
    SVGFECompositeLighter{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeOut{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeOver{node: FilterOpGraphNode},
    /// composite 2 images with chosen composite mode with parameters for that mode
    /// parameters: FilterOpGraphNode
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feCompositeElement
    SVGFECompositeXOR{node: FilterOpGraphNode},
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    ///  preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeDuplicate{node: FilterOpGraphNode, order_x: i32,
        order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
        target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
        preserve_alpha: i32},
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    ///  preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeNone{node: FilterOpGraphNode, order_x: i32,
        order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
        target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
        preserve_alpha: i32},
    /// transform image through convolution matrix of up to 25 values (spec
    /// allows more but for performance reasons we do not)
    /// parameters: FilterOpGraphNode, orderX, orderY, kernelValues[25],
    ///  divisor, bias, targetX, targetY, kernelUnitLengthX, kernelUnitLengthY,
    /// preserveAlpha
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#feConvolveMatrixElement
    SVGFEConvolveMatrixEdgeModeWrap{node: FilterOpGraphNode, order_x: i32,
        order_y: i32, kernel: [f32; 25], divisor: f32, bias: f32, target_x: i32,
        target_y: i32, kernel_unit_length_x: f32, kernel_unit_length_y: f32,
        preserve_alpha: i32},
    /// calculate lighting based on heightmap image with provided values for a
    /// distant light source with specified direction
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, azimuth, elevation
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDistantLightElement
    SVGFEDiffuseLightingDistant{node: FilterOpGraphNode, surface_scale: f32,
        diffuse_constant: f32, kernel_unit_length_x: f32,
        kernel_unit_length_y: f32, azimuth: f32, elevation: f32},
    /// calculate lighting based on heightmap image with provided values for a
    /// point light source at specified location
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    ///  https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEPointLightElement
    SVGFEDiffuseLightingPoint{node: FilterOpGraphNode, surface_scale: f32,
        diffuse_constant: f32, kernel_unit_length_x: f32,
        kernel_unit_length_y: f32, x: f32, y: f32, z: f32},
    /// calculate lighting based on heightmap image with provided values for a
    /// spot light source at specified location pointing at specified target
    /// location with specified hotspot sharpness and cone angle
    /// parameters: FilterOpGraphNode, surfaceScale, diffuseConstant,
    ///  kernelUnitLengthX, kernelUnitLengthY, x, y, z, pointsAtX, pointsAtY,
    ///  pointsAtZ, specularExponent, limitingConeAngle
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDiffuseLightingElement
    /// https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFESpotLightElement
    SVGFEDiffuseLightingSpot{node: FilterOpGraphNode, surface_scale: f32,
        diffuse_constant: f32, kernel_unit_length_x: f32,
        kernel_unit_length_y: f32, x: f32, y: f32, z: f32, points_at_x: f32,
        points_at_y: f32, points_at_z: f32, cone_exponent: f32,
        limiting_cone_angle: f32},
    /// calculate a distorted version of first input image using offset values
    /// from second input image at specified intensity
    /// parameters: FilterOpGraphNode, scale, xChannelSelector, yChannelSelector
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
    /// Spec: https://www.w3.org/TR/filter-effects-1/#InterfaceSVGFEDisplacementMapElement
    SVGFEDisplacementMap{node: FilterOpGraphNode, scale: f32,
        x_channel_selector: u32, y_channel_selector: u32},
    /// create and merge a dropshadow version of the specified image's alpha
    /// channel with specified offset and blur radius
    /// parameters: FilterOpGraphNode, flood_color, flood_opacity, dx, dy,
    ///  stdDeviationX, stdDeviationY
    /// SVG filter semantics - selectable input(s), selectable between linear
    /// (default) and sRGB color space for calculations
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.8 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge