read_fonts/tables/
colr.rs1#[cfg(feature = "std")]
4mod closure;
5
6use super::variations::{DeltaSetIndexMap, ItemVariationStore};
7
8include!("../../generated/generated_colr.rs");
9
10pub type PaintId = usize;
12
13impl<'a> Colr<'a> {
14 pub fn v0_base_glyph(&self, glyph_id: GlyphId) -> Result<Option<Range<usize>>, ReadError> {
20 let records = self.base_glyph_records().ok_or(ReadError::NullOffset)??;
21 let Ok(glyph_id) = glyph_id.try_into() else {
22 return Ok(None);
23 };
24 let record = match records.binary_search_by(|rec| rec.glyph_id().cmp(&glyph_id)) {
25 Ok(ix) => &records[ix],
26 _ => return Ok(None),
27 };
28 let start = record.first_layer_index() as usize;
29 let end = start + record.num_layers() as usize;
30 Ok(Some(start..end))
31 }
32
33 pub fn v0_layer(&self, index: usize) -> Result<(GlyphId16, u16), ReadError> {
38 let layers = self.layer_records().ok_or(ReadError::NullOffset)??;
39 let layer = layers.get(index).ok_or(ReadError::OutOfBounds)?;
40 Ok((layer.glyph_id(), layer.palette_index()))
41 }
42
43 pub fn v1_base_glyph(
48 &self,
49 glyph_id: GlyphId,
50 ) -> Result<Option<(Paint<'a>, PaintId)>, ReadError> {
51 let Ok(glyph_id) = glyph_id.try_into() else {
52 return Ok(None);
53 };
54 let list = self.base_glyph_list().ok_or(ReadError::NullOffset)??;
55 let records = list.base_glyph_paint_records();
56 let record = match records.binary_search_by(|rec| rec.glyph_id().cmp(&glyph_id)) {
57 Ok(ix) => &records[ix],
58 _ => return Ok(None),
59 };
60 let offset_data = list.offset_data();
61 let id = record.paint_offset().to_u32() as usize + offset_data.as_ref().as_ptr() as usize;
64 Ok(Some((record.paint(offset_data)?, id)))
65 }
66
67 pub fn v1_layer(&self, index: usize) -> Result<(Paint<'a>, PaintId), ReadError> {
72 let list = self.layer_list().ok_or(ReadError::NullOffset)??;
73 let offset = list
74 .paint_offsets()
75 .get(index)
76 .ok_or(ReadError::OutOfBounds)?
77 .get();
78 let offset_data = list.offset_data();
79 let id = offset.to_u32() as usize + offset_data.as_ref().as_ptr() as usize;
82 Ok((offset.resolve(offset_data)?, id))
83 }
84
85 pub fn v1_clip_box(&self, glyph_id: GlyphId) -> Result<Option<ClipBox<'a>>, ReadError> {
87 use core::cmp::Ordering;
88 let Ok(glyph_id): Result<GlyphId16, _> = glyph_id.try_into() else {
89 return Ok(None);
90 };
91 let list = self.clip_list().ok_or(ReadError::NullOffset)??;
92 let clips = list.clips();
93 let clip = match clips.binary_search_by(|clip| {
94 if glyph_id < clip.start_glyph_id() {
95 Ordering::Greater
96 } else if glyph_id > clip.end_glyph_id() {
97 Ordering::Less
98 } else {
99 Ordering::Equal
100 }
101 }) {
102 Ok(ix) => &clips[ix],
103 _ => return Ok(None),
104 };
105 Ok(Some(clip.clip_box(list.offset_data())?))
106 }
107}