Skip to content

Commit 1b5175d

Browse files
authored
[read-fonts] add mapping/iter support to CmapSubtable (googlefonts#1656)
Moving towards making all of the skrifa charmap functionality available in read-fonts to reduce code duplication.
1 parent caab2c5 commit 1b5175d

File tree

1 file changed

+73
-9
lines changed

1 file changed

+73
-9
lines changed

read-fonts/src/tables/cmap.rs

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,7 @@ impl<'a> Cmap<'a> {
4444
let codepoint = codepoint.into();
4545
for record in self.encoding_records() {
4646
if let Ok(subtable) = record.subtable(self.offset_data()) {
47-
if let Some(gid) = match subtable {
48-
CmapSubtable::Format0(format0) => format0.map_codepoint(codepoint),
49-
CmapSubtable::Format4(format4) => format4.map_codepoint(codepoint),
50-
CmapSubtable::Format6(format6) => format6.map_codepoint(codepoint),
51-
CmapSubtable::Format12(format12) => format12.map_codepoint(codepoint),
52-
CmapSubtable::Format13(format13) => format13.map_codepoint(codepoint),
53-
_ => None,
54-
} {
47+
if let Some(gid) = subtable.map_codepoint(codepoint) {
5548
return Some(gid);
5649
}
5750
}
@@ -162,7 +155,7 @@ impl EncodingRecord {
162155
}
163156
}
164157

165-
impl CmapSubtable<'_> {
158+
impl<'a> CmapSubtable<'a> {
166159
pub fn language(&self) -> u32 {
167160
match self {
168161
Self::Format0(item) => item.language() as u32,
@@ -175,6 +168,77 @@ impl CmapSubtable<'_> {
175168
_ => 0,
176169
}
177170
}
171+
172+
/// Attempts to map the given codepoint to a nominal glyph identifier using
173+
/// the underlying subtable.
174+
#[inline]
175+
pub fn map_codepoint(&self, codepoint: impl Into<u32>) -> Option<GlyphId> {
176+
match self {
177+
Self::Format0(item) => item.map_codepoint(codepoint),
178+
Self::Format4(item) => item.map_codepoint(codepoint),
179+
Self::Format6(item) => item.map_codepoint(codepoint),
180+
Self::Format10(item) => item.map_codepoint(codepoint),
181+
Self::Format12(item) => item.map_codepoint(codepoint),
182+
Self::Format13(item) => item.map_codepoint(codepoint),
183+
_ => None,
184+
}
185+
}
186+
187+
/// Returns an iterator over all (codepoint, glyph identifier) pairs
188+
/// in the subtable.
189+
///
190+
/// Malicious and malformed fonts can produce a large number of invalid
191+
/// pairs. Use [`Self::iter_with_limits`] to generate a pruned sequence
192+
/// that is limited to reasonable values.
193+
pub fn iter(&self) -> CmapSubtableIter<'a> {
194+
let limits = CmapIterLimits {
195+
max_char: u32::MAX,
196+
glyph_count: u32::MAX,
197+
};
198+
self.iter_with_limits(limits)
199+
}
200+
201+
/// Returns an iterator over all (codepoint, glyph identifier) pairs
202+
/// in the subtable within the given limits.
203+
pub fn iter_with_limits(&self, limits: CmapIterLimits) -> CmapSubtableIter<'a> {
204+
match self {
205+
Self::Format4(item) => CmapSubtableIter::Format4(item.iter()),
206+
Self::Format6(item) => CmapSubtableIter::Format6(item.iter()),
207+
Self::Format10(item) => CmapSubtableIter::Format10(item.iter()),
208+
Self::Format12(item) => CmapSubtableIter::Format12(item.iter_with_limits(limits)),
209+
Self::Format13(item) => CmapSubtableIter::Format13(item.iter_with_limits(limits)),
210+
_ => CmapSubtableIter::None,
211+
}
212+
}
213+
}
214+
215+
/// Iterator over all (codepoint, glyph identifier) pairs in
216+
/// the subtable.
217+
#[derive(Clone)]
218+
#[non_exhaustive]
219+
pub enum CmapSubtableIter<'a> {
220+
None,
221+
Format4(Cmap4Iter<'a>),
222+
Format6(Cmap6Iter<'a>),
223+
Format10(Cmap10Iter<'a>),
224+
Format12(Cmap12Iter<'a>),
225+
Format13(Cmap13Iter<'a>),
226+
}
227+
228+
impl<'a> Iterator for CmapSubtableIter<'a> {
229+
type Item = (u32, GlyphId);
230+
231+
#[inline]
232+
fn next(&mut self) -> Option<Self::Item> {
233+
match self {
234+
Self::None => None,
235+
Self::Format4(iter) => iter.next(),
236+
Self::Format6(iter) => iter.next(),
237+
Self::Format10(iter) => iter.next(),
238+
Self::Format12(iter) => iter.next(),
239+
Self::Format13(iter) => iter.next(),
240+
}
241+
}
178242
}
179243

180244
impl Cmap0<'_> {

0 commit comments

Comments
 (0)