1use crate::{
2 point, AtlasTextureId, AtlasTile, Bounds, ContentMask, Corners, Edges, Hsla, Pixels, Point,
3 ScaledPixels, StackingOrder,
4};
5use collections::BTreeMap;
6use std::{fmt::Debug, iter::Peekable, mem, slice};
7
8// Exported to metal
9pub(crate) type PointF = Point<f32>;
10#[allow(non_camel_case_types, unused)]
11pub(crate) type PathVertex_ScaledPixels = PathVertex<ScaledPixels>;
12
13pub type LayerId = u32;
14
15pub type DrawOrder = u32;
16
17pub(crate) struct SceneBuilder {
18 last_order: Option<(StackingOrder, LayerId)>,
19 layers_by_order: BTreeMap<StackingOrder, LayerId>,
20 shadows: Vec<Shadow>,
21 quads: Vec<Quad>,
22 paths: Vec<Path<ScaledPixels>>,
23 underlines: Vec<Underline>,
24 monochrome_sprites: Vec<MonochromeSprite>,
25 polychrome_sprites: Vec<PolychromeSprite>,
26 surfaces: Vec<Surface>,
27}
28
29impl Default for SceneBuilder {
30 fn default() -> Self {
31 SceneBuilder {
32 last_order: None,
33 layers_by_order: BTreeMap::new(),
34 shadows: Vec::new(),
35 quads: Vec::new(),
36 paths: Vec::new(),
37 underlines: Vec::new(),
38 monochrome_sprites: Vec::new(),
39 polychrome_sprites: Vec::new(),
40 surfaces: Vec::new(),
41 }
42 }
43}
44
45impl SceneBuilder {
46 pub fn build(&mut self) -> Scene {
47 let mut orders = vec![0; self.layers_by_order.len()];
48 for (ix, layer_id) in self.layers_by_order.values().enumerate() {
49 orders[*layer_id as usize] = ix as u32;
50 }
51 self.layers_by_order.clear();
52 self.last_order = None;
53
54 for shadow in &mut self.shadows {
55 shadow.order = orders[shadow.order as usize];
56 }
57 self.shadows.sort_by_key(|shadow| shadow.order);
58
59 for quad in &mut self.quads {
60 quad.order = orders[quad.order as usize];
61 }
62 self.quads.sort_by_key(|quad| quad.order);
63
64 for path in &mut self.paths {
65 path.order = orders[path.order as usize];
66 }
67 self.paths.sort_by_key(|path| path.order);
68
69 for underline in &mut self.underlines {
70 underline.order = orders[underline.order as usize];
71 }
72 self.underlines.sort_by_key(|underline| underline.order);
73
74 for monochrome_sprite in &mut self.monochrome_sprites {
75 monochrome_sprite.order = orders[monochrome_sprite.order as usize];
76 }
77 self.monochrome_sprites.sort_by_key(|sprite| sprite.order);
78
79 for polychrome_sprite in &mut self.polychrome_sprites {
80 polychrome_sprite.order = orders[polychrome_sprite.order as usize];
81 }
82 self.polychrome_sprites.sort_by_key(|sprite| sprite.order);
83
84 for surface in &mut self.surfaces {
85 surface.order = orders[surface.order as usize];
86 }
87 self.surfaces.sort_by_key(|surface| surface.order);
88
89 Scene {
90 shadows: mem::take(&mut self.shadows),
91 quads: mem::take(&mut self.quads),
92 paths: mem::take(&mut self.paths),
93 underlines: mem::take(&mut self.underlines),
94 monochrome_sprites: mem::take(&mut self.monochrome_sprites),
95 polychrome_sprites: mem::take(&mut self.polychrome_sprites),
96 surfaces: mem::take(&mut self.surfaces),
97 }
98 }
99
100 pub fn insert(&mut self, order: &StackingOrder, primitive: impl Into<Primitive>) {
101 let primitive = primitive.into();
102 let clipped_bounds = primitive
103 .bounds()
104 .intersect(&primitive.content_mask().bounds);
105 if clipped_bounds.size.width <= ScaledPixels(0.)
106 || clipped_bounds.size.height <= ScaledPixels(0.)
107 {
108 return;
109 }
110
111 let layer_id = self.layer_id_for_order(order);
112 match primitive {
113 Primitive::Shadow(mut shadow) => {
114 shadow.order = layer_id;
115 self.shadows.push(shadow);
116 }
117 Primitive::Quad(mut quad) => {
118 quad.order = layer_id;
119 self.quads.push(quad);
120 }
121 Primitive::Path(mut path) => {
122 path.order = layer_id;
123 path.id = PathId(self.paths.len());
124 self.paths.push(path);
125 }
126 Primitive::Underline(mut underline) => {
127 underline.order = layer_id;
128 self.underlines.push(underline);
129 }
130 Primitive::MonochromeSprite(mut sprite) => {
131 sprite.order = layer_id;
132 self.monochrome_sprites.push(sprite);
133 }
134 Primitive::PolychromeSprite(mut sprite) => {
135 sprite.order = layer_id;
136 self.polychrome_sprites.push(sprite);
137 }
138 Primitive::Surface(mut surface) => {
139 surface.order = layer_id;
140 self.surfaces.push(surface);
141 }
142 }
143 }
144
145 fn layer_id_for_order(&mut self, order: &StackingOrder) -> u32 {
146 if let Some((last_order, last_layer_id)) = self.last_order.as_ref() {
147 if last_order == order {
148 return *last_layer_id;
149 }
150 };
151
152 let layer_id = if let Some(layer_id) = self.layers_by_order.get(order) {
153 *layer_id
154 } else {
155 let next_id = self.layers_by_order.len() as LayerId;
156 self.layers_by_order.insert(order.clone(), next_id);
157 next_id
158 };
159 self.last_order = Some((order.clone(), layer_id));
160 layer_id
161 }
162}
163
164pub struct Scene {
165 pub shadows: Vec<Shadow>,
166 pub quads: Vec<Quad>,
167 pub paths: Vec<Path<ScaledPixels>>,
168 pub underlines: Vec<Underline>,
169 pub monochrome_sprites: Vec<MonochromeSprite>,
170 pub polychrome_sprites: Vec<PolychromeSprite>,
171 pub surfaces: Vec<Surface>,
172}
173
174impl Scene {
175 #[allow(dead_code)]
176 pub fn paths(&self) -> &[Path<ScaledPixels>] {
177 &self.paths
178 }
179
180 pub(crate) fn batches(&self) -> impl Iterator<Item = PrimitiveBatch> {
181 BatchIterator {
182 shadows: &self.shadows,
183 shadows_start: 0,
184 shadows_iter: self.shadows.iter().peekable(),
185 quads: &self.quads,
186 quads_start: 0,
187 quads_iter: self.quads.iter().peekable(),
188 paths: &self.paths,
189 paths_start: 0,
190 paths_iter: self.paths.iter().peekable(),
191 underlines: &self.underlines,
192 underlines_start: 0,
193 underlines_iter: self.underlines.iter().peekable(),
194 monochrome_sprites: &self.monochrome_sprites,
195 monochrome_sprites_start: 0,
196 monochrome_sprites_iter: self.monochrome_sprites.iter().peekable(),
197 polychrome_sprites: &self.polychrome_sprites,
198 polychrome_sprites_start: 0,
199 polychrome_sprites_iter: self.polychrome_sprites.iter().peekable(),
200 surfaces: &self.surfaces,
201 surfaces_start: 0,
202 surfaces_iter: self.surfaces.iter().peekable(),
203 }
204 }
205}
206
207struct BatchIterator<'a> {
208 shadows: &'a [Shadow],
209 shadows_start: usize,
210 shadows_iter: Peekable<slice::Iter<'a, Shadow>>,
211 quads: &'a [Quad],
212 quads_start: usize,
213 quads_iter: Peekable<slice::Iter<'a, Quad>>,
214 paths: &'a [Path<ScaledPixels>],
215 paths_start: usize,
216 paths_iter: Peekable<slice::Iter<'a, Path<ScaledPixels>>>,
217 underlines: &'a [Underline],
218 underlines_start: usize,
219 underlines_iter: Peekable<slice::Iter<'a, Underline>>,
220 monochrome_sprites: &'a [MonochromeSprite],
221 monochrome_sprites_start: usize,
222 monochrome_sprites_iter: Peekable<slice::Iter<'a, MonochromeSprite>>,
223 polychrome_sprites: &'a [PolychromeSprite],
224 polychrome_sprites_start: usize,
225 polychrome_sprites_iter: Peekable<slice::Iter<'a, PolychromeSprite>>,
226 surfaces: &'a [Surface],
227 surfaces_start: usize,
228 surfaces_iter: Peekable<slice::Iter<'a, Surface>>,
229}
230
231impl<'a> Iterator for BatchIterator<'a> {
232 type Item = PrimitiveBatch<'a>;
233
234 fn next(&mut self) -> Option<Self::Item> {
235 let mut orders_and_kinds = [
236 (
237 self.shadows_iter.peek().map(|s| s.order),
238 PrimitiveKind::Shadow,
239 ),
240 (self.quads_iter.peek().map(|q| q.order), PrimitiveKind::Quad),
241 (self.paths_iter.peek().map(|q| q.order), PrimitiveKind::Path),
242 (
243 self.underlines_iter.peek().map(|u| u.order),
244 PrimitiveKind::Underline,
245 ),
246 (
247 self.monochrome_sprites_iter.peek().map(|s| s.order),
248 PrimitiveKind::MonochromeSprite,
249 ),
250 (
251 self.polychrome_sprites_iter.peek().map(|s| s.order),
252 PrimitiveKind::PolychromeSprite,
253 ),
254 (
255 self.surfaces_iter.peek().map(|s| s.order),
256 PrimitiveKind::Surface,
257 ),
258 ];
259 orders_and_kinds.sort_by_key(|(order, kind)| (order.unwrap_or(u32::MAX), *kind));
260
261 let first = orders_and_kinds[0];
262 let second = orders_and_kinds[1];
263 let (batch_kind, max_order) = if first.0.is_some() {
264 (first.1, second.0.unwrap_or(u32::MAX))
265 } else {
266 return None;
267 };
268
269 match batch_kind {
270 PrimitiveKind::Shadow => {
271 let shadows_start = self.shadows_start;
272 let mut shadows_end = shadows_start + 1;
273 self.shadows_iter.next();
274 while self
275 .shadows_iter
276 .next_if(|shadow| shadow.order < max_order)
277 .is_some()
278 {
279 shadows_end += 1;
280 }
281 self.shadows_start = shadows_end;
282 Some(PrimitiveBatch::Shadows(
283 &self.shadows[shadows_start..shadows_end],
284 ))
285 }
286 PrimitiveKind::Quad => {
287 let quads_start = self.quads_start;
288 let mut quads_end = quads_start + 1;
289 self.quads_iter.next();
290 while self
291 .quads_iter
292 .next_if(|quad| quad.order < max_order)
293 .is_some()
294 {
295 quads_end += 1;
296 }
297 self.quads_start = quads_end;
298 Some(PrimitiveBatch::Quads(&self.quads[quads_start..quads_end]))
299 }
300 PrimitiveKind::Path => {
301 let paths_start = self.paths_start;
302 let mut paths_end = paths_start + 1;
303 self.paths_iter.next();
304 while self
305 .paths_iter
306 .next_if(|path| path.order < max_order)
307 .is_some()
308 {
309 paths_end += 1;
310 }
311 self.paths_start = paths_end;
312 Some(PrimitiveBatch::Paths(&self.paths[paths_start..paths_end]))
313 }
314 PrimitiveKind::Underline => {
315 let underlines_start = self.underlines_start;
316 let mut underlines_end = underlines_start + 1;
317 self.underlines_iter.next();
318 while self
319 .underlines_iter
320 .next_if(|underline| underline.order < max_order)
321 .is_some()
322 {
323 underlines_end += 1;
324 }
325 self.underlines_start = underlines_end;
326 Some(PrimitiveBatch::Underlines(
327 &self.underlines[underlines_start..underlines_end],
328 ))
329 }
330 PrimitiveKind::MonochromeSprite => {
331 let texture_id = self.monochrome_sprites_iter.peek().unwrap().tile.texture_id;
332 let sprites_start = self.monochrome_sprites_start;
333 let mut sprites_end = sprites_start + 1;
334 self.monochrome_sprites_iter.next();
335 while self
336 .monochrome_sprites_iter
337 .next_if(|sprite| {
338 sprite.order < max_order && sprite.tile.texture_id == texture_id
339 })
340 .is_some()
341 {
342 sprites_end += 1;
343 }
344 self.monochrome_sprites_start = sprites_end;
345 Some(PrimitiveBatch::MonochromeSprites {
346 texture_id,
347 sprites: &self.monochrome_sprites[sprites_start..sprites_end],
348 })
349 }
350 PrimitiveKind::PolychromeSprite => {
351 let texture_id = self.polychrome_sprites_iter.peek().unwrap().tile.texture_id;
352 let sprites_start = self.polychrome_sprites_start;
353 let mut sprites_end = self.polychrome_sprites_start + 1;
354 self.polychrome_sprites_iter.next();
355 while self
356 .polychrome_sprites_iter
357 .next_if(|sprite| {
358 sprite.order < max_order && sprite.tile.texture_id == texture_id
359 })
360 .is_some()
361 {
362 sprites_end += 1;
363 }
364 self.polychrome_sprites_start = sprites_end;
365 Some(PrimitiveBatch::PolychromeSprites {
366 texture_id,
367 sprites: &self.polychrome_sprites[sprites_start..sprites_end],
368 })
369 }
370 PrimitiveKind::Surface => {
371 let surfaces_start = self.surfaces_start;
372 let mut surfaces_end = surfaces_start + 1;
373 self.surfaces_iter.next();
374 while self
375 .surfaces_iter
376 .next_if(|surface| surface.order < max_order)
377 .is_some()
378 {
379 surfaces_end += 1;
380 }
381 self.surfaces_start = surfaces_end;
382 Some(PrimitiveBatch::Surfaces(
383 &self.surfaces[surfaces_start..surfaces_end],
384 ))
385 }
386 }
387 }
388}
389
390#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
391pub enum PrimitiveKind {
392 Shadow,
393 #[default]
394 Quad,
395 Path,
396 Underline,
397 MonochromeSprite,
398 PolychromeSprite,
399 Surface,
400}
401
402pub enum Primitive {
403 Shadow(Shadow),
404 Quad(Quad),
405 Path(Path<ScaledPixels>),
406 Underline(Underline),
407 MonochromeSprite(MonochromeSprite),
408 PolychromeSprite(PolychromeSprite),
409 Surface(Surface),
410}
411
412impl Primitive {
413 pub fn bounds(&self) -> &Bounds<ScaledPixels> {
414 match self {
415 Primitive::Shadow(shadow) => &shadow.bounds,
416 Primitive::Quad(quad) => &quad.bounds,
417 Primitive::Path(path) => &path.bounds,
418 Primitive::Underline(underline) => &underline.bounds,
419 Primitive::MonochromeSprite(sprite) => &sprite.bounds,
420 Primitive::PolychromeSprite(sprite) => &sprite.bounds,
421 Primitive::Surface(surface) => &surface.bounds,
422 }
423 }
424
425 pub fn content_mask(&self) -> &ContentMask<ScaledPixels> {
426 match self {
427 Primitive::Shadow(shadow) => &shadow.content_mask,
428 Primitive::Quad(quad) => &quad.content_mask,
429 Primitive::Path(path) => &path.content_mask,
430 Primitive::Underline(underline) => &underline.content_mask,
431 Primitive::MonochromeSprite(sprite) => &sprite.content_mask,
432 Primitive::PolychromeSprite(sprite) => &sprite.content_mask,
433 Primitive::Surface(surface) => &surface.content_mask,
434 }
435 }
436}
437
438#[derive(Debug)]
439pub(crate) enum PrimitiveBatch<'a> {
440 Shadows(&'a [Shadow]),
441 Quads(&'a [Quad]),
442 Paths(&'a [Path<ScaledPixels>]),
443 Underlines(&'a [Underline]),
444 MonochromeSprites {
445 texture_id: AtlasTextureId,
446 sprites: &'a [MonochromeSprite],
447 },
448 PolychromeSprites {
449 texture_id: AtlasTextureId,
450 sprites: &'a [PolychromeSprite],
451 },
452 Surfaces(&'a [Surface]),
453}
454
455#[derive(Default, Debug, Clone, Eq, PartialEq)]
456#[repr(C)]
457pub struct Quad {
458 pub order: u32, // Initially a LayerId, then a DrawOrder.
459 pub bounds: Bounds<ScaledPixels>,
460 pub content_mask: ContentMask<ScaledPixels>,
461 pub background: Hsla,
462 pub border_color: Hsla,
463 pub corner_radii: Corners<ScaledPixels>,
464 pub border_widths: Edges<ScaledPixels>,
465}
466
467impl Ord for Quad {
468 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
469 self.order.cmp(&other.order)
470 }
471}
472
473impl PartialOrd for Quad {
474 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
475 Some(self.cmp(other))
476 }
477}
478
479impl From<Quad> for Primitive {
480 fn from(quad: Quad) -> Self {
481 Primitive::Quad(quad)
482 }
483}
484
485#[derive(Debug, Clone, Eq, PartialEq)]
486#[repr(C)]
487pub struct Underline {
488 pub order: u32,
489 pub bounds: Bounds<ScaledPixels>,
490 pub content_mask: ContentMask<ScaledPixels>,
491 pub thickness: ScaledPixels,
492 pub color: Hsla,
493 pub wavy: bool,
494}
495
496impl Ord for Underline {
497 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
498 self.order.cmp(&other.order)
499 }
500}
501
502impl PartialOrd for Underline {
503 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
504 Some(self.cmp(other))
505 }
506}
507
508impl From<Underline> for Primitive {
509 fn from(underline: Underline) -> Self {
510 Primitive::Underline(underline)
511 }
512}
513
514#[derive(Debug, Clone, Eq, PartialEq)]
515#[repr(C)]
516pub struct Shadow {
517 pub order: u32,
518 pub bounds: Bounds<ScaledPixels>,
519 pub corner_radii: Corners<ScaledPixels>,
520 pub content_mask: ContentMask<ScaledPixels>,
521 pub color: Hsla,
522 pub blur_radius: ScaledPixels,
523}
524
525impl Ord for Shadow {
526 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
527 self.order.cmp(&other.order)
528 }
529}
530
531impl PartialOrd for Shadow {
532 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
533 Some(self.cmp(other))
534 }
535}
536
537impl From<Shadow> for Primitive {
538 fn from(shadow: Shadow) -> Self {
539 Primitive::Shadow(shadow)
540 }
541}
542
543#[derive(Clone, Debug, Eq, PartialEq)]
544#[repr(C)]
545pub struct MonochromeSprite {
546 pub order: u32,
547 pub bounds: Bounds<ScaledPixels>,
548 pub content_mask: ContentMask<ScaledPixels>,
549 pub color: Hsla,
550 pub tile: AtlasTile,
551}
552
553impl Ord for MonochromeSprite {
554 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
555 match self.order.cmp(&other.order) {
556 std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
557 order => order,
558 }
559 }
560}
561
562impl PartialOrd for MonochromeSprite {
563 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
564 Some(self.cmp(other))
565 }
566}
567
568impl From<MonochromeSprite> for Primitive {
569 fn from(sprite: MonochromeSprite) -> Self {
570 Primitive::MonochromeSprite(sprite)
571 }
572}
573
574#[derive(Clone, Debug, Eq, PartialEq)]
575#[repr(C)]
576pub struct PolychromeSprite {
577 pub order: u32,
578 pub bounds: Bounds<ScaledPixels>,
579 pub content_mask: ContentMask<ScaledPixels>,
580 pub corner_radii: Corners<ScaledPixels>,
581 pub tile: AtlasTile,
582 pub grayscale: bool,
583}
584
585impl Ord for PolychromeSprite {
586 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
587 match self.order.cmp(&other.order) {
588 std::cmp::Ordering::Equal => self.tile.tile_id.cmp(&other.tile.tile_id),
589 order => order,
590 }
591 }
592}
593
594impl PartialOrd for PolychromeSprite {
595 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
596 Some(self.cmp(other))
597 }
598}
599
600impl From<PolychromeSprite> for Primitive {
601 fn from(sprite: PolychromeSprite) -> Self {
602 Primitive::PolychromeSprite(sprite)
603 }
604}
605
606#[derive(Clone, Debug, Eq, PartialEq)]
607pub struct Surface {
608 pub order: u32,
609 pub bounds: Bounds<ScaledPixels>,
610 pub content_mask: ContentMask<ScaledPixels>,
611 pub image_buffer: media::core_video::CVImageBuffer,
612}
613
614impl Ord for Surface {
615 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
616 self.order.cmp(&other.order)
617 }
618}
619
620impl PartialOrd for Surface {
621 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
622 Some(self.cmp(other))
623 }
624}
625
626impl From<Surface> for Primitive {
627 fn from(surface: Surface) -> Self {
628 Primitive::Surface(surface)
629 }
630}
631
632#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
633pub(crate) struct PathId(pub(crate) usize);
634
635#[derive(Debug)]
636pub struct Path<P: Clone + Default + Debug> {
637 pub(crate) id: PathId,
638 order: u32,
639 pub(crate) bounds: Bounds<P>,
640 pub(crate) content_mask: ContentMask<P>,
641 pub(crate) vertices: Vec<PathVertex<P>>,
642 pub(crate) color: Hsla,
643 start: Point<P>,
644 current: Point<P>,
645 contour_count: usize,
646}
647
648impl Path<Pixels> {
649 pub fn new(start: Point<Pixels>) -> Self {
650 Self {
651 id: PathId(0),
652 order: 0,
653 vertices: Vec::new(),
654 start,
655 current: start,
656 bounds: Bounds {
657 origin: start,
658 size: Default::default(),
659 },
660 content_mask: Default::default(),
661 color: Default::default(),
662 contour_count: 0,
663 }
664 }
665
666 pub fn scale(&self, factor: f32) -> Path<ScaledPixels> {
667 Path {
668 id: self.id,
669 order: self.order,
670 bounds: self.bounds.scale(factor),
671 content_mask: self.content_mask.scale(factor),
672 vertices: self
673 .vertices
674 .iter()
675 .map(|vertex| vertex.scale(factor))
676 .collect(),
677 start: self.start.map(|start| start.scale(factor)),
678 current: self.current.scale(factor),
679 contour_count: self.contour_count,
680 color: self.color,
681 }
682 }
683
684 pub fn line_to(&mut self, to: Point<Pixels>) {
685 self.contour_count += 1;
686 if self.contour_count > 1 {
687 self.push_triangle(
688 (self.start, self.current, to),
689 (point(0., 1.), point(0., 1.), point(0., 1.)),
690 );
691 }
692 self.current = to;
693 }
694
695 pub fn curve_to(&mut self, to: Point<Pixels>, ctrl: Point<Pixels>) {
696 self.contour_count += 1;
697 if self.contour_count > 1 {
698 self.push_triangle(
699 (self.start, self.current, to),
700 (point(0., 1.), point(0., 1.), point(0., 1.)),
701 );
702 }
703
704 self.push_triangle(
705 (self.current, ctrl, to),
706 (point(0., 0.), point(0.5, 0.), point(1., 1.)),
707 );
708 self.current = to;
709 }
710
711 fn push_triangle(
712 &mut self,
713 xy: (Point<Pixels>, Point<Pixels>, Point<Pixels>),
714 st: (Point<f32>, Point<f32>, Point<f32>),
715 ) {
716 self.bounds = self
717 .bounds
718 .union(&Bounds {
719 origin: xy.0,
720 size: Default::default(),
721 })
722 .union(&Bounds {
723 origin: xy.1,
724 size: Default::default(),
725 })
726 .union(&Bounds {
727 origin: xy.2,
728 size: Default::default(),
729 });
730
731 self.vertices.push(PathVertex {
732 xy_position: xy.0,
733 st_position: st.0,
734 content_mask: Default::default(),
735 });
736 self.vertices.push(PathVertex {
737 xy_position: xy.1,
738 st_position: st.1,
739 content_mask: Default::default(),
740 });
741 self.vertices.push(PathVertex {
742 xy_position: xy.2,
743 st_position: st.2,
744 content_mask: Default::default(),
745 });
746 }
747}
748
749impl Eq for Path<ScaledPixels> {}
750
751impl PartialEq for Path<ScaledPixels> {
752 fn eq(&self, other: &Self) -> bool {
753 self.order == other.order
754 }
755}
756
757impl Ord for Path<ScaledPixels> {
758 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
759 self.order.cmp(&other.order)
760 }
761}
762
763impl PartialOrd for Path<ScaledPixels> {
764 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
765 Some(self.cmp(other))
766 }
767}
768
769impl From<Path<ScaledPixels>> for Primitive {
770 fn from(path: Path<ScaledPixels>) -> Self {
771 Primitive::Path(path)
772 }
773}
774
775#[derive(Clone, Debug)]
776#[repr(C)]
777pub struct PathVertex<P: Clone + Default + Debug> {
778 pub(crate) xy_position: Point<P>,
779 pub(crate) st_position: Point<f32>,
780 pub(crate) content_mask: ContentMask<P>,
781}
782
783impl PathVertex<Pixels> {
784 pub fn scale(&self, factor: f32) -> PathVertex<ScaledPixels> {
785 PathVertex {
786 xy_position: self.xy_position.scale(factor),
787 st_position: self.st_position,
788 content_mask: self.content_mask.scale(factor),
789 }
790 }
791}
792
793#[derive(Copy, Clone, Debug)]
794pub struct AtlasId(pub(crate) usize);