scene.rs

  1use std::cmp;
  2
  3use super::{Bounds, Hsla, Pixels, Point};
  4use crate::{Corners, Edges, FontId, GlyphId};
  5use bytemuck::{Pod, Zeroable};
  6use plane_split::BspSplitter;
  7
  8// Exported to metal
  9pub type PointF = Point<f32>;
 10
 11pub struct Scene {
 12    opaque_primitives: PrimitiveBatch,
 13    transparent_primitives: slotmap::SlotMap<slotmap::DefaultKey, Primitive>,
 14    splitter: BspSplitter<slotmap::DefaultKey>,
 15    max_order: u32,
 16}
 17
 18impl Scene {
 19    pub fn new() -> Scene {
 20        Scene {
 21            opaque_primitives: PrimitiveBatch::default(),
 22            transparent_primitives: slotmap::SlotMap::new(),
 23            splitter: BspSplitter::new(),
 24            max_order: 0,
 25        }
 26    }
 27
 28    pub fn insert(&mut self, primitive: impl Into<Primitive>) {
 29        let primitive = primitive.into();
 30        self.max_order = cmp::max(self.max_order, primitive.order());
 31        match primitive {
 32            Primitive::Quad(quad) => self.opaque_primitives.quads.push(quad),
 33            Primitive::Glyph(glyph) => self.opaque_primitives.glyphs.push(glyph),
 34            Primitive::Underline(underline) => self.opaque_primitives.underlines.push(underline),
 35        }
 36    }
 37
 38    pub fn opaque_primitives(&self) -> &PrimitiveBatch {
 39        &self.opaque_primitives
 40    }
 41
 42    pub fn max_order(&self) -> u32 {
 43        self.max_order
 44    }
 45}
 46
 47#[derive(Clone, Debug)]
 48pub enum Primitive {
 49    Quad(Quad),
 50    Glyph(RenderedGlyph),
 51    Underline(Underline),
 52}
 53
 54impl Primitive {
 55    pub fn order(&self) -> u32 {
 56        match self {
 57            Primitive::Quad(quad) => quad.order,
 58            Primitive::Glyph(glyph) => glyph.order,
 59            Primitive::Underline(underline) => underline.order,
 60        }
 61    }
 62
 63    pub fn is_transparent(&self) -> bool {
 64        match self {
 65            Primitive::Quad(quad) => {
 66                quad.background.is_transparent() && quad.border_color.is_transparent()
 67            }
 68            Primitive::Glyph(glyph) => glyph.color.is_transparent(),
 69            Primitive::Underline(underline) => underline.color.is_transparent(),
 70        }
 71    }
 72}
 73
 74#[derive(Default)]
 75pub struct PrimitiveBatch {
 76    pub quads: Vec<Quad>,
 77    pub glyphs: Vec<RenderedGlyph>,
 78    pub underlines: Vec<Underline>,
 79}
 80
 81#[derive(Debug, Clone, Copy, Zeroable, Pod)]
 82#[repr(C)]
 83pub struct Quad {
 84    pub order: u32,
 85    pub bounds: Bounds<Pixels>,
 86    pub clip_bounds: Bounds<Pixels>,
 87    pub clip_corner_radii: Corners<Pixels>,
 88    pub background: Hsla,
 89    pub border_color: Hsla,
 90    pub corner_radii: Corners<Pixels>,
 91    pub border_widths: Edges<Pixels>,
 92}
 93
 94impl Quad {
 95    pub fn vertices(&self) -> impl Iterator<Item = Point<Pixels>> {
 96        let x1 = self.bounds.origin.x;
 97        let y1 = self.bounds.origin.y;
 98        let x2 = x1 + self.bounds.size.width;
 99        let y2 = y1 + self.bounds.size.height;
100        [
101            Point::new(x1, y1),
102            Point::new(x2, y1),
103            Point::new(x2, y2),
104            Point::new(x1, y2),
105        ]
106        .into_iter()
107    }
108}
109
110impl From<Quad> for Primitive {
111    fn from(quad: Quad) -> Self {
112        Primitive::Quad(quad)
113    }
114}
115
116#[derive(Debug, Clone, Copy)]
117#[repr(C)]
118pub struct RenderedGlyph {
119    pub order: u32,
120    pub font_id: FontId,
121    pub font_size: f32,
122    pub id: GlyphId,
123    pub origin: Point<Pixels>,
124    pub color: Hsla,
125}
126
127impl From<RenderedGlyph> for Primitive {
128    fn from(glyph: RenderedGlyph) -> Self {
129        Primitive::Glyph(glyph)
130    }
131}
132
133#[derive(Copy, Clone, Default, Debug, Zeroable, Pod)]
134#[repr(C)]
135pub struct Underline {
136    pub order: u32,
137    pub origin: Point<Pixels>,
138    pub width: Pixels,
139    pub thickness: Pixels,
140    pub color: Hsla,
141    pub style: LineStyle,
142}
143
144#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)]
145#[repr(C)]
146pub enum LineStyle {
147    #[default]
148    Solid = 0,
149    Squiggly = 1,
150}
151
152unsafe impl Zeroable for LineStyle {}
153unsafe impl Pod for LineStyle {}
154
155impl From<Underline> for Primitive {
156    fn from(underline: Underline) -> Self {
157        Primitive::Underline(underline)
158    }
159}