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