1//! A container to store multiple paths contiguously.
2
3use crate::builder::*;
4use crate::math::*;
5use crate::path;
6use crate::{Attributes, EndpointId, PathSlice, NO_ATTRIBUTES};
7
8use core::fmt;
9use core::iter::{FromIterator, FusedIterator, IntoIterator};
10use core::ops::Range;
11
12use alloc::vec::Vec;
13
14#[derive(Clone, Debug)]
15struct PathDescriptor {
16 points: (u32, u32),
17 verbs: (u32, u32),
18 num_attributes: u32,
19}
20
21/// An object that stores multiple paths contiguously.
22#[derive(Clone, Default)]
23pub struct PathBuffer {
24 points: Vec<Point>,
25 verbs: Vec<path::Verb>,
26 paths: Vec<PathDescriptor>,
27}
28
29impl PathBuffer {
30 #[inline]
31 pub fn new() -> Self {
32 PathBuffer {
33 points: Vec::new(),
34 verbs: Vec::new(),
35 paths: Vec::new(),
36 }
37 }
38
39 #[inline]
40 pub fn with_capacity(endpoints: usize, ctrl_points: usize, paths: usize) -> Self {
41 let mut buffer = PathBuffer::new();
42 buffer.reserve(endpoints, ctrl_points, paths);
43
44 buffer
45 }
46
47 #[inline]
48 pub fn as_slice(&self) -> PathBufferSlice {
49 PathBufferSlice {
50 points: &self.points,
51 verbs: &self.verbs,
52 paths: &self.paths,
53 }
54 }
55
56 #[inline]
57 pub fn get(&self, index: usize) -> PathSlice {
58 let desc = &self.paths[index];
59 PathSlice {
60 points: &self.points[desc.points.0 as usize..desc.points.1 as usize],
61 verbs: &self.verbs[desc.verbs.0 as usize..desc.verbs.1 as usize],
62 num_attributes: desc.num_attributes as usize,
63 }
64 }
65
66 #[inline]
67 pub fn indices(&self) -> Range<usize> {
68 0..self.paths.len()
69 }
70
71 #[inline]
72 pub fn iter(&self) -> Iter<'_> {
73 Iter::new(&self.points, &self.verbs, &self.paths)
74 }
75
76 #[inline]
77 /// Returns the number of paths in the path buffer.
78 pub fn len(&self) -> usize {
79 self.paths.len()
80 }
81
82 /// Returns whether the path buffer is empty.
83 #[inline]
84 pub fn is_empty(&self) -> bool {
85 self.paths.is_empty()
86 }
87
88 #[inline]
89 pub fn builder(&mut self) -> Builder {
90 Builder::new(self)
91 }
92
93 #[inline]
94 pub fn clear(&mut self) {
95 self.points.clear();
96 self.verbs.clear();
97 }
98
99 #[inline]
100 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize, paths: usize) {
101 self.points.reserve(endpoints + ctrl_points);
102 self.verbs.reserve(endpoints);
103 self.paths.reserve(paths);
104 }
105}
106
107impl fmt::Debug for PathBuffer {
108 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
109 self.as_slice().fmt(formatter)
110 }
111}
112
113impl<'l> FromIterator<PathSlice<'l>> for PathBuffer {
114 fn from_iter<T: IntoIterator<Item = PathSlice<'l>>>(iter: T) -> PathBuffer {
115 iter.into_iter()
116 .fold(init:PathBuffer::new(), |mut buffer: PathBuffer, path: PathSlice<'_>| {
117 let builder: Builder<'_> = buffer.builder();
118 pathBuilder<'_>.iter()
119 .fold(init:builder, |mut builder: Builder<'_>, event: Event, …>| {
120 builder.path_event(event, NO_ATTRIBUTES);
121 builder
122 })
123 .build();
124 buffer
125 })
126 }
127}
128
129/// A view on a `PathBuffer`.
130#[derive(Clone)]
131pub struct PathBufferSlice<'l> {
132 points: &'l [Point],
133 verbs: &'l [path::Verb],
134 paths: &'l [PathDescriptor],
135}
136
137impl<'l> PathBufferSlice<'l> {
138 #[inline]
139 pub fn get(&self, index: usize) -> PathSlice {
140 let desc = &self.paths[index];
141 PathSlice {
142 points: &self.points[desc.points.0 as usize..desc.points.1 as usize],
143 verbs: &self.verbs[desc.verbs.0 as usize..desc.verbs.1 as usize],
144 num_attributes: desc.num_attributes as usize,
145 }
146 }
147
148 #[inline]
149 pub fn indices(&self) -> Range<usize> {
150 0..self.paths.len()
151 }
152
153 #[inline]
154 pub fn iter(&self) -> Iter<'_> {
155 Iter::new(self.points, self.verbs, self.paths)
156 }
157
158 /// Returns the number of paths in the path buffer.
159 #[inline]
160 pub fn len(&self) -> usize {
161 self.paths.len()
162 }
163
164 /// Returns whether the path buffer is empty.
165 #[inline]
166 pub fn is_empty(&self) -> bool {
167 self.paths.is_empty()
168 }
169}
170
171impl<'l> fmt::Debug for PathBufferSlice<'l> {
172 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
173 write!(
174 formatter,
175 "PathBuffer {{ paths: {:?}, points: {:?}, verbs: {:?}, ",
176 self.paths.len(),
177 self.points.len(),
178 self.verbs.len(),
179 )?;
180 for idx: usize in self.indices() {
181 write!(formatter, "#{idx:?}: ")?;
182 self.get(index:idx).fmt(formatter)?;
183 write!(formatter, ", ")?;
184 }
185 write!(formatter, " }}")
186 }
187}
188
189/// A Builder that appends a path to an existing PathBuffer.
190///
191/// Implements the `PathBuilder` trait.
192pub struct Builder<'l> {
193 buffer: &'l mut PathBuffer,
194 builder: path::Builder,
195 points_start: u32,
196 verbs_start: u32,
197}
198
199impl<'l> Builder<'l> {
200 #[inline]
201 fn new(buffer: &'l mut PathBuffer) -> Self {
202 let mut builder = path::Path::builder();
203 core::mem::swap(&mut buffer.points, &mut builder.inner_mut().points);
204 core::mem::swap(&mut buffer.verbs, &mut builder.inner_mut().verbs);
205 let points_start = builder.inner().points.len() as u32;
206 let verbs_start = builder.inner().verbs.len() as u32;
207 Builder {
208 buffer,
209 builder,
210 points_start,
211 verbs_start,
212 }
213 }
214
215 #[inline]
216 pub fn with_attributes(self, num_attributes: usize) -> BuilderWithAttributes<'l> {
217 assert_eq!(self.builder.inner().verbs.len(), self.verbs_start as usize);
218
219 BuilderWithAttributes {
220 buffer: self.buffer,
221 builder: path::BuilderWithAttributes {
222 builder: self.builder.into_inner(),
223 num_attributes,
224 first_attributes: alloc::vec![0.0; num_attributes],
225 },
226 points_start: self.points_start,
227 verbs_start: self.verbs_start,
228 }
229 }
230
231 #[inline]
232 pub fn build(mut self) -> usize {
233 let points_end = self.builder.inner().points.len() as u32;
234 let verbs_end = self.builder.inner().verbs.len() as u32;
235 core::mem::swap(
236 &mut self.builder.inner_mut().points,
237 &mut self.buffer.points,
238 );
239 core::mem::swap(&mut self.builder.inner_mut().verbs, &mut self.buffer.verbs);
240
241 let index = self.buffer.paths.len();
242 self.buffer.paths.push(PathDescriptor {
243 points: (self.points_start, points_end),
244 verbs: (self.verbs_start, verbs_end),
245 num_attributes: 0,
246 });
247
248 index
249 }
250
251 #[inline]
252 fn adjust_id(&self, mut id: EndpointId) -> EndpointId {
253 id.0 -= self.points_start;
254
255 id
256 }
257
258 #[inline]
259 pub fn begin(&mut self, at: Point) -> EndpointId {
260 let id = self.builder.begin(at);
261 self.adjust_id(id)
262 }
263
264 #[inline]
265 pub fn end(&mut self, close: bool) {
266 self.builder.end(close)
267 }
268
269 #[inline]
270 pub fn line_to(&mut self, to: Point) -> EndpointId {
271 let id = self.builder.line_to(to);
272 self.adjust_id(id)
273 }
274
275 #[inline]
276 pub fn quadratic_bezier_to(&mut self, ctrl: Point, to: Point) -> EndpointId {
277 let id = self.builder.quadratic_bezier_to(ctrl, to);
278 self.adjust_id(id)
279 }
280
281 #[inline]
282 pub fn cubic_bezier_to(&mut self, ctrl1: Point, ctrl2: Point, to: Point) -> EndpointId {
283 let id = self.builder.cubic_bezier_to(ctrl1, ctrl2, to);
284 self.adjust_id(id)
285 }
286
287 #[inline]
288 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
289 self.builder.reserve(endpoints, ctrl_points);
290 }
291}
292
293impl<'l> PathBuilder for Builder<'l> {
294 #[inline]
295 fn num_attributes(&self) -> usize {
296 0
297 }
298
299 #[inline]
300 fn begin(&mut self, at: Point, _attributes: Attributes) -> EndpointId {
301 self.begin(at)
302 }
303
304 #[inline]
305 fn end(&mut self, close: bool) {
306 self.end(close);
307 }
308
309 #[inline]
310 fn line_to(&mut self, to: Point, _attributes: Attributes) -> EndpointId {
311 self.line_to(to)
312 }
313
314 #[inline]
315 fn quadratic_bezier_to(
316 &mut self,
317 ctrl: Point,
318 to: Point,
319 _attributes: Attributes,
320 ) -> EndpointId {
321 self.quadratic_bezier_to(ctrl, to)
322 }
323
324 #[inline]
325 fn cubic_bezier_to(
326 &mut self,
327 ctrl1: Point,
328 ctrl2: Point,
329 to: Point,
330 _attributes: Attributes,
331 ) -> EndpointId {
332 self.cubic_bezier_to(ctrl1, ctrl2, to)
333 }
334
335 #[inline]
336 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
337 self.reserve(endpoints, ctrl_points);
338 }
339}
340
341impl<'l> Build for Builder<'l> {
342 type PathType = usize;
343 fn build(self) -> usize {
344 self.build()
345 }
346}
347
348/// A Builder that appends a path to an existing PathBuffer, with custom attributes.
349pub struct BuilderWithAttributes<'l> {
350 buffer: &'l mut PathBuffer,
351 builder: path::BuilderWithAttributes,
352 points_start: u32,
353 verbs_start: u32,
354}
355
356impl<'l> BuilderWithAttributes<'l> {
357 #[inline]
358 pub fn new(buffer: &'l mut PathBuffer, num_attributes: usize) -> Self {
359 let mut builder = path::Path::builder().into_inner();
360 core::mem::swap(&mut buffer.points, &mut builder.points);
361 core::mem::swap(&mut buffer.verbs, &mut builder.verbs);
362 let points_start = builder.points.len() as u32;
363 let verbs_start = builder.verbs.len() as u32;
364 BuilderWithAttributes {
365 buffer,
366 builder: path::BuilderWithAttributes {
367 builder,
368 num_attributes,
369 first_attributes: alloc::vec![0.0; num_attributes],
370 },
371 points_start,
372 verbs_start,
373 }
374 }
375
376 #[inline]
377 pub fn build(mut self) -> usize {
378 let points_end = self.builder.builder.points.len() as u32;
379 let verbs_end = self.builder.builder.verbs.len() as u32;
380 core::mem::swap(&mut self.builder.builder.points, &mut self.buffer.points);
381 core::mem::swap(&mut self.builder.builder.verbs, &mut self.buffer.verbs);
382
383 let index = self.buffer.paths.len();
384 self.buffer.paths.push(PathDescriptor {
385 points: (self.points_start, points_end),
386 verbs: (self.verbs_start, verbs_end),
387 num_attributes: 0,
388 });
389
390 index
391 }
392
393 #[inline]
394 fn adjust_id(&self, mut id: EndpointId) -> EndpointId {
395 id.0 -= self.points_start;
396
397 id
398 }
399
400 #[inline]
401 pub fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
402 let id = self.builder.begin(at, attributes);
403 self.adjust_id(id)
404 }
405
406 #[inline]
407 pub fn end(&mut self, close: bool) {
408 self.builder.end(close)
409 }
410
411 #[inline]
412 pub fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
413 let id = self.builder.line_to(to, attributes);
414 self.adjust_id(id)
415 }
416
417 #[inline]
418 pub fn quadratic_bezier_to(
419 &mut self,
420 ctrl: Point,
421 to: Point,
422 attributes: Attributes,
423 ) -> EndpointId {
424 let id = self.builder.quadratic_bezier_to(ctrl, to, attributes);
425 self.adjust_id(id)
426 }
427
428 #[inline]
429 pub fn cubic_bezier_to(
430 &mut self,
431 ctrl1: Point,
432 ctrl2: Point,
433 to: Point,
434 attributes: Attributes,
435 ) -> EndpointId {
436 let id = self.builder.cubic_bezier_to(ctrl1, ctrl2, to, attributes);
437 self.adjust_id(id)
438 }
439
440 #[inline]
441 pub fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
442 self.builder.reserve(endpoints, ctrl_points);
443 }
444}
445
446impl<'l> PathBuilder for BuilderWithAttributes<'l> {
447 #[inline]
448 fn num_attributes(&self) -> usize {
449 self.builder.num_attributes()
450 }
451
452 #[inline]
453 fn begin(&mut self, at: Point, attributes: Attributes) -> EndpointId {
454 self.begin(at, attributes)
455 }
456
457 #[inline]
458 fn end(&mut self, close: bool) {
459 self.end(close);
460 }
461
462 #[inline]
463 fn line_to(&mut self, to: Point, attributes: Attributes) -> EndpointId {
464 self.line_to(to, attributes)
465 }
466
467 #[inline]
468 fn quadratic_bezier_to(
469 &mut self,
470 ctrl: Point,
471 to: Point,
472 attributes: Attributes,
473 ) -> EndpointId {
474 self.quadratic_bezier_to(ctrl, to, attributes)
475 }
476
477 #[inline]
478 fn cubic_bezier_to(
479 &mut self,
480 ctrl1: Point,
481 ctrl2: Point,
482 to: Point,
483 attributes: Attributes,
484 ) -> EndpointId {
485 self.cubic_bezier_to(ctrl1, ctrl2, to, attributes)
486 }
487
488 #[inline]
489 fn reserve(&mut self, endpoints: usize, ctrl_points: usize) {
490 self.reserve(endpoints, ctrl_points);
491 }
492}
493
494impl<'l> Build for BuilderWithAttributes<'l> {
495 type PathType = usize;
496 fn build(self) -> usize {
497 self.build()
498 }
499}
500
501/// Iterator over the paths in a [`PathBufferSlice`].
502#[derive(Clone)]
503pub struct Iter<'l> {
504 points: &'l [Point],
505 verbs: &'l [path::Verb],
506 paths: ::core::slice::Iter<'l, PathDescriptor>,
507}
508
509impl<'l> Iter<'l> {
510 fn new(points: &'l [Point], verbs: &'l [path::Verb], paths: &'l [PathDescriptor]) -> Iter<'l> {
511 Iter {
512 points,
513 verbs,
514 paths: paths.iter(),
515 }
516 }
517}
518
519impl<'l> Iterator for Iter<'l> {
520 type Item = PathSlice<'l>;
521
522 fn next(&mut self) -> Option<PathSlice<'l>> {
523 let path: &PathDescriptor = self.paths.next()?;
524 Some(PathSlice {
525 points: &self.points[path.points.0 as usize..path.points.1 as usize],
526 verbs: &self.verbs[path.verbs.0 as usize..path.verbs.1 as usize],
527 num_attributes: path.num_attributes as usize,
528 })
529 }
530
531 fn size_hint(&self) -> (usize, Option<usize>) {
532 self.paths.size_hint()
533 }
534}
535
536// slice::Iter is Fused and ExactSize
537impl<'l> FusedIterator for Iter<'l> {}
538impl<'l> ExactSizeIterator for Iter<'l> {}
539
540impl<'l> DoubleEndedIterator for Iter<'l> {
541 fn next_back(&mut self) -> Option<PathSlice<'l>> {
542 let path: &PathDescriptor = self.paths.next_back()?;
543 Some(PathSlice {
544 points: &self.points[path.points.0 as usize..path.points.1 as usize],
545 verbs: &self.verbs[path.verbs.0 as usize..path.verbs.1 as usize],
546 num_attributes: path.num_attributes as usize,
547 })
548 }
549}
550
551#[test]
552fn simple() {
553 use crate::PathEvent;
554
555 let mut buffer = PathBuffer::new();
556
557 let mut builder = buffer.builder();
558 builder.begin(point(0.0, 0.0));
559 builder.line_to(point(10.0, 0.0));
560 builder.line_to(point(10.0, 10.0));
561 let a = builder.line_to(point(0.0, 10.0));
562 builder.end(true);
563
564 let p1 = builder.build();
565
566 let mut builder = buffer.builder();
567 builder.begin(point(0.0, 0.0));
568 builder.line_to(point(20.0, 0.0));
569 builder.line_to(point(20.0, 20.0));
570 let b = builder.line_to(point(0.0, 20.0));
571 builder.end(false);
572
573 let p2 = builder.build();
574
575 let mut iter = buffer.get(p1).iter();
576 assert_eq!(
577 iter.next(),
578 Some(PathEvent::Begin {
579 at: point(0.0, 0.0)
580 })
581 );
582 assert_eq!(
583 iter.next(),
584 Some(PathEvent::Line {
585 from: point(0.0, 0.0),
586 to: point(10.0, 0.0)
587 })
588 );
589 assert_eq!(
590 iter.next(),
591 Some(PathEvent::Line {
592 from: point(10.0, 0.0),
593 to: point(10.0, 10.0)
594 })
595 );
596 assert_eq!(
597 iter.next(),
598 Some(PathEvent::Line {
599 from: point(10.0, 10.0),
600 to: point(0.0, 10.0)
601 })
602 );
603 assert_eq!(
604 iter.next(),
605 Some(PathEvent::End {
606 last: point(0.0, 10.0),
607 first: point(0.0, 0.0),
608 close: true
609 })
610 );
611 assert_eq!(iter.next(), None);
612
613 let mut iter = buffer.get(p2).iter();
614 assert_eq!(
615 iter.next(),
616 Some(PathEvent::Begin {
617 at: point(0.0, 0.0)
618 })
619 );
620 assert_eq!(
621 iter.next(),
622 Some(PathEvent::Line {
623 from: point(0.0, 0.0),
624 to: point(20.0, 0.0)
625 })
626 );
627 assert_eq!(
628 iter.next(),
629 Some(PathEvent::Line {
630 from: point(20.0, 0.0),
631 to: point(20.0, 20.0)
632 })
633 );
634 assert_eq!(
635 iter.next(),
636 Some(PathEvent::Line {
637 from: point(20.0, 20.0),
638 to: point(0.0, 20.0)
639 })
640 );
641 assert_eq!(
642 iter.next(),
643 Some(PathEvent::End {
644 last: point(0.0, 20.0),
645 first: point(0.0, 0.0),
646 close: false
647 })
648 );
649 assert_eq!(iter.next(), None);
650
651 assert_eq!(buffer.get(p1)[a], point(0.0, 10.0));
652 assert_eq!(buffer.get(p2)[b], point(0.0, 20.0));
653}
654