1use font_types::{GlyphId, GlyphId16};
4
5use crate::{collections::IntSet, tables::variations::NO_VARIATION_INDEX, ResolveOffset};
6
7use super::{
8 Clip, ClipBox, ClipBoxFormat2, ClipList, ColorLine, ColorStop, Colr, Paint, PaintColrGlyph,
9 PaintColrLayers, PaintComposite, PaintGlyph, PaintLinearGradient, PaintRadialGradient,
10 PaintRotate, PaintRotateAroundCenter, PaintScale, PaintScaleAroundCenter, PaintScaleUniform,
11 PaintScaleUniformAroundCenter, PaintSkew, PaintSkewAroundCenter, PaintSolid,
12 PaintSweepGradient, PaintTransform, PaintTranslate, PaintVarLinearGradient,
13 PaintVarRadialGradient, PaintVarRotate, PaintVarRotateAroundCenter, PaintVarScale,
14 PaintVarScaleAroundCenter, PaintVarScaleUniform, PaintVarScaleUniformAroundCenter,
15 PaintVarSkew, PaintVarSkewAroundCenter, PaintVarSolid, PaintVarSweepGradient,
16 PaintVarTransform, PaintVarTranslate, VarAffine2x3, VarColorLine, VarColorStop,
17};
18
19impl Colr<'_> {
20 pub fn v0_closure_palette_indices(
23 &self,
24 glyph_set: &IntSet<GlyphId>,
25 palette_indices: &mut IntSet<u16>,
26 ) {
27 let Some(Ok(records)) = self.base_glyph_records() else {
28 return;
29 };
30 for glyph_id in glyph_set.iter() {
31 let Ok(glyph_id) = glyph_id.try_into() else {
32 continue;
33 };
34 let record = match records.binary_search_by(|rec| rec.glyph_id().cmp(&glyph_id)) {
35 Ok(idx) => records[idx],
36 _ => continue,
37 };
38 let start = record.first_layer_index() as usize;
39 let end = start + record.num_layers() as usize;
40 for layer_index in start..end {
41 if let Ok((_gid, palette_id)) = self.v0_layer(layer_index) {
42 palette_indices.insert(palette_id);
43 }
44 }
45 }
46 }
47
48 pub fn v1_closure(
50 &self,
51 glyph_set: &mut IntSet<GlyphId>,
52 layer_indices: &mut IntSet<u32>,
53 palette_indices: &mut IntSet<u16>,
54 variation_indices: &mut IntSet<u32>,
55 ) {
56 if self.version() < 1 {
57 return;
58 }
59
60 let mut c =
61 Colrv1ClosureContext::new(layer_indices, palette_indices, variation_indices, self);
62 if let Some(Ok(base_glyph_list)) = self.base_glyph_list() {
63 let base_glyph_records = base_glyph_list.base_glyph_paint_records();
64 let offset_data = base_glyph_list.offset_data();
65 for paint_record in base_glyph_records {
66 let gid = paint_record.glyph_id();
67 if !glyph_set.contains(GlyphId::from(gid)) {
68 continue;
69 }
70 if let Ok(paint) = paint_record.paint(offset_data) {
71 c.dispatch(&paint);
72 }
73 }
74
75 glyph_set.union(&c.glyph_set);
76 }
77
78 if let Some(Ok(clip_list)) = self.clip_list() {
79 c.glyph_set.union(glyph_set);
80 for clip_record in clip_list.clips() {
81 clip_record.v1_closure(&mut c, &clip_list);
82 }
83 }
84 }
85
86 pub fn v0_closure_glyphs(
88 &self,
89 glyph_set: &IntSet<GlyphId>,
90 glyphset_colrv0: &mut IntSet<GlyphId>,
91 ) {
92 glyphset_colrv0.union(glyph_set);
93 let Some(Ok(records)) = self.base_glyph_records() else {
94 return;
95 };
96 for glyph_id in glyph_set.iter() {
97 let Ok(glyph_id) = glyph_id.try_into() else {
98 continue;
99 };
100 let record = match records.binary_search_by(|rec| rec.glyph_id().cmp(&glyph_id)) {
101 Ok(idx) => records[idx],
102 _ => continue,
103 };
104 let start = record.first_layer_index() as usize;
105 let end = start + record.num_layers() as usize;
106 for layer_index in start..end {
107 if let Ok((gid, _palette_id)) = self.v0_layer(layer_index) {
108 glyphset_colrv0.insert(GlyphId::from(gid));
109 }
110 }
111 }
112 }
113}
114
115struct Colrv1ClosureContext<'a> {
116 glyph_set: IntSet<GlyphId>,
117 layer_indices: &'a mut IntSet<u32>,
118 palette_indices: &'a mut IntSet<u16>,
119 variation_indices: &'a mut IntSet<u32>,
120 colr: &'a Colr<'a>,
121 nesting_level_left: u8,
122 visited_paints: IntSet<u32>,
123 colr_head: usize,
124}
125
126impl<'a> Colrv1ClosureContext<'a> {
127 pub fn new(
128 layer_indices: &'a mut IntSet<u32>,
129 palette_indices: &'a mut IntSet<u16>,
130 variation_indices: &'a mut IntSet<u32>,
131 colr: &'a Colr,
132 ) -> Self {
133 let colr_head = colr.offset_data().as_bytes().as_ptr() as usize;
134 Self {
135 glyph_set: IntSet::empty(),
136 layer_indices,
137 palette_indices,
138 variation_indices,
139 colr,
140 nesting_level_left: 64,
141 visited_paints: IntSet::empty(),
142 colr_head,
143 }
144 }
145
146 fn dispatch(&mut self, paint: &Paint) {
147 if self.nesting_level_left == 0 {
148 return;
149 }
150
151 if self.paint_visited(paint) {
152 return;
153 }
154 self.nesting_level_left -= 1;
155 paint.v1_closure(self);
156 self.nesting_level_left += 1;
157 }
158
159 fn paint_visited(&mut self, paint: &Paint) -> bool {
160 let offset = (paint.offset_data().as_bytes().as_ptr() as usize - self.colr_head) as u32;
161 if self.visited_paints.contains(offset) {
162 return true;
163 }
164
165 self.visited_paints.insert(offset);
166 false
167 }
168
169 fn add_layer_indices(&mut self, first_layer_index: u32, last_layer_index: u32) {
170 self.layer_indices
171 .insert_range(first_layer_index..=last_layer_index);
172 }
173
174 fn add_palette_index(&mut self, palette_index: u16) {
175 self.palette_indices.insert(palette_index);
176 }
177
178 fn add_variation_indices(&mut self, var_index_base: u32, num_vars: u8) {
179 if num_vars == 0 || var_index_base == NO_VARIATION_INDEX {
180 return;
181 }
182
183 let last_var_index = var_index_base + num_vars as u32 - 1;
184 self.variation_indices
185 .insert_range(var_index_base..=last_var_index);
186 }
187
188 fn add_glyph_id(&mut self, gid: GlyphId16) {
189 self.glyph_set.insert(GlyphId::from(gid));
190 }
191}
192
193impl ColorStop {
194 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
195 c.add_palette_index(self.palette_index());
196 }
197}
198
199impl VarColorStop {
200 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
201 c.add_palette_index(self.palette_index());
202 c.add_variation_indices(self.var_index_base(), 2);
203 }
204}
205
206impl ColorLine<'_> {
207 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
208 for colorstop in self.color_stops() {
209 colorstop.v1_closure(c);
210 }
211 }
212}
213
214impl VarColorLine<'_> {
215 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
216 for var_colorstop in self.color_stops() {
217 var_colorstop.v1_closure(c);
218 }
219 }
220}
221
222impl Paint<'_> {
223 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
224 match self {
225 Self::ColrLayers(item) => item.v1_closure(c),
226 Self::Solid(item) => item.v1_closure(c),
227 Self::VarSolid(item) => item.v1_closure(c),
228 Self::LinearGradient(item) => item.v1_closure(c),
229 Self::VarLinearGradient(item) => item.v1_closure(c),
230 Self::RadialGradient(item) => item.v1_closure(c),
231 Self::VarRadialGradient(item) => item.v1_closure(c),
232 Self::SweepGradient(item) => item.v1_closure(c),
233 Self::VarSweepGradient(item) => item.v1_closure(c),
234 Self::Glyph(item) => item.v1_closure(c),
235 Self::ColrGlyph(item) => item.v1_closure(c),
236 Self::Transform(item) => item.v1_closure(c),
237 Self::VarTransform(item) => item.v1_closure(c),
238 Self::Translate(item) => item.v1_closure(c),
239 Self::VarTranslate(item) => item.v1_closure(c),
240 Self::Scale(item) => item.v1_closure(c),
241 Self::VarScale(item) => item.v1_closure(c),
242 Self::ScaleAroundCenter(item) => item.v1_closure(c),
243 Self::VarScaleAroundCenter(item) => item.v1_closure(c),
244 Self::ScaleUniform(item) => item.v1_closure(c),
245 Self::VarScaleUniform(item) => item.v1_closure(c),
246 Self::ScaleUniformAroundCenter(item) => item.v1_closure(c),
247 Self::VarScaleUniformAroundCenter(item) => item.v1_closure(c),
248 Self::Rotate(item) => item.v1_closure(c),
249 Self::VarRotate(item) => item.v1_closure(c),
250 Self::RotateAroundCenter(item) => item.v1_closure(c),
251 Self::VarRotateAroundCenter(item) => item.v1_closure(c),
252 Self::Skew(item) => item.v1_closure(c),
253 Self::VarSkew(item) => item.v1_closure(c),
254 Self::SkewAroundCenter(item) => item.v1_closure(c),
255 Self::VarSkewAroundCenter(item) => item.v1_closure(c),
256 Self::Composite(item) => item.v1_closure(c),
257 }
258 }
259}
260
261impl PaintColrLayers<'_> {
262 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
263 let num_layers = self.num_layers();
264 if num_layers == 0 {
265 return;
266 }
267
268 let Some(Ok(layer_list)) = c.colr.layer_list() else {
269 return;
270 };
271 let first_layer_index = self.first_layer_index();
272 let last_layer_index = first_layer_index + num_layers as u32 - 1;
273 c.add_layer_indices(first_layer_index, last_layer_index);
274
275 let offset_data = layer_list.offset_data();
276 for layer_index in first_layer_index..=last_layer_index {
277 if let Some(paint_offset) = layer_list.paint_offsets().get(layer_index as usize) {
278 if let Ok(paint) = paint_offset.get().resolve::<Paint>(offset_data) {
279 c.dispatch(&paint);
280 }
281 }
282 }
283 }
284}
285
286impl PaintSolid<'_> {
287 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
288 c.add_palette_index(self.palette_index());
289 }
290}
291
292impl PaintVarSolid<'_> {
293 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
294 c.add_palette_index(self.palette_index());
295 c.add_variation_indices(self.var_index_base(), 1);
296 }
297}
298
299impl PaintLinearGradient<'_> {
300 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
301 if let Ok(colorline) = self.color_line() {
302 colorline.v1_closure(c);
303 }
304 }
305}
306
307impl PaintVarLinearGradient<'_> {
308 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
309 if let Ok(var_colorline) = self.color_line() {
310 var_colorline.v1_closure(c);
311 }
312 c.add_variation_indices(self.var_index_base(), 6);
313 }
314}
315
316impl PaintRadialGradient<'_> {
317 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
318 if let Ok(colorline) = self.color_line() {
319 colorline.v1_closure(c);
320 }
321 }
322}
323
324impl PaintVarRadialGradient<'_> {
325 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
326 if let Ok(var_colorline) = self.color_line() {
327 var_colorline.v1_closure(c);
328 }
329 c.add_variation_indices(self.var_index_base(), 6);
330 }
331}
332
333impl PaintSweepGradient<'_> {
334 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
335 if let Ok(colorline) = self.color_line() {
336 colorline.v1_closure(c);
337 }
338 }
339}
340
341impl PaintVarSweepGradient<'_> {
342 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
343 if let Ok(var_colorline) = self.color_line() {
344 var_colorline.v1_closure(c);
345 }
346 c.add_variation_indices(self.var_index_base(), 4);
347 }
348}
349
350impl PaintGlyph<'_> {
351 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
352 c.add_glyph_id(self.glyph_id());
353 if let Ok(paint) = self.paint() {
354 c.dispatch(&paint);
355 }
356 }
357}
358
359impl PaintColrGlyph<'_> {
360 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
361 let glyph_id = self.glyph_id();
362 let Some(Ok(list)) = c.colr.base_glyph_list() else {
363 return;
364 };
365 let records = list.base_glyph_paint_records();
366 let record = match records.binary_search_by(|rec| rec.glyph_id().cmp(&glyph_id)) {
367 Ok(ix) => &records[ix],
368 _ => return,
369 };
370 if let Ok(paint) = record.paint(list.offset_data()) {
371 c.add_glyph_id(glyph_id);
372 c.dispatch(&paint);
373 }
374 }
375}
376
377impl PaintTransform<'_> {
378 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
379 if let Ok(paint) = self.paint() {
380 c.dispatch(&paint);
381 }
382 }
383}
384
385impl VarAffine2x3<'_> {
386 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
387 c.add_variation_indices(self.var_index_base(), 6);
388 }
389}
390
391impl PaintVarTransform<'_> {
392 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
393 if let Ok(paint) = self.paint() {
394 c.dispatch(&paint);
395 if let Ok(affine2x3) = self.transform() {
396 affine2x3.v1_closure(c);
397 }
398 }
399 }
400}
401
402impl PaintTranslate<'_> {
403 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
404 if let Ok(paint) = self.paint() {
405 c.dispatch(&paint);
406 }
407 }
408}
409
410impl PaintVarTranslate<'_> {
411 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
412 if let Ok(paint) = self.paint() {
413 c.dispatch(&paint);
414 c.add_variation_indices(self.var_index_base(), 2);
415 }
416 }
417}
418
419impl PaintScale<'_> {
420 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
421 if let Ok(paint) = self.paint() {
422 c.dispatch(&paint);
423 }
424 }
425}
426
427impl PaintVarScale<'_> {
428 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
429 if let Ok(paint) = self.paint() {
430 c.dispatch(&paint);
431 c.add_variation_indices(self.var_index_base(), 2);
432 }
433 }
434}
435
436impl PaintScaleAroundCenter<'_> {
437 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
438 if let Ok(paint) = self.paint() {
439 c.dispatch(&paint);
440 }
441 }
442}
443
444impl PaintVarScaleAroundCenter<'_> {
445 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
446 if let Ok(paint) = self.paint() {
447 c.dispatch(&paint);
448 c.add_variation_indices(self.var_index_base(), 4);
449 }
450 }
451}
452
453impl PaintScaleUniform<'_> {
454 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
455 if let Ok(paint) = self.paint() {
456 c.dispatch(&paint);
457 }
458 }
459}
460
461impl PaintVarScaleUniform<'_> {
462 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
463 if let Ok(paint) = self.paint() {
464 c.dispatch(&paint);
465 c.add_variation_indices(self.var_index_base(), 1);
466 }
467 }
468}
469
470impl PaintScaleUniformAroundCenter<'_> {
471 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
472 if let Ok(paint) = self.paint() {
473 c.dispatch(&paint);
474 }
475 }
476}
477
478impl PaintVarScaleUniformAroundCenter<'_> {
479 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
480 if let Ok(paint) = self.paint() {
481 c.dispatch(&paint);
482 c.add_variation_indices(self.var_index_base(), 3);
483 }
484 }
485}
486
487impl PaintRotate<'_> {
488 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
489 if let Ok(paint) = self.paint() {
490 c.dispatch(&paint);
491 }
492 }
493}
494
495impl PaintVarRotate<'_> {
496 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
497 if let Ok(paint) = self.paint() {
498 c.dispatch(&paint);
499 c.add_variation_indices(self.var_index_base(), 1);
500 }
501 }
502}
503
504impl PaintRotateAroundCenter<'_> {
505 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
506 if let Ok(paint) = self.paint() {
507 c.dispatch(&paint);
508 }
509 }
510}
511
512impl PaintVarRotateAroundCenter<'_> {
513 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
514 if let Ok(paint) = self.paint() {
515 c.dispatch(&paint);
516 c.add_variation_indices(self.var_index_base(), 3);
517 }
518 }
519}
520
521impl PaintSkew<'_> {
522 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
523 if let Ok(paint) = self.paint() {
524 c.dispatch(&paint);
525 }
526 }
527}
528
529impl PaintVarSkew<'_> {
530 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
531 if let Ok(paint) = self.paint() {
532 c.dispatch(&paint);
533 c.add_variation_indices(self.var_index_base(), 2);
534 }
535 }
536}
537
538impl PaintSkewAroundCenter<'_> {
539 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
540 if let Ok(paint) = self.paint() {
541 c.dispatch(&paint);
542 }
543 }
544}
545
546impl PaintVarSkewAroundCenter<'_> {
547 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
548 if let Ok(paint) = self.paint() {
549 c.dispatch(&paint);
550 c.add_variation_indices(self.var_index_base(), 4);
551 }
552 }
553}
554
555impl PaintComposite<'_> {
556 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
557 if let Ok(source_paint) = self.source_paint() {
558 c.dispatch(&source_paint);
559 }
560
561 if let Ok(backdrop_paint) = self.backdrop_paint() {
562 c.dispatch(&backdrop_paint);
563 }
564 }
565}
566
567impl Clip {
568 fn v1_closure(&self, c: &mut Colrv1ClosureContext, clip_list: &ClipList) {
569 let Ok(clip_box) = self.clip_box(clip_list.offset_data()) else {
570 return;
571 };
572 let mut included_gids = IntSet::empty();
574 let start_id = GlyphId::from(self.start_glyph_id());
575 let end_id = GlyphId::from(self.end_glyph_id());
576 included_gids.insert_range(start_id..=end_id);
577 included_gids.intersect(&c.glyph_set);
578
579 if included_gids.is_empty() {
580 return;
581 }
582 clip_box.v1_closure(c);
583 }
584}
585
586impl ClipBox<'_> {
587 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
588 if let Self::Format2(item) = self {
589 item.v1_closure(c)
590 }
591 }
592}
593
594impl ClipBoxFormat2<'_> {
595 fn v1_closure(&self, c: &mut Colrv1ClosureContext) {
596 c.add_variation_indices(self.var_index_base(), 4);
597 }
598}
599
600#[cfg(test)]
601mod tests {
602 use super::*;
603 use crate::{FontRef, GlyphId, TableProvider};
604
605 #[test]
606 fn test_colr_v0_closure() {
607 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
608 let colr = font.colr().unwrap();
609
610 let mut input_glyph_set = IntSet::empty();
611 input_glyph_set.insert(GlyphId::new(168));
612
613 let mut glyph_set_colred = IntSet::empty();
614
615 colr.v0_closure_glyphs(&input_glyph_set, &mut glyph_set_colred);
616 assert_eq!(glyph_set_colred.len(), 9);
617 assert!(glyph_set_colred.contains(GlyphId::new(5)));
618 assert!(glyph_set_colred.contains(GlyphId::new(168)));
619 assert!(glyph_set_colred.contains(GlyphId::new(170)));
620 assert!(glyph_set_colred.contains(GlyphId::new(171)));
621 assert!(glyph_set_colred.contains(GlyphId::new(172)));
622 assert!(glyph_set_colred.contains(GlyphId::new(173)));
623 assert!(glyph_set_colred.contains(GlyphId::new(174)));
624 assert!(glyph_set_colred.contains(GlyphId::new(175)));
625 assert!(glyph_set_colred.contains(GlyphId::new(176)));
626
627 let mut palette_indices = IntSet::empty();
628 colr.v0_closure_palette_indices(&glyph_set_colred, &mut palette_indices);
629 assert_eq!(palette_indices.len(), 8);
630 assert!(palette_indices.contains(0));
631 assert!(palette_indices.contains(1));
632 assert!(palette_indices.contains(2));
633 assert!(palette_indices.contains(3));
634 assert!(palette_indices.contains(4));
635 assert!(palette_indices.contains(5));
636 assert!(palette_indices.contains(6));
637 assert!(palette_indices.contains(10));
638 }
639
640 #[test]
641 fn test_colr_v0_closure_not_found() {
642 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
643 let colr = font.colr().unwrap();
644
645 let mut input_glyph_set = IntSet::empty();
646 input_glyph_set.insert(GlyphId::new(8));
647
648 let mut glyph_set_colred = IntSet::empty();
649
650 colr.v0_closure_glyphs(&input_glyph_set, &mut glyph_set_colred);
651 assert_eq!(glyph_set_colred.len(), 1);
652 assert!(glyph_set_colred.contains(GlyphId::new(8)));
653 }
654
655 #[test]
656 fn test_colr_v1_closure_no_var() {
657 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
658 let colr = font.colr().unwrap();
659
660 let mut glyph_set = IntSet::empty();
661 glyph_set.insert(GlyphId::new(220));
662 glyph_set.insert(GlyphId::new(120));
663
664 let mut layer_indices = IntSet::empty();
665 let mut palette_indices = IntSet::empty();
666 let mut variation_indices = IntSet::empty();
667
668 colr.v1_closure(
669 &mut glyph_set,
670 &mut layer_indices,
671 &mut palette_indices,
672 &mut variation_indices,
673 );
674
675 assert_eq!(glyph_set.len(), 6);
676 assert!(glyph_set.contains(GlyphId::new(6)));
677 assert!(glyph_set.contains(GlyphId::new(7)));
678 assert!(glyph_set.contains(GlyphId::new(220)));
679 assert!(glyph_set.contains(GlyphId::new(3)));
680 assert!(glyph_set.contains(GlyphId::new(2)));
681 assert!(glyph_set.contains(GlyphId::new(120)));
682
683 assert_eq!(palette_indices.len(), 5);
684 assert!(palette_indices.contains(0));
685 assert!(palette_indices.contains(4));
686 assert!(palette_indices.contains(10));
687 assert!(palette_indices.contains(11));
688 assert!(palette_indices.contains(12));
689
690 assert_eq!(layer_indices.len(), 2);
691 assert!(layer_indices.contains(0));
692 assert!(layer_indices.contains(1));
693
694 assert!(variation_indices.is_empty());
695 }
696
697 #[test]
698 fn test_colr_v1_closure_w_var() {
699 let font = FontRef::new(font_test_data::COLRV0V1_VARIABLE).unwrap();
700 let colr = font.colr().unwrap();
701
702 let mut glyph_set = IntSet::empty();
703 glyph_set.insert(GlyphId::new(109));
704
705 let mut layer_indices = IntSet::empty();
706 let mut palette_indices = IntSet::empty();
707 let mut variation_indices = IntSet::empty();
708
709 colr.v1_closure(
710 &mut glyph_set,
711 &mut layer_indices,
712 &mut palette_indices,
713 &mut variation_indices,
714 );
715
716 assert_eq!(glyph_set.len(), 2);
717 assert!(glyph_set.contains(GlyphId::new(3)));
718 assert!(glyph_set.contains(GlyphId::new(109)));
719
720 assert_eq!(palette_indices.len(), 2);
721 assert!(palette_indices.contains(1));
722 assert!(palette_indices.contains(4));
723
724 assert!(layer_indices.is_empty());
725
726 assert_eq!(variation_indices.len(), 6);
727 assert!(variation_indices.contains(51));
728 assert!(variation_indices.contains(52));
729 assert!(variation_indices.contains(53));
730 assert!(variation_indices.contains(54));
731 assert!(variation_indices.contains(55));
732 assert!(variation_indices.contains(56));
733 }
734}