diff --git a/crates/gpui3/src/geometry.rs b/crates/gpui3/src/geometry.rs index 93d7dd2a0804604e7bbe5886c22df1d91a2619f5..0580160f07fbaa72f7d2d03f7096cd36d9542009 100644 --- a/crates/gpui3/src/geometry.rs +++ b/crates/gpui3/src/geometry.rs @@ -289,6 +289,12 @@ impl + Sub> Bound let lower_right = self.lower_right().min(&other.lower_right()); Self::from_corners(upper_left, lower_right) } + + pub fn union(&self, other: &Self) -> Self { + let top_left = self.origin.min(&other.origin); + let bottom_right = self.lower_right().max(&other.lower_right()); + Bounds::from_corners(top_left, bottom_right) + } } impl Mul for Bounds diff --git a/crates/gpui3/src/scene.rs b/crates/gpui3/src/scene.rs index 8cabda9f9f0a8c2743085a27edacfd1d878a012a..9ddb69ccae659b630136fcd4dba402f216a715d6 100644 --- a/crates/gpui3/src/scene.rs +++ b/crates/gpui3/src/scene.rs @@ -1,11 +1,16 @@ use crate::{ - AtlasTextureId, AtlasTile, Bounds, Corners, Edges, Hsla, Point, ScaledContentMask, ScaledPixels, + point, px, AtlasTextureId, AtlasTile, Bounds, Corners, Edges, Hsla, Pixels, Point, + ScaledContentMask, ScaledPixels, }; use collections::BTreeMap; use etagere::euclid::{Point3D, Vector3D}; use plane_split::{BspSplitter, Polygon as BspPolygon}; use smallvec::SmallVec; -use std::{iter::Peekable, mem, slice}; +use std::{ + iter::Peekable, + mem, slice, + sync::atomic::{AtomicU32, Ordering::SeqCst}, +}; // Exported to metal pub type PointF = Point; @@ -492,6 +497,96 @@ impl From for Primitive { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct PathId(u32); + +pub struct PathBuilder { + bounds: Bounds, + vertices: Vec, + start: Option>, + current: Point, +} + +impl PathBuilder { + pub fn new() -> Self { + const NEXT_PATH_ID: AtomicU32 = AtomicU32::new(0); + + Self { + vertices: Vec::new(), + start: Default::default(), + current: Default::default(), + bounds: Default::default(), + } + } + + pub fn line_to(&mut self, to: Point) { + if let Some(start) = self.start { + self.push_triangle( + (start, self.current, to), + (point(0., 1.), point(0., 1.), point(0., 1.)), + ); + } else { + self.start = Some(to); + } + self.current = to; + } + + pub fn curve_to(&mut self, to: Point, ctrl: Point) { + self.line_to(to); + self.push_triangle( + (self.current, ctrl, to), + (point(0., 0.), point(0.5, 0.), point(1., 1.)), + ); + } + + fn push_triangle( + &mut self, + xy: (Point, Point, Point), + st: (Point, Point, Point), + ) { + if self.vertices.is_empty() { + self.bounds = Bounds { + origin: xy.0, + size: Default::default(), + }; + } + self.bounds = self + .bounds + .union(&Bounds { + origin: xy.0, + size: Default::default(), + }) + .union(&Bounds { + origin: xy.1, + size: Default::default(), + }) + .union(&Bounds { + origin: xy.2, + size: Default::default(), + }); + + self.vertices.push(PathVertex { + xy_position: xy.0, + st_position: st.0, + }); + self.vertices.push(PathVertex { + xy_position: xy.1, + st_position: st.1, + }); + self.vertices.push(PathVertex { + xy_position: xy.2, + st_position: st.2, + }); + } +} + +#[derive(Clone, Debug)] +#[repr(C)] +pub struct PathVertex { + pub xy_position: Point, + pub st_position: Point, +} + #[derive(Copy, Clone, Debug)] pub struct AtlasId(pub(crate) usize);