diff --git a/crates/gpui/src/bounds_tree.rs b/crates/gpui/src/bounds_tree.rs index 77107b413b..b31b677128 100644 --- a/crates/gpui/src/bounds_tree.rs +++ b/crates/gpui/src/bounds_tree.rs @@ -5,31 +5,32 @@ use std::{ ops::{Add, Sub}, }; -#[derive(Debug, Default)] -pub struct BoundsTree { +#[derive(Debug)] +pub struct BoundsTree +where + U: Default + Clone + Debug, + T: Clone + Debug, +{ root: Option, - nodes: Vec>, + nodes: Vec>, stack: Vec, } -impl BoundsTree +impl BoundsTree where U: Clone + Debug + PartialOrd + Add + Sub + Half + Default, + T: Clone + Debug, { - pub fn new() -> Self { - BoundsTree::default() - } - pub fn clear(&mut self) { self.root = None; self.nodes.clear(); self.stack.clear(); } - pub fn insert(&mut self, new_bounds: Bounds) -> u32 { + pub fn insert(&mut self, new_bounds: Bounds, payload: T) -> u32 { // If the tree is empty, make the root the new leaf. if self.root.is_none() { - let new_node = self.push_leaf(new_bounds, 1); + let new_node = self.push_leaf(new_bounds, payload, 1); self.root = Some(new_node); return 1; } @@ -84,7 +85,7 @@ where } let ordering = max_intersecting_ordering + 1; - let new_node = self.push_leaf(new_bounds, ordering); + let new_node = self.push_leaf(new_bounds, payload, ordering); let new_parent = self.push_internal(sibling, new_node); // If there was an old parent, we need to update its children indices. @@ -147,8 +148,12 @@ where max_ordering } - fn push_leaf(&mut self, bounds: Bounds, order: u32) -> usize { - self.nodes.push(Node::Leaf { bounds, order }); + fn push_leaf(&mut self, bounds: Bounds, payload: T, order: u32) -> usize { + self.nodes.push(Node::Leaf { + bounds, + payload, + order, + }); self.nodes.len() - 1 } @@ -167,26 +172,39 @@ where } #[inline(always)] - fn node(&self, index: usize) -> &Node { + fn node(&self, index: usize) -> &Node { &self.nodes[index] } #[inline(always)] - fn node_mut(&mut self, index: usize) -> &mut Node { + fn node_mut(&mut self, index: usize) -> &mut Node { &mut self.nodes[index] } } -#[derive(Default, Debug, Clone, PartialEq)] -pub struct Primitive { - bounds: Bounds, - order: u32, +impl Default for BoundsTree +where + U: Default + Clone + Debug, + T: Clone + Debug, +{ + fn default() -> Self { + BoundsTree { + root: None, + nodes: Vec::new(), + stack: Vec::new(), + } + } } -#[derive(Debug)] -enum Node { +#[derive(Debug, Clone)] +enum Node +where + U: Clone + Default + Debug, + T: Clone + Debug, +{ Leaf { bounds: Bounds, + payload: T, order: u32, }, Internal { @@ -197,9 +215,10 @@ enum Node { }, } -impl Node +impl Node where U: Clone + Default + Debug, + T: Clone + Debug, { fn bounds(&self) -> &Bounds { match self { @@ -217,219 +236,3 @@ where } } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::{Point, Size}; - use rand::{Rng, SeedableRng}; - use std::{fs, path::Path}; - - #[test] - fn test_bounds_insertion_with_two_bounds() { - let mut tree = BoundsTree::new(); - let bounds1 = Bounds { - origin: Point { x: 0.0, y: 0.0 }, - size: Size { - width: 10.0, - height: 10.0, - }, - }; - let bounds2 = Bounds { - origin: Point { x: 5.0, y: 5.0 }, - size: Size { - width: 10.0, - height: 10.0, - }, - }; - - // Insert the first Bounds. - assert_eq!(tree.insert(bounds1), 1); - - // Insert the second Bounds, which overlaps with the first. - assert_eq!(tree.insert(bounds2), 2); - } - - #[test] - fn test_adjacent_bounds() { - let mut tree = BoundsTree::new(); - let bounds1 = Bounds { - origin: Point { x: 0.0, y: 0.0 }, - size: Size { - width: 10.0, - height: 10.0, - }, - }; - let bounds2 = Bounds { - origin: Point { x: 10.0, y: 0.0 }, - size: Size { - width: 10.0, - height: 10.0, - }, - }; - - // Insert the first bounds. - assert_eq!(tree.insert(bounds1), 1); - - // Insert the second bounds, which is adjacent to the first but not overlapping. - assert_eq!(tree.insert(bounds2), 1); - } - - #[test] - fn test_random_iterations() { - let max_bounds = 100; - - let mut actual_intersections: Vec = Vec::new(); - for seed in 1..=1000 { - // let seed = 44; - let debug = false; - if debug { - let svg_path = Path::new("./svg"); - if svg_path.exists() { - fs::remove_dir_all("./svg").unwrap(); - } - fs::create_dir_all("./svg").unwrap(); - } - - dbg!(seed); - - let mut tree = BoundsTree::new(); - let mut rng = rand::rngs::StdRng::seed_from_u64(seed as u64); - let mut expected_quads: Vec> = Vec::new(); - - let mut insert_time = std::time::Duration::ZERO; - - // Insert a random number of random Bounds into the tree. - let num_bounds = rng.gen_range(1..=max_bounds); - for quad_id in 0..num_bounds { - let min_x: f32 = rng.gen_range(-100.0..100.0); - let min_y: f32 = rng.gen_range(-100.0..100.0); - let max_x: f32 = rng.gen_range(min_x..min_x + 50.0); - let max_y: f32 = rng.gen_range(min_y..min_y + 50.0); - let bounds = Bounds { - origin: Point { x: min_x, y: min_y }, - size: Size { - width: max_x - min_x, - height: max_y - min_y, - }, - }; - - let expected_ordering = expected_quads - .iter() - .filter_map(|quad| { - (quad.bounds.origin.x < bounds.origin.x + bounds.size.width - && quad.bounds.origin.x + quad.bounds.size.width > bounds.origin.x - && quad.bounds.origin.y < bounds.origin.y + bounds.size.height - && quad.bounds.origin.y + quad.bounds.size.height > bounds.origin.y) - .then_some(quad.order) - }) - .max() - .unwrap_or(0) - + 1; - expected_quads.push(Primitive { - bounds, - order: expected_ordering, - }); - if debug { - println!("inserting {} with Bounds: {:?}", quad_id, bounds); - draw_bounds( - format!("./svg/expected_bounds_after_{}.svg", quad_id), - &expected_quads, - ); - } - - // Insert the Bounds into the tree and collect intersections. - actual_intersections.clear(); - let t0 = std::time::Instant::now(); - let actual_ordering = tree.insert(bounds); - insert_time += t0.elapsed(); - assert_eq!(actual_ordering, expected_ordering); - - if debug { - tree.draw(format!("./svg/bounds_tree_after_{}.svg", quad_id)); - } - } - } - } - - fn draw_bounds(svg_path: impl AsRef, bounds: &[Primitive]) { - let mut svg_content = String::from( - r#""#, - ); - - for quad in bounds { - svg_content.push_str(&format!( - r#""#, - quad.bounds.origin.x, - quad.bounds.origin.y, - quad.bounds.size.width, - quad.bounds.size.height - )); - svg_content.push_str(&format!( - r#""#, - quad.bounds.origin.x + quad.bounds.size.width / 2.0, - quad.bounds.origin.y + quad.bounds.size.height / 2.0, - )); - } - - svg_content.push_str(""); - fs::write(svg_path, &svg_content).unwrap(); - } - - impl BoundsTree { - fn draw(&self, svg_path: impl AsRef) { - let root_bounds = self.node(self.root.unwrap()).bounds(); - - let mut svg_content = format!( - r#""#, - root_bounds.origin.x, - root_bounds.origin.y, - root_bounds.size.width, - root_bounds.size.height - ); - - fn draw_node(svg_content: &mut String, nodes: &[Node], index: usize) { - match &nodes[index] { - Node::Internal { - bounds, - left, - right, - .. - } => { - svg_content.push_str(&format!( - r#""#, - bounds.origin.x, - bounds.origin.y, - bounds.size.width, - bounds.size.height, - (index * 50) % 255, // Red component - (index * 120) % 255, // Green component - (index * 180) % 255, // Blue component - (index * 50) % 255, // Red stroke - (index * 120) % 255, // Green stroke - (index * 180) % 255 // Blue stroke - )); - draw_node(svg_content, nodes, *left); - draw_node(svg_content, nodes, *right); - } - Node::Leaf { bounds, .. } => { - svg_content.push_str(&format!( - r#""#, - bounds.origin.x, - bounds.origin.y, - bounds.size.width, - bounds.size.height - )); - } - } - } - - if let Some(root) = self.root { - draw_node(&mut svg_content, &self.nodes, root); - } - - svg_content.push_str(""); - std::fs::write(svg_path, &svg_content).unwrap(); - } - } -} diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index 7584170039..ba60543a58 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -1,8 +1,8 @@ use crate::{ point, AtlasTextureId, AtlasTile, Bounds, BoundsTree, ContentMask, Corners, Edges, EntityId, - Hsla, Pixels, Point, ScaledPixels, + Hsla, Pixels, Point, ScaledPixels, SharedString, }; -use collections::FxHashSet; +use collections::{FxHashMap, FxHashSet, HashMap}; use std::{fmt::Debug, iter::Peekable, slice}; #[allow(non_camel_case_types, unused)] @@ -37,14 +37,14 @@ impl From for EntityId { #[derive(Default)] pub(crate) struct Scene { - pub(crate) shadows: Vec, - pub(crate) quads: Vec, - pub(crate) paths: Vec>, - pub(crate) underlines: Vec, - pub(crate) monochrome_sprites: Vec, - pub(crate) polychrome_sprites: Vec, + pub(crate) shadows: PrimitiveSet, + pub(crate) quads: PrimitiveSet, + pub(crate) paths: PrimitiveSet>, + pub(crate) underlines: PrimitiveSet, + pub(crate) monochrome_sprites: PrimitiveSet, + pub(crate) polychrome_sprites: PrimitiveSet, pub(crate) surfaces: Vec, - bounds_tree: BoundsTree, + bounds_tree: BoundsTree, } impl Scene { @@ -60,79 +60,217 @@ impl Scene { } pub fn paths(&self) -> &[Path] { - &self.paths + &self.paths.primitives } pub(crate) fn batches(&self) -> impl Iterator { BatchIterator { - shadows: &self.shadows, + shadows: &self.shadows.primitives, shadows_start: 0, - shadows_iter: self.shadows.iter().peekable(), - quads: &self.quads, + shadows_iter: self.shadows.primitives.iter().peekable(), + quads: &self.quads.primitives, quads_start: 0, - quads_iter: self.quads.iter().peekable(), - paths: &self.paths, + quads_iter: self.quads.primitives.iter().peekable(), + paths: &self.paths.primitives, paths_start: 0, - paths_iter: self.paths.iter().peekable(), - underlines: &self.underlines, + paths_iter: self.paths.primitives.iter().peekable(), + underlines: &self.underlines.primitives, underlines_start: 0, - underlines_iter: self.underlines.iter().peekable(), - monochrome_sprites: &self.monochrome_sprites, + underlines_iter: self.underlines.primitives.iter().peekable(), + monochrome_sprites: &self.monochrome_sprites.primitives, monochrome_sprites_start: 0, - monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(), - polychrome_sprites: &self.polychrome_sprites, + monochrome_sprites_iter: self.monochrome_sprites.primitives.iter().peekable(), + polychrome_sprites: &self.polychrome_sprites.primitives, polychrome_sprites_start: 0, - polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(), + polychrome_sprites_iter: self.polychrome_sprites.primitives.iter().peekable(), surfaces: &self.surfaces, surfaces_start: 0, surfaces_iter: self.surfaces.iter().peekable(), } } - pub(crate) fn insert(&mut self, primitive: impl Into) -> Option { - let primitive = primitive.into(); - let clipped_bounds = primitive - .bounds() - .intersect(&primitive.content_mask().bounds); + pub(crate) fn insert_shadow( + &mut self, + shadow: Shadow, + hover: Option, + group_hover: Option<(SharedString, Option)>, + ) -> Option { + let clipped_bounds = shadow.bounds.intersect(&shadow.content_mask.bounds); if clipped_bounds.size.width <= ScaledPixels(0.) || clipped_bounds.size.height <= ScaledPixels(0.) { return None; } - let order = self.bounds_tree.insert(clipped_bounds); - match primitive { - Primitive::Shadow(mut shadow) => { - shadow.order = order; - self.shadows.push(shadow); - } - Primitive::Quad(mut quad) => { - quad.order = order; - self.quads.push(quad); - } - Primitive::Path(mut path) => { - path.order = order; - path.id = PathId(self.paths.len()); - self.paths.push(path); - } - Primitive::Underline(mut underline) => { - underline.order = order; - self.underlines.push(underline); - } - Primitive::MonochromeSprite(mut sprite) => { - sprite.order = order; - self.monochrome_sprites.push(sprite); - } - Primitive::PolychromeSprite(mut sprite) => { - sprite.order = order; - self.polychrome_sprites.push(sprite); - } - Primitive::Surface(mut surface) => { - surface.order = order; - self.surfaces.push(surface); - } + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::Shadow, + index: self.shadows.primitives.len(), + }, + ); + self.shadows + .insert(Shadow { order, ..shadow }, hover, group_hover); + Some(order) + } + + pub(crate) fn insert_quad( + &mut self, + quad: Quad, + hover: Option, + group_hover: Option<(SharedString, Option)>, + ) -> Option { + let clipped_bounds = quad.bounds.intersect(&quad.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; } + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::Quad, + index: self.quads.primitives.len(), + }, + ); + self.quads + .insert(Quad { order, ..quad }, hover, group_hover); + Some(order) + } + + pub(crate) fn insert_path( + &mut self, + path: Path, + hover: Option>, + group_hover: Option<(SharedString, Option>)>, + ) -> Option { + let clipped_bounds = path.bounds.intersect(&path.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; + } + + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::Path, + index: self.paths.primitives.len(), + }, + ); + self.paths + .insert(Path { order, ..path }, hover, group_hover); + Some(order) + } + + pub(crate) fn insert_underline( + &mut self, + underline: Underline, + hover: Option, + group_hover: Option<(SharedString, Option)>, + ) -> Option { + let clipped_bounds = underline.bounds.intersect(&underline.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; + } + + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::Underline, + index: self.underlines.primitives.len(), + }, + ); + self.underlines + .insert(Underline { order, ..underline }, hover, group_hover); + Some(order) + } + + pub(crate) fn insert_monochrome_sprite( + &mut self, + monochrome_sprite: MonochromeSprite, + hover: Option, + group_hover: Option<(SharedString, Option)>, + ) -> Option { + let clipped_bounds = monochrome_sprite + .bounds + .intersect(&monochrome_sprite.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; + } + + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::MonochromeSprite, + index: self.monochrome_sprites.primitives.len(), + }, + ); + self.monochrome_sprites.insert( + MonochromeSprite { + order, + ..monochrome_sprite + }, + hover, + group_hover, + ); + Some(order) + } + + pub(crate) fn insert_polychrome_sprite( + &mut self, + polychrome_sprite: PolychromeSprite, + hover: Option, + group_hover: Option<(SharedString, Option)>, + ) -> Option { + let clipped_bounds = polychrome_sprite + .bounds + .intersect(&polychrome_sprite.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; + } + + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::PolychromeSprite, + index: self.polychrome_sprites.primitives.len(), + }, + ); + self.polychrome_sprites.insert( + PolychromeSprite { + order, + ..polychrome_sprite + }, + hover, + group_hover, + ); + Some(order) + } + + pub(crate) fn insert_surface(&mut self, surface: Surface) -> Option { + let clipped_bounds = surface.bounds.intersect(&surface.content_mask.bounds); + if clipped_bounds.size.width <= ScaledPixels(0.) + || clipped_bounds.size.height <= ScaledPixels(0.) + { + return None; + } + + let order = self.bounds_tree.insert( + clipped_bounds, + PrimitiveIndex { + kind: PrimitiveKind::Surface, + index: self.surfaces.len(), + }, + ); + self.surfaces.push(Surface { order, ..surface }); Some(order) } @@ -189,19 +327,101 @@ impl Scene { } pub fn finish(&mut self) { - self.shadows.sort_unstable_by_key(|shadow| shadow.order); - self.quads.sort_unstable_by_key(|quad| quad.order); - self.paths.sort_unstable_by_key(|path| path.order); + self.shadows + .primitives + .sort_unstable_by_key(|shadow| shadow.order); + self.quads + .primitives + .sort_unstable_by_key(|quad| quad.order); + self.paths + .primitives + .sort_unstable_by_key(|path| path.order); self.underlines + .primitives .sort_unstable_by_key(|underline| underline.order); self.monochrome_sprites + .primitives .sort_unstable_by_key(|sprite| sprite.order); self.polychrome_sprites + .primitives .sort_unstable_by_key(|sprite| sprite.order); self.surfaces.sort_unstable_by_key(|surface| surface.order); } } +pub(crate) struct PrimitiveSet

{ + pub(crate) primitives: Vec

, + hovers: FxHashMap>, +} + +impl

PrimitiveSet

{ + /// Returns the number of primitives in the set. + pub(crate) fn len(&self) -> usize { + self.primitives.len() + } + + /// Inserts a primitive into the set and associates hover and group hover information with it. + /// + /// # Arguments + /// + /// * `primitive` - The primitive to insert. + /// * `hover` - An optional hover state for the primitive. + /// * `group_hover` - An optional group hover state for the primitive, with an associated shared string. + /// + /// # Examples + /// + /// ``` + /// # use zed::SharedString; + /// let mut primitive_set = PrimitiveSet::default(); + /// let primitive = Quad::default(); + /// let hover = Some(Quad::default()); + /// let group_hover = Some((SharedString::from("group"), Some(Quad::default()))); + /// + /// primitive_set.insert(primitive, hover, group_hover); + /// ``` + fn insert( + &mut self, + primitive: P, + hover: Option

, + group_hover: Option<(SharedString, Option

)>, + ) { + let index = self.primitives.len(); + self.primitives.push(primitive); + if hover.is_some() || group_hover.is_some() { + self.hovers + .insert(index, PrimitiveHover { hover, group_hover }); + } + } + + /// Clears all primitives and associated hover information from the set. + /// + /// # Examples + /// + /// ``` + /// # let mut primitive_set = PrimitiveSet::default(); + /// primitive_set.clear(); + /// assert!(primitive_set.len() == 0); + /// ``` + fn clear(&mut self) { + self.primitives.clear(); + self.hovers.clear(); + } +} + +impl

Default for PrimitiveSet

{ + fn default() -> Self { + Self { + primitives: Vec::new(), + hovers: HashMap::default(), + } + } +} + +struct PrimitiveHover

{ + hover: Option

, + group_hover: Option<(SharedString, Option

)>, +} + struct BatchIterator<'a> { shadows: &'a [Shadow], shadows_start: usize, @@ -399,40 +619,10 @@ pub(crate) enum PrimitiveKind { Surface, } -pub(crate) enum Primitive { - Shadow(Shadow), - Quad(Quad), - Path(Path), - Underline(Underline), - MonochromeSprite(MonochromeSprite), - PolychromeSprite(PolychromeSprite), - Surface(Surface), -} - -impl Primitive { - pub fn bounds(&self) -> &Bounds { - match self { - Primitive::Shadow(shadow) => &shadow.bounds, - Primitive::Quad(quad) => &quad.bounds, - Primitive::Path(path) => &path.bounds, - Primitive::Underline(underline) => &underline.bounds, - Primitive::MonochromeSprite(sprite) => &sprite.bounds, - Primitive::PolychromeSprite(sprite) => &sprite.bounds, - Primitive::Surface(surface) => &surface.bounds, - } - } - - pub fn content_mask(&self) -> &ContentMask { - match self { - Primitive::Shadow(shadow) => &shadow.content_mask, - Primitive::Quad(quad) => &quad.content_mask, - Primitive::Path(path) => &path.content_mask, - Primitive::Underline(underline) => &underline.content_mask, - Primitive::MonochromeSprite(sprite) => &sprite.content_mask, - Primitive::PolychromeSprite(sprite) => &sprite.content_mask, - Primitive::Surface(surface) => &surface.content_mask, - } - } +#[derive(Clone, Debug)] +struct PrimitiveIndex { + kind: PrimitiveKind, + index: usize, } #[derive(Debug)] @@ -478,12 +668,6 @@ impl PartialOrd for Quad { } } -impl From for Primitive { - fn from(quad: Quad) -> Self { - Primitive::Quad(quad) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] #[repr(C)] pub(crate) struct Underline { @@ -509,12 +693,6 @@ impl PartialOrd for Underline { } } -impl From for Primitive { - fn from(underline: Underline) -> Self { - Primitive::Underline(underline) - } -} - #[derive(Debug, Clone, Eq, PartialEq)] #[repr(C)] pub(crate) struct Shadow { @@ -541,12 +719,6 @@ impl PartialOrd for Shadow { } } -impl From for Primitive { - fn from(shadow: Shadow) -> Self { - Primitive::Shadow(shadow) - } -} - #[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] pub(crate) struct MonochromeSprite { @@ -574,12 +746,6 @@ impl PartialOrd for MonochromeSprite { } } -impl From for Primitive { - fn from(sprite: MonochromeSprite) -> Self { - Primitive::MonochromeSprite(sprite) - } -} - #[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] pub(crate) struct PolychromeSprite { @@ -609,12 +775,6 @@ impl PartialOrd for PolychromeSprite { } } -impl From for Primitive { - fn from(sprite: PolychromeSprite) -> Self { - Primitive::PolychromeSprite(sprite) - } -} - #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct Surface { pub view_id: ViewId, @@ -638,12 +798,6 @@ impl PartialOrd for Surface { } } -impl From for Primitive { - fn from(surface: Surface) -> Self { - Primitive::Surface(surface) - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) struct PathId(pub(crate) usize); @@ -792,12 +946,6 @@ impl PartialOrd for Path { } } -impl From> for Primitive { - fn from(path: Path) -> Self { - Primitive::Path(path) - } -} - #[derive(Clone, Debug)] #[repr(C)] pub(crate) struct PathVertex { diff --git a/crates/gpui/src/window/element_cx.rs b/crates/gpui/src/window/element_cx.rs index fcf3e60708..629307750e 100644 --- a/crates/gpui/src/window/element_cx.rs +++ b/crates/gpui/src/window/element_cx.rs @@ -666,17 +666,21 @@ impl<'a> ElementContext<'a> { let mut shadow_bounds = bounds; shadow_bounds.origin += shadow.offset; shadow_bounds.dilate(shadow.spread_radius); - window.next_frame.scene.insert(Shadow { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds: shadow_bounds.scale(scale_factor), - content_mask: content_mask.scale(scale_factor), - corner_radii: corner_radii.scale(scale_factor), - color: shadow.color, - blur_radius: shadow.blur_radius.scale(scale_factor), - pad: 0, - }); + window.next_frame.scene.insert_shadow( + Shadow { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds: shadow_bounds.scale(scale_factor), + content_mask: content_mask.scale(scale_factor), + corner_radii: corner_radii.scale(scale_factor), + color: shadow.color, + blur_radius: shadow.blur_radius.scale(scale_factor), + pad: 0, + }, + None, + None, + ); } } @@ -689,17 +693,21 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(Quad { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds: quad.bounds.scale(scale_factor), - content_mask: content_mask.scale(scale_factor), - background: quad.background, - border_color: quad.border_color, - corner_radii: quad.corner_radii.scale(scale_factor), - border_widths: quad.border_widths.scale(scale_factor), - }); + window.next_frame.scene.insert_quad( + Quad { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds: quad.bounds.scale(scale_factor), + content_mask: content_mask.scale(scale_factor), + background: quad.background, + border_color: quad.border_color, + corner_radii: quad.corner_radii.scale(scale_factor), + border_widths: quad.border_widths.scale(scale_factor), + }, + None, + None, + ); } /// Paint the given `Path` into the scene for the next frame at the current z-index. @@ -712,7 +720,10 @@ impl<'a> ElementContext<'a> { path.color = color.into(); path.view_id = view_id.into(); let window = &mut *self.window; - window.next_frame.scene.insert(path.scale(scale_factor)); + window + .next_frame + .scene + .insert_path(path.scale(scale_factor), None, None); } /// Paint an underline into the scene for the next frame at the current z-index. @@ -736,16 +747,20 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(Underline { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds: bounds.scale(scale_factor), - content_mask: content_mask.scale(scale_factor), - color: style.color.unwrap_or_default(), - thickness: style.thickness.scale(scale_factor), - wavy: style.wavy, - }); + window.next_frame.scene.insert_underline( + Underline { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds: bounds.scale(scale_factor), + content_mask: content_mask.scale(scale_factor), + color: style.color.unwrap_or_default(), + thickness: style.thickness.scale(scale_factor), + wavy: style.wavy, + }, + None, + None, + ); } /// Paint a strikethrough into the scene for the next frame at the current z-index. @@ -765,16 +780,20 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(Underline { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds: bounds.scale(scale_factor), - content_mask: content_mask.scale(scale_factor), - thickness: style.thickness.scale(scale_factor), - color: style.color.unwrap_or_default(), - wavy: false, - }); + window.next_frame.scene.insert_underline( + Underline { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds: bounds.scale(scale_factor), + content_mask: content_mask.scale(scale_factor), + thickness: style.thickness.scale(scale_factor), + color: style.color.unwrap_or_default(), + wavy: false, + }, + None, + None, + ); } /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index. @@ -822,15 +841,19 @@ impl<'a> ElementContext<'a> { let content_mask = self.content_mask().scale(scale_factor); let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(MonochromeSprite { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds, - content_mask, - color, - tile, - }); + window.next_frame.scene.insert_monochrome_sprite( + MonochromeSprite { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds, + content_mask, + color, + tile, + }, + None, + None, + ); } Ok(()) } @@ -877,17 +900,21 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(PolychromeSprite { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds, - corner_radii: Default::default(), - content_mask, - tile, - grayscale: false, - pad: 0, - }); + window.next_frame.scene.insert_polychrome_sprite( + PolychromeSprite { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds, + corner_radii: Default::default(), + content_mask, + tile, + grayscale: false, + pad: 0, + }, + None, + None, + ); } Ok(()) } @@ -920,15 +947,19 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(MonochromeSprite { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds, - content_mask, - color, - tile, - }); + window.next_frame.scene.insert_monochrome_sprite( + MonochromeSprite { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds, + content_mask, + color, + tile, + }, + None, + None, + ); Ok(()) } @@ -956,17 +987,21 @@ impl<'a> ElementContext<'a> { let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(PolychromeSprite { - view_id: view_id.into(), - layer_id: 0, - order: 0, - bounds, - content_mask, - corner_radii, - tile, - grayscale, - pad: 0, - }); + window.next_frame.scene.insert_polychrome_sprite( + PolychromeSprite { + view_id: view_id.into(), + layer_id: 0, + order: 0, + bounds, + content_mask, + corner_radii, + tile, + grayscale, + pad: 0, + }, + None, + None, + ); Ok(()) } @@ -978,7 +1013,7 @@ impl<'a> ElementContext<'a> { let content_mask = self.content_mask().scale(scale_factor); let view_id = self.parent_view_id(); let window = &mut *self.window; - window.next_frame.scene.insert(crate::Surface { + window.next_frame.scene.insert_surface(crate::Surface { view_id: view_id.into(), layer_id: 0, order: 0,