aboutsummaryrefslogtreecommitdiffstats
path: root/third_party/webrender/webrender_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webrender/webrender_api/src')
-rw-r--r--third_party/webrender/webrender_api/src/channel.rs180
-rw-r--r--third_party/webrender/webrender_api/src/color.rs160
-rw-r--r--third_party/webrender/webrender_api/src/display_item.rs1738
-rw-r--r--third_party/webrender/webrender_api/src/display_item_cache.rs115
-rw-r--r--third_party/webrender/webrender_api/src/display_list.rs2057
-rw-r--r--third_party/webrender/webrender_api/src/font.rs605
-rw-r--r--third_party/webrender/webrender_api/src/gradient_builder.rs180
-rw-r--r--third_party/webrender/webrender_api/src/image.rs580
-rw-r--r--third_party/webrender/webrender_api/src/lib.rs665
-rw-r--r--third_party/webrender/webrender_api/src/units.rs325
10 files changed, 0 insertions, 6605 deletions
diff --git a/third_party/webrender/webrender_api/src/channel.rs b/third_party/webrender/webrender_api/src/channel.rs
deleted file mode 100644
index 7d21c6e4339..00000000000
--- a/third_party/webrender/webrender_api/src/channel.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 crate::{Epoch, PipelineId};
-use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
-use std::io::{self, Cursor, Error, ErrorKind, Read};
-use std::mem;
-
-pub use crossbeam_channel as crossbeam;
-
-#[cfg(not(target_os = "windows"))]
-pub use crossbeam_channel::{Sender, Receiver};
-
-#[cfg(target_os = "windows")]
-pub use std::sync::mpsc::{Sender, Receiver};
-
-#[derive(Clone)]
-pub struct Payload {
- /// An epoch used to get the proper payload for a pipeline id frame request.
- ///
- /// TODO(emilio): Is this still relevant? We send the messages for the same
- /// pipeline in order, so we shouldn't need it. Seems like this was only
- /// wallpapering (in most cases) the underlying problem in #991.
- pub epoch: Epoch,
- /// A pipeline id to key the payload with, along with the epoch.
- pub pipeline_id: PipelineId,
- pub display_list_data: Vec<u8>,
-}
-
-impl Payload {
- /// Convert the payload to a raw byte vector, in order for it to be
- /// efficiently shared via shmem, for example.
- /// This is a helper static method working on a slice.
- pub fn construct_data(epoch: Epoch, pipeline_id: PipelineId, dl_data: &[u8]) -> Vec<u8> {
- let mut data = Vec::with_capacity(
- mem::size_of::<u32>() + 2 * mem::size_of::<u32>() + mem::size_of::<u64>() + dl_data.len(),
- );
- data.write_u32::<LittleEndian>(epoch.0).unwrap();
- data.write_u32::<LittleEndian>(pipeline_id.0).unwrap();
- data.write_u32::<LittleEndian>(pipeline_id.1).unwrap();
- data.write_u64::<LittleEndian>(dl_data.len() as u64)
- .unwrap();
- data.extend_from_slice(dl_data);
- data
- }
- /// Convert the payload to a raw byte vector, in order for it to be
- /// efficiently shared via shmem, for example.
- pub fn to_data(&self) -> Vec<u8> {
- Self::construct_data(self.epoch, self.pipeline_id, &self.display_list_data)
- }
-
- /// Deserializes the given payload from a raw byte vector.
- pub fn from_data(data: &[u8]) -> Payload {
- let mut payload_reader = Cursor::new(data);
- let epoch = Epoch(payload_reader.read_u32::<LittleEndian>().unwrap());
- let pipeline_id = PipelineId(
- payload_reader.read_u32::<LittleEndian>().unwrap(),
- payload_reader.read_u32::<LittleEndian>().unwrap(),
- );
-
- let dl_size = payload_reader.read_u64::<LittleEndian>().unwrap() as usize;
- let mut built_display_list_data = vec![0; dl_size];
- payload_reader
- .read_exact(&mut built_display_list_data[..])
- .unwrap();
-
- assert_eq!(payload_reader.position(), data.len() as u64);
-
- Payload {
- epoch,
- pipeline_id,
- display_list_data: built_display_list_data,
- }
- }
-}
-
-pub type PayloadSender = MsgSender<Payload>;
-
-pub type PayloadReceiver = MsgReceiver<Payload>;
-
-pub struct MsgReceiver<T> {
- rx: Receiver<T>,
-}
-
-impl<T> MsgReceiver<T> {
- pub fn recv(&self) -> Result<T, Error> {
- self.rx.recv().map_err(|e| io::Error::new(ErrorKind::Other, e.to_string()))
- }
-
- pub fn to_crossbeam_receiver(self) -> Receiver<T> {
- self.rx
- }
-}
-
-#[derive(Clone)]
-pub struct MsgSender<T> {
- tx: Sender<T>,
-}
-
-impl<T> MsgSender<T> {
- pub fn send(&self, data: T) -> Result<(), Error> {
- self.tx.send(data).map_err(|_| Error::new(ErrorKind::Other, "cannot send on closed channel"))
- }
-}
-
-pub fn payload_channel() -> Result<(PayloadSender, PayloadReceiver), Error> {
- let (tx, rx) = unbounded_channel();
- Ok((PayloadSender { tx }, PayloadReceiver { rx }))
-}
-
-pub fn msg_channel<T>() -> Result<(MsgSender<T>, MsgReceiver<T>), Error> {
- let (tx, rx) = unbounded_channel();
- Ok((MsgSender { tx }, MsgReceiver { rx }))
-}
-
-///
-/// These serialize methods are needed to satisfy the compiler
-/// which uses these implementations for the recording tool.
-/// The recording tool only outputs messages that don't contain
-/// Senders or Receivers, so in theory these should never be
-/// called in the in-process config. If they are called,
-/// there may be a bug in the messages that the replay tool is writing.
-///
-
-impl<T> Serialize for MsgSender<T> {
- fn serialize<S: Serializer>(&self, _: S) -> Result<S::Ok, S::Error> {
- unreachable!();
- }
-}
-
-impl<'de, T> Deserialize<'de> for MsgSender<T> {
- fn deserialize<D>(_: D) -> Result<MsgSender<T>, D::Error>
- where D: Deserializer<'de> {
- unreachable!();
- }
-}
-
-/// A create a channel intended for one-shot uses, for example the channels
-/// created to block on a synchronous query and then discarded,
-#[cfg(not(target_os = "windows"))]
-pub fn single_msg_channel<T>() -> (Sender<T>, Receiver<T>) {
- crossbeam_channel::bounded(1)
-}
-
-/// A fast MPMC message channel that can hold a fixed number of messages.
-///
-/// If the channel is full, the sender will block upon sending extra messages
-/// until the receiver has consumed some messages.
-/// The capacity parameter should be chosen either:
-/// - high enough to avoid blocking on the common cases,
-/// - or, on the contrary, using the blocking behavior as a means to prevent
-/// fast producers from building up work faster than it is consumed.
-#[cfg(not(target_os = "windows"))]
-pub fn fast_channel<T>(capacity: usize) -> (Sender<T>, Receiver<T>) {
- crossbeam_channel::bounded(capacity)
-}
-
-/// Creates an MPMC channel that is a bit slower than the fast_channel but doesn't
-/// have a limit on the number of messages held at a given time and therefore
-/// doesn't block when sending.
-#[cfg(not(target_os = "windows"))]
-pub use crossbeam_channel::unbounded as unbounded_channel;
-
-
-#[cfg(target_os = "windows")]
-pub fn fast_channel<T>(_cap: usize) -> (Sender<T>, Receiver<T>) {
- std::sync::mpsc::channel()
-}
-
-#[cfg(target_os = "windows")]
-pub fn unbounded_channel<T>() -> (Sender<T>, Receiver<T>) {
- std::sync::mpsc::channel()
-}
-
-#[cfg(target_os = "windows")]
-pub fn single_msg_channel<T>() -> (Sender<T>, Receiver<T>) {
- std::sync::mpsc::channel()
-}
diff --git a/third_party/webrender/webrender_api/src/color.rs b/third_party/webrender/webrender_api/src/color.rs
deleted file mode 100644
index f19f83bb3d0..00000000000
--- a/third_party/webrender/webrender_api/src/color.rs
+++ /dev/null
@@ -1,160 +0,0 @@
-/* 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 peek_poke::PeekPoke;
-use std::cmp;
-use std::hash::{Hash, Hasher};
-
-/// Represents pre-multiplied RGBA colors with floating point numbers.
-///
-/// All components must be between 0.0 and 1.0.
-/// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
-///
-/// In premultiplied colors transitions to transparent always look "nice"
-/// therefore they are used in CSS gradients.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
-pub struct PremultipliedColorF {
- pub r: f32,
- pub g: f32,
- pub b: f32,
- pub a: f32,
-}
-
-#[allow(missing_docs)]
-impl PremultipliedColorF {
- pub const BLACK: PremultipliedColorF = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
- pub const TRANSPARENT: PremultipliedColorF = PremultipliedColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
- pub const WHITE: PremultipliedColorF = PremultipliedColorF { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
-
- pub fn to_array(&self) -> [f32; 4] {
- [self.r, self.g, self.b, self.a]
- }
-}
-
-/// Represents RGBA screen colors with floating point numbers.
-///
-/// All components must be between 0.0 and 1.0.
-/// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct ColorF {
- pub r: f32,
- pub g: f32,
- pub b: f32,
- pub a: f32,
-}
-
-#[allow(missing_docs)]
-impl ColorF {
- pub const BLACK: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
- pub const TRANSPARENT: ColorF = ColorF { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
- pub const WHITE: ColorF = ColorF { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
-
- /// Constructs a new `ColorF` from its components.
- pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
- ColorF { r, g, b, a }
- }
-
- /// Multiply the RGB channels (but not alpha) with a given factor.
- pub fn scale_rgb(&self, scale: f32) -> Self {
- ColorF {
- r: self.r * scale,
- g: self.g * scale,
- b: self.b * scale,
- a: self.a,
- }
- }
-
- // Scale the alpha by a given factor.
- pub fn scale_alpha(&self, scale: f32) -> Self {
- ColorF {
- r: self.r,
- g: self.g,
- b: self.b,
- a: self.a * scale,
- }
- }
-
- pub fn to_array(&self) -> [f32; 4] {
- [self.r, self.g, self.b, self.a]
- }
-
- /// Multiply the RGB components with the alpha channel.
- pub fn premultiplied(&self) -> PremultipliedColorF {
- let c = self.scale_rgb(self.a);
- PremultipliedColorF { r: c.r, g: c.g, b: c.b, a: c.a }
- }
-}
-
-// Floats don't impl Hash/Eq/Ord...
-impl Eq for PremultipliedColorF {}
-impl Ord for PremultipliedColorF {
- fn cmp(&self, other: &Self) -> cmp::Ordering {
- self.partial_cmp(other).unwrap_or(cmp::Ordering::Equal)
- }
-}
-
-#[cfg_attr(feature = "cargo-clippy", allow(clippy::derive_hash_xor_eq))]
-impl Hash for PremultipliedColorF {
- fn hash<H: Hasher>(&self, state: &mut H) {
- // Note: this is inconsistent with the Eq impl for -0.0 (don't care).
- self.r.to_bits().hash(state);
- self.g.to_bits().hash(state);
- self.b.to_bits().hash(state);
- self.a.to_bits().hash(state);
- }
-}
-
-/// Represents RGBA screen colors with one byte per channel.
-///
-/// If the alpha value `a` is 255 the color is opaque.
-#[repr(C)]
-#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct ColorU {
- pub r: u8,
- pub g: u8,
- pub b: u8,
- pub a: u8,
-}
-
-impl ColorU {
- /// Constructs a new additive `ColorU` from its components.
- pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
- ColorU { r, g, b, a }
- }
-}
-
-fn round_to_int(x: f32) -> u8 {
- debug_assert!((0.0 <= x) && (x <= 1.0), "{} should be between 0 and 1", x);
- let f = (255.0 * x) + 0.5;
- let val = f.floor();
- debug_assert!(val <= 255.0);
- val as u8
-}
-
-// TODO: We shouldn't really convert back to `ColorU` ever,
-// since it's lossy. One of the blockers is that all of our debug colors
-// are specified in `ColorF`. Changing it to `ColorU` would be nice.
-impl From<ColorF> for ColorU {
- fn from(color: ColorF) -> Self {
- ColorU {
- r: round_to_int(color.r),
- g: round_to_int(color.g),
- b: round_to_int(color.b),
- a: round_to_int(color.a),
- }
- }
-}
-
-impl From<ColorU> for ColorF {
- fn from(color: ColorU) -> Self {
- ColorF {
- r: color.r as f32 / 255.0,
- g: color.g as f32 / 255.0,
- b: color.b as f32 / 255.0,
- a: color.a as f32 / 255.0,
- }
- }
-}
diff --git a/third_party/webrender/webrender_api/src/display_item.rs b/third_party/webrender/webrender_api/src/display_item.rs
deleted file mode 100644
index 5c425b9ed17..00000000000
--- a/third_party/webrender/webrender_api/src/display_item.rs
+++ /dev/null
@@ -1,1738 +0,0 @@
-/* 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;
-use crate::{PipelineId, PropertyBinding};
-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;
-
-bitflags! {
- #[repr(C)]
- #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
- pub struct 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;
- /// If set, this primitive represents a scroll bar thumb
- const IS_SCROLLBAR_THUMB = 1 << 2;
- /// 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 << 3;
- /// 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 << 4;
- }
-}
-
-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_id: ClipId,
- /// 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_id: space_and_clip.clip_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_id: ClipId,
-}
-
-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_id: ClipId::root(pipeline_id),
- }
- }
-}
-
-#[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),
- Clip(ClipDisplayItem),
- ClipChain(ClipChainItem),
-
- // Spaces and Frames that content can be scoped under.
- ScrollFrame(ScrollFrameDisplayItem),
- StickyFrame(StickyFrameDisplayItem),
- 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),
- Clip(ClipDisplayItem, Vec<ComplexClipRegion>),
- ClipChain(ClipChainItem, Vec<ClipId>),
-
- ScrollFrame(ScrollFrameDisplayItem),
- StickyFrame(StickyFrameDisplayItem),
- 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 parent_space_and_clip: SpaceAndClipInfo,
- 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 parent_space_and_clip: SpaceAndClipInfo,
- pub clip_rect: LayoutRect,
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct RoundedRectClipDisplayItem {
- pub id: ClipId,
- pub parent_space_and_clip: SpaceAndClipInfo,
- pub clip: ComplexClipRegion,
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct ClipDisplayItem {
- pub id: ClipId,
- pub parent_space_and_clip: SpaceAndClipInfo,
- pub clip_rect: LayoutRect,
-} // IMPLICIT: complex_clips: Vec<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 StickyFrameDisplayItem {
- 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,
-}
-
-#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub enum ScrollSensitivity {
- ScriptAndInputEvents,
- Script,
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct ScrollFrameDisplayItem {
- /// The id of the clip this scroll frame creates
- pub clip_id: ClipId,
- /// 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 clip_rect: LayoutRect,
- pub parent_space_and_clip: SpaceAndClipInfo,
- pub external_id: ExternalScrollId,
- pub scroll_sensitivity: ScrollSensitivity,
- /// 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,
-}
-
-/// 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 common: CommonItemProperties,
- 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>,
-} // 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),
- 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,
-
- /// The outset for the border.
- /// TODO(mrobinson): This should be removed and handled by the client.
- pub outset: LayoutSideOffsets, // TODO: what unit is this in?
-}
-
-#[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 {
- 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,
- },
- /// 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.
- 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,
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct PushStackingContextDisplayItem {
- pub origin: LayoutPoint,
- pub spatial_id: SpatialId,
- pub prim_flags: PrimitiveFlags,
- 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_id: Option<ClipId>,
- 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);
- }
- }
- }
-}
-
-bitflags! {
- #[repr(C)]
- #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
- pub struct StackingContextFlags: u8 {
- /// If true, this stacking context represents a backdrop root, per the CSS
- /// filter-effects specification (see https://drafts.fxtf.org/filter-effects-2/#BackdropRoot).
- const IS_BACKDROP_ROOT = 1 << 0;
- /// 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 << 1;
- }
-}
-
-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,
-}
-
-#[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.min(1.0).max(0.0);
- self.color.g = self.color.g.min(1.0).max(0.0);
- self.color.b = self.color.b.min(1.0).max(0.0);
- self.color.a = self.color.a.min(1.0).max(0.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.min(1.0).max(0.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();
- }
-}
-
-/// CSS filter.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
-pub enum FilterOp {
- /// Filter that does no transformation of the colors, needed for
- /// debug purposes only.
- Identity,
- Blur(f32, f32),
- Brightness(f32),
- Contrast(f32),
- Grayscale(f32),
- HueRotate(f32),
- Invert(f32),
- Opacity(PropertyBinding<f32>, f32),
- Saturate(f32),
- Sepia(f32),
- DropShadow(Shadow),
- ColorMatrix([f32; 20]),
- SrgbToLinear,
- LinearToSrgb,
- ComponentTransfer,
- Flood(ColorF),
-}
-
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
-pub enum ComponentTransferFuncType {
- Identity = 0,
- Table = 1,
- Discrete = 2,
- Linear = 3,
- Gamma = 4,
-}
-
-#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
-pub struct FilterData {
- pub func_r_type: ComponentTransferFuncType,
- pub r_values: Vec<f32>,
- pub func_g_type: ComponentTransferFuncType,
- pub g_values: Vec<f32>,
- pub func_b_type: ComponentTransferFuncType,
- pub b_values: Vec<f32>,
- pub func_a_type: ComponentTransferFuncType,
- pub a_values: Vec<f32>,
-}
-
-fn sanitize_func_type(
- func_type: ComponentTransferFuncType,
- values: &[f32],
-) -> ComponentTransferFuncType {
- if values.is_empty() {
- return ComponentTransferFuncType::Identity;
- }
- if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
- return ComponentTransferFuncType::Identity;
- }
- if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
- return ComponentTransferFuncType::Identity;
- }
- func_type
-}
-
-fn sanitize_values(
- func_type: ComponentTransferFuncType,
- values: &[f32],
-) -> bool {
- if values.len() < 2 && func_type == ComponentTransferFuncType::Linear {
- return false;
- }
- if values.len() < 3 && func_type == ComponentTransferFuncType::Gamma {
- return false;
- }
- true
-}
-
-impl FilterData {
- /// Ensure that the number of values matches up with the function type.
- pub fn sanitize(&self) -> FilterData {
- FilterData {
- func_r_type: sanitize_func_type(self.func_r_type, &self.r_values),
- r_values:
- if sanitize_values(self.func_r_type, &self.r_values) {
- self.r_values.clone()
- } else {
- Vec::new()
- },
- func_g_type: sanitize_func_type(self.func_g_type, &self.g_values),
- g_values:
- if sanitize_values(self.func_g_type, &self.g_values) {
- self.g_values.clone()
- } else {
- Vec::new()
- },
-
- func_b_type: sanitize_func_type(self.func_b_type, &self.b_values),
- b_values:
- if sanitize_values(self.func_b_type, &self.b_values) {
- self.b_values.clone()
- } else {
- Vec::new()
- },
-
- func_a_type: sanitize_func_type(self.func_a_type, &self.a_values),
- a_values:
- if sanitize_values(self.func_a_type, &self.a_values) {
- self.a_values.clone()
- } else {
- Vec::new()
- },
-
- }
- }
-
- pub fn is_identity(&self) -> bool {
- self.func_r_type == ComponentTransferFuncType::Identity &&
- self.func_g_type == ComponentTransferFuncType::Identity &&
- self.func_b_type == ComponentTransferFuncType::Identity &&
- self.func_a_type == ComponentTransferFuncType::Identity
- }
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct IframeDisplayItem {
- pub bounds: LayoutRect,
- pub clip_rect: LayoutRect,
- pub space_and_clip: SpaceAndClipInfo,
- pub pipeline_id: PipelineId,
- pub ignore_missing_pipeline: bool,
-}
-
-/// This describes an image that fills the specified area. It stretches or shrinks
-/// the image as necessary. While RepeatingImageDisplayItem could otherwise provide
-/// a superset of the functionality, it has been problematic inferring the desired
-/// repetition properties when snapping changes the size of the primitive.
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct ImageDisplayItem {
- pub common: CommonItemProperties,
- /// The area to tile the image 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 image_key: ImageKey,
- pub image_rendering: ImageRendering,
- pub alpha_type: AlphaType,
- /// A hack used by gecko to color a simple bitmap font used for tofu glyphs
- pub color: ColorF,
-}
-
-/// This describes a background-image and its tiling. It repeats in a grid to fill
-/// the specified area.
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct RepeatingImageDisplayItem {
- pub common: CommonItemProperties,
- /// The area to tile the image 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 large to make a single tile of the image (common case: bounds.size)
- pub stretch_size: LayoutSize,
- /// The space between tiles (common case: 0)
- pub tile_spacing: LayoutSize,
- pub image_key: ImageKey,
- pub image_rendering: ImageRendering,
- pub alpha_type: AlphaType,
- /// A hack used by gecko to color a simple bitmap font used for tofu glyphs
- pub color: ColorF,
-}
-
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum ImageRendering {
- Auto = 0,
- CrispEdges = 1,
- Pixelated = 2,
-}
-
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum AlphaType {
- Alpha = 0,
- PremultipliedAlpha = 1,
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct YuvImageDisplayItem {
- pub common: CommonItemProperties,
- pub bounds: LayoutRect,
- pub yuv_data: YuvData,
- pub color_depth: ColorDepth,
- pub color_space: YuvColorSpace,
- pub color_range: ColorRange,
- pub image_rendering: ImageRendering,
-}
-
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum YuvColorSpace {
- Rec601 = 0,
- Rec709 = 1,
- Rec2020 = 2,
- Identity = 3, // aka RGB as per ISO/IEC 23091-2:2019
-}
-
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum ColorRange {
- Limited = 0,
- Full = 1,
-}
-
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
-pub enum YuvData {
- NV12(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
- PlanarYCbCr(ImageKey, ImageKey, ImageKey), // (Y channel, Cb channel, Cr Channel)
- InterleavedYCbCr(ImageKey), // (YCbCr interleaved channel)
-}
-
-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, PeekPoke)]
-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, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct ImageMask {
- pub image: ImageKey,
- pub rect: LayoutRect,
- pub repeat: bool,
-}
-
-impl ImageMask {
- /// Get a local clipping rect contributed by this mask.
- 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, PeekPoke)]
-pub enum ClipMode {
- Clip, // Pixels inside the region are visible.
- ClipOut, // Pixels outside the region are visible.
-}
-
-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, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
-pub struct ComplexClipRegion {
- /// The boundaries of the rectangle.
- pub rect: LayoutRect,
- /// Border radii of this rectangle.
- pub radii: BorderRadius,
- /// Whether we are clipping inside or outside
- /// the region.
- 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
- }
- }
-
- /// Return whether, in each corner, the radius in *either* direction is zero.
- /// This means that none of the corners are rounded.
- pub fn is_zero(&self) -> bool {
- let corner_is_zero = |corner: &LayoutSize| corner.width == 0.0 || corner.height == 0.0;
- corner_is_zero(&self.top_left) &&
- corner_is_zero(&self.top_right) &&
- corner_is_zero(&self.bottom_right) &&
- corner_is_zero(&self.bottom_left)
- }
-}
-
-impl ComplexClipRegion {
- /// Create a new complex clip region.
- pub fn new(
- rect: LayoutRect,
- radii: BorderRadius,
- mode: ClipMode,
- ) -> Self {
- ComplexClipRegion { rect, radii, mode }
- }
-}
-
-impl ComplexClipRegion {
- /// Get a local clipping rect contributed by this clip region.
- pub fn get_local_clip_rect(&self) -> Option<LayoutRect> {
- match self.mode {
- ClipMode::Clip => {
- Some(self.rect)
- }
- ClipMode::ClipOut => {
- None
- }
- }
- }
-}
-
-pub const POLYGON_CLIP_VERTEX_MAX: usize = 16;
-
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
-pub enum FillRule {
- Nonzero = 0x1, // Behaves as the SVG fill-rule definition for nonzero.
- Evenodd = 0x2, // Behaves as the SVG fill-rule definition for evenodd.
-}
-
-impl From<u8> for FillRule {
- fn from(fill_rule: u8) -> Self {
- match fill_rule {
- 0x1 => FillRule::Nonzero,
- 0x2 => FillRule::Evenodd,
- _ => panic!("Unexpected FillRule value."),
- }
- }
-}
-
-impl From<FillRule> for u8 {
- fn from(fill_rule: FillRule) -> Self {
- match fill_rule {
- FillRule::Nonzero => 0x1,
- FillRule::Evenodd => 0x2,
- }
- }
-}
-
-#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
-pub struct ClipChainId(pub u64, pub PipelineId);
-
-/// A reference to a clipping node defining how an item is clipped.
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
-pub enum ClipId {
- Clip(usize, PipelineId),
- ClipChain(ClipChainId),
-}
-
-const ROOT_CLIP_ID: usize = 0;
-
-impl ClipId {
- /// Return the root clip ID - effectively doing no clipping.
- pub fn root(pipeline_id: PipelineId) -> Self {
- ClipId::Clip(ROOT_CLIP_ID, pipeline_id)
- }
-
- /// Return an invalid clip ID - needed in places where we carry
- /// one but need to not attempt to use it.
- 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,
- }
- }
-}
-
-/// A reference to a spatial node defining item positioning.
-#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
-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
- }
-}
-
-/// An external identifier that uniquely identifies a scroll frame independent of its ClipId, which
-/// may change from frame to frame. This should be unique within a pipeline. WebRender makes no
-/// attempt to ensure uniqueness. The zero value is reserved for use by the root scroll node of
-/// every pipeline, which always has an external id.
-///
-/// When setting display lists with the `preserve_frame_state` this id is used to preserve scroll
-/// offsets between different sets of SpatialNodes which are ScrollFrames.
-#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
-#[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
- }
-}
-
-impl DisplayItem {
- pub fn debug_name(&self) -> &'static str {
- match *self {
- DisplayItem::Border(..) => "border",
- DisplayItem::BoxShadow(..) => "box_shadow",
- DisplayItem::ClearRectangle(..) => "clear_rectangle",
- DisplayItem::HitTest(..) => "hit_test",
- DisplayItem::RectClip(..) => "rect_clip",
- DisplayItem::RoundedRectClip(..) => "rounded_rect_clip",
- DisplayItem::ImageMaskClip(..) => "image_mask_clip",
- DisplayItem::Clip(..) => "clip",
- DisplayItem::ClipChain(..) => "clip_chain",
- DisplayItem::ConicGradient(..) => "conic_gradient",
- DisplayItem::Gradient(..) => "gradient",
- DisplayItem::Iframe(..) => "iframe",
- DisplayItem::Image(..) => "image",
- DisplayItem::RepeatingImage(..) => "repeating_image",
- DisplayItem::Line(..) => "line",
- DisplayItem::PopAllShadows => "pop_all_shadows",
- DisplayItem::PopReferenceFrame => "pop_reference_frame",
- DisplayItem::PopStackingContext => "pop_stacking_context",
- DisplayItem::PushShadow(..) => "push_shadow",
- DisplayItem::PushReferenceFrame(..) => "push_reference_frame",
- DisplayItem::PushStackingContext(..) => "push_stacking_context",
- DisplayItem::SetFilterOps => "set_filter_ops",
- DisplayItem::SetFilterData => "set_filter_data",
- DisplayItem::SetFilterPrimitives => "set_filter_primitives",
- DisplayItem::SetPoints => "set_points",
- DisplayItem::RadialGradient(..) => "radial_gradient",
- DisplayItem::Rectangle(..) => "rectangle",
- DisplayItem::ScrollFrame(..) => "scroll_frame",
- DisplayItem::SetGradientStops => "set_gradient_stops",
- DisplayItem::ReuseItems(..) => "reuse_item",
- DisplayItem::RetainedItems(..) => "retained_items",
- DisplayItem::StickyFrame(..) => "sticky_frame",
- DisplayItem::Text(..) => "text",
- DisplayItem::YuvImage(..) => "yuv_image",
- DisplayItem::BackdropFilter(..) => "backdrop_filter",
- }
- }
-}
-
-macro_rules! impl_default_for_enums {
- ($($enum:ident => $init:expr ),+) => {
- $(impl Default for $enum {
- #[allow(unused_imports)]
- fn default() -> Self {
- use $enum::*;
- $init
- }
- })*
- }
-}
-
-impl_default_for_enums! {
- DisplayItem => PopStackingContext,
- ScrollSensitivity => ScriptAndInputEvents,
- LineOrientation => Vertical,
- LineStyle => Solid,
- RepeatMode => Stretch,
- NinePatchBorderSource => Image(ImageKey::default()),
- BorderDetails => Normal(NormalBorder::default()),
- BorderRadiusKind => Uniform,
- BorderStyle => None,
- BoxShadowClipMode => Outset,
- ExtendMode => Clamp,
- FilterOp => Identity,
- ComponentTransferFuncType => Identity,
- ClipMode => Clip,
- FillRule => Nonzero,
- ClipId => ClipId::invalid(),
- ReferenceFrameKind => Transform {
- is_2d_scale_translation: false,
- should_snap: false,
- },
- Rotation => Degree0,
- TransformStyle => Flat,
- RasterSpace => Local(f32::default()),
- MixBlendMode => Normal,
- ImageRendering => Auto,
- AlphaType => Alpha,
- YuvColorSpace => Rec601,
- ColorRange => Limited,
- YuvData => NV12(ImageKey::default(), ImageKey::default()),
- YuvFormat => NV12,
- FilterPrimitiveInput => Original,
- ColorSpace => Srgb,
- CompositeOperator => Over
-}
diff --git a/third_party/webrender/webrender_api/src/display_item_cache.rs b/third_party/webrender/webrender_api/src/display_item_cache.rs
deleted file mode 100644
index 8a28ac4ab2c..00000000000
--- a/third_party/webrender/webrender_api/src/display_item_cache.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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 crate::display_item::*;
-use crate::display_list::*;
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct CachedDisplayItem {
- item: DisplayItem,
- data: Vec<u8>,
-}
-
-impl CachedDisplayItem {
- pub fn display_item(&self) -> &DisplayItem {
- &self.item
- }
-
- pub fn data_as_item_range<T>(&self) -> ItemRange<T> {
- ItemRange::new(&self.data)
- }
-}
-
-impl MallocSizeOf for CachedDisplayItem {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- self.data.size_of(ops)
- }
-}
-
-impl From<DisplayItemRef<'_, '_>> for CachedDisplayItem {
- fn from(item_ref: DisplayItemRef) -> Self {
- let item = item_ref.item();
-
- match item {
- DisplayItem::Text(..) => CachedDisplayItem {
- item: *item,
- data: item_ref.glyphs().bytes().to_vec(),
- },
- _ => CachedDisplayItem {
- item: *item,
- data: Vec::new(),
- },
- }
- }
-}
-
-#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
-struct CacheEntry {
- items: Vec<CachedDisplayItem>,
- occupied: bool,
-}
-
-#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
-pub struct DisplayItemCache {
- entries: Vec<CacheEntry>,
-}
-
-impl DisplayItemCache {
- fn add_item(&mut self, key: ItemKey, item: CachedDisplayItem) {
- let entry = &mut self.entries[key as usize];
- entry.items.push(item);
- entry.occupied = true;
- }
-
- fn clear_entry(&mut self, key: ItemKey) {
- let entry = &mut self.entries[key as usize];
- entry.items.clear();
- entry.occupied = false;
- }
-
- fn grow_if_needed(&mut self, capacity: usize) {
- if capacity > self.entries.len() {
- self.entries.resize_with(capacity, || CacheEntry {
- items: Vec::new(),
- occupied: false,
- });
- }
- }
-
- pub fn get_items(&self, key: ItemKey) -> &[CachedDisplayItem] {
- let entry = &self.entries[key as usize];
- debug_assert!(entry.occupied);
- entry.items.as_slice()
- }
-
- pub fn new() -> Self {
- Self {
- entries: Vec::new(),
- }
- }
-
- pub fn update(&mut self, display_list: &BuiltDisplayList) {
- self.grow_if_needed(display_list.cache_size());
-
- let mut iter = display_list.extra_data_iter();
- let mut current_key: Option<ItemKey> = None;
- loop {
- let item = match iter.next() {
- Some(item) => item,
- None => break,
- };
-
- if let DisplayItem::RetainedItems(key) = item.item() {
- current_key = Some(*key);
- self.clear_entry(*key);
- continue;
- }
-
- let key = current_key.expect("Missing RetainedItems marker");
- let cached_item = CachedDisplayItem::from(item);
- self.add_item(key, cached_item);
- }
- }
-}
diff --git a/third_party/webrender/webrender_api/src/display_list.rs b/third_party/webrender/webrender_api/src/display_list.rs
deleted file mode 100644
index e2498c5c194..00000000000
--- a/third_party/webrender/webrender_api/src/display_list.rs
+++ /dev/null
@@ -1,2057 +0,0 @@
-/* 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;
-use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec, strip_red_zone};
-use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
-#[cfg(feature = "deserialize")]
-use serde::de::Deserializer;
-#[cfg(feature = "serialize")]
-use serde::ser::{Serializer, SerializeSeq};
-use serde::{Deserialize, Serialize};
-use std::io::Write;
-use std::marker::PhantomData;
-use std::ops::Range;
-use std::mem;
-use std::collections::HashMap;
-use time::precise_time_ns;
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-// local imports
-use crate::display_item as di;
-use crate::display_item_cache::*;
-use crate::{PipelineId, PropertyBinding};
-use crate::gradient_builder::GradientBuilder;
-use crate::color::ColorF;
-use crate::font::{FontInstanceKey, GlyphInstance, GlyphOptions};
-use crate::image::{ColorDepth, ImageKey};
-use crate::units::*;
-
-
-// We don't want to push a long text-run. If a text-run is too long, split it into several parts.
-// This needs to be set to (renderer::MAX_VERTEX_TEXTURE_WIDTH - VECS_PER_TEXT_RUN) * 2
-pub const MAX_TEXT_RUN_LENGTH: usize = 2040;
-
-// See ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
-// TODO(mrobinson): It would be a good idea to eliminate the root scroll frame which is only
-// used by Servo.
-const FIRST_SPATIAL_NODE_INDEX: usize = 2;
-
-// See ROOT_SCROLL_NODE_SPATIAL_ID
-const FIRST_CLIP_NODE_INDEX: usize = 1;
-
-#[repr(C)]
-#[derive(Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
-pub struct ItemRange<'a, T> {
- bytes: &'a [u8],
- _boo: PhantomData<T>,
-}
-
-impl<'a, T> Copy for ItemRange<'a, T> {}
-impl<'a, T> Clone for ItemRange<'a, T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-impl<'a, T> Default for ItemRange<'a, T> {
- fn default() -> Self {
- ItemRange {
- bytes: Default::default(),
- _boo: PhantomData,
- }
- }
-}
-
-impl<'a, T> ItemRange<'a, T> {
- pub fn new(bytes: &'a [u8]) -> Self {
- Self {
- bytes,
- _boo: PhantomData
- }
- }
-
- pub fn is_empty(&self) -> bool {
- // Nothing more than space for a length (0).
- self.bytes.len() <= mem::size_of::<usize>()
- }
-
- pub fn bytes(&self) -> &[u8] {
- &self.bytes
- }
-}
-
-impl<'a, T: Default> ItemRange<'a, T> {
- pub fn iter(&self) -> AuxIter<'a, T> {
- AuxIter::new(T::default(), self.bytes)
- }
-}
-
-impl<'a, T> IntoIterator for ItemRange<'a, T>
-where
- T: Copy + Default + peek_poke::Peek,
-{
- type Item = T;
- type IntoIter = AuxIter<'a, T>;
- fn into_iter(self) -> Self::IntoIter {
- self.iter()
- }
-}
-
-#[derive(Copy, Clone)]
-pub struct TempFilterData<'a> {
- pub func_types: ItemRange<'a, di::ComponentTransferFuncType>,
- pub r_values: ItemRange<'a, f32>,
- pub g_values: ItemRange<'a, f32>,
- pub b_values: ItemRange<'a, f32>,
- pub a_values: ItemRange<'a, f32>,
-}
-
-/// A display list.
-#[derive(Clone, Default)]
-pub struct BuiltDisplayList {
- /// Serde encoded bytes. Mostly DisplayItems, but some mixed in slices.
- data: Vec<u8>,
- descriptor: BuiltDisplayListDescriptor,
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, Deserialize, Serialize)]
-pub enum GeckoDisplayListType {
- None,
- Partial(f64),
- Full(f64),
-}
-
-impl Default for GeckoDisplayListType {
- fn default() -> Self { GeckoDisplayListType::None }
-}
-
-/// Describes the memory layout of a display list.
-///
-/// A display list consists of some number of display list items, followed by a number of display
-/// items.
-#[repr(C)]
-#[derive(Copy, Clone, Default, Deserialize, Serialize)]
-pub struct BuiltDisplayListDescriptor {
- /// Gecko specific information about the display list.
- gecko_display_list_type: GeckoDisplayListType,
- /// The first IPC time stamp: before any work has been done
- builder_start_time: u64,
- /// The second IPC time stamp: after serialization
- builder_finish_time: u64,
- /// The third IPC time stamp: just before sending
- send_start_time: u64,
- /// The amount of clipping nodes created while building this display list.
- total_clip_nodes: usize,
- /// The amount of spatial nodes created while building this display list.
- total_spatial_nodes: usize,
- /// The size of the cache for this display list.
- cache_size: usize,
- /// The offset for additional display list data.
- extra_data_offset: usize,
-}
-
-#[derive(Clone)]
-pub struct DisplayListWithCache {
- display_list: BuiltDisplayList,
- cache: DisplayItemCache,
-}
-
-impl DisplayListWithCache {
- pub fn iter(&self) -> BuiltDisplayListIter {
- self.display_list.iter_with_cache(&self.cache)
- }
-
- pub fn new_from_list(display_list: BuiltDisplayList) -> Self {
- let mut cache = DisplayItemCache::new();
- cache.update(&display_list);
-
- DisplayListWithCache {
- display_list,
- cache
- }
- }
-
- pub fn update(&mut self, display_list: BuiltDisplayList) {
- self.cache.update(&display_list);
- self.display_list = display_list;
- }
-
- pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
- self.display_list.descriptor()
- }
-
- pub fn times(&self) -> (u64, u64, u64) {
- self.display_list.times()
- }
-
- pub fn data(&self) -> &[u8] {
- self.display_list.data()
- }
-}
-
-impl MallocSizeOf for DisplayListWithCache {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- self.display_list.data.size_of(ops) + self.cache.size_of(ops)
- }
-}
-
-#[cfg(feature = "serialize")]
-impl Serialize for DisplayListWithCache {
- fn serialize<S: Serializer>(
- &self,
- serializer: S
- ) -> Result<S::Ok, S::Error> {
- BuiltDisplayList::serialize_with_iterator(serializer, self.iter())
- }
-}
-
-#[cfg(feature = "deserialize")]
-impl<'de> Deserialize<'de> for DisplayListWithCache {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: Deserializer<'de>,
- {
- let display_list = BuiltDisplayList::deserialize(deserializer)?;
- let cache = DisplayItemCache::new();
-
- Ok(DisplayListWithCache {
- display_list,
- cache,
- })
- }
-}
-
-impl BuiltDisplayListDescriptor {}
-
-pub struct BuiltDisplayListIter<'a> {
- list: &'a BuiltDisplayList,
- data: &'a [u8],
- cache: Option<&'a DisplayItemCache>,
- pending_items: std::slice::Iter<'a, CachedDisplayItem>,
- cur_cached_item: Option<&'a CachedDisplayItem>,
- cur_item: di::DisplayItem,
- cur_stops: ItemRange<'a, di::GradientStop>,
- cur_glyphs: ItemRange<'a, GlyphInstance>,
- cur_filters: ItemRange<'a, di::FilterOp>,
- cur_filter_data: Vec<TempFilterData<'a>>,
- cur_filter_primitives: ItemRange<'a, di::FilterPrimitive>,
- cur_clip_chain_items: ItemRange<'a, di::ClipId>,
- cur_complex_clip: ItemRange<'a, di::ComplexClipRegion>,
- cur_points: ItemRange<'a, LayoutPoint>,
- peeking: Peek,
- /// Should just be initialized but never populated in release builds
- debug_stats: DebugStats,
-}
-
-/// Internal info used for more detailed analysis of serialized display lists
-#[allow(dead_code)]
-struct DebugStats {
- /// Last address in the buffer we pointed to, for computing serialized sizes
- last_addr: usize,
- stats: HashMap<&'static str, ItemStats>,
-}
-
-impl DebugStats {
- #[cfg(feature = "display_list_stats")]
- fn _update_entry(&mut self, name: &'static str, item_count: usize, byte_count: usize) {
- let entry = self.stats.entry(name).or_default();
- entry.total_count += item_count;
- entry.num_bytes += byte_count;
- }
-
- /// Computes the number of bytes we've processed since we last called
- /// this method, so we can compute the serialized size of a display item.
- #[cfg(feature = "display_list_stats")]
- fn debug_num_bytes(&mut self, data: &[u8]) -> usize {
- let old_addr = self.last_addr;
- let new_addr = data.as_ptr() as usize;
- let delta = new_addr - old_addr;
- self.last_addr = new_addr;
-
- delta
- }
-
- /// Logs stats for the last deserialized display item
- #[cfg(feature = "display_list_stats")]
- fn log_item(&mut self, data: &[u8], item: &di::DisplayItem) {
- let num_bytes = self.debug_num_bytes(data);
- self._update_entry(item.debug_name(), 1, num_bytes);
- }
-
- /// Logs the stats for the given serialized slice
- #[cfg(feature = "display_list_stats")]
- fn log_slice<T: Copy + Default + peek_poke::Peek>(
- &mut self,
- slice_name: &'static str,
- range: &ItemRange<T>,
- ) {
- // Run this so log_item_stats is accurate, but ignore its result
- // because log_slice_stats may be called after multiple slices have been
- // processed, and the `range` has everything we need.
- self.last_addr = range.bytes.as_ptr() as usize + range.bytes.len();
-
- self._update_entry(slice_name, range.iter().len(), range.bytes.len());
- }
-
- #[cfg(not(feature = "display_list_stats"))]
- fn log_slice<T>(&mut self, _slice_name: &str, _range: &ItemRange<T>) {
- /* no-op */
- }
-}
-
-/// Stats for an individual item
-#[derive(Copy, Clone, Debug, Default)]
-pub struct ItemStats {
- /// How many instances of this kind of item we deserialized
- pub total_count: usize,
- /// How many bytes we processed for this kind of item
- pub num_bytes: usize,
-}
-
-pub struct DisplayItemRef<'a: 'b, 'b> {
- iter: &'b BuiltDisplayListIter<'a>,
-}
-
-// Some of these might just become ItemRanges
-impl<'a, 'b> DisplayItemRef<'a, 'b> {
- pub fn display_list(&self) -> &BuiltDisplayList {
- self.iter.display_list()
- }
-
- // Creates a new iterator where this element's iterator is, to hack around borrowck.
- pub fn sub_iter(&self) -> BuiltDisplayListIter<'a> {
- self.iter.sub_iter()
- }
-
- pub fn item(&self) -> &di::DisplayItem {
- self.iter.current_item()
- }
-
- pub fn clip_chain_items(&self) -> ItemRange<di::ClipId> {
- self.iter.cur_clip_chain_items
- }
-
- pub fn complex_clip(&self) -> ItemRange<di::ComplexClipRegion> {
- self.iter.cur_complex_clip
- }
-
- pub fn points(&self) -> ItemRange<LayoutPoint> {
- self.iter.cur_points
- }
-
- pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
- self.iter.glyphs()
- }
-
- pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
- self.iter.gradient_stops()
- }
-
- pub fn filters(&self) -> ItemRange<di::FilterOp> {
- self.iter.cur_filters
- }
-
- pub fn filter_datas(&self) -> &Vec<TempFilterData> {
- &self.iter.cur_filter_data
- }
-
- pub fn filter_primitives(&self) -> ItemRange<di::FilterPrimitive> {
- self.iter.cur_filter_primitives
- }
-}
-
-#[derive(PartialEq)]
-enum Peek {
- StartPeeking,
- IsPeeking,
- NotPeeking,
-}
-
-#[derive(Clone)]
-pub struct AuxIter<'a, T> {
- item: T,
- data: &'a [u8],
- size: usize,
-// _boo: PhantomData<T>,
-}
-
-impl BuiltDisplayList {
- pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> Self {
- BuiltDisplayList { data, descriptor }
- }
-
- pub fn into_data(self) -> (Vec<u8>, BuiltDisplayListDescriptor) {
- (self.data, self.descriptor)
- }
-
- pub fn data(&self) -> &[u8] {
- &self.data[..]
- }
-
- pub fn item_slice(&self) -> &[u8] {
- &self.data[..self.descriptor.extra_data_offset]
- }
-
- pub fn extra_slice(&self) -> &[u8] {
- &self.data[self.descriptor.extra_data_offset..]
- }
-
- pub fn descriptor(&self) -> &BuiltDisplayListDescriptor {
- &self.descriptor
- }
-
- pub fn set_send_time_ns(&mut self, time: u64) {
- self.descriptor.send_start_time = time;
- }
-
- pub fn times(&self) -> (u64, u64, u64) {
- (
- self.descriptor.builder_start_time,
- self.descriptor.builder_finish_time,
- self.descriptor.send_start_time,
- )
- }
-
- pub fn gecko_display_list_stats(&self) -> (f64, bool) {
- match self.descriptor.gecko_display_list_type {
- GeckoDisplayListType::Full(duration) => (duration, true),
- GeckoDisplayListType::Partial(duration) => (duration, false),
- _ => (0.0, false)
- }
- }
-
- pub fn total_clip_nodes(&self) -> usize {
- self.descriptor.total_clip_nodes
- }
-
- pub fn total_spatial_nodes(&self) -> usize {
- self.descriptor.total_spatial_nodes
- }
-
- pub fn iter(&self) -> BuiltDisplayListIter {
- BuiltDisplayListIter::new(self, self.item_slice(), None)
- }
-
- pub fn extra_data_iter(&self) -> BuiltDisplayListIter {
- BuiltDisplayListIter::new(self, self.extra_slice(), None)
- }
-
- pub fn iter_with_cache<'a>(
- &'a self,
- cache: &'a DisplayItemCache
- ) -> BuiltDisplayListIter<'a> {
- BuiltDisplayListIter::new(self, self.item_slice(), Some(cache))
- }
-
- pub fn cache_size(&self) -> usize {
- self.descriptor.cache_size
- }
-
- #[cfg(feature = "serialize")]
- pub fn serialize_with_iterator<S: Serializer>(
- serializer: S,
- mut iterator: BuiltDisplayListIter,
- ) -> Result<S::Ok, S::Error> {
- use crate::display_item::DisplayItem as Real;
- use crate::display_item::DebugDisplayItem as Debug;
-
- let mut seq = serializer.serialize_seq(None)?;
-
- while let Some(item) = iterator.next_raw() {
- let serial_di = match *item.item() {
- Real::Clip(v) => Debug::Clip(
- v,
- item.iter.cur_complex_clip.iter().collect()
- ),
- Real::ClipChain(v) => Debug::ClipChain(
- v,
- item.iter.cur_clip_chain_items.iter().collect()
- ),
- Real::ScrollFrame(v) => Debug::ScrollFrame(v),
- Real::Text(v) => Debug::Text(
- v,
- item.iter.cur_glyphs.iter().collect()
- ),
- Real::SetFilterOps => Debug::SetFilterOps(
- item.iter.cur_filters.iter().collect()
- ),
- Real::SetFilterData => {
- debug_assert!(!item.iter.cur_filter_data.is_empty(),
- "next_raw should have populated cur_filter_data");
- let temp_filter_data = &item.iter.cur_filter_data[item.iter.cur_filter_data.len()-1];
-
- let func_types: Vec<di::ComponentTransferFuncType> =
- temp_filter_data.func_types.iter().collect();
- debug_assert!(func_types.len() == 4,
- "someone changed the number of filter funcs without updating this code");
- Debug::SetFilterData(di::FilterData {
- func_r_type: func_types[0],
- r_values: temp_filter_data.r_values.iter().collect(),
- func_g_type: func_types[1],
- g_values: temp_filter_data.g_values.iter().collect(),
- func_b_type: func_types[2],
- b_values: temp_filter_data.b_values.iter().collect(),
- func_a_type: func_types[3],
- a_values: temp_filter_data.a_values.iter().collect(),
- })
- },
- Real::SetFilterPrimitives => Debug::SetFilterPrimitives(
- item.iter.cur_filter_primitives.iter().collect()
- ),
- Real::SetGradientStops => Debug::SetGradientStops(
- item.iter.cur_stops.iter().collect()
- ),
- Real::SetPoints => Debug::SetPoints(
- item.iter.cur_points.iter().collect()
- ),
- Real::RectClip(v) => Debug::RectClip(v),
- Real::RoundedRectClip(v) => Debug::RoundedRectClip(v),
- Real::ImageMaskClip(v) => Debug::ImageMaskClip(v),
- Real::StickyFrame(v) => Debug::StickyFrame(v),
- Real::Rectangle(v) => Debug::Rectangle(v),
- Real::ClearRectangle(v) => Debug::ClearRectangle(v),
- Real::HitTest(v) => Debug::HitTest(v),
- Real::Line(v) => Debug::Line(v),
- Real::Image(v) => Debug::Image(v),
- Real::RepeatingImage(v) => Debug::RepeatingImage(v),
- Real::YuvImage(v) => Debug::YuvImage(v),
- Real::Border(v) => Debug::Border(v),
- Real::BoxShadow(v) => Debug::BoxShadow(v),
- Real::Gradient(v) => Debug::Gradient(v),
- Real::RadialGradient(v) => Debug::RadialGradient(v),
- Real::ConicGradient(v) => Debug::ConicGradient(v),
- Real::Iframe(v) => Debug::Iframe(v),
- Real::PushReferenceFrame(v) => Debug::PushReferenceFrame(v),
- Real::PushStackingContext(v) => Debug::PushStackingContext(v),
- Real::PushShadow(v) => Debug::PushShadow(v),
- Real::BackdropFilter(v) => Debug::BackdropFilter(v),
-
- Real::PopReferenceFrame => Debug::PopReferenceFrame,
- Real::PopStackingContext => Debug::PopStackingContext,
- Real::PopAllShadows => Debug::PopAllShadows,
- Real::ReuseItems(_) |
- Real::RetainedItems(_) => unreachable!("Unexpected item"),
- };
- seq.serialize_element(&serial_di)?
- }
- seq.end()
- }
-}
-
-/// Returns the byte-range the slice occupied.
-fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
- let mut skip_offset = 0usize;
- *data = peek_from_slice(data, &mut skip_offset);
- let (skip, rest) = data.split_at(skip_offset);
-
- // Adjust data pointer to skip read values
- *data = rest;
-
- ItemRange {
- bytes: skip,
- _boo: PhantomData,
- }
-}
-
-impl<'a> BuiltDisplayListIter<'a> {
- pub fn new(
- list: &'a BuiltDisplayList,
- data: &'a [u8],
- cache: Option<&'a DisplayItemCache>,
- ) -> Self {
- Self {
- list,
- data,
- cache,
- pending_items: [].iter(),
- cur_cached_item: None,
- cur_item: di::DisplayItem::PopStackingContext,
- cur_stops: ItemRange::default(),
- cur_glyphs: ItemRange::default(),
- cur_filters: ItemRange::default(),
- cur_filter_data: Vec::new(),
- cur_filter_primitives: ItemRange::default(),
- cur_clip_chain_items: ItemRange::default(),
- cur_complex_clip: ItemRange::default(),
- cur_points: ItemRange::default(),
- peeking: Peek::NotPeeking,
- debug_stats: DebugStats {
- last_addr: data.as_ptr() as usize,
- stats: HashMap::default(),
- },
- }
- }
-
- pub fn sub_iter(&self) -> Self {
- let mut iter = BuiltDisplayListIter::new(
- self.list, self.data, self.cache
- );
- iter.pending_items = self.pending_items.clone();
- iter
- }
-
- pub fn display_list(&self) -> &'a BuiltDisplayList {
- self.list
- }
-
- pub fn current_item(&self) -> &di::DisplayItem {
- match self.cur_cached_item {
- Some(cached_item) => cached_item.display_item(),
- None => &self.cur_item
- }
- }
-
- fn cached_item_range_or<T>(
- &self,
- data: ItemRange<'a, T>
- ) -> ItemRange<'a, T> {
- match self.cur_cached_item {
- Some(cached_item) => cached_item.data_as_item_range(),
- None => data,
- }
- }
-
- pub fn glyphs(&self) -> ItemRange<GlyphInstance> {
- self.cached_item_range_or(self.cur_glyphs)
- }
-
- pub fn gradient_stops(&self) -> ItemRange<di::GradientStop> {
- self.cached_item_range_or(self.cur_stops)
- }
-
- fn advance_pending_items(&mut self) -> bool {
- self.cur_cached_item = self.pending_items.next();
- self.cur_cached_item.is_some()
- }
-
- pub fn next<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
- use crate::DisplayItem::*;
-
- match self.peeking {
- Peek::IsPeeking => {
- self.peeking = Peek::NotPeeking;
- return Some(self.as_ref());
- }
- Peek::StartPeeking => {
- self.peeking = Peek::IsPeeking;
- }
- Peek::NotPeeking => { /* do nothing */ }
- }
-
- // Don't let these bleed into another item
- self.cur_stops = ItemRange::default();
- self.cur_complex_clip = ItemRange::default();
- self.cur_clip_chain_items = ItemRange::default();
- self.cur_points = ItemRange::default();
- self.cur_filters = ItemRange::default();
- self.cur_filter_primitives = ItemRange::default();
- self.cur_filter_data.clear();
-
- loop {
- self.next_raw()?;
- match self.cur_item {
- SetGradientStops |
- SetFilterOps |
- SetFilterData |
- SetFilterPrimitives |
- SetPoints => {
- // These are marker items for populating other display items, don't yield them.
- continue;
- }
- _ => {
- break;
- }
- }
- }
-
- Some(self.as_ref())
- }
-
- /// Gets the next display item, even if it's a dummy. Also doesn't handle peeking
- /// and may leave irrelevant ranges live (so a Clip may have GradientStops if
- /// for some reason you ask).
- pub fn next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
- use crate::DisplayItem::*;
-
- if self.advance_pending_items() {
- return Some(self.as_ref());
- }
-
- // A "red zone" of DisplayItem::max_size() bytes has been added to the
- // end of the serialized display list. If this amount, or less, is
- // remaining then we've reached the end of the display list.
- if self.data.len() <= di::DisplayItem::max_size() {
- return None;
- }
-
- self.data = peek_from_slice(self.data, &mut self.cur_item);
- self.log_item_stats();
-
- match self.cur_item {
- SetGradientStops => {
- self.cur_stops = skip_slice::<di::GradientStop>(&mut self.data);
- self.debug_stats.log_slice("set_gradient_stops.stops", &self.cur_stops);
- }
- SetFilterOps => {
- self.cur_filters = skip_slice::<di::FilterOp>(&mut self.data);
- self.debug_stats.log_slice("set_filter_ops.ops", &self.cur_filters);
- }
- SetFilterData => {
- self.cur_filter_data.push(TempFilterData {
- func_types: skip_slice::<di::ComponentTransferFuncType>(&mut self.data),
- r_values: skip_slice::<f32>(&mut self.data),
- g_values: skip_slice::<f32>(&mut self.data),
- b_values: skip_slice::<f32>(&mut self.data),
- a_values: skip_slice::<f32>(&mut self.data),
- });
-
- let data = *self.cur_filter_data.last().unwrap();
- self.debug_stats.log_slice("set_filter_data.func_types", &data.func_types);
- self.debug_stats.log_slice("set_filter_data.r_values", &data.r_values);
- self.debug_stats.log_slice("set_filter_data.g_values", &data.g_values);
- self.debug_stats.log_slice("set_filter_data.b_values", &data.b_values);
- self.debug_stats.log_slice("set_filter_data.a_values", &data.a_values);
- }
- SetFilterPrimitives => {
- self.cur_filter_primitives = skip_slice::<di::FilterPrimitive>(&mut self.data);
- self.debug_stats.log_slice("set_filter_primitives.primitives", &self.cur_filter_primitives);
- }
- SetPoints => {
- self.cur_points = skip_slice::<LayoutPoint>(&mut self.data);
- self.debug_stats.log_slice("set_points.points", &self.cur_points);
- }
- ClipChain(_) => {
- self.cur_clip_chain_items = skip_slice::<di::ClipId>(&mut self.data);
- self.debug_stats.log_slice("clip_chain.clip_ids", &self.cur_clip_chain_items);
- }
- Clip(_) => {
- self.cur_complex_clip = skip_slice::<di::ComplexClipRegion>(&mut self.data);
- self.debug_stats.log_slice("clip.complex_clips", &self.cur_complex_clip);
- }
- Text(_) => {
- self.cur_glyphs = skip_slice::<GlyphInstance>(&mut self.data);
- self.debug_stats.log_slice("text.glyphs", &self.cur_glyphs);
- }
- ReuseItems(key) => {
- match self.cache {
- Some(cache) => {
- self.pending_items = cache.get_items(key).iter();
- self.advance_pending_items();
- }
- None => {
- unreachable!("Cache marker without cache!");
- }
- }
- }
- _ => { /* do nothing */ }
- }
-
- Some(self.as_ref())
- }
-
- pub fn as_ref<'b>(&'b self) -> DisplayItemRef<'a, 'b> {
- DisplayItemRef {
- iter: self,
- }
- }
-
- pub fn skip_current_stacking_context(&mut self) {
- let mut depth = 0;
- while let Some(item) = self.next() {
- match *item.item() {
- di::DisplayItem::PushStackingContext(..) => depth += 1,
- di::DisplayItem::PopStackingContext if depth == 0 => return,
- di::DisplayItem::PopStackingContext => depth -= 1,
- _ => {}
- }
- }
- }
-
- pub fn current_stacking_context_empty(&mut self) -> bool {
- match self.peek() {
- Some(item) => *item.item() == di::DisplayItem::PopStackingContext,
- None => true,
- }
- }
-
- pub fn peek<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
- if self.peeking == Peek::NotPeeking {
- self.peeking = Peek::StartPeeking;
- self.next()
- } else {
- Some(self.as_ref())
- }
- }
-
- /// Get the debug stats for what this iterator has deserialized.
- /// Should always be empty in release builds.
- pub fn debug_stats(&mut self) -> Vec<(&'static str, ItemStats)> {
- let mut result = self.debug_stats.stats.drain().collect::<Vec<_>>();
- result.sort_by_key(|stats| stats.0);
- result
- }
-
- /// Adds the debug stats from another to our own, assuming we are a sub-iter of the other
- /// (so we can ignore where they were in the traversal).
- pub fn merge_debug_stats_from(&mut self, other: &mut Self) {
- for (key, other_entry) in other.debug_stats.stats.iter() {
- let entry = self.debug_stats.stats.entry(key).or_default();
-
- entry.total_count += other_entry.total_count;
- entry.num_bytes += other_entry.num_bytes;
- }
- }
-
- /// Logs stats for the last deserialized display item
- #[cfg(feature = "display_list_stats")]
- fn log_item_stats(&mut self) {
- self.debug_stats.log_item(self.data, &self.cur_item);
- }
-
- #[cfg(not(feature = "display_list_stats"))]
- fn log_item_stats(&mut self) { /* no-op */ }
-}
-
-impl<'a, T> AuxIter<'a, T> {
- pub fn new(item: T, mut data: &'a [u8]) -> Self {
- let mut size = 0usize;
- if !data.is_empty() {
- data = peek_from_slice(data, &mut size);
- };
-
- AuxIter {
- item,
- data,
- size,
-// _boo: PhantomData,
- }
- }
-}
-
-impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
- type Item = T;
-
- fn next(&mut self) -> Option<Self::Item> {
- if self.size == 0 {
- None
- } else {
- self.size -= 1;
- self.data = peek_from_slice(self.data, &mut self.item);
- Some(self.item)
- }
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.size, Some(self.size))
- }
-}
-
-impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
-
-#[cfg(feature = "serialize")]
-impl Serialize for BuiltDisplayList {
- fn serialize<S: Serializer>(
- &self,
- serializer: S
- ) -> Result<S::Ok, S::Error> {
- Self::serialize_with_iterator(serializer, self.iter())
- }
-}
-
-// The purpose of this implementation is to deserialize
-// a display list from one format just to immediately
-// serialize then into a "built" `Vec<u8>`.
-
-#[cfg(feature = "deserialize")]
-impl<'de> Deserialize<'de> for BuiltDisplayList {
- fn deserialize<D: Deserializer<'de>>(
- deserializer: D
- ) -> Result<Self, D::Error> {
- use crate::display_item::DisplayItem as Real;
- use crate::display_item::DebugDisplayItem as Debug;
-
- let list = Vec::<Debug>::deserialize(deserializer)?;
-
- let mut data = Vec::new();
- let mut temp = Vec::new();
- let mut total_clip_nodes = FIRST_CLIP_NODE_INDEX;
- let mut total_spatial_nodes = FIRST_SPATIAL_NODE_INDEX;
- for complete in list {
- let item = match complete {
- Debug::Clip(v, complex_clips) => {
- total_clip_nodes += 1;
- DisplayListBuilder::push_iter_impl(&mut temp, complex_clips);
- Real::Clip(v)
- },
- Debug::ClipChain(v, clip_chain_ids) => {
- DisplayListBuilder::push_iter_impl(&mut temp, clip_chain_ids);
- Real::ClipChain(v)
- }
- Debug::ScrollFrame(v) => {
- total_spatial_nodes += 1;
- total_clip_nodes += 1;
- Real::ScrollFrame(v)
- }
- Debug::StickyFrame(v) => {
- total_spatial_nodes += 1;
- Real::StickyFrame(v)
- }
- Debug::Text(v, glyphs) => {
- DisplayListBuilder::push_iter_impl(&mut temp, glyphs);
- Real::Text(v)
- },
- Debug::Iframe(v) => {
- total_clip_nodes += 1;
- Real::Iframe(v)
- }
- Debug::PushReferenceFrame(v) => {
- total_spatial_nodes += 1;
- Real::PushReferenceFrame(v)
- }
- Debug::SetFilterOps(filters) => {
- DisplayListBuilder::push_iter_impl(&mut temp, filters);
- Real::SetFilterOps
- },
- Debug::SetFilterData(filter_data) => {
- let func_types: Vec<di::ComponentTransferFuncType> =
- [filter_data.func_r_type,
- filter_data.func_g_type,
- filter_data.func_b_type,
- filter_data.func_a_type].to_vec();
- DisplayListBuilder::push_iter_impl(&mut temp, func_types);
- DisplayListBuilder::push_iter_impl(&mut temp, filter_data.r_values);
- DisplayListBuilder::push_iter_impl(&mut temp, filter_data.g_values);
- DisplayListBuilder::push_iter_impl(&mut temp, filter_data.b_values);
- DisplayListBuilder::push_iter_impl(&mut temp, filter_data.a_values);
- Real::SetFilterData
- },
- Debug::SetFilterPrimitives(filter_primitives) => {
- DisplayListBuilder::push_iter_impl(&mut temp, filter_primitives);
- Real::SetFilterPrimitives
- }
- Debug::SetGradientStops(stops) => {
- DisplayListBuilder::push_iter_impl(&mut temp, stops);
- Real::SetGradientStops
- },
- Debug::SetPoints(points) => {
- DisplayListBuilder::push_iter_impl(&mut temp, points);
- Real::SetPoints
- },
- Debug::RectClip(v) => Real::RectClip(v),
- Debug::RoundedRectClip(v) => Real::RoundedRectClip(v),
- Debug::ImageMaskClip(v) => Real::ImageMaskClip(v),
- Debug::Rectangle(v) => Real::Rectangle(v),
- Debug::ClearRectangle(v) => Real::ClearRectangle(v),
- Debug::HitTest(v) => Real::HitTest(v),
- Debug::Line(v) => Real::Line(v),
- Debug::Image(v) => Real::Image(v),
- Debug::RepeatingImage(v) => Real::RepeatingImage(v),
- Debug::YuvImage(v) => Real::YuvImage(v),
- Debug::Border(v) => Real::Border(v),
- Debug::BoxShadow(v) => Real::BoxShadow(v),
- Debug::Gradient(v) => Real::Gradient(v),
- Debug::RadialGradient(v) => Real::RadialGradient(v),
- Debug::ConicGradient(v) => Real::ConicGradient(v),
- Debug::PushStackingContext(v) => Real::PushStackingContext(v),
- Debug::PushShadow(v) => Real::PushShadow(v),
- Debug::BackdropFilter(v) => Real::BackdropFilter(v),
-
- Debug::PopStackingContext => Real::PopStackingContext,
- Debug::PopReferenceFrame => Real::PopReferenceFrame,
- Debug::PopAllShadows => Real::PopAllShadows,
- };
- poke_into_vec(&item, &mut data);
- // the aux data is serialized after the item, hence the temporary
- data.extend(temp.drain(..));
- }
-
- // Add `DisplayItem::max_size` zone of zeroes to the end of display list
- // so there is at least this amount available in the display list during
- // serialization.
- ensure_red_zone::<di::DisplayItem>(&mut data);
- let extra_data_offset = data.len();
-
- Ok(BuiltDisplayList {
- data,
- descriptor: BuiltDisplayListDescriptor {
- gecko_display_list_type: GeckoDisplayListType::None,
- builder_start_time: 0,
- builder_finish_time: 1,
- send_start_time: 1,
- total_clip_nodes,
- total_spatial_nodes,
- extra_data_offset,
- cache_size: 0,
- },
- })
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct SaveState {
- dl_len: usize,
- next_clip_index: usize,
- next_spatial_index: usize,
- next_clip_chain_id: u64,
-}
-
-/// DisplayListSection determines the target buffer for the display items.
-pub enum DisplayListSection {
- /// The main/default buffer: contains item data and item group markers.
- Data,
- /// Auxiliary buffer: contains the item data for item groups.
- ExtraData,
- /// Temporary buffer: contains the data for pending item group. Flushed to
- /// one of the buffers above, after item grouping finishes.
- Chunk,
-}
-
-#[derive(Clone)]
-pub struct DisplayListBuilder {
- pub data: Vec<u8>,
- pub pipeline_id: PipelineId,
-
- extra_data: Vec<u8>,
- pending_chunk: Vec<u8>,
- writing_to_chunk: bool,
-
- next_clip_index: usize,
- next_spatial_index: usize,
- next_clip_chain_id: u64,
- builder_start_time: u64,
-
- save_state: Option<SaveState>,
-
- cache_size: usize,
- serialized_content_buffer: Option<String>,
-}
-
-impl DisplayListBuilder {
- pub fn new(pipeline_id: PipelineId) -> Self {
- Self::with_capacity(pipeline_id, 0)
- }
-
- pub fn with_capacity(
- pipeline_id: PipelineId,
- capacity: usize,
- ) -> Self {
- let start_time = precise_time_ns();
-
- DisplayListBuilder {
- data: Vec::with_capacity(capacity),
- pipeline_id,
-
- extra_data: Vec::new(),
- pending_chunk: Vec::new(),
- writing_to_chunk: false,
-
- next_clip_index: FIRST_CLIP_NODE_INDEX,
- next_spatial_index: FIRST_SPATIAL_NODE_INDEX,
- next_clip_chain_id: 0,
- builder_start_time: start_time,
- save_state: None,
- cache_size: 0,
- serialized_content_buffer: None,
- }
- }
-
- /// Saves the current display list state, so it may be `restore()`'d.
- ///
- /// # Conditions:
- ///
- /// * Doesn't support popping clips that were pushed before the save.
- /// * Doesn't support nested saves.
- /// * Must call `clear_save()` if the restore becomes unnecessary.
- pub fn save(&mut self) {
- assert!(self.save_state.is_none(), "DisplayListBuilder doesn't support nested saves");
-
- self.save_state = Some(SaveState {
- dl_len: self.data.len(),
- next_clip_index: self.next_clip_index,
- next_spatial_index: self.next_spatial_index,
- next_clip_chain_id: self.next_clip_chain_id,
- });
- }
-
- /// Restores the state of the builder to when `save()` was last called.
- pub fn restore(&mut self) {
- let state = self.save_state.take().expect("No save to restore DisplayListBuilder from");
-
- self.data.truncate(state.dl_len);
- self.next_clip_index = state.next_clip_index;
- self.next_spatial_index = state.next_spatial_index;
- self.next_clip_chain_id = state.next_clip_chain_id;
- }
-
- /// Discards the builder's save (indicating the attempted operation was successful).
- pub fn clear_save(&mut self) {
- self.save_state.take().expect("No save to clear in DisplayListBuilder");
- }
-
- /// Emits a debug representation of display items in the list, for debugging
- /// purposes. If the range's start parameter is specified, only display
- /// items starting at that index (inclusive) will be printed. If the range's
- /// end parameter is specified, only display items before that index
- /// (exclusive) will be printed. Calling this function with end <= start is
- /// allowed but is just a waste of CPU cycles. The function emits the
- /// debug representation of the selected display items, one per line, with
- /// the given indent, to the provided sink object. The return value is
- /// the total number of items in the display list, which allows the
- /// caller to subsequently invoke this function to only dump the newly-added
- /// items.
- pub fn emit_display_list<W>(
- &mut self,
- indent: usize,
- range: Range<Option<usize>>,
- mut sink: W,
- ) -> usize
- where
- W: Write
- {
- let mut temp = BuiltDisplayList::default();
- ensure_red_zone::<di::DisplayItem>(&mut self.data);
- temp.descriptor.extra_data_offset = self.data.len();
- mem::swap(&mut temp.data, &mut self.data);
-
- let mut index: usize = 0;
- {
- let mut cache = DisplayItemCache::new();
- cache.update(&temp);
- let mut iter = temp.iter_with_cache(&cache);
- while let Some(item) = iter.next_raw() {
- if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) {
- writeln!(sink, "{}{:?}", " ".repeat(indent), item.item()).unwrap();
- }
- index += 1;
- }
- }
-
- self.data = temp.data;
- strip_red_zone::<di::DisplayItem>(&mut self.data);
- index
- }
-
- /// Print the display items in the list to stdout.
- pub fn dump_serialized_display_list(&mut self) {
- self.serialized_content_buffer = Some(String::new());
- }
-
- fn add_to_display_list_dump<T: std::fmt::Debug>(&mut self, item: T) {
- if let Some(ref mut content) = self.serialized_content_buffer {
- use std::fmt::Write;
- write!(content, "{:?}\n", item).expect("DL dump write failed.");
- }
- }
-
- /// Returns the default section that DisplayListBuilder will write to,
- /// if no section is specified explicitly.
- fn default_section(&self) -> DisplayListSection {
- if self.writing_to_chunk {
- DisplayListSection::Chunk
- } else {
- DisplayListSection::Data
- }
- }
-
- fn buffer_from_section(
- &mut self,
- section: DisplayListSection
- ) -> &mut Vec<u8> {
- match section {
- DisplayListSection::Data => &mut self.data,
- DisplayListSection::ExtraData => &mut self.extra_data,
- DisplayListSection::Chunk => &mut self.pending_chunk,
- }
- }
-
- #[inline]
- pub fn push_item_to_section(
- &mut self,
- item: &di::DisplayItem,
- section: DisplayListSection,
- ) {
- poke_into_vec(item, self.buffer_from_section(section));
- self.add_to_display_list_dump(item);
- }
-
- /// Add an item to the display list.
- ///
- /// NOTE: It is usually preferable to use the specialized methods to push
- /// display items. Pushing unexpected or invalid items here may
- /// result in WebRender panicking or behaving in unexpected ways.
- #[inline]
- pub fn push_item(&mut self, item: &di::DisplayItem) {
- self.push_item_to_section(item, self.default_section());
- }
-
- fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
- where
- I: IntoIterator,
- I::IntoIter: ExactSizeIterator,
- I::Item: Poke,
- {
- let iter = iter_source.into_iter();
- let len = iter.len();
- // Format:
- // payload_byte_size: usize, item_count: usize, [I; item_count]
-
- // Track the the location of where to write byte size with offsets
- // instead of pointers because data may be moved in memory during
- // `serialize_iter_fast`.
- let byte_size_offset = data.len();
-
- // We write a dummy value so there's room for later
- poke_into_vec(&0usize, data);
- poke_into_vec(&len, data);
- let count = poke_extend_vec(iter, data);
- debug_assert_eq!(len, count, "iterator.len() returned two different values");
-
- // Add red zone
- ensure_red_zone::<I::Item>(data);
-
- // Now write the actual byte_size
- let final_offset = data.len();
- debug_assert!(final_offset >= (byte_size_offset + mem::size_of::<usize>()),
- "space was never allocated for this array's byte_size");
- let byte_size = final_offset - byte_size_offset - mem::size_of::<usize>();
- poke_inplace_slice(&byte_size, &mut data[byte_size_offset..]);
- }
-
- /// Push items from an iterator to the display list.
- ///
- /// NOTE: Pushing unexpected or invalid items to the display list
- /// may result in panic and confusion.
- pub fn push_iter<I>(&mut self, iter: I)
- where
- I: IntoIterator,
- I::IntoIter: ExactSizeIterator,
- I::Item: Poke,
- {
- let mut buffer = self.buffer_from_section(self.default_section());
- Self::push_iter_impl(&mut buffer, iter);
- }
-
- pub fn push_rect(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- color: ColorF,
- ) {
- let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
- common: *common,
- color: PropertyBinding::Value(color),
- bounds,
- });
- self.push_item(&item);
- }
-
- pub fn push_rect_with_animation(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- color: PropertyBinding<ColorF>,
- ) {
- let item = di::DisplayItem::Rectangle(di::RectangleDisplayItem {
- common: *common,
- color,
- bounds,
- });
- self.push_item(&item);
- }
-
- pub fn push_clear_rect(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- ) {
- let item = di::DisplayItem::ClearRectangle(di::ClearRectangleDisplayItem {
- common: *common,
- bounds,
- });
- self.push_item(&item);
- }
-
- pub fn push_hit_test(
- &mut self,
- common: &di::CommonItemProperties,
- tag: di::ItemTag,
- ) {
- let item = di::DisplayItem::HitTest(di::HitTestDisplayItem {
- common: *common,
- tag,
- });
- self.push_item(&item);
- }
-
- pub fn push_line(
- &mut self,
- common: &di::CommonItemProperties,
- area: &LayoutRect,
- wavy_line_thickness: f32,
- orientation: di::LineOrientation,
- color: &ColorF,
- style: di::LineStyle,
- ) {
- let item = di::DisplayItem::Line(di::LineDisplayItem {
- common: *common,
- area: *area,
- wavy_line_thickness,
- orientation,
- color: *color,
- style,
- });
-
- self.push_item(&item);
- }
-
- pub fn push_image(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- image_rendering: di::ImageRendering,
- alpha_type: di::AlphaType,
- key: ImageKey,
- color: ColorF,
- ) {
- let item = di::DisplayItem::Image(di::ImageDisplayItem {
- common: *common,
- bounds,
- image_key: key,
- image_rendering,
- alpha_type,
- color,
- });
-
- self.push_item(&item);
- }
-
- pub fn push_repeating_image(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- stretch_size: LayoutSize,
- tile_spacing: LayoutSize,
- image_rendering: di::ImageRendering,
- alpha_type: di::AlphaType,
- key: ImageKey,
- color: ColorF,
- ) {
- let item = di::DisplayItem::RepeatingImage(di::RepeatingImageDisplayItem {
- common: *common,
- bounds,
- image_key: key,
- stretch_size,
- tile_spacing,
- image_rendering,
- alpha_type,
- color,
- });
-
- self.push_item(&item);
- }
-
- /// Push a yuv image. All planar data in yuv image should use the same buffer type.
- pub fn push_yuv_image(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- yuv_data: di::YuvData,
- color_depth: ColorDepth,
- color_space: di::YuvColorSpace,
- color_range: di::ColorRange,
- image_rendering: di::ImageRendering,
- ) {
- let item = di::DisplayItem::YuvImage(di::YuvImageDisplayItem {
- common: *common,
- bounds,
- yuv_data,
- color_depth,
- color_space,
- color_range,
- image_rendering,
- });
- self.push_item(&item);
- }
-
- pub fn push_text(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- glyphs: &[GlyphInstance],
- font_key: FontInstanceKey,
- color: ColorF,
- glyph_options: Option<GlyphOptions>,
- ) {
- let item = di::DisplayItem::Text(di::TextDisplayItem {
- common: *common,
- bounds,
- color,
- font_key,
- glyph_options,
- });
-
- for split_glyphs in glyphs.chunks(MAX_TEXT_RUN_LENGTH) {
- self.push_item(&item);
- self.push_iter(split_glyphs);
- }
- }
-
- /// NOTE: gradients must be pushed in the order they're created
- /// because create_gradient stores the stops in anticipation.
- pub fn create_gradient(
- &mut self,
- start_point: LayoutPoint,
- end_point: LayoutPoint,
- stops: Vec<di::GradientStop>,
- extend_mode: di::ExtendMode,
- ) -> di::Gradient {
- let mut builder = GradientBuilder::with_stops(stops);
- let gradient = builder.gradient(start_point, end_point, extend_mode);
- self.push_stops(builder.stops());
- gradient
- }
-
- /// NOTE: gradients must be pushed in the order they're created
- /// because create_gradient stores the stops in anticipation.
- pub fn create_radial_gradient(
- &mut self,
- center: LayoutPoint,
- radius: LayoutSize,
- stops: Vec<di::GradientStop>,
- extend_mode: di::ExtendMode,
- ) -> di::RadialGradient {
- let mut builder = GradientBuilder::with_stops(stops);
- let gradient = builder.radial_gradient(center, radius, extend_mode);
- self.push_stops(builder.stops());
- gradient
- }
-
- /// NOTE: gradients must be pushed in the order they're created
- /// because create_gradient stores the stops in anticipation.
- pub fn create_conic_gradient(
- &mut self,
- center: LayoutPoint,
- angle: f32,
- stops: Vec<di::GradientStop>,
- extend_mode: di::ExtendMode,
- ) -> di::ConicGradient {
- let mut builder = GradientBuilder::with_stops(stops);
- let gradient = builder.conic_gradient(center, angle, extend_mode);
- self.push_stops(builder.stops());
- gradient
- }
-
- pub fn push_border(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- widths: LayoutSideOffsets,
- details: di::BorderDetails,
- ) {
- let item = di::DisplayItem::Border(di::BorderDisplayItem {
- common: *common,
- bounds,
- details,
- widths,
- });
-
- self.push_item(&item);
- }
-
- pub fn push_box_shadow(
- &mut self,
- common: &di::CommonItemProperties,
- box_bounds: LayoutRect,
- offset: LayoutVector2D,
- color: ColorF,
- blur_radius: f32,
- spread_radius: f32,
- border_radius: di::BorderRadius,
- clip_mode: di::BoxShadowClipMode,
- ) {
- let item = di::DisplayItem::BoxShadow(di::BoxShadowDisplayItem {
- common: *common,
- box_bounds,
- offset,
- color,
- blur_radius,
- spread_radius,
- border_radius,
- clip_mode,
- });
-
- self.push_item(&item);
- }
-
- /// Pushes a linear gradient to be displayed.
- ///
- /// The gradient itself is described in the
- /// `gradient` parameter. It is drawn on
- /// a "tile" with the dimensions from `tile_size`.
- /// These tiles are now repeated to the right and
- /// to the bottom infinitely. If `tile_spacing`
- /// is not zero spacers with the given dimensions
- /// are inserted between the tiles as seams.
- ///
- /// The origin of the tiles is given in `layout.rect.origin`.
- /// If the gradient should only be displayed once limit
- /// the `layout.rect.size` to a single tile.
- /// The gradient is only visible within the local clip.
- pub fn push_gradient(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- gradient: di::Gradient,
- tile_size: LayoutSize,
- tile_spacing: LayoutSize,
- ) {
- let item = di::DisplayItem::Gradient(di::GradientDisplayItem {
- common: *common,
- bounds,
- gradient,
- tile_size,
- tile_spacing,
- });
-
- self.push_item(&item);
- }
-
- /// Pushes a radial gradient to be displayed.
- ///
- /// See [`push_gradient`](#method.push_gradient) for explanation.
- pub fn push_radial_gradient(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- gradient: di::RadialGradient,
- tile_size: LayoutSize,
- tile_spacing: LayoutSize,
- ) {
- let item = di::DisplayItem::RadialGradient(di::RadialGradientDisplayItem {
- common: *common,
- bounds,
- gradient,
- tile_size,
- tile_spacing,
- });
-
- self.push_item(&item);
- }
-
- /// Pushes a conic gradient to be displayed.
- ///
- /// See [`push_gradient`](#method.push_gradient) for explanation.
- pub fn push_conic_gradient(
- &mut self,
- common: &di::CommonItemProperties,
- bounds: LayoutRect,
- gradient: di::ConicGradient,
- tile_size: LayoutSize,
- tile_spacing: LayoutSize,
- ) {
- let item = di::DisplayItem::ConicGradient(di::ConicGradientDisplayItem {
- common: *common,
- bounds,
- gradient,
- tile_size,
- tile_spacing,
- });
-
- self.push_item(&item);
- }
-
- pub fn push_reference_frame(
- &mut self,
- origin: LayoutPoint,
- parent_spatial_id: di::SpatialId,
- transform_style: di::TransformStyle,
- transform: PropertyBinding<LayoutTransform>,
- kind: di::ReferenceFrameKind,
- ) -> di::SpatialId {
- let id = self.generate_spatial_index();
-
- let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
- parent_spatial_id,
- origin,
- reference_frame: di::ReferenceFrame {
- transform_style,
- transform: di::ReferenceTransformBinding::Static {
- binding: transform,
- },
- kind,
- id,
- },
- });
-
- self.push_item(&item);
- id
- }
-
- pub fn push_computed_frame(
- &mut self,
- origin: LayoutPoint,
- parent_spatial_id: di::SpatialId,
- scale_from: Option<LayoutSize>,
- vertical_flip: bool,
- rotation: di::Rotation,
- ) -> di::SpatialId {
- let id = self.generate_spatial_index();
-
- let item = di::DisplayItem::PushReferenceFrame(di::ReferenceFrameDisplayListItem {
- parent_spatial_id,
- origin,
- reference_frame: di::ReferenceFrame {
- transform_style: di::TransformStyle::Flat,
- transform: di::ReferenceTransformBinding::Computed {
- scale_from,
- vertical_flip,
- rotation,
- },
- kind: di::ReferenceFrameKind::Transform {
- is_2d_scale_translation: false,
- should_snap: false,
- },
- id,
- },
- });
-
- self.push_item(&item);
- id
- }
-
- pub fn pop_reference_frame(&mut self) {
- self.push_item(&di::DisplayItem::PopReferenceFrame);
- }
-
- pub fn push_stacking_context(
- &mut self,
- origin: LayoutPoint,
- spatial_id: di::SpatialId,
- prim_flags: di::PrimitiveFlags,
- clip_id: Option<di::ClipId>,
- transform_style: di::TransformStyle,
- mix_blend_mode: di::MixBlendMode,
- filters: &[di::FilterOp],
- filter_datas: &[di::FilterData],
- filter_primitives: &[di::FilterPrimitive],
- raster_space: di::RasterSpace,
- flags: di::StackingContextFlags,
- ) {
- self.push_filters(filters, filter_datas, filter_primitives);
-
- let item = di::DisplayItem::PushStackingContext(di::PushStackingContextDisplayItem {
- origin,
- spatial_id,
- prim_flags,
- stacking_context: di::StackingContext {
- transform_style,
- mix_blend_mode,
- clip_id,
- raster_space,
- flags,
- },
- });
-
- self.push_item(&item);
- }
-
- /// Helper for examples/ code.
- pub fn push_simple_stacking_context(
- &mut self,
- origin: LayoutPoint,
- spatial_id: di::SpatialId,
- prim_flags: di::PrimitiveFlags,
- ) {
- self.push_simple_stacking_context_with_filters(
- origin,
- spatial_id,
- prim_flags,
- &[],
- &[],
- &[],
- );
- }
-
- /// Helper for examples/ code.
- pub fn push_simple_stacking_context_with_filters(
- &mut self,
- origin: LayoutPoint,
- spatial_id: di::SpatialId,
- prim_flags: di::PrimitiveFlags,
- filters: &[di::FilterOp],
- filter_datas: &[di::FilterData],
- filter_primitives: &[di::FilterPrimitive],
- ) {
- self.push_stacking_context(
- origin,
- spatial_id,
- prim_flags,
- None,
- di::TransformStyle::Flat,
- di::MixBlendMode::Normal,
- filters,
- filter_datas,
- filter_primitives,
- di::RasterSpace::Screen,
- di::StackingContextFlags::empty(),
- );
- }
-
- pub fn pop_stacking_context(&mut self) {
- self.push_item(&di::DisplayItem::PopStackingContext);
- }
-
- pub fn push_stops(&mut self, stops: &[di::GradientStop]) {
- if stops.is_empty() {
- return;
- }
- self.push_item(&di::DisplayItem::SetGradientStops);
- self.push_iter(stops);
- }
-
- pub fn push_backdrop_filter(
- &mut self,
- common: &di::CommonItemProperties,
- filters: &[di::FilterOp],
- filter_datas: &[di::FilterData],
- filter_primitives: &[di::FilterPrimitive],
- ) {
- self.push_filters(filters, filter_datas, filter_primitives);
-
- let item = di::DisplayItem::BackdropFilter(di::BackdropFilterDisplayItem {
- common: *common,
- });
- self.push_item(&item);
- }
-
- pub fn push_filters(
- &mut self,
- filters: &[di::FilterOp],
- filter_datas: &[di::FilterData],
- filter_primitives: &[di::FilterPrimitive],
- ) {
- if !filters.is_empty() {
- self.push_item(&di::DisplayItem::SetFilterOps);
- self.push_iter(filters);
- }
-
- for filter_data in filter_datas {
- let func_types = [
- filter_data.func_r_type, filter_data.func_g_type,
- filter_data.func_b_type, filter_data.func_a_type];
- self.push_item(&di::DisplayItem::SetFilterData);
- self.push_iter(&func_types);
- self.push_iter(&filter_data.r_values);
- self.push_iter(&filter_data.g_values);
- self.push_iter(&filter_data.b_values);
- self.push_iter(&filter_data.a_values);
- }
-
- if !filter_primitives.is_empty() {
- self.push_item(&di::DisplayItem::SetFilterPrimitives);
- self.push_iter(filter_primitives);
- }
- }
-
- fn generate_clip_index(&mut self) -> di::ClipId {
- self.next_clip_index += 1;
- di::ClipId::Clip(self.next_clip_index - 1, self.pipeline_id)
- }
-
- fn generate_spatial_index(&mut self) -> di::SpatialId {
- self.next_spatial_index += 1;
- di::SpatialId::new(self.next_spatial_index - 1, self.pipeline_id)
- }
-
- fn generate_clip_chain_id(&mut self) -> di::ClipChainId {
- self.next_clip_chain_id += 1;
- di::ClipChainId(self.next_clip_chain_id - 1, self.pipeline_id)
- }
-
- pub fn define_scroll_frame(
- &mut self,
- parent_space_and_clip: &di::SpaceAndClipInfo,
- external_id: di::ExternalScrollId,
- content_rect: LayoutRect,
- clip_rect: LayoutRect,
- scroll_sensitivity: di::ScrollSensitivity,
- external_scroll_offset: LayoutVector2D,
- ) -> di::SpaceAndClipInfo {
- let clip_id = self.generate_clip_index();
- let scroll_frame_id = self.generate_spatial_index();
- let item = di::DisplayItem::ScrollFrame(di::ScrollFrameDisplayItem {
- content_rect,
- clip_rect,
- parent_space_and_clip: *parent_space_and_clip,
- clip_id,
- scroll_frame_id,
- external_id,
- scroll_sensitivity,
- external_scroll_offset,
- });
-
- self.push_item(&item);
-
- di::SpaceAndClipInfo {
- spatial_id: scroll_frame_id,
- clip_id,
- }
- }
-
- pub fn define_clip_chain<I>(
- &mut self,
- parent: Option<di::ClipChainId>,
- clips: I,
- ) -> di::ClipChainId
- where
- I: IntoIterator<Item = di::ClipId>,
- I::IntoIter: ExactSizeIterator + Clone,
- {
- let id = self.generate_clip_chain_id();
- self.push_item(&di::DisplayItem::ClipChain(di::ClipChainItem { id, parent }));
- self.push_iter(clips);
- id
- }
-
- pub fn define_clip_image_mask(
- &mut self,
- parent_space_and_clip: &di::SpaceAndClipInfo,
- image_mask: di::ImageMask,
- points: &[LayoutPoint],
- fill_rule: di::FillRule,
- ) -> di::ClipId {
- let id = self.generate_clip_index();
- let item = di::DisplayItem::ImageMaskClip(di::ImageMaskClipDisplayItem {
- id,
- parent_space_and_clip: *parent_space_and_clip,
- image_mask,
- fill_rule,
- });
-
- // We only need to supply points if there are at least 3, which is the
- // minimum to specify a polygon. BuiltDisplayListIter.next ensures that points
- // are cleared between processing other display items, so we'll correctly get
- // zero points when no SetPoints item has been pushed.
- if points.len() >= 3 {
- self.push_item(&di::DisplayItem::SetPoints);
- self.push_iter(points);
- }
- self.push_item(&item);
- id
- }
-
- pub fn define_clip_rect(
- &mut self,
- parent_space_and_clip: &di::SpaceAndClipInfo,
- clip_rect: LayoutRect,
- ) -> di::ClipId {
- let id = self.generate_clip_index();
- let item = di::DisplayItem::RectClip(di::RectClipDisplayItem {
- id,
- parent_space_and_clip: *parent_space_and_clip,
- clip_rect,
- });
-
- self.push_item(&item);
- id
- }
-
- pub fn define_clip_rounded_rect(
- &mut self,
- parent_space_and_clip: &di::SpaceAndClipInfo,
- clip: di::ComplexClipRegion,
- ) -> di::ClipId {
- let id = self.generate_clip_index();
- let item = di::DisplayItem::RoundedRectClip(di::RoundedRectClipDisplayItem {
- id,
- parent_space_and_clip: *parent_space_and_clip,
- clip,
- });
-
- self.push_item(&item);
- id
- }
-
- pub fn define_clip<I>(
- &mut self,
- parent_space_and_clip: &di::SpaceAndClipInfo,
- clip_rect: LayoutRect,
- complex_clips: I,
- ) -> di::ClipId
- where
- I: IntoIterator<Item = di::ComplexClipRegion>,
- I::IntoIter: ExactSizeIterator + Clone,
- {
- let id = self.generate_clip_index();
- let item = di::DisplayItem::Clip(di::ClipDisplayItem {
- id,
- parent_space_and_clip: *parent_space_and_clip,
- clip_rect,
- });
-
- self.push_item(&item);
- self.push_iter(complex_clips);
- id
- }
-
- pub fn define_sticky_frame(
- &mut self,
- parent_spatial_id: di::SpatialId,
- frame_rect: LayoutRect,
- margins: SideOffsets2D<Option<f32>, LayoutPixel>,
- vertical_offset_bounds: di::StickyOffsetBounds,
- horizontal_offset_bounds: di::StickyOffsetBounds,
- previously_applied_offset: LayoutVector2D,
- ) -> di::SpatialId {
- let id = self.generate_spatial_index();
- let item = di::DisplayItem::StickyFrame(di::StickyFrameDisplayItem {
- parent_spatial_id,
- id,
- bounds: frame_rect,
- margins,
- vertical_offset_bounds,
- horizontal_offset_bounds,
- previously_applied_offset,
- });
-
- self.push_item(&item);
- id
- }
-
- pub fn push_iframe(
- &mut self,
- bounds: LayoutRect,
- clip_rect: LayoutRect,
- space_and_clip: &di::SpaceAndClipInfo,
- pipeline_id: PipelineId,
- ignore_missing_pipeline: bool
- ) {
- let item = di::DisplayItem::Iframe(di::IframeDisplayItem {
- bounds,
- clip_rect,
- space_and_clip: *space_and_clip,
- pipeline_id,
- ignore_missing_pipeline,
- });
- self.push_item(&item);
- }
-
- pub fn push_shadow(
- &mut self,
- space_and_clip: &di::SpaceAndClipInfo,
- shadow: di::Shadow,
- should_inflate: bool,
- ) {
- let item = di::DisplayItem::PushShadow(di::PushShadowDisplayItem {
- space_and_clip: *space_and_clip,
- shadow,
- should_inflate,
- });
- self.push_item(&item);
- }
-
- pub fn pop_all_shadows(&mut self) {
- self.push_item(&di::DisplayItem::PopAllShadows);
- }
-
- pub fn start_item_group(&mut self) {
- debug_assert!(!self.writing_to_chunk);
- debug_assert!(self.pending_chunk.is_empty());
-
- self.writing_to_chunk = true;
- }
-
- fn flush_pending_item_group(&mut self, key: di::ItemKey) {
- // Push RetainedItems-marker to extra_data section.
- self.push_retained_items(key);
-
- // Push pending chunk to extra_data section.
- self.extra_data.append(&mut self.pending_chunk);
-
- // Push ReuseItems-marker to data section.
- self.push_reuse_items(key);
- }
-
- pub fn finish_item_group(&mut self, key: di::ItemKey) -> bool {
- debug_assert!(self.writing_to_chunk);
- self.writing_to_chunk = false;
-
- if self.pending_chunk.is_empty() {
- return false;
- }
-
- self.flush_pending_item_group(key);
- true
- }
-
- pub fn cancel_item_group(&mut self, discard: bool) {
- debug_assert!(self.writing_to_chunk);
- self.writing_to_chunk = false;
-
- if discard {
- self.pending_chunk.clear();
- } else {
- // Push pending chunk to data section.
- self.data.append(&mut self.pending_chunk);
- }
- }
-
- pub fn push_reuse_items(&mut self, key: di::ItemKey) {
- self.push_item_to_section(
- &di::DisplayItem::ReuseItems(key),
- DisplayListSection::Data
- );
- }
-
- fn push_retained_items(&mut self, key: di::ItemKey) {
- self.push_item_to_section(
- &di::DisplayItem::RetainedItems(key),
- DisplayListSection::ExtraData
- );
- }
-
- pub fn set_cache_size(&mut self, cache_size: usize) {
- self.cache_size = cache_size;
- }
-
- pub fn finalize(mut self) -> (PipelineId, BuiltDisplayList) {
- assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
-
- if let Some(content) = self.serialized_content_buffer.take() {
- println!("-- WebRender display list for {:?} --\n{}",
- self.pipeline_id, content);
- }
-
- // Add `DisplayItem::max_size` zone of zeroes to the end of display list
- // so there is at least this amount available in the display list during
- // serialization.
- ensure_red_zone::<di::DisplayItem>(&mut self.data);
-
- let extra_data_offset = self.data.len();
-
- if self.extra_data.len() > 0 {
- ensure_red_zone::<di::DisplayItem>(&mut self.extra_data);
- self.data.extend(self.extra_data);
- }
-
- let end_time = precise_time_ns();
- (
- self.pipeline_id,
- BuiltDisplayList {
- descriptor: BuiltDisplayListDescriptor {
- gecko_display_list_type: GeckoDisplayListType::None,
- builder_start_time: self.builder_start_time,
- builder_finish_time: end_time,
- send_start_time: end_time,
- total_clip_nodes: self.next_clip_index,
- total_spatial_nodes: self.next_spatial_index,
- cache_size: self.cache_size,
- extra_data_offset,
- },
- data: self.data,
- },
- )
- }
-}
diff --git a/third_party/webrender/webrender_api/src/font.rs b/third_party/webrender/webrender_api/src/font.rs
deleted file mode 100644
index 3052db8f9e1..00000000000
--- a/third_party/webrender/webrender_api/src/font.rs
+++ /dev/null
@@ -1,605 +0,0 @@
-/* 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/. */
-
-#[cfg(target_os = "macos")]
-use core_foundation::string::CFString;
-#[cfg(target_os = "macos")]
-use core_graphics::font::CGFont;
-use peek_poke::PeekPoke;
-#[cfg(target_os = "macos")]
-use serde::de::{self, Deserialize, Deserializer};
-#[cfg(target_os = "macos")]
-use serde::ser::{Serialize, Serializer};
-use std::cmp::Ordering;
-use std::hash::{Hash, Hasher};
-#[cfg(not(target_os = "macos"))]
-use std::path::PathBuf;
-use std::sync::{Arc, RwLock, RwLockReadGuard};
-use std::collections::HashMap;
-// local imports
-use crate::IdNamespace;
-use crate::channel::Sender;
-use crate::color::ColorU;
-use crate::units::LayoutPoint;
-
-/// Hashable floating-point storage for font size.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd, Deserialize, Serialize)]
-pub struct FontSize(pub f32);
-
-impl Ord for FontSize {
- fn cmp(&self, other: &FontSize) -> Ordering {
- self.partial_cmp(other).unwrap_or(Ordering::Equal)
- }
-}
-
-impl Eq for FontSize {}
-
-impl Hash for FontSize {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.0.to_bits().hash(state);
- }
-}
-
-impl From<f32> for FontSize {
- fn from(size: f32) -> Self { FontSize(size) }
-}
-
-impl From<FontSize> for f32 {
- fn from(size: FontSize) -> Self { size.0 }
-}
-
-impl FontSize {
- pub fn zero() -> Self { FontSize(0.0) }
-
- pub fn from_f32_px(size: f32) -> Self { FontSize(size) }
-
- pub fn to_f32_px(&self) -> f32 { self.0 }
-
- pub fn from_f64_px(size: f64) -> Self { FontSize(size as f32) }
-
- pub fn to_f64_px(&self) -> f64 { self.0 as f64 }
-}
-
-/// Immutable description of a font instance requested by the user of the API.
-///
-/// `BaseFontInstance` can be identified by a `FontInstanceKey` so we should
-/// never need to hash it.
-#[derive(Clone, PartialEq, Eq, Debug, Ord, PartialOrd, MallocSizeOf)]
-#[cfg_attr(feature = "serialize", derive(Serialize))]
-#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-pub struct BaseFontInstance {
- ///
- pub instance_key: FontInstanceKey,
- ///
- pub font_key: FontKey,
- ///
- pub size: FontSize,
- ///
- pub bg_color: ColorU,
- ///
- pub render_mode: FontRenderMode,
- ///
- pub flags: FontInstanceFlags,
- ///
- pub synthetic_italics: SyntheticItalics,
- ///
- #[cfg_attr(any(feature = "serialize", feature = "deserialize"), serde(skip))]
- pub platform_options: Option<FontInstancePlatformOptions>,
- ///
- pub variations: Vec<FontVariation>,
-}
-
-pub type FontInstanceMap = HashMap<FontInstanceKey, Arc<BaseFontInstance>>;
-/// A map of font instance data accessed concurrently from multiple threads.
-#[derive(Clone)]
-#[cfg_attr(feature = "serialize", derive(Serialize))]
-#[cfg_attr(feature = "deserialize", derive(Deserialize))]
-pub struct SharedFontInstanceMap {
- map: Arc<RwLock<FontInstanceMap>>,
-}
-
-impl SharedFontInstanceMap {
- /// Creates an empty shared map.
- pub fn new() -> Self {
- SharedFontInstanceMap {
- map: Arc::new(RwLock::new(HashMap::default()))
- }
- }
-
- /// Acquires a write lock on the shared map.
- pub fn lock(&mut self) -> Option<RwLockReadGuard<FontInstanceMap>> {
- self.map.read().ok()
- }
-
- ///
- pub fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData> {
- match self.map.read().unwrap().get(&key) {
- Some(instance) => Some(FontInstanceData {
- font_key: instance.font_key,
- size: instance.size.into(),
- options: Some(FontInstanceOptions {
- render_mode: instance.render_mode,
- flags: instance.flags,
- bg_color: instance.bg_color,
- synthetic_italics: instance.synthetic_italics,
- }),
- platform_options: instance.platform_options,
- variations: instance.variations.clone(),
- }),
- None => None,
- }
- }
-
- /// Replace the shared map with the provided map.
- pub fn set(&mut self, map: FontInstanceMap) {
- *self.map.write().unwrap() = map;
- }
-
- ///
- pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<Arc<BaseFontInstance>> {
- let instance_map = self.map.read().unwrap();
- instance_map.get(&instance_key).map(|instance| { Arc::clone(instance) })
- }
-
- ///
- pub fn add_font_instance(
- &mut self,
- instance_key: FontInstanceKey,
- font_key: FontKey,
- size: f32,
- options: Option<FontInstanceOptions>,
- platform_options: Option<FontInstancePlatformOptions>,
- variations: Vec<FontVariation>,
- ) {
- let FontInstanceOptions {
- render_mode,
- flags,
- bg_color,
- synthetic_italics,
- ..
- } = options.unwrap_or_default();
-
- let instance = Arc::new(BaseFontInstance {
- instance_key,
- font_key,
- size: size.into(),
- bg_color,
- render_mode,
- flags,
- synthetic_italics,
- platform_options,
- variations,
- });
-
- self.map
- .write()
- .unwrap()
- .insert(instance_key, instance);
- }
-
- ///
- pub fn delete_font_instance(&mut self, instance_key: FontInstanceKey) {
- self.map.write().unwrap().remove(&instance_key);
- }
-
- ///
- pub fn clear_namespace(&mut self, namespace: IdNamespace) {
- self.map
- .write()
- .unwrap()
- .retain(|key, _| key.0 != namespace);
- }
-
- ///
- pub fn clone_map(&self) -> FontInstanceMap {
- self.map.read().unwrap().clone()
- }
-}
-
-#[cfg(not(target_os = "macos"))]
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub struct NativeFontHandle {
- pub path: PathBuf,
- pub index: u32,
-}
-
-#[cfg(target_os = "macos")]
-#[derive(Clone)]
-pub struct NativeFontHandle(pub CGFont);
-
-#[cfg(target_os = "macos")]
-impl Serialize for NativeFontHandle {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: Serializer,
- {
- self.0
- .postscript_name()
- .to_string()
- .serialize(serializer)
- }
-}
-
-#[cfg(target_os = "macos")]
-impl<'de> Deserialize<'de> for NativeFontHandle {
- fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
- where
- D: Deserializer<'de>,
- {
- let postscript_name: String = Deserialize::deserialize(deserializer)?;
-
- match CGFont::from_name(&CFString::new(&*postscript_name)) {
- Ok(font) => Ok(NativeFontHandle(font)),
- Err(_) => Err(de::Error::custom(
- "Couldn't find a font with that PostScript name!",
- )),
- }
- }
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, Deserialize, Serialize, Debug)]
-pub struct GlyphDimensions {
- pub left: i32,
- pub top: i32,
- pub width: i32,
- pub height: i32,
- pub advance: f32,
-}
-
-pub struct GlyphDimensionRequest {
- pub key: FontInstanceKey,
- pub glyph_indices: Vec<GlyphIndex>,
- pub sender: Sender<Vec<Option<GlyphDimensions>>>,
-}
-
-pub struct GlyphIndexRequest {
- pub key: FontKey,
- pub text: String,
- pub sender: Sender<Vec<Option<u32>>>,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)]
-pub struct FontKey(pub IdNamespace, pub u32);
-
-impl FontKey {
- pub fn new(namespace: IdNamespace, key: u32) -> FontKey {
- FontKey(namespace, key)
- }
-}
-
-/// Container for the raw data describing a font. This might be a stream of
-/// bytes corresponding to a downloaded font, or a handle to a native font from
-/// the operating system.
-///
-/// Note that fonts need to be instantiated before being used, which involves
-/// assigning size and various other options. The word 'template' here is
-/// intended to distinguish this data from instance-specific data.
-#[derive(Clone)]
-pub enum FontTemplate {
- Raw(Arc<Vec<u8>>, u32),
- Native(NativeFontHandle),
-}
-
-#[repr(u8)]
-#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
-pub enum FontRenderMode {
- Mono = 0,
- Alpha,
- Subpixel,
-}
-
-impl Default for FontRenderMode {
- fn default() -> Self {
- FontRenderMode::Mono
- }
-}
-
-impl FontRenderMode {
- // Combine two font render modes such that the lesser amount of AA limits the AA of the result.
- pub fn limit_by(self, other: FontRenderMode) -> FontRenderMode {
- match (self, other) {
- (FontRenderMode::Subpixel, _) | (_, FontRenderMode::Mono) => other,
- _ => self,
- }
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)]
-pub struct FontVariation {
- pub tag: u32,
- pub value: f32,
-}
-
-impl Ord for FontVariation {
- fn cmp(&self, other: &FontVariation) -> Ordering {
- self.tag.cmp(&other.tag)
- .then(self.value.to_bits().cmp(&other.value.to_bits()))
- }
-}
-
-impl PartialEq for FontVariation {
- fn eq(&self, other: &FontVariation) -> bool {
- self.tag == other.tag &&
- self.value.to_bits() == other.value.to_bits()
- }
-}
-
-impl Eq for FontVariation {}
-
-impl Hash for FontVariation {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.tag.hash(state);
- self.value.to_bits().hash(state);
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, PeekPoke)]
-pub struct GlyphOptions {
- pub render_mode: FontRenderMode,
- pub flags: FontInstanceFlags,
-}
-
-impl Default for GlyphOptions {
- fn default() -> Self {
- GlyphOptions {
- render_mode: FontRenderMode::Subpixel,
- flags: FontInstanceFlags::empty(),
- }
- }
-}
-
-bitflags! {
- #[repr(C)]
- #[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
- pub struct FontInstanceFlags: u32 {
- // Common flags
- const SYNTHETIC_BOLD = 1 << 1;
- const EMBEDDED_BITMAPS = 1 << 2;
- const SUBPIXEL_BGR = 1 << 3;
- const TRANSPOSE = 1 << 4;
- const FLIP_X = 1 << 5;
- const FLIP_Y = 1 << 6;
- const SUBPIXEL_POSITION = 1 << 7;
- const VERTICAL = 1 << 8;
-
- // Internal flags
- const TRANSFORM_GLYPHS = 1 << 12;
- const TEXTURE_PADDING = 1 << 13;
-
- // Windows flags
- const FORCE_GDI = 1 << 16;
- const FORCE_SYMMETRIC = 1 << 17;
- const NO_SYMMETRIC = 1 << 18;
-
- // Mac flags
- const FONT_SMOOTHING = 1 << 16;
-
- // FreeType flags
- const FORCE_AUTOHINT = 1 << 16;
- const NO_AUTOHINT = 1 << 17;
- const VERTICAL_LAYOUT = 1 << 18;
- const LCD_VERTICAL = 1 << 19;
- }
-}
-
-impl Default for FontInstanceFlags {
- #[cfg(target_os = "windows")]
- fn default() -> FontInstanceFlags {
- FontInstanceFlags::SUBPIXEL_POSITION
- }
-
- #[cfg(target_os = "macos")]
- fn default() -> FontInstanceFlags {
- FontInstanceFlags::SUBPIXEL_POSITION |
- FontInstanceFlags::FONT_SMOOTHING
- }
-
- #[cfg(not(any(target_os = "macos", target_os = "windows")))]
- fn default() -> FontInstanceFlags {
- FontInstanceFlags::SUBPIXEL_POSITION
- }
-}
-
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct SyntheticItalics {
- // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point.
- pub angle: i16,
-}
-
-impl SyntheticItalics {
- pub const ANGLE_SCALE: f32 = 256.0;
-
- pub fn from_degrees(degrees: f32) -> Self {
- SyntheticItalics { angle: (degrees.max(-89.0).min(89.0) * Self::ANGLE_SCALE) as i16 }
- }
-
- pub fn to_degrees(self) -> f32 {
- self.angle as f32 / Self::ANGLE_SCALE
- }
-
- pub fn to_radians(self) -> f32 {
- self.to_degrees().to_radians()
- }
-
- pub fn to_skew(self) -> f32 {
- self.to_radians().tan()
- }
-
- pub fn enabled() -> Self {
- Self::from_degrees(14.0)
- }
-
- pub fn disabled() -> Self {
- SyntheticItalics { angle: 0 }
- }
-
- pub fn is_enabled(self) -> bool {
- self.angle != 0
- }
-}
-
-impl Default for SyntheticItalics {
- fn default() -> Self {
- SyntheticItalics::disabled()
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct FontInstanceOptions {
- pub render_mode: FontRenderMode,
- pub flags: FontInstanceFlags,
- /// When bg_color.a is != 0 and render_mode is FontRenderMode::Subpixel,
- /// the text will be rendered with bg_color.r/g/b as an opaque estimated
- /// background color.
- pub bg_color: ColorU,
- pub synthetic_italics: SyntheticItalics,
-}
-
-impl Default for FontInstanceOptions {
- fn default() -> FontInstanceOptions {
- FontInstanceOptions {
- render_mode: FontRenderMode::Subpixel,
- flags: Default::default(),
- bg_color: ColorU::new(0, 0, 0, 0),
- synthetic_italics: SyntheticItalics::disabled(),
- }
- }
-}
-
-#[cfg(target_os = "windows")]
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct FontInstancePlatformOptions {
- pub gamma: u16, // percent
- pub contrast: u8, // percent
- pub cleartype_level: u8, // percent
-}
-
-#[cfg(target_os = "windows")]
-impl Default for FontInstancePlatformOptions {
- fn default() -> FontInstancePlatformOptions {
- FontInstancePlatformOptions {
- gamma: 180, // Default DWrite gamma
- contrast: 100,
- cleartype_level: 100,
- }
- }
-}
-
-#[cfg(target_os = "macos")]
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct FontInstancePlatformOptions {
- pub unused: u32,
-}
-
-#[cfg(target_os = "macos")]
-impl Default for FontInstancePlatformOptions {
- fn default() -> FontInstancePlatformOptions {
- FontInstancePlatformOptions {
- unused: 0,
- }
- }
-}
-
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub enum FontLCDFilter {
- None,
- Default,
- Light,
- Legacy,
-}
-
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub enum FontHinting {
- None,
- Mono,
- Light,
- Normal,
- LCD,
-}
-
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
-pub struct FontInstancePlatformOptions {
- pub lcd_filter: FontLCDFilter,
- pub hinting: FontHinting,
-}
-
-#[cfg(not(any(target_os = "macos", target_os = "windows")))]
-impl Default for FontInstancePlatformOptions {
- fn default() -> FontInstancePlatformOptions {
- FontInstancePlatformOptions {
- lcd_filter: FontLCDFilter::Default,
- hinting: FontHinting::LCD,
- }
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, MallocSizeOf, PeekPoke)]
-#[derive(Deserialize, Serialize)]
-pub struct FontInstanceKey(pub IdNamespace, pub u32);
-
-impl FontInstanceKey {
- pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey {
- FontInstanceKey(namespace, key)
- }
-}
-
-/// Data corresponding to an instantiation of a font, with size and
-/// other options specified.
-///
-/// Note that the actual font is stored out-of-band in `FontTemplate`.
-#[derive(Clone)]
-pub struct FontInstanceData {
- pub font_key: FontKey,
- pub size: f32,
- pub options: Option<FontInstanceOptions>,
- pub platform_options: Option<FontInstancePlatformOptions>,
- pub variations: Vec<FontVariation>,
-}
-
-pub type GlyphIndex = u32;
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct GlyphInstance {
- pub index: GlyphIndex,
- pub point: LayoutPoint,
-}
-
-impl Default for GlyphInstance {
- fn default() -> Self {
- GlyphInstance {
- index: 0,
- point: LayoutPoint::zero(),
- }
- }
-}
-
-impl Eq for GlyphInstance {}
-
-#[cfg_attr(feature = "cargo-clippy", allow(clippy::derive_hash_xor_eq))]
-impl Hash for GlyphInstance {
- fn hash<H: Hasher>(&self, state: &mut H) {
- // Note: this is inconsistent with the Eq impl for -0.0 (don't care).
- self.index.hash(state);
- self.point.x.to_bits().hash(state);
- self.point.y.to_bits().hash(state);
- }
-}
diff --git a/third_party/webrender/webrender_api/src/gradient_builder.rs b/third_party/webrender/webrender_api/src/gradient_builder.rs
deleted file mode 100644
index 6347396f791..00000000000
--- a/third_party/webrender/webrender_api/src/gradient_builder.rs
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 crate::display_item as di;
-use crate::units::*;
-
-
-/// Construct a gradient to be used in display lists.
-///
-/// Each gradient needs at least two stops.
-pub struct GradientBuilder {
- stops: Vec<di::GradientStop>,
-}
-
-impl GradientBuilder {
- /// Create a new gradient builder.
- pub fn new() -> Self {
- GradientBuilder {
- stops: Vec::new(),
- }
- }
-
- /// Create a gradient builder with a list of stops.
- pub fn with_stops(stops: Vec<di::GradientStop>) -> GradientBuilder {
- GradientBuilder { stops }
- }
-
- /// Push an additional stop for the gradient.
- pub fn push(&mut self, stop: di::GradientStop) {
- self.stops.push(stop);
- }
-
- /// Get a reference to the list of stops.
- pub fn stops(&self) -> &[di::GradientStop] {
- self.stops.as_ref()
- }
-
- /// Return the gradient stops vector.
- pub fn into_stops(self) -> Vec<di::GradientStop> {
- self.stops
- }
-
- /// Produce a linear gradient, normalize the stops.
- pub fn gradient(
- &mut self,
- start_point: LayoutPoint,
- end_point: LayoutPoint,
- extend_mode: di::ExtendMode,
- ) -> di::Gradient {
- let (start_offset, end_offset) = self.normalize(extend_mode);
- let start_to_end = end_point - start_point;
-
- di::Gradient {
- start_point: start_point + start_to_end * start_offset,
- end_point: start_point + start_to_end * end_offset,
- extend_mode,
- }
- }
-
- /// Produce a radial gradient, normalize the stops.
- ///
- /// Will replace the gradient with a single color
- /// if the radius negative.
- pub fn radial_gradient(
- &mut self,
- center: LayoutPoint,
- radius: LayoutSize,
- extend_mode: di::ExtendMode,
- ) -> di::RadialGradient {
- if radius.width <= 0.0 || radius.height <= 0.0 {
- // The shader cannot handle a non positive radius. So
- // reuse the stops vector and construct an equivalent
- // gradient.
- let last_color = self.stops.last().unwrap().color;
-
- self.stops.clear();
- self.stops.push(di::GradientStop { offset: 0.0, color: last_color, });
- self.stops.push(di::GradientStop { offset: 1.0, color: last_color, });
-
- return di::RadialGradient {
- center,
- radius: LayoutSize::new(1.0, 1.0),
- start_offset: 0.0,
- end_offset: 1.0,
- extend_mode,
- };
- }
-
- let (start_offset, end_offset) =
- self.normalize(extend_mode);
-
- di::RadialGradient {
- center,
- radius,
- start_offset,
- end_offset,
- extend_mode,
- }
- }
-
- /// Produce a conic gradient, normalize the stops.
- pub fn conic_gradient(
- &mut self,
- center: LayoutPoint,
- angle: f32,
- extend_mode: di::ExtendMode,
- ) -> di::ConicGradient {
- let (start_offset, end_offset) =
- self.normalize(extend_mode);
-
- di::ConicGradient {
- center,
- angle,
- start_offset,
- end_offset,
- extend_mode,
- }
- }
-
- /// Gradients can be defined with stops outside the range of [0, 1]
- /// when this happens the gradient needs to be normalized by adjusting
- /// the gradient stops and gradient line into an equivalent gradient
- /// with stops in the range [0, 1]. this is done by moving the beginning
- /// of the gradient line to where stop[0] and the end of the gradient line
- /// to stop[n-1]. this function adjusts the stops in place, and returns
- /// the amount to adjust the gradient line start and stop.
- fn normalize(&mut self, extend_mode: di::ExtendMode) -> (f32, f32) {
- let stops = &mut self.stops;
- assert!(stops.len() >= 2);
-
- let first = *stops.first().unwrap();
- let last = *stops.last().unwrap();
-
- // Express the assertion so that if one of the offsets is NaN, we don't panic
- // and instead take the branch that handles degenerate gradients.
- assert!(!(first.offset > last.offset));
-
- let stops_delta = last.offset - first.offset;
-
- if stops_delta > 0.000001 {
- for stop in stops {
- stop.offset = (stop.offset - first.offset) / stops_delta;
- }
-
- (first.offset, last.offset)
- } else {
- // We have a degenerate gradient and can't accurately transform the stops
- // what happens here depends on the repeat behavior, but in any case
- // we reconstruct the gradient stops to something simpler and equivalent
- stops.clear();
-
- match extend_mode {
- di::ExtendMode::Clamp => {
- // This gradient is two colors split at the offset of the stops,
- // so create a gradient with two colors split at 0.5 and adjust
- // the gradient line so 0.5 is at the offset of the stops
- stops.push(di::GradientStop { color: first.color, offset: 0.0, });
- stops.push(di::GradientStop { color: first.color, offset: 0.5, });
- stops.push(di::GradientStop { color: last.color, offset: 0.5, });
- stops.push(di::GradientStop { color: last.color, offset: 1.0, });
-
- let offset = last.offset;
-
- (offset - 0.5, offset + 0.5)
- }
- di::ExtendMode::Repeat => {
- // A repeating gradient with stops that are all in the same
- // position should just display the last color. I believe the
- // spec says that it should be the average color of the gradient,
- // but this matches what Gecko and Blink does
- stops.push(di::GradientStop { color: last.color, offset: 0.0, });
- stops.push(di::GradientStop { color: last.color, offset: 1.0, });
-
- (0.0, 1.0)
- }
- }
- }
- }
-}
diff --git a/third_party/webrender/webrender_api/src/image.rs b/third_party/webrender/webrender_api/src/image.rs
deleted file mode 100644
index 23c660b647e..00000000000
--- a/third_party/webrender/webrender_api/src/image.rs
+++ /dev/null
@@ -1,580 +0,0 @@
-/* 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/. */
-
-#![deny(missing_docs)]
-
-use euclid::{size2, Rect, num::Zero};
-use peek_poke::PeekPoke;
-use std::ops::{Add, Sub};
-use std::sync::Arc;
-// local imports
-use crate::{IdNamespace, TileSize};
-use crate::display_item::ImageRendering;
-use crate::font::{FontInstanceKey, FontInstanceData, FontKey, FontTemplate};
-use crate::units::*;
-
-/// The default tile size for blob images and regular images larger than
-/// the maximum texture size.
-pub const DEFAULT_TILE_SIZE: TileSize = 512;
-
-/// An opaque identifier describing an image registered with WebRender.
-/// This is used as a handle to reference images, and is used as the
-/// hash map key for the actual image storage in the `ResourceCache`.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct ImageKey(pub IdNamespace, pub u32);
-
-impl Default for ImageKey {
- fn default() -> Self {
- ImageKey::DUMMY
- }
-}
-
-impl ImageKey {
- /// Placeholder Image key, used to represent None.
- pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);
-
- /// Mints a new ImageKey. The given ID must be unique.
- pub fn new(namespace: IdNamespace, key: u32) -> Self {
- ImageKey(namespace, key)
- }
-}
-
-/// An opaque identifier describing a blob image registered with WebRender.
-/// This is used as a handle to reference blob images, and can be used as an
-/// image in display items.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
-pub struct BlobImageKey(pub ImageKey);
-
-impl BlobImageKey {
- /// Interpret this blob image as an image for a display item.
- pub fn as_image(self) -> ImageKey {
- self.0
- }
-}
-
-/// An arbitrary identifier for an external image provided by the
-/// application. It must be a unique identifier for each external
-/// image.
-#[repr(C)]
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
-pub struct ExternalImageId(pub u64);
-
-/// The source for an external image.
-pub enum ExternalImageSource<'a> {
- /// A raw pixel buffer.
- RawData(&'a [u8]),
- /// A gl::GLuint texture handle.
- NativeTexture(u32),
- /// An invalid source.
- Invalid,
-}
-
-/// The data that an external client should provide about
-/// an external image. For instance, if providing video frames,
-/// the application could call wr.render() whenever a new
-/// video frame is ready. Note that the UV coords are supplied
-/// in texel-space!
-pub struct ExternalImage<'a> {
- /// UV coordinates for the image.
- pub uv: TexelRect,
- /// The source for this image's contents.
- pub source: ExternalImageSource<'a>,
-}
-
-/// The interfaces that an application can implement to support providing
-/// external image buffers.
-/// When the application passes an external image to WR, it should keep that
-/// external image life time. People could check the epoch id in RenderNotifier
-/// at the client side to make sure that the external image is not used by WR.
-/// Then, do the clean up for that external image.
-pub trait ExternalImageHandler {
- /// Lock the external image. Then, WR could start to read the image content.
- /// The WR client should not change the image content until the unlock()
- /// call. Provide ImageRendering for NativeTexture external images.
- fn lock(&mut self, key: ExternalImageId, channel_index: u8, rendering: ImageRendering) -> ExternalImage;
- /// Unlock the external image. WR should not read the image content
- /// after this call.
- fn unlock(&mut self, key: ExternalImageId, channel_index: u8);
-}
-
-/// Specifies the type of texture target in driver terms.
-#[repr(u8)]
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
-pub enum ImageBufferKind {
- /// Standard texture. This maps to GL_TEXTURE_2D in OpenGL.
- Texture2D = 0,
- /// Rectangle texture. This maps to GL_TEXTURE_RECTANGLE in OpenGL. This
- /// is similar to a standard texture, with a few subtle differences
- /// (no mipmaps, non-power-of-two dimensions, different coordinate space)
- /// that make it useful for representing the kinds of textures we use
- /// in WebRender. See https://www.khronos.org/opengl/wiki/Rectangle_Texture
- /// for background on Rectangle textures.
- TextureRect = 1,
- /// External texture. This maps to GL_TEXTURE_EXTERNAL_OES in OpenGL, which
- /// is an extension. This is used for image formats that OpenGL doesn't
- /// understand, particularly YUV. See
- /// https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
- TextureExternal = 2,
-}
-
-/// Storage format identifier for externally-managed images.
-#[repr(u8)]
-#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
-pub enum ExternalImageType {
- /// The image is texture-backed.
- TextureHandle(ImageBufferKind),
- /// The image is heap-allocated by the embedding.
- Buffer,
-}
-
-/// Descriptor for external image resources. See `ImageData`.
-#[repr(C)]
-#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)]
-pub struct ExternalImageData {
- /// The identifier of this external image, provided by the embedding.
- pub id: ExternalImageId,
- /// For multi-plane images (i.e. YUV), indicates the plane of the
- /// original image that this struct represents. 0 for single-plane images.
- pub channel_index: u8,
- /// Storage format identifier.
- pub image_type: ExternalImageType,
-}
-
-/// Specifies the format of a series of pixels, in driver terms.
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
-pub enum ImageFormat {
- /// One-channel, byte storage. The "red" doesn't map to the color
- /// red per se, and is just the way that OpenGL has historically referred
- /// to single-channel buffers.
- R8 = 1,
- /// One-channel, short storage
- R16 = 2,
- /// Four channels, byte storage.
- BGRA8 = 3,
- /// Four channels, float storage.
- RGBAF32 = 4,
- /// Two-channels, byte storage. Similar to `R8`, this just means
- /// "two channels" rather than "red and green".
- RG8 = 5,
- /// Two-channels, byte storage. Similar to `R16`, this just means
- /// "two channels" rather than "red and green".
- RG16 = 6,
-
- /// Four channels, signed integer storage.
- RGBAI32 = 7,
- /// Four channels, byte storage.
- RGBA8 = 8,
-}
-
-impl ImageFormat {
- /// Returns the number of bytes per pixel for the given format.
- pub fn bytes_per_pixel(self) -> i32 {
- match self {
- ImageFormat::R8 => 1,
- ImageFormat::R16 => 2,
- ImageFormat::BGRA8 => 4,
- ImageFormat::RGBAF32 => 16,
- ImageFormat::RG8 => 2,
- ImageFormat::RG16 => 4,
- ImageFormat::RGBAI32 => 16,
- ImageFormat::RGBA8 => 4,
- }
- }
-}
-
-/// Specifies the color depth of an image. Currently only used for YUV images.
-#[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum ColorDepth {
- /// 8 bits image (most common)
- Color8,
- /// 10 bits image
- Color10,
- /// 12 bits image
- Color12,
- /// 16 bits image
- Color16,
-}
-
-impl Default for ColorDepth {
- fn default() -> Self {
- ColorDepth::Color8
- }
-}
-
-impl ColorDepth {
- /// Return the numerical bit depth value for the type.
- pub fn bit_depth(self) -> u32 {
- match self {
- ColorDepth::Color8 => 8,
- ColorDepth::Color10 => 10,
- ColorDepth::Color12 => 12,
- ColorDepth::Color16 => 16,
- }
- }
- /// 10 and 12 bits images are encoded using 16 bits integer, we need to
- /// rescale the 10 or 12 bits value to extend to 16 bits.
- pub fn rescaling_factor(self) -> f32 {
- match self {
- ColorDepth::Color8 => 1.0,
- ColorDepth::Color10 => 64.0,
- ColorDepth::Color12 => 16.0,
- ColorDepth::Color16 => 1.0,
- }
- }
-}
-
-bitflags! {
- /// Various flags that are part of an image descriptor.
- #[derive(Deserialize, Serialize)]
- pub struct ImageDescriptorFlags: u32 {
- /// Whether this image is opaque, or has an alpha channel. Avoiding blending
- /// for opaque surfaces is an important optimization.
- const IS_OPAQUE = 1;
- /// Whether to allow the driver to automatically generate mipmaps. If images
- /// are already downscaled appropriately, mipmap generation can be wasted
- /// work, and cause performance problems on some cards/drivers.
- ///
- /// See https://github.com/servo/webrender/pull/2555/
- const ALLOW_MIPMAPS = 2;
- }
-}
-
-/// Metadata (but not storage) describing an image In WebRender.
-#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct ImageDescriptor {
- /// Format of the image data.
- pub format: ImageFormat,
- /// Width and length of the image data, in pixels.
- pub size: DeviceIntSize,
- /// The number of bytes from the start of one row to the next. If non-None,
- /// `compute_stride` will return this value, otherwise it returns
- /// `width * bpp`. Different source of images have different alignment
- /// constraints for rows, so the stride isn't always equal to width * bpp.
- pub stride: Option<i32>,
- /// Offset in bytes of the first pixel of this image in its backing buffer.
- /// This is used for tiling, wherein WebRender extracts chunks of input images
- /// in order to cache, manipulate, and render them individually. This offset
- /// tells the texture upload machinery where to find the bytes to upload for
- /// this tile. Non-tiled images generally set this to zero.
- pub offset: i32,
- /// Various bool flags related to this descriptor.
- pub flags: ImageDescriptorFlags,
-}
-
-impl ImageDescriptor {
- /// Mints a new ImageDescriptor.
- pub fn new(
- width: i32,
- height: i32,
- format: ImageFormat,
- flags: ImageDescriptorFlags,
- ) -> Self {
- ImageDescriptor {
- size: size2(width, height),
- format,
- stride: None,
- offset: 0,
- flags,
- }
- }
-
- /// Returns the stride, either via an explicit stride stashed on the object
- /// or by the default computation.
- pub fn compute_stride(&self) -> i32 {
- self.stride.unwrap_or(self.size.width * self.format.bytes_per_pixel())
- }
-
- /// Computes the total size of the image, in bytes.
- pub fn compute_total_size(&self) -> i32 {
- self.compute_stride() * self.size.height
- }
-
- /// Computes the bounding rectangle for the image, rooted at (0, 0).
- pub fn full_rect(&self) -> DeviceIntRect {
- DeviceIntRect::new(
- DeviceIntPoint::zero(),
- self.size,
- )
- }
-
- /// Returns true if this descriptor is opaque
- pub fn is_opaque(&self) -> bool {
- self.flags.contains(ImageDescriptorFlags::IS_OPAQUE)
- }
-
- /// Returns true if this descriptor allows mipmaps
- pub fn allow_mipmaps(&self) -> bool {
- self.flags.contains(ImageDescriptorFlags::ALLOW_MIPMAPS)
- }
-}
-
-/// Represents the backing store of an arbitrary series of pixels for display by
-/// WebRender. This storage can take several forms.
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub enum ImageData {
- /// A simple series of bytes, provided by the embedding and owned by WebRender.
- /// The format is stored out-of-band, currently in ImageDescriptor.
- Raw(#[serde(with = "serde_image_data_raw")] Arc<Vec<u8>>),
- /// An image owned by the embedding, and referenced by WebRender. This may
- /// take the form of a texture or a heap-allocated buffer.
- External(ExternalImageData),
-}
-
-mod serde_image_data_raw {
- use serde::{Deserializer, Serializer};
- use serde_bytes;
- use std::sync::Arc;
-
- pub fn serialize<S: Serializer>(bytes: &Arc<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error> {
- serde_bytes::serialize(bytes.as_slice(), serializer)
- }
-
- pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Arc<Vec<u8>>, D::Error> {
- serde_bytes::deserialize(deserializer).map(Arc::new)
- }
-}
-
-impl ImageData {
- /// Mints a new raw ImageData, taking ownership of the bytes.
- pub fn new(bytes: Vec<u8>) -> Self {
- ImageData::Raw(Arc::new(bytes))
- }
-
- /// Mints a new raw ImageData from Arc-ed bytes.
- pub fn new_shared(bytes: Arc<Vec<u8>>) -> Self {
- ImageData::Raw(bytes)
- }
-}
-
-/// The resources exposed by the resource cache available for use by the blob rasterizer.
-pub trait BlobImageResources {
- /// Returns the `FontTemplate` for the given key.
- fn get_font_data(&self, key: FontKey) -> &FontTemplate;
- /// Returns the `FontInstanceData` for the given key, if found.
- fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData>;
-}
-
-/// A handler on the render backend that can create rasterizer objects which will
-/// be sent to the scene builder thread to execute the rasterization.
-///
-/// The handler is responsible for collecting resources, managing/updating blob commands
-/// and creating the rasterizer objects, but isn't expected to do any rasterization itself.
-pub trait BlobImageHandler: Send {
- /// Creates a snapshot of the current state of blob images in the handler.
- fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer>;
-
- /// Creates an empty blob handler of the same type.
- ///
- /// This is used to allow creating new API endpoints with blob handlers installed on them.
- fn create_similar(&self) -> Box<dyn BlobImageHandler>;
-
- /// A hook to let the blob image handler update any state related to resources that
- /// are not bundled in the blob recording itself.
- fn prepare_resources(
- &mut self,
- services: &dyn BlobImageResources,
- requests: &[BlobImageParams],
- );
-
- /// Register a blob image.
- fn add(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
- tile_size: TileSize);
-
- /// Update an already registered blob image.
- fn update(&mut self, key: BlobImageKey, data: Arc<BlobImageData>, visible_rect: &DeviceIntRect,
- dirty_rect: &BlobDirtyRect);
-
- /// Delete an already registered blob image.
- fn delete(&mut self, key: BlobImageKey);
-
- /// A hook to let the handler clean up any state related to a font which the resource
- /// cache is about to delete.
- fn delete_font(&mut self, key: FontKey);
-
- /// A hook to let the handler clean up any state related to a font instance which the
- /// resource cache is about to delete.
- fn delete_font_instance(&mut self, key: FontInstanceKey);
-
- /// A hook to let the handler clean up any state related a given namespace before the
- /// resource cache deletes them.
- fn clear_namespace(&mut self, namespace: IdNamespace);
-
- /// Whether to allow rendering blobs on multiple threads.
- fn enable_multithreading(&mut self, enable: bool);
-}
-
-/// A group of rasterization requests to execute synchronously on the scene builder thread.
-pub trait AsyncBlobImageRasterizer : Send {
- /// Rasterize the requests.
- ///
- /// Gecko uses te priority hint to schedule work in a way that minimizes the risk
- /// of high priority work being blocked by (or enqued behind) low priority work.
- fn rasterize(
- &mut self,
- requests: &[BlobImageParams],
- low_priority: bool
- ) -> Vec<(BlobImageRequest, BlobImageResult)>;
-}
-
-
-/// Input parameters for the BlobImageRasterizer.
-#[derive(Copy, Clone, Debug)]
-pub struct BlobImageParams {
- /// A key that identifies the blob image rasterization request.
- pub request: BlobImageRequest,
- /// Description of the format of the blob's output image.
- pub descriptor: BlobImageDescriptor,
- /// An optional sub-rectangle of the image to avoid re-rasterizing
- /// the entire image when only a portion is updated.
- ///
- /// If set to None the entire image is rasterized.
- pub dirty_rect: BlobDirtyRect,
-}
-
-/// The possible states of a Dirty rect.
-///
-/// This exists because people kept getting confused with `Option<Rect>`.
-#[derive(Debug, Serialize, Deserialize)]
-pub enum DirtyRect<T: Copy, U> {
- /// Everything is Dirty, equivalent to Partial(image_bounds)
- All,
- /// Some specific amount is dirty
- Partial(Rect<T, U>)
-}
-
-impl<T, U> DirtyRect<T, U>
-where
- T: Copy + Clone
- + PartialOrd + PartialEq
- + Add<T, Output = T>
- + Sub<T, Output = T>
- + Zero
-{
- /// Creates an empty DirtyRect (indicating nothing is invalid)
- pub fn empty() -> Self {
- DirtyRect::Partial(Rect::zero())
- }
-
- /// Returns whether the dirty rect is empty
- pub fn is_empty(&self) -> bool {
- match self {
- DirtyRect::All => false,
- DirtyRect::Partial(rect) => rect.is_empty(),
- }
- }
-
- /// Replaces self with the empty rect and returns the old value.
- pub fn replace_with_empty(&mut self) -> Self {
- ::std::mem::replace(self, DirtyRect::empty())
- }
-
- /// Maps over the contents of Partial.
- pub fn map<F>(self, func: F) -> Self
- where F: FnOnce(Rect<T, U>) -> Rect<T, U>,
- {
- use crate::DirtyRect::*;
-
- match self {
- All => All,
- Partial(rect) => Partial(func(rect)),
- }
- }
-
- /// Unions the dirty rects.
- pub fn union(&self, other: &Self) -> Self {
- use crate::DirtyRect::*;
-
- match (*self, *other) {
- (All, _) | (_, All) => All,
- (Partial(rect1), Partial(rect2)) => Partial(rect1.union(&rect2)),
- }
- }
-
- /// Intersects the dirty rects.
- pub fn intersection(&self, other: &Self) -> Self {
- use crate::DirtyRect::*;
-
- match (*self, *other) {
- (All, rect) | (rect, All) => rect,
- (Partial(rect1), Partial(rect2)) => {
- Partial(rect1.intersection(&rect2).unwrap_or_else(Rect::zero))
- }
- }
- }
-
- /// Converts the dirty rect into a subrect of the given one via intersection.
- pub fn to_subrect_of(&self, rect: &Rect<T, U>) -> Rect<T, U> {
- use crate::DirtyRect::*;
-
- match *self {
- All => *rect,
- Partial(dirty_rect) => {
- dirty_rect.intersection(rect).unwrap_or_else(Rect::zero)
- }
- }
- }
-}
-
-impl<T: Copy, U> Copy for DirtyRect<T, U> {}
-impl<T: Copy, U> Clone for DirtyRect<T, U> {
- fn clone(&self) -> Self { *self }
-}
-
-impl<T: Copy, U> From<Rect<T, U>> for DirtyRect<T, U> {
- fn from(rect: Rect<T, U>) -> Self {
- DirtyRect::Partial(rect)
- }
-}
-
-/// Backing store for blob image command streams.
-pub type BlobImageData = Vec<u8>;
-
-/// Result type for blob raserization.
-pub type BlobImageResult = Result<RasterizedBlobImage, BlobImageError>;
-
-/// Metadata (but not storage) for a blob image.
-#[repr(C)]
-#[derive(Copy, Clone, Debug)]
-pub struct BlobImageDescriptor {
- /// Surface of the image or tile to render in the same coordinate space as
- /// the drawing commands.
- pub rect: LayoutIntRect,
- /// Format for the data in the backing store.
- pub format: ImageFormat,
-}
-
-/// Representation of a rasterized blob image. This is obtained by passing
-/// `BlobImageData` to the embedding via the rasterization callback.
-pub struct RasterizedBlobImage {
- /// The rectangle that was rasterized in device pixels, relative to the
- /// image or tile.
- pub rasterized_rect: DeviceIntRect,
- /// Backing store. The format is stored out of band in `BlobImageDescriptor`.
- pub data: Arc<Vec<u8>>,
-}
-
-/// Error code for when blob rasterization failed.
-#[derive(Clone, Debug)]
-pub enum BlobImageError {
- /// Out of memory.
- Oom,
- /// Other failure, embedding-specified.
- Other(String),
-}
-
-
-
-/// A key identifying blob image rasterization work requested from the blob
-/// image rasterizer.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct BlobImageRequest {
- /// Unique handle to the image.
- pub key: BlobImageKey,
- /// Tiling offset in number of tiles.
- pub tile: TileOffset,
-}
diff --git a/third_party/webrender/webrender_api/src/lib.rs b/third_party/webrender/webrender_api/src/lib.rs
deleted file mode 100644
index f5cda1fbf65..00000000000
--- a/third_party/webrender/webrender_api/src/lib.rs
+++ /dev/null
@@ -1,665 +0,0 @@
-/* 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/. */
-
-//! The `webrender_api` crate contains an assortment types and functions used
-//! by WebRender consumers as well as, in many cases, WebRender itself.
-//!
-//! This separation allows Servo to parallelize compilation across `webrender`
-//! and other crates that depend on `webrender_api`. So in practice, we put
-//! things in this crate when Servo needs to use them. Firefox depends on the
-//! `webrender` crate directly, and so this distinction is not really relevant
-//! there.
-
-#![cfg_attr(feature = "nightly", feature(nonzero))]
-#![cfg_attr(feature = "cargo-clippy", allow(clippy::float_cmp, clippy::too_many_arguments))]
-#![cfg_attr(feature = "cargo-clippy", allow(clippy::unreadable_literal, clippy::new_without_default))]
-
-pub use crossbeam_channel;
-pub use euclid;
-
-#[macro_use]
-extern crate bitflags;
-#[cfg(feature = "nightly")]
-extern crate core;
-#[macro_use]
-extern crate malloc_size_of_derive;
-#[macro_use]
-extern crate serde_derive;
-
-use malloc_size_of;
-use peek_poke;
-
-pub mod channel;
-mod color;
-mod display_item;
-mod display_item_cache;
-mod display_list;
-mod font;
-mod gradient_builder;
-mod image;
-pub mod units;
-
-pub use crate::color::*;
-pub use crate::display_item::*;
-pub use crate::display_item_cache::DisplayItemCache;
-pub use crate::display_list::*;
-pub use crate::font::*;
-pub use crate::gradient_builder::*;
-pub use crate::image::*;
-
-use crate::units::*;
-use crate::channel::Receiver;
-use std::marker::PhantomData;
-use std::sync::Arc;
-use std::os::raw::c_void;
-use peek_poke::PeekPoke;
-
-/// Width and height in device pixels of image tiles.
-pub type TileSize = u16;
-
-/// Various settings that the caller can select based on desired tradeoffs
-/// between rendering quality and performance / power usage.
-#[derive(Copy, Clone, Deserialize, Serialize)]
-pub struct QualitySettings {
- /// If true, disable creating separate picture cache slices when the
- /// scroll root changes. This gives maximum opportunity to find an
- /// opaque background, which enables subpixel AA. However, it is
- /// usually significantly more expensive to render when scrolling.
- pub force_subpixel_aa_where_possible: bool,
-}
-
-impl Default for QualitySettings {
- fn default() -> Self {
- QualitySettings {
- // Prefer performance over maximum subpixel AA quality, since WR
- // already enables subpixel AA in more situations than other browsers.
- force_subpixel_aa_where_possible: false,
- }
- }
-}
-
-/// An epoch identifies the state of a pipeline in time.
-///
-/// This is mostly used as a synchronization mechanism to observe how/when particular pipeline
-/// updates propagate through WebRender and are applied at various stages.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
-pub struct Epoch(pub u32);
-
-impl Epoch {
- /// Magic invalid epoch value.
- pub fn invalid() -> Epoch {
- Epoch(u32::MAX)
- }
-}
-
-/// ID namespaces uniquely identify different users of WebRender's API.
-///
-/// For example in Gecko each content process uses a separate id namespace.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
-#[derive(Deserialize, Serialize)]
-pub struct IdNamespace(pub u32);
-
-/// A key uniquely identifying a WebRender document.
-///
-/// Instances can manage one or several documents (using the same render backend thread).
-/// Each document will internally correspond to a single scene, and scenes are made of
-/// one or several pipelines.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct DocumentId {
- ///
- pub namespace_id: IdNamespace,
- ///
- pub id: u32,
-}
-
-impl DocumentId {
- ///
- pub fn new(namespace_id: IdNamespace, id: u32) -> Self {
- DocumentId {
- namespace_id,
- id,
- }
- }
-
- ///
- pub const INVALID: DocumentId = DocumentId { namespace_id: IdNamespace(0), id: 0 };
-}
-
-/// This type carries no valuable semantics for WR. However, it reflects the fact that
-/// clients (Servo) may generate pipelines by different semi-independent sources.
-/// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
-/// Having this extra Id field enables them to generate `PipelineId` without collision.
-pub type PipelineSourceId = u32;
-
-/// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
-/// it's clonable, serializable, comparable, and hashable.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct PipelineId(pub PipelineSourceId, pub u32);
-
-impl Default for PipelineId {
- fn default() -> Self {
- PipelineId::dummy()
- }
-}
-
-impl PipelineId {
- ///
- pub fn dummy() -> Self {
- PipelineId(!0, !0)
- }
-}
-
-
-/// An opaque pointer-sized value.
-#[repr(C)]
-#[derive(Clone)]
-pub struct ExternalEvent {
- raw: usize,
-}
-
-unsafe impl Send for ExternalEvent {}
-
-impl ExternalEvent {
- /// Creates the event from an opaque pointer-sized value.
- pub fn from_raw(raw: usize) -> Self {
- ExternalEvent { raw }
- }
- /// Consumes self to make it obvious that the event should be forwarded only once.
- pub fn unwrap(self) -> usize {
- self.raw
- }
-}
-
-/// Describe whether or not scrolling should be clamped by the content bounds.
-#[derive(Clone, Deserialize, Serialize)]
-pub enum ScrollClamping {
- ///
- ToContentBounds,
- ///
- NoClamping,
-}
-
-/// A handler to integrate WebRender with the thread that contains the `Renderer`.
-pub trait RenderNotifier: Send {
- ///
- fn clone(&self) -> Box<dyn RenderNotifier>;
- /// Wake the thread containing the `Renderer` up (after updates have been put
- /// in the renderer's queue).
- fn wake_up(
- &self,
- composite_needed: bool,
- );
- /// Notify the thread containing the `Renderer` that a new frame is ready.
- fn new_frame_ready(&self, _: DocumentId, scrolled: bool, composite_needed: bool, render_time_ns: Option<u64>);
- /// A Gecko-specific notification mechanism to get some code executed on the
- /// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
- /// probably use the latter instead.
- fn external_event(&self, _evt: ExternalEvent) {
- unimplemented!()
- }
- /// Notify the thread containing the `Renderer` that the render backend has been
- /// shut down.
- fn shut_down(&self) {}
-}
-
-/// A stage of the rendering pipeline.
-#[repr(u32)]
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Checkpoint {
- ///
- SceneBuilt,
- ///
- FrameBuilt,
- ///
- FrameTexturesUpdated,
- ///
- FrameRendered,
- /// NotificationRequests get notified with this if they get dropped without having been
- /// notified. This provides the guarantee that if a request is created it will get notified.
- TransactionDropped,
-}
-
-/// A handler to notify when a transaction reaches certain stages of the rendering
-/// pipeline.
-pub trait NotificationHandler : Send + Sync {
- /// Entry point of the handler to implement. Invoked by WebRender.
- fn notify(&self, when: Checkpoint);
-}
-
-/// A request to notify a handler when the transaction reaches certain stages of the
-/// rendering pipeline.
-///
-/// The request is guaranteed to be notified once and only once, even if the transaction
-/// is dropped before the requested check-point.
-pub struct NotificationRequest {
- handler: Option<Box<dyn NotificationHandler>>,
- when: Checkpoint,
-}
-
-impl NotificationRequest {
- /// Constructor.
- pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
- NotificationRequest {
- handler: Some(handler),
- when,
- }
- }
-
- /// The specified stage at which point the handler should be notified.
- pub fn when(&self) -> Checkpoint { self.when }
-
- /// Called by WebRender at specified stages to notify the registered handler.
- pub fn notify(mut self) {
- if let Some(handler) = self.handler.take() {
- handler.notify(self.when);
- }
- }
-}
-
-/// An object that can perform hit-testing without doing synchronous queries to
-/// the RenderBackendThread.
-pub trait ApiHitTester: Send + Sync {
- /// Does a hit test on display items in the specified document, at the given
- /// point. If a pipeline_id is specified, it is used to further restrict the
- /// hit results so that only items inside that pipeline are matched. The vector
- /// of hit results will contain all display items that match, ordered from
- /// front to back.
- fn hit_test(&self, pipeline_id: Option<PipelineId>, point: WorldPoint, flags: HitTestFlags) -> HitTestResult;
-}
-
-/// A hit tester requested to the render backend thread but not necessarily ready yet.
-///
-/// The request should be resolved as late as possible to reduce the likelihood of blocking.
-pub struct HitTesterRequest {
- #[doc(hidden)]
- pub rx: Receiver<Arc<dyn ApiHitTester>>,
-}
-
-impl HitTesterRequest {
- /// Block until the hit tester is available and return it, consuming teh request.
- pub fn resolve(self) -> Arc<dyn ApiHitTester> {
- self.rx.recv().unwrap()
- }
-}
-
-/// Describe an item that matched a hit-test query.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
-pub struct HitTestItem {
- /// The pipeline that the display item that was hit belongs to.
- pub pipeline: PipelineId,
-
- /// The tag of the hit display item.
- pub tag: ItemTag,
-
- /// The hit point in the coordinate space of the "viewport" of the display item. The
- /// viewport is the scroll node formed by the root reference frame of the display item's
- /// pipeline.
- pub point_in_viewport: LayoutPoint,
-
- /// The coordinates of the original hit test point relative to the origin of this item.
- /// This is useful for calculating things like text offsets in the client.
- pub point_relative_to_item: LayoutPoint,
-}
-
-/// Returned by `RenderApi::hit_test`.
-#[derive(Clone, Debug, Default, Deserialize, Serialize)]
-pub struct HitTestResult {
- /// List of items that are match the hit-test query.
- pub items: Vec<HitTestItem>,
-}
-
-bitflags! {
- #[derive(Deserialize, MallocSizeOf, Serialize)]
- ///
- pub struct HitTestFlags: u8 {
- ///
- const FIND_ALL = 0b00000001;
- ///
- const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010;
- }
-}
-
-impl Drop for NotificationRequest {
- fn drop(&mut self) {
- if let Some(ref mut handler) = self.handler {
- handler.notify(Checkpoint::TransactionDropped);
- }
- }
-}
-
-// This Clone impl yields an "empty" request because we don't want the requests
-// to be notified twice so the request is owned by only one of the API messages
-// (the original one) after the clone.
-// This works in practice because the notifications requests are used for
-// synchronization so we don't need to include them in the recording mechanism
-// in wrench that clones the messages.
-impl Clone for NotificationRequest {
- fn clone(&self) -> Self {
- NotificationRequest {
- when: self.when,
- handler: None,
- }
- }
-}
-
-
-/// A key to identify an animated property binding.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
-pub struct PropertyBindingId {
- pub namespace: IdNamespace,
- pub uid: u32,
-}
-
-impl PropertyBindingId {
- /// Constructor.
- pub fn new(value: u64) -> Self {
- PropertyBindingId {
- namespace: IdNamespace((value >> 32) as u32),
- uid: value as u32,
- }
- }
-}
-
-/// A unique key that is used for connecting animated property
-/// values to bindings in the display list.
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub struct PropertyBindingKey<T> {
- ///
- pub id: PropertyBindingId,
- #[doc(hidden)]
- pub _phantom: PhantomData<T>,
-}
-
-/// Construct a property value from a given key and value.
-impl<T: Copy> PropertyBindingKey<T> {
- ///
- pub fn with(self, value: T) -> PropertyValue<T> {
- PropertyValue { key: self, value }
- }
-}
-
-impl<T> PropertyBindingKey<T> {
- /// Constructor.
- pub fn new(value: u64) -> Self {
- PropertyBindingKey {
- id: PropertyBindingId::new(value),
- _phantom: PhantomData,
- }
- }
-}
-
-/// A binding property can either be a specific value
-/// (the normal, non-animated case) or point to a binding location
-/// to fetch the current value from.
-/// Note that Binding has also a non-animated value, the value is
-/// used for the case where the animation is still in-delay phase
-/// (i.e. the animation doesn't produce any animation values).
-#[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
-pub enum PropertyBinding<T> {
- /// Non-animated value.
- Value(T),
- /// Animated binding.
- Binding(PropertyBindingKey<T>, T),
-}
-
-impl<T: Default> Default for PropertyBinding<T> {
- fn default() -> Self {
- PropertyBinding::Value(Default::default())
- }
-}
-
-impl<T> From<T> for PropertyBinding<T> {
- fn from(value: T) -> PropertyBinding<T> {
- PropertyBinding::Value(value)
- }
-}
-
-impl From<PropertyBindingKey<ColorF>> for PropertyBindingKey<ColorU> {
- fn from(key: PropertyBindingKey<ColorF>) -> PropertyBindingKey<ColorU> {
- PropertyBindingKey {
- id: key.id.clone(),
- _phantom: PhantomData,
- }
- }
-}
-
-impl From<PropertyBindingKey<ColorU>> for PropertyBindingKey<ColorF> {
- fn from(key: PropertyBindingKey<ColorU>) -> PropertyBindingKey<ColorF> {
- PropertyBindingKey {
- id: key.id.clone(),
- _phantom: PhantomData,
- }
- }
-}
-
-impl From<PropertyBinding<ColorF>> for PropertyBinding<ColorU> {
- fn from(value: PropertyBinding<ColorF>) -> PropertyBinding<ColorU> {
- match value {
- PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
- PropertyBinding::Binding(k, v) => {
- PropertyBinding::Binding(k.into(), v.into())
- }
- }
- }
-}
-
-impl From<PropertyBinding<ColorU>> for PropertyBinding<ColorF> {
- fn from(value: PropertyBinding<ColorU>) -> PropertyBinding<ColorF> {
- match value {
- PropertyBinding::Value(value) => PropertyBinding::Value(value.into()),
- PropertyBinding::Binding(k, v) => {
- PropertyBinding::Binding(k.into(), v.into())
- }
- }
- }
-}
-
-/// The current value of an animated property. This is
-/// supplied by the calling code.
-#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
-pub struct PropertyValue<T> {
- ///
- pub key: PropertyBindingKey<T>,
- ///
- pub value: T,
-}
-
-/// When using `generate_frame()`, a list of `PropertyValue` structures
-/// can optionally be supplied to provide the current value of any
-/// animated properties.
-#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
-pub struct DynamicProperties {
- ///
- pub transforms: Vec<PropertyValue<LayoutTransform>>,
- /// opacity
- pub floats: Vec<PropertyValue<f32>>,
- /// background color
- pub colors: Vec<PropertyValue<ColorF>>,
-}
-
-/// A C function that takes a pointer to a heap allocation and returns its size.
-///
-/// This is borrowed from the malloc_size_of crate, upon which we want to avoid
-/// a dependency from WebRender.
-pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
-
-bitflags! {
- /// Flags to enable/disable various builtin debugging tools.
- #[repr(C)]
- #[derive(Default, Deserialize, MallocSizeOf, Serialize)]
- pub struct DebugFlags: u32 {
- /// Display the frame profiler on screen.
- const PROFILER_DBG = 1 << 0;
- /// Display intermediate render targets on screen.
- const RENDER_TARGET_DBG = 1 << 1;
- /// Display all texture cache pages on screen.
- const TEXTURE_CACHE_DBG = 1 << 2;
- /// Display GPU timing results.
- const GPU_TIME_QUERIES = 1 << 3;
- /// Query the number of pixels that pass the depth test divided and show it
- /// in the profiler as a percentage of the number of pixels in the screen
- /// (window width times height).
- const GPU_SAMPLE_QUERIES = 1 << 4;
- /// Render each quad with their own draw call.
- ///
- /// Terrible for performance but can help with understanding the drawing
- /// order when inspecting renderdoc or apitrace recordings.
- const DISABLE_BATCHING = 1 << 5;
- /// Display the pipeline epochs.
- const EPOCHS = 1 << 6;
- /// Print driver messages to stdout.
- const ECHO_DRIVER_MESSAGES = 1 << 7;
- /// Show an overlay displaying overdraw amount.
- const SHOW_OVERDRAW = 1 << 8;
- /// Display the contents of GPU cache.
- const GPU_CACHE_DBG = 1 << 9;
- /// Clear evicted parts of the texture cache for debugging purposes.
- const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 10;
- /// Show picture caching debug overlay
- const PICTURE_CACHING_DBG = 1 << 11;
- /// Highlight all primitives with colors based on kind.
- const PRIMITIVE_DBG = 1 << 12;
- /// Draw a zoom widget showing part of the framebuffer zoomed in.
- const ZOOM_DBG = 1 << 13;
- /// Scale the debug renderer down for a smaller screen. This will disrupt
- /// any mapping between debug display items and page content, so shouldn't
- /// be used with overlays like the picture caching or primitive display.
- const SMALL_SCREEN = 1 << 14;
- /// Disable various bits of the WebRender pipeline, to help narrow
- /// down where slowness might be coming from.
- const DISABLE_OPAQUE_PASS = 1 << 15;
- ///
- const DISABLE_ALPHA_PASS = 1 << 16;
- ///
- const DISABLE_CLIP_MASKS = 1 << 17;
- ///
- const DISABLE_TEXT_PRIMS = 1 << 18;
- ///
- const DISABLE_GRADIENT_PRIMS = 1 << 19;
- ///
- const OBSCURE_IMAGES = 1 << 20;
- /// Taint the transparent area of the glyphs with a random opacity to easily
- /// see when glyphs are re-rasterized.
- const GLYPH_FLASHING = 1 << 21;
- /// The profiler only displays information that is out of the ordinary.
- const SMART_PROFILER = 1 << 22;
- /// If set, dump picture cache invalidation debug to console.
- const INVALIDATION_DBG = 1 << 23;
- /// Log tile cache to memory for later saving as part of wr-capture
- const TILE_CACHE_LOGGING_DBG = 1 << 24;
- /// Collect and dump profiler statistics to captures.
- const PROFILER_CAPTURE = (1 as u32) << 25; // need "as u32" until we have cbindgen#556
- /// Invalidate picture tiles every frames (useful when inspecting GPU work in external tools).
- const FORCE_PICTURE_INVALIDATION = (1 as u32) << 26;
- const USE_BATCHED_TEXTURE_UPLOADS = (1 as u32) << 27;
- const USE_DRAW_CALLS_FOR_TEXTURE_COPY = (1 as u32) << 28;
- }
-}
-
-/// Information specific to a primitive type that
-/// uniquely identifies a primitive template by key.
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
-pub enum PrimitiveKeyKind {
- /// Clear an existing rect, used for special effects on some platforms.
- Clear,
- ///
- Rectangle {
- ///
- color: PropertyBinding<ColorU>,
- },
-}
-
-///
-#[derive(Clone)]
-pub struct ScrollNodeState {
- ///
- pub id: ExternalScrollId,
- ///
- pub scroll_offset: LayoutVector2D,
-}
-
-///
-#[derive(Clone, Copy, Debug)]
-pub enum ScrollLocation {
- /// Scroll by a certain amount.
- Delta(LayoutVector2D),
- /// Scroll to very top of element.
- Start,
- /// Scroll to very bottom of element.
- End,
-}
-
-/// Represents a zoom factor.
-#[derive(Clone, Copy, Debug)]
-pub struct ZoomFactor(f32);
-
-impl ZoomFactor {
- /// Construct a new zoom factor.
- pub fn new(scale: f32) -> Self {
- ZoomFactor(scale)
- }
-
- /// Get the zoom factor as an untyped float.
- pub fn get(self) -> f32 {
- self.0
- }
-}
-
-/// Crash annotations included in crash reports.
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub enum CrashAnnotation {
- CompileShader = 0,
- DrawShader = 1,
-}
-
-/// Handler to expose support for annotating crash reports.
-pub trait CrashAnnotator : Send {
- fn set(&self, annotation: CrashAnnotation, value: &std::ffi::CStr);
- fn clear(&self, annotation: CrashAnnotation);
- fn box_clone(&self) -> Box<dyn CrashAnnotator>;
-}
-
-impl Clone for Box<dyn CrashAnnotator> {
- fn clone(&self) -> Box<dyn CrashAnnotator> {
- self.box_clone()
- }
-}
-
-/// Guard to add a crash annotation at creation, and clear it at destruction.
-pub struct CrashAnnotatorGuard<'a> {
- annotator: &'a Option<Box<dyn CrashAnnotator>>,
- annotation: CrashAnnotation,
-}
-
-impl<'a> CrashAnnotatorGuard<'a> {
- pub fn new(
- annotator: &'a Option<Box<dyn CrashAnnotator>>,
- annotation: CrashAnnotation,
- value: &std::ffi::CStr,
- ) -> Self {
- if let Some(ref annotator) = annotator {
- annotator.set(annotation, value);
- }
- Self {
- annotator,
- annotation,
- }
- }
-}
-
-impl<'a> Drop for CrashAnnotatorGuard<'a> {
- fn drop(&mut self) {
- if let Some(ref annotator) = self.annotator {
- annotator.clear(self.annotation);
- }
- }
-}
diff --git a/third_party/webrender/webrender_api/src/units.rs b/third_party/webrender/webrender_api/src/units.rs
deleted file mode 100644
index 5ec6a80e920..00000000000
--- a/third_party/webrender/webrender_api/src/units.rs
+++ /dev/null
@@ -1,325 +0,0 @@
-/* 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/. */
-
-//! A collection of coordinate spaces and their corresponding Point, Size and Rect types.
-//!
-//! Physical pixels take into account the device pixel ratio and their dimensions tend
-//! to correspond to the allocated size of resources in memory, while logical pixels
-//! don't have the device pixel ratio applied which means they are agnostic to the usage
-//! of hidpi screens and the like.
-//!
-//! The terms "layer" and "stacking context" can be used interchangeably
-//! in the context of coordinate systems.
-
-pub use app_units::Au;
-use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
-use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D, Box2D};
-use euclid::HomogeneousVector;
-use peek_poke::PeekPoke;
-// local imports
-use crate::image::DirtyRect;
-
-/// Geometry in the coordinate system of the render target (screen or intermediate
-/// surface) in physical pixels.
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
-pub struct DevicePixel;
-
-pub type DeviceIntRect = Rect<i32, DevicePixel>;
-pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
-pub type DeviceIntSize = Size2D<i32, DevicePixel>;
-pub type DeviceIntLength = Length<i32, DevicePixel>;
-pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
-
-pub type DeviceRect = Rect<f32, DevicePixel>;
-pub type DeviceBox2D = Box2D<f32, DevicePixel>;
-pub type DevicePoint = Point2D<f32, DevicePixel>;
-pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
-pub type DeviceSize = Size2D<f32, DevicePixel>;
-pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
-
-/// Geometry in the coordinate system of the framebuffer in physical pixels.
-/// It's Y-flipped comparing to DevicePixel.
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
-pub struct FramebufferPixel;
-
-pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
-pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
-pub type FramebufferIntRect = Rect<i32, FramebufferPixel>;
-
-/// Geometry in the coordinate system of a Picture (intermediate
-/// surface) in physical pixels.
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
-pub struct PicturePixel;
-
-pub type PictureIntRect = Rect<i32, PicturePixel>;
-pub type PictureIntPoint = Point2D<i32, PicturePixel>;
-pub type PictureIntSize = Size2D<i32, PicturePixel>;
-pub type PictureRect = Rect<f32, PicturePixel>;
-pub type PicturePoint = Point2D<f32, PicturePixel>;
-pub type PictureSize = Size2D<f32, PicturePixel>;
-pub type PicturePoint3D = Point3D<f32, PicturePixel>;
-pub type PictureVector2D = Vector2D<f32, PicturePixel>;
-pub type PictureVector3D = Vector3D<f32, PicturePixel>;
-pub type PictureBox2D = Box2D<f32, PicturePixel>;
-
-/// Geometry gets rasterized in a given root coordinate space. This
-/// is often the root spatial node (world space), but may be a local
-/// space for a variety of reasons (e.g. perspective).
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
-pub struct RasterPixel;
-
-pub type RasterIntRect = Rect<i32, RasterPixel>;
-pub type RasterIntPoint = Point2D<i32, RasterPixel>;
-pub type RasterIntSize = Size2D<i32, RasterPixel>;
-pub type RasterRect = Rect<f32, RasterPixel>;
-pub type RasterPoint = Point2D<f32, RasterPixel>;
-pub type RasterSize = Size2D<f32, RasterPixel>;
-pub type RasterPoint3D = Point3D<f32, RasterPixel>;
-pub type RasterVector2D = Vector2D<f32, RasterPixel>;
-pub type RasterVector3D = Vector3D<f32, RasterPixel>;
-
-/// Geometry in a stacking context's local coordinate space (logical pixels).
-#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
-pub struct LayoutPixel;
-
-pub type LayoutRect = Rect<f32, LayoutPixel>;
-pub type LayoutPoint = Point2D<f32, LayoutPixel>;
-pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
-pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
-pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
-pub type LayoutSize = Size2D<f32, LayoutPixel>;
-pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
-
-pub type LayoutIntRect = Rect<i32, LayoutPixel>;
-pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
-pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
-
-/// Geometry in the document's coordinate space (logical pixels).
-#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)]
-pub struct WorldPixel;
-
-pub type WorldRect = Rect<f32, WorldPixel>;
-pub type WorldPoint = Point2D<f32, WorldPixel>;
-pub type WorldSize = Size2D<f32, WorldPixel>;
-pub type WorldPoint3D = Point3D<f32, WorldPixel>;
-pub type WorldVector2D = Vector2D<f32, WorldPixel>;
-pub type WorldVector3D = Vector3D<f32, WorldPixel>;
-
-/// Offset in number of tiles.
-#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
-pub struct Tiles;
-pub type TileOffset = Point2D<i32, Tiles>;
-pub type TileRange = Rect<i32, Tiles>;
-
-/// Scaling ratio from world pixels to device pixels.
-pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
-/// Scaling ratio from layout to world. Used for cases where we know the layout
-/// is in world space, or specifically want to treat it this way.
-pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
-/// A complete scaling ratio from layout space to device pixel space.
-pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
-
-pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
-pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
-pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
-
-pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
-pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
-
-pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
-pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
-
-pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
-pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
-
-// Fixed position coordinates, to avoid float precision errors.
-pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
-pub type LayoutRectAu = Rect<Au, LayoutPixel>;
-pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
-pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
-pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
-
-pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
-pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
-
-pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
-
-/// Stores two coordinates in texel space. The coordinates
-/// are stored in texel coordinates because the texture atlas
-/// may grow. Storing them as texel coords and normalizing
-/// the UVs in the vertex shader means nothing needs to be
-/// updated on the CPU when the texture size changes.
-#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
-pub struct TexelRect {
- pub uv0: DevicePoint,
- pub uv1: DevicePoint,
-}
-
-impl TexelRect {
- pub fn new(u0: f32, v0: f32, u1: f32, v1: f32) -> Self {
- TexelRect {
- uv0: DevicePoint::new(u0, v0),
- uv1: DevicePoint::new(u1, v1),
- }
- }
-
- pub fn invalid() -> Self {
- TexelRect {
- uv0: DevicePoint::new(-1.0, -1.0),
- uv1: DevicePoint::new(-1.0, -1.0),
- }
- }
-}
-
-impl Into<TexelRect> for DeviceIntRect {
- fn into(self) -> TexelRect {
- TexelRect {
- uv0: self.min().to_f32(),
- uv1: self.max().to_f32(),
- }
- }
-}
-
-const MAX_AU_FLOAT: f32 = 1.0e6;
-
-pub trait AuHelpers<T> {
- fn from_au(data: T) -> Self;
- fn to_au(&self) -> T;
-}
-
-impl AuHelpers<LayoutSizeAu> for LayoutSize {
- fn from_au(size: LayoutSizeAu) -> Self {
- LayoutSize::new(
- size.width.to_f32_px(),
- size.height.to_f32_px(),
- )
- }
-
- fn to_au(&self) -> LayoutSizeAu {
- let width = self.width.min(2.0 * MAX_AU_FLOAT);
- let height = self.height.min(2.0 * MAX_AU_FLOAT);
-
- LayoutSizeAu::new(
- Au::from_f32_px(width),
- Au::from_f32_px(height),
- )
- }
-}
-
-impl AuHelpers<LayoutVector2DAu> for LayoutVector2D {
- fn from_au(size: LayoutVector2DAu) -> Self {
- LayoutVector2D::new(
- size.x.to_f32_px(),
- size.y.to_f32_px(),
- )
- }
-
- fn to_au(&self) -> LayoutVector2DAu {
- LayoutVector2DAu::new(
- Au::from_f32_px(self.x),
- Au::from_f32_px(self.y),
- )
- }
-}
-
-impl AuHelpers<LayoutPointAu> for LayoutPoint {
- fn from_au(point: LayoutPointAu) -> Self {
- LayoutPoint::new(
- point.x.to_f32_px(),
- point.y.to_f32_px(),
- )
- }
-
- fn to_au(&self) -> LayoutPointAu {
- let x = self.x.min(MAX_AU_FLOAT).max(-MAX_AU_FLOAT);
- let y = self.y.min(MAX_AU_FLOAT).max(-MAX_AU_FLOAT);
-
- LayoutPointAu::new(
- Au::from_f32_px(x),
- Au::from_f32_px(y),
- )
- }
-}
-
-impl AuHelpers<LayoutRectAu> for LayoutRect {
- fn from_au(rect: LayoutRectAu) -> Self {
- LayoutRect::new(
- LayoutPoint::from_au(rect.origin),
- LayoutSize::from_au(rect.size),
- )
- }
-
- fn to_au(&self) -> LayoutRectAu {
- LayoutRectAu::new(
- self.origin.to_au(),
- self.size.to_au(),
- )
- }
-}
-
-impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets {
- fn from_au(offsets: LayoutSideOffsetsAu) -> Self {
- LayoutSideOffsets::new(
- offsets.top.to_f32_px(),
- offsets.right.to_f32_px(),
- offsets.bottom.to_f32_px(),
- offsets.left.to_f32_px(),
- )
- }
-
- fn to_au(&self) -> LayoutSideOffsetsAu {
- LayoutSideOffsetsAu::new(
- Au::from_f32_px(self.top),
- Au::from_f32_px(self.right),
- Au::from_f32_px(self.bottom),
- Au::from_f32_px(self.left),
- )
- }
-}
-
-pub trait RectExt {
- type Point;
- fn top_left(&self) -> Self::Point;
- fn top_right(&self) -> Self::Point;
- fn bottom_left(&self) -> Self::Point;
- fn bottom_right(&self) -> Self::Point;
-}
-
-impl<U> RectExt for Rect<f32, U> {
- type Point = Point2D<f32, U>;
- fn top_left(&self) -> Self::Point {
- self.min()
- }
- fn top_right(&self) -> Self::Point {
- Point2D::new(self.max_x(), self.min_y())
- }
- fn bottom_left(&self) -> Self::Point {
- Point2D::new(self.min_x(), self.max_y())
- }
- fn bottom_right(&self) -> Self::Point {
- self.max()
- }
-}
-
-// A few helpers to convert to cast between coordinate spaces that are often equivalent.
-
-#[inline]
-pub fn layout_rect_as_picture_rect(layout_rect: &LayoutRect) -> PictureRect {
- layout_rect.cast_unit()
-}
-
-#[inline]
-pub fn layout_vector_as_picture_vector(layout_vector: LayoutVector2D) -> PictureVector2D {
- layout_vector.cast_unit()
-}
-
-#[inline]
-pub fn device_size_as_framebuffer_size(framebuffer_size: DeviceIntSize) -> FramebufferIntSize {
- framebuffer_size.cast_unit()
-}
-
-#[inline]
-pub fn device_rect_as_framebuffer_rect(framebuffer_rect: &DeviceIntRect) -> FramebufferIntRect {
- framebuffer_rect.cast_unit()
-}