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