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