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 scale_factor: f32,
17}
18
19impl Scene {
20 pub fn new(scale_factor: f32) -> Scene {
21 Scene {
22 opaque_primitives: PrimitiveBatch::default(),
23 transparent_primitives: slotmap::SlotMap::new(),
24 splitter: BspSplitter::new(),
25 max_order: 0,
26 scale_factor,
27 }
28 }
29
30 pub fn insert(&mut self, primitive: impl Into<Primitive>) {
31 let mut primitive = primitive.into();
32 primitive.scale(self.scale_factor);
33 self.max_order = cmp::max(self.max_order, primitive.order());
34 match primitive {
35 Primitive::Quad(quad) => self.opaque_primitives.quads.push(quad),
36 }
37 }
38
39 pub fn opaque_primitives(&self) -> &PrimitiveBatch {
40 &self.opaque_primitives
41 }
42
43 pub fn max_order(&self) -> u32 {
44 self.max_order
45 }
46}
47
48#[derive(Clone, Debug)]
49pub enum Primitive {
50 Quad(Quad),
51}
52
53impl Primitive {
54 pub fn order(&self) -> u32 {
55 match self {
56 Primitive::Quad(quad) => quad.order,
57 }
58 }
59
60 pub fn is_transparent(&self) -> bool {
61 match self {
62 Primitive::Quad(quad) => {
63 quad.background.is_transparent() && quad.border_color.is_transparent()
64 }
65 }
66 }
67
68 pub fn scale(&mut self, factor: f32) {
69 match self {
70 Primitive::Quad(quad) => {
71 quad.scale(factor);
72 }
73 }
74 }
75}
76
77#[derive(Default)]
78pub struct PrimitiveBatch {
79 pub quads: Vec<Quad>,
80}
81
82#[derive(Debug, Clone, Copy, Zeroable, Pod)]
83#[repr(C)]
84pub struct Quad {
85 pub order: u32,
86 pub bounds: Bounds<Pixels>,
87 pub clip_bounds: Bounds<Pixels>,
88 pub clip_corner_radii: Corners<Pixels>,
89 pub background: Hsla,
90 pub border_color: Hsla,
91 pub corner_radii: Corners<Pixels>,
92 pub border_widths: Edges<Pixels>,
93}
94
95impl Quad {
96 pub fn vertices(&self) -> impl Iterator<Item = Point<Pixels>> {
97 let x1 = self.bounds.origin.x;
98 let y1 = self.bounds.origin.y;
99 let x2 = x1 + self.bounds.size.width;
100 let y2 = y1 + self.bounds.size.height;
101 [
102 Point::new(x1, y1),
103 Point::new(x2, y1),
104 Point::new(x2, y2),
105 Point::new(x1, y2),
106 ]
107 .into_iter()
108 }
109}
110
111impl Quad {
112 pub fn scale(&mut self, factor: f32) {
113 self.bounds.origin *= factor;
114 self.bounds.size *= factor;
115 self.clip_bounds.origin *= factor;
116 self.clip_corner_radii *= factor;
117 self.corner_radii *= factor;
118 self.border_widths *= factor;
119 }
120}
121
122impl From<Quad> for Primitive {
123 fn from(quad: Quad) -> Self {
124 Primitive::Quad(quad)
125 }
126}