WIP: Replace primitives based on hover

This commit is contained in:
Nathan Sobo
2024-02-24 18:31:31 -07:00
parent 2d6a227258
commit 2db6ccd803
3 changed files with 445 additions and 459 deletions

View File

@@ -5,31 +5,32 @@ use std::{
ops::{Add, Sub},
};
#[derive(Debug, Default)]
pub struct BoundsTree<U: Default + Clone + Debug> {
#[derive(Debug)]
pub struct BoundsTree<U, T>
where
U: Default + Clone + Debug,
T: Clone + Debug,
{
root: Option<usize>,
nodes: Vec<Node<U>>,
nodes: Vec<Node<U, T>>,
stack: Vec<usize>,
}
impl<U> BoundsTree<U>
impl<U, T> BoundsTree<U, T>
where
U: Clone + Debug + PartialOrd + Add<U, Output = U> + Sub<Output = U> + 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<U>) -> u32 {
pub fn insert(&mut self, new_bounds: Bounds<U>, 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<U>, order: u32) -> usize {
self.nodes.push(Node::Leaf { bounds, order });
fn push_leaf(&mut self, bounds: Bounds<U>, 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<U> {
fn node(&self, index: usize) -> &Node<U, T> {
&self.nodes[index]
}
#[inline(always)]
fn node_mut(&mut self, index: usize) -> &mut Node<U> {
fn node_mut(&mut self, index: usize) -> &mut Node<U, T> {
&mut self.nodes[index]
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct Primitive<U: Clone + Default + Debug> {
bounds: Bounds<U>,
order: u32,
impl<U, T> Default for BoundsTree<U, T>
where
U: Default + Clone + Debug,
T: Clone + Debug,
{
fn default() -> Self {
BoundsTree {
root: None,
nodes: Vec::new(),
stack: Vec::new(),
}
}
}
#[derive(Debug)]
enum Node<U: Clone + Default + Debug> {
#[derive(Debug, Clone)]
enum Node<U, T>
where
U: Clone + Default + Debug,
T: Clone + Debug,
{
Leaf {
bounds: Bounds<U>,
payload: T,
order: u32,
},
Internal {
@@ -197,9 +215,10 @@ enum Node<U: Clone + Default + Debug> {
},
}
impl<U> Node<U>
impl<U, T> Node<U, T>
where
U: Clone + Default + Debug,
T: Clone + Debug,
{
fn bounds(&self) -> &Bounds<U> {
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<usize> = 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<Primitive<f32>> = 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<Path>, bounds: &[Primitive<f32>]) {
let mut svg_content = String::from(
r#"<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-100 -100 200 200" style="border:1px solid black;">"#,
);
for quad in bounds {
svg_content.push_str(&format!(
r#"<rect x="{}" y="{}" width="{}" height="{}" style="fill:none;stroke:black;stroke-width:1" />"#,
quad.bounds.origin.x,
quad.bounds.origin.y,
quad.bounds.size.width,
quad.bounds.size.height
));
svg_content.push_str(&format!(
r#"<text x="{}" y="{}" font-size="3" text-anchor="middle" alignment-baseline="central"></text>"#,
quad.bounds.origin.x + quad.bounds.size.width / 2.0,
quad.bounds.origin.y + quad.bounds.size.height / 2.0,
));
}
svg_content.push_str("</svg>");
fs::write(svg_path, &svg_content).unwrap();
}
impl BoundsTree<f32> {
fn draw(&self, svg_path: impl AsRef<std::path::Path>) {
let root_bounds = self.node(self.root.unwrap()).bounds();
let mut svg_content = format!(
r#"<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="border:1px solid black;" viewBox="{} {} {} {}">"#,
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<f32>], index: usize) {
match &nodes[index] {
Node::Internal {
bounds,
left,
right,
..
} => {
svg_content.push_str(&format!(
r#"<rect x="{}" y="{}" width="{}" height="{}" style="fill:rgba({},{},{},0.1);stroke:rgba({},{},{},1);stroke-width:1" />"#,
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#"<rect x="{}" y="{}" width="{}" height="{}" style="fill:none;stroke:black;stroke-width:1" />"#,
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("</svg>");
std::fs::write(svg_path, &svg_content).unwrap();
}
}
}

View File

@@ -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<ViewId> for EntityId {
#[derive(Default)]
pub(crate) struct Scene {
pub(crate) shadows: Vec<Shadow>,
pub(crate) quads: Vec<Quad>,
pub(crate) paths: Vec<Path<ScaledPixels>>,
pub(crate) underlines: Vec<Underline>,
pub(crate) monochrome_sprites: Vec<MonochromeSprite>,
pub(crate) polychrome_sprites: Vec<PolychromeSprite>,
pub(crate) shadows: PrimitiveSet<Shadow>,
pub(crate) quads: PrimitiveSet<Quad>,
pub(crate) paths: PrimitiveSet<Path<ScaledPixels>>,
pub(crate) underlines: PrimitiveSet<Underline>,
pub(crate) monochrome_sprites: PrimitiveSet<MonochromeSprite>,
pub(crate) polychrome_sprites: PrimitiveSet<PolychromeSprite>,
pub(crate) surfaces: Vec<Surface>,
bounds_tree: BoundsTree<ScaledPixels>,
bounds_tree: BoundsTree<ScaledPixels, PrimitiveIndex>,
}
impl Scene {
@@ -60,79 +60,217 @@ impl Scene {
}
pub fn paths(&self) -> &[Path<ScaledPixels>] {
&self.paths
&self.paths.primitives
}
pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
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<Primitive>) -> Option<u32> {
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<Shadow>,
group_hover: Option<(SharedString, Option<Shadow>)>,
) -> Option<u32> {
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<Quad>,
group_hover: Option<(SharedString, Option<Quad>)>,
) -> Option<u32> {
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<ScaledPixels>,
hover: Option<Path<ScaledPixels>>,
group_hover: Option<(SharedString, Option<Path<ScaledPixels>>)>,
) -> Option<u32> {
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<Underline>,
group_hover: Option<(SharedString, Option<Underline>)>,
) -> Option<u32> {
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<MonochromeSprite>,
group_hover: Option<(SharedString, Option<MonochromeSprite>)>,
) -> Option<u32> {
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<PolychromeSprite>,
group_hover: Option<(SharedString, Option<PolychromeSprite>)>,
) -> Option<u32> {
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<u32> {
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<P> {
pub(crate) primitives: Vec<P>,
hovers: FxHashMap<usize, PrimitiveHover<P>>,
}
impl<P> PrimitiveSet<P> {
/// 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<P>,
group_hover: Option<(SharedString, Option<P>)>,
) {
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<P> Default for PrimitiveSet<P> {
fn default() -> Self {
Self {
primitives: Vec::new(),
hovers: HashMap::default(),
}
}
}
struct PrimitiveHover<P> {
hover: Option<P>,
group_hover: Option<(SharedString, Option<P>)>,
}
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<ScaledPixels>),
Underline(Underline),
MonochromeSprite(MonochromeSprite),
PolychromeSprite(PolychromeSprite),
Surface(Surface),
}
impl Primitive {
pub fn bounds(&self) -> &Bounds<ScaledPixels> {
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<ScaledPixels> {
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<Quad> 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<Underline> 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<Shadow> 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<MonochromeSprite> 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<PolychromeSprite> 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<Surface> 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<ScaledPixels> {
}
}
impl From<Path<ScaledPixels>> for Primitive {
fn from(path: Path<ScaledPixels>) -> Self {
Primitive::Path(path)
}
}
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct PathVertex<P: Clone + Default + Debug> {

View File

@@ -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,