@@ -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
180244impl Cmap0 < ' _ > {
0 commit comments