1 #![allow(unknown_lints)]
2 #![warn(clippy)]
3 #![allow(too_many_arguments, cast_lossless, many_single_char_names,)]
4 
5 extern crate byteorder;
6 
7 use byteorder::{BigEndian as BE, ByteOrder};
8 use std::ops::Deref;
9 
10 #[derive(Clone, Debug)]
11 pub struct FontInfo<Data: Deref<Target = [u8]>> {
12     data: Data, // pointer to .ttf file
13     // fontstart: usize,       // offset of start of font
14     num_glyphs: u32, // number of glyphs, needed for range checking
15     loca: u32,
16     head: u32,
17     glyf: u32,
18     hhea: u32,
19     hmtx: u32,
20     name: u32,
21     kern: u32,                // table locations as offset from start of .ttf
22     index_map: u32,           // a cmap mapping for our chosen character encoding
23     index_to_loc_format: u32, // format needed to map from glyph index to glyph
24 }
25 
26 #[derive(Copy, Clone, Debug)]
27 #[repr(C)]
28 pub struct Vertex {
29     pub x: i16,
30     pub y: i16,
31     pub cx: i16,
32     pub cy: i16,
33     type_: u8,
34 }
35 
36 impl Vertex {
vertex_type(&self) -> VertexType37     pub fn vertex_type(&self) -> VertexType {
38         match self.type_ {
39             1 => VertexType::MoveTo,
40             2 => VertexType::LineTo,
41             3 => VertexType::CurveTo,
42             type_ => panic!("Invalid vertex type: {}", type_),
43         }
44     }
45 }
46 
47 #[test]
test_vertex_type()48 fn test_vertex_type() {
49     fn v(type_: VertexType) -> Vertex {
50         Vertex {
51             x: 0,
52             y: 0,
53             cx: 0,
54             cy: 0,
55             type_: type_ as u8,
56         }
57     }
58     assert_eq!(v(VertexType::MoveTo).vertex_type(), VertexType::MoveTo);
59     assert_eq!(v(VertexType::LineTo).vertex_type(), VertexType::LineTo);
60     assert_eq!(v(VertexType::CurveTo).vertex_type(), VertexType::CurveTo);
61 }
62 
63 #[test]
64 #[should_panic]
test_invalid_vertex_type()65 fn test_invalid_vertex_type() {
66     let v = Vertex {
67         x: 0,
68         y: 0,
69         cx: 0,
70         cy: 0,
71         type_: 255,
72     };
73     let s = match v.vertex_type() {
74         VertexType::MoveTo => "move to",
75         VertexType::LineTo => "line to",
76         VertexType::CurveTo => "curve to",
77     };
78     // With `Vertex::vertex_type` defined as `transmute` this would be undefined
79     // behavior:
80     println!("{}", s);
81 }
82 
83 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
84 #[repr(u8)]
85 pub enum VertexType {
86     MoveTo = 1,
87     LineTo = 2,
88     CurveTo = 3,
89 }
90 
91 #[derive(Copy, Clone, Debug)]
92 pub struct Rect<T> {
93     pub x0: T,
94     pub y0: T,
95     pub x1: T,
96     pub y1: T,
97 }
98 
99 #[derive(Copy, Clone, Debug)]
100 pub struct HMetrics {
101     pub advance_width: i32,
102     pub left_side_bearing: i32,
103 }
104 
105 #[derive(Copy, Clone, Debug)]
106 pub struct VMetrics {
107     pub ascent: i32,
108     pub descent: i32,
109     pub line_gap: i32,
110 }
111 
112 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
113 #[repr(C)]
114 pub enum PlatformId {
115     // platformID
116     Unicode = 0,
117     Mac = 1,
118     Iso = 2,
119     Microsoft = 3,
120 }
platform_id(v: u16) -> Option<PlatformId>121 fn platform_id(v: u16) -> Option<PlatformId> {
122     use PlatformId::*;
123     match v {
124         0 => Some(Unicode),
125         1 => Some(Mac),
126         2 => Some(Iso),
127         3 => Some(Microsoft),
128         _ => None,
129     }
130 }
131 
132 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
133 #[repr(C)]
134 #[allow(non_camel_case_types)]
135 pub enum UnicodeEid {
136     // encodingID for PLATFORM_ID_UNICODE
137     Unicode_1_0 = 0,
138     Unicode_1_1 = 1,
139     Iso_10646 = 2,
140     Unicode_2_0_Bmp = 3,
141     Unicode_2_0_Full = 4,
142 }
unicode_eid(v: u16) -> Option<UnicodeEid>143 fn unicode_eid(v: u16) -> Option<UnicodeEid> {
144     use UnicodeEid::*;
145     match v {
146         0 => Some(Unicode_1_0),
147         1 => Some(Unicode_1_1),
148         2 => Some(Iso_10646),
149         3 => Some(Unicode_2_0_Bmp),
150         4 => Some(Unicode_2_0_Full),
151         _ => None,
152     }
153 }
154 
155 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
156 #[repr(C)]
157 pub enum MicrosoftEid {
158     // encodingID for PLATFORM_ID_MICROSOFT
159     Symbol = 0,
160     UnicodeBMP = 1,
161     Shiftjis = 2,
162     UnicodeFull = 10,
163 }
microsoft_eid(v: u16) -> Option<MicrosoftEid>164 fn microsoft_eid(v: u16) -> Option<MicrosoftEid> {
165     use MicrosoftEid::*;
166     match v {
167         0 => Some(Symbol),
168         1 => Some(UnicodeBMP),
169         2 => Some(Shiftjis),
170         10 => Some(UnicodeFull),
171         _ => None,
172     }
173 }
174 
175 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
176 #[repr(C)]
177 pub enum MacEid {
178     // encodingID for PLATFORM_ID_MAC; same as Script Manager codes
179     Roman = 0,
180     Arabic = 4,
181     Japanese = 1,
182     Hebrew = 5,
183     ChineseTrad = 2,
184     Greek = 6,
185     Korean = 3,
186     Russian = 7,
187 }
mac_eid(v: u16) -> Option<MacEid>188 fn mac_eid(v: u16) -> Option<MacEid> {
189     use MacEid::*;
190     match v {
191         0 => Some(Roman),
192         1 => Some(Japanese),
193         2 => Some(ChineseTrad),
194         3 => Some(Korean),
195         4 => Some(Arabic),
196         5 => Some(Hebrew),
197         6 => Some(Greek),
198         7 => Some(Russian),
199         _ => None,
200     }
201 }
202 
203 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
204 #[repr(C)]
205 pub enum MicrosoftLang {
206     // languageID for PLATFORM_ID_MICROSOFT; same as LCID...
207     // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
208     English = 0x0409,
209     Italian = 0x0410,
210     Chinese = 0x0804,
211     Japanese = 0x0411,
212     Dutch = 0x0413,
213     Korean = 0x0412,
214     French = 0x040c,
215     Russian = 0x0419,
216     German = 0x0407,
217     // Spanish = 0x0409,
218     Hebrew = 0x040d,
219     Swedish = 0x041D,
220 }
microsoft_lang(v: u16) -> Option<MicrosoftLang>221 fn microsoft_lang(v: u16) -> Option<MicrosoftLang> {
222     use MicrosoftLang::*;
223     match v {
224         0x0409 => Some(English),
225         0x0804 => Some(Chinese),
226         0x0413 => Some(Dutch),
227         0x040c => Some(French),
228         0x0407 => Some(German),
229         0x040d => Some(Hebrew),
230         0x0410 => Some(Italian),
231         0x0411 => Some(Japanese),
232         0x0412 => Some(Korean),
233         0x0419 => Some(Russian),
234         0x041D => Some(Swedish),
235         _ => None,
236     }
237 }
238 
239 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
240 #[repr(C)]
241 pub enum MacLang {
242     // languageID for PLATFORM_ID_MAC
243     English = 0,
244     Japanese = 11,
245     Arabic = 12,
246     Korean = 23,
247     Dutch = 4,
248     Russian = 32,
249     French = 1,
250     Spanish = 6,
251     German = 2,
252     Swedish = 5,
253     Hebrew = 10,
254     ChineseSimplified = 33,
255     Italian = 3,
256     ChineseTrad = 19,
257 }
mac_lang(v: u16) -> Option<MacLang>258 fn mac_lang(v: u16) -> Option<MacLang> {
259     use MacLang::*;
260     match v {
261         0 => Some(English),
262         12 => Some(Arabic),
263         4 => Some(Dutch),
264         1 => Some(French),
265         2 => Some(German),
266         10 => Some(Hebrew),
267         3 => Some(Italian),
268         11 => Some(Japanese),
269         23 => Some(Korean),
270         32 => Some(Russian),
271         6 => Some(Spanish),
272         5 => Some(Swedish),
273         33 => Some(ChineseSimplified),
274         19 => Some(ChineseTrad),
275         _ => None,
276     }
277 }
278 
279 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
280 pub enum PlatformEncodingLanguageId {
281     Unicode(Option<Result<UnicodeEid, u16>>, Option<u16>),
282     Mac(Option<Result<MacEid, u16>>, Option<Result<MacLang, u16>>),
283     Iso(Option<u16>, Option<u16>),
284     Microsoft(
285         Option<Result<MicrosoftEid, u16>>,
286         Option<Result<MicrosoftLang, u16>>,
287     ),
288 }
platform_encoding_id( platform_id: PlatformId, encoding_id: Option<u16>, language_id: Option<u16>, ) -> PlatformEncodingLanguageId289 fn platform_encoding_id(
290     platform_id: PlatformId,
291     encoding_id: Option<u16>,
292     language_id: Option<u16>,
293 ) -> PlatformEncodingLanguageId {
294     match platform_id {
295         PlatformId::Unicode => PlatformEncodingLanguageId::Unicode(
296             encoding_id.map(|id| unicode_eid(id).ok_or(id)),
297             language_id,
298         ),
299         PlatformId::Mac => PlatformEncodingLanguageId::Mac(
300             encoding_id.map(|id| mac_eid(id).ok_or(id)),
301             language_id.map(|id| mac_lang(id).ok_or(id)),
302         ),
303         PlatformId::Iso => PlatformEncodingLanguageId::Iso(encoding_id, language_id),
304         PlatformId::Microsoft => PlatformEncodingLanguageId::Microsoft(
305             encoding_id.map(|id| microsoft_eid(id).ok_or(id)),
306             language_id.map(|id| microsoft_lang(id).ok_or(id)),
307         ),
308     }
309 }
310 
311 // # accessors to parse data from file
312 
313 // on platforms that don't allow misaligned reads, if we want to allow
314 // truetype fonts that aren't padded to alignment, define
315 // ALLOW_UNALIGNED_TRUETYPE
316 
317 /// Return `true` if `data` holds a font stored in a format this crate
318 /// recognizes, according to its signature in the initial bytes.
is_font(data: &[u8]) -> bool319 pub fn is_font(data: &[u8]) -> bool {
320     if data.len() >= 4 {
321         let tag = &data[0..4];
322         tag == [b'1', 0, 0, 0] || tag == b"typ1" || tag == b"OTTO" || tag == [0, 1, 0, 0]
323     } else {
324         false
325     }
326 }
327 
328 /// Return `true` if `data` holds a TrueType Collection, according to its
329 /// signature in the initial bytes. A TrueType Collection stores several fonts
330 /// in a single file, allowing them to share data for glyphs they have in
331 /// common.
is_collection(data: &[u8]) -> bool332 pub fn is_collection(data: &[u8]) -> bool {
333     data.len() >= 4 && &data[0..4] == b"ttcf"
334 }
335 
find_table(data: &[u8], fontstart: usize, tag: &[u8]) -> u32336 fn find_table(data: &[u8], fontstart: usize, tag: &[u8]) -> u32 {
337     let num_tables = BE::read_u16(&data[fontstart + 4..]);
338     let tabledir = fontstart + 12;
339     for i in 0..num_tables {
340         let loc = tabledir + 16 * (i as usize);
341         if &data[loc..loc + 4] == tag {
342             return BE::read_u32(&data[loc + 8..]);
343         }
344     }
345     0
346 }
347 
348 /// Each .ttf/.ttc file may have more than one font. Each font has a sequential
349 /// index number starting from 0. Call this function to get the font offset for
350 /// a given index; it returns None if the index is out of range. A regular .ttf
351 /// file will only define one font and it always be at offset 0, so it will
352 /// return Some(0) for index 0, and None for all other indices. You can just
353 /// skip this step if you know it's that kind of font.
get_font_offset_for_index(font_collection: &[u8], index: i32) -> Option<u32>354 pub fn get_font_offset_for_index(font_collection: &[u8], index: i32) -> Option<u32> {
355     // if it's just a font, there's only one valid index
356     if is_font(font_collection) {
357         return if index == 0 { Some(0) } else { None };
358     }
359     // check if it's a TTC
360     if is_collection(font_collection)
361         && (BE::read_u32(&font_collection[4..]) == 0x0001_0000
362             || BE::read_u32(&font_collection[4..]) == 0x0002_0000)
363     {
364         let n = BE::read_i32(&font_collection[8..]);
365         if index >= n {
366             return None;
367         }
368         return Some(BE::read_u32(&font_collection[12 + (index as usize) * 4..]));
369     }
370     None
371 }
372 
373 macro_rules! read_ints {
374     ($n:expr, i16, $data:expr) => {{
375         let mut nums = [0; $n];
376         let data = $data;
377         BE::read_i16_into(&data[..$n * 2], &mut nums);
378         nums
379     }};
380     ($n:expr, u16, $data:expr) => {{
381         let mut nums = [0; $n];
382         let data = $data;
383         BE::read_u16_into(&data[..$n * 2], &mut nums);
384         nums
385     }};
386     ($n:expr, u32, $data:expr) => {{
387         let mut nums = [0; $n];
388         let data = $data;
389         BE::read_u32_into(&data[..$n * 4], &mut nums);
390         nums
391     }};
392 }
393 
394 impl<Data: Deref<Target = [u8]>> FontInfo<Data> {
395     /// Given an offset into the file that defines a font, this function builds
396     /// the necessary cached info for the rest of the system.
new(data: Data, fontstart: usize) -> Option<FontInfo<Data>>397     pub fn new(data: Data, fontstart: usize) -> Option<FontInfo<Data>> {
398         let cmap = find_table(&data, fontstart, b"cmap"); // required
399         let loca = find_table(&data, fontstart, b"loca"); // required
400         let head = find_table(&data, fontstart, b"head"); // required
401         let glyf = find_table(&data, fontstart, b"glyf"); // required
402         let hhea = find_table(&data, fontstart, b"hhea"); // required
403         let hmtx = find_table(&data, fontstart, b"hmtx"); // required
404         let name = find_table(&data, fontstart, b"name"); // not required
405         let kern = find_table(&data, fontstart, b"kern"); // not required
406         if cmap == 0 || loca == 0 || head == 0 || glyf == 0 || hhea == 0 || hmtx == 0 {
407             return None;
408         }
409         let t = find_table(&data, fontstart, b"maxp");
410         let num_glyphs = if t != 0 {
411             BE::read_u16(&data[t as usize + 4..])
412         } else {
413             0xffff
414         };
415 
416         // find a cmap encoding table we understand *now* to avoid searching
417         // later. (todo: could make this installable)
418         // the same regardless of glyph.
419         let num_tables = BE::read_u16(&data[cmap as usize + 2..]);
420         let mut index_map = 0;
421         for i in 0..num_tables {
422             let encoding_record = (cmap + 4 + 8 * (i as u32)) as usize;
423             // find an encoding we understand:
424             match platform_id(BE::read_u16(&data[encoding_record..])) {
425                 Some(PlatformId::Microsoft) => {
426                     match microsoft_eid(BE::read_u16(&data[encoding_record + 2..])) {
427                         Some(MicrosoftEid::UnicodeBMP) | Some(MicrosoftEid::UnicodeFull) => {
428                             // MS/Unicode
429                             index_map = cmap + BE::read_u32(&data[encoding_record + 4..]);
430                         }
431                         _ => (),
432                     }
433                 }
434                 Some(PlatformId::Unicode) => {
435                     // Mac/iOS has these
436                     // all the encodingIDs are unicode, so we don't bother to check it
437                     index_map = cmap + BE::read_u32(&data[encoding_record + 4..]);
438                 }
439                 _ => (),
440             }
441         }
442         if index_map == 0 {
443             return None;
444         }
445         let index_to_loc_format = BE::read_u16(&data[head as usize + 50..]) as u32;
446         Some(FontInfo {
447             // fontstart: fontstart,
448             data,
449             loca,
450             head,
451             glyf,
452             hhea,
453             hmtx,
454             name,
455             kern,
456             num_glyphs: num_glyphs as u32,
457             index_map,
458             index_to_loc_format,
459         })
460     }
461 
get_num_glyphs(&self) -> u32462     pub fn get_num_glyphs(&self) -> u32 {
463         self.num_glyphs
464     }
465 
466     /// If you're going to perform multiple operations on the same character
467     /// and you want a speed-up, call this function with the character you're
468     /// going to process, then use glyph-based functions instead of the
469     /// codepoint-based functions.
find_glyph_index(&self, unicode_codepoint: u32) -> u32470     pub fn find_glyph_index(&self, unicode_codepoint: u32) -> u32 {
471         let data = &self.data;
472         let index_map = &data[self.index_map as usize..]; //self.index_map as usize;
473 
474         let format = BE::read_u16(index_map);
475         match format {
476             0 => {
477                 // apple byte encoding
478                 let bytes = BE::read_u16(&index_map[2..]);
479                 if unicode_codepoint < bytes as u32 - 6 {
480                     return index_map[6 + unicode_codepoint as usize] as u32;
481                 }
482                 0
483             }
484             6 => {
485                 let first = BE::read_u16(&index_map[6..]) as u32;
486                 let count = BE::read_u16(&index_map[8..]) as u32;
487                 if unicode_codepoint >= first && unicode_codepoint < first + count {
488                     return BE::read_u16(&index_map[10 + (unicode_codepoint - first) as usize * 2..])
489                         as u32;
490                 }
491                 0
492             }
493             2 => {
494                 // @TODO: high-byte mapping for japanese/chinese/korean
495                 panic!("Index map format unsupported: 2");
496             }
497             4 => {
498                 // standard mapping for windows fonts: binary search collection of ranges
499                 let segcount = BE::read_u16(&index_map[6..]) as usize >> 1;
500                 let mut search_range = BE::read_u16(&index_map[8..]) as usize >> 1;
501                 let mut entry_selector = BE::read_u16(&index_map[10..]);
502                 let range_shift = BE::read_u16(&index_map[12..]) as usize >> 1;
503 
504                 // do a binary search of the segments
505                 let end_count = self.index_map as usize + 14;
506                 let mut search = end_count;
507 
508                 if unicode_codepoint > 0xffff {
509                     return 0;
510                 }
511 
512                 // they lie from endCount .. endCount + segCount
513                 // but searchRange is the nearest power of two, so...
514                 if unicode_codepoint >= BE::read_u16(&data[search + range_shift * 2..]) as u32 {
515                     search += range_shift * 2;
516                 }
517 
518                 // now decrement to bias correctly to find smallest
519                 search -= 2;
520                 while entry_selector != 0 {
521                     search_range >>= 1;
522                     let end = BE::read_u16(&data[search + search_range * 2..]) as u32;
523                     if unicode_codepoint > end {
524                         search += search_range * 2;
525                     }
526                     entry_selector -= 1;
527                 }
528                 search += 2;
529 
530                 {
531                     let item = (search - end_count) >> 1;
532                     assert!(
533                         unicode_codepoint <= BE::read_u16(&data[end_count + 2 * item..]) as u32
534                     );
535                     let start = BE::read_u16(&index_map[14 + segcount * 2 + 2 + 2 * item..]) as u32;
536                     if unicode_codepoint < start {
537                         return 0;
538                     }
539                     let offset =
540                         BE::read_u16(&index_map[14 + segcount * 6 + 2 + 2 * item..]) as usize;
541                     if offset == 0 {
542                         return (unicode_codepoint as i32 + BE::read_i16(
543                             &index_map[14 + segcount * 4 + 2 + 2 * item..],
544                         ) as i32) as u16 as u32;
545                     }
546                     BE::read_u16(
547                         &index_map[offset
548                                        + (unicode_codepoint - start) as usize * 2
549                                        + 14
550                                        + segcount * 6
551                                        + 2
552                                        + 2 * item..],
553                     ) as u32
554                 }
555             }
556             12 | 13 => {
557                 let mut low = 0u32;
558                 let mut high = BE::read_u32(&index_map[12..]);
559                 let groups = &index_map[16..];
560 
561                 // Binary search of the right group
562                 while low < high {
563                     let mid = (low + high) / 2; // rounds down, so low <= mid < high
564                     let mid12 = (mid * 12) as usize;
565                     let group = &groups[mid12..mid12 + 12];
566                     let start_char = BE::read_u32(group);
567                     if unicode_codepoint < start_char {
568                         high = mid;
569                     } else if unicode_codepoint > BE::read_u32(&group[4..]) {
570                         low = mid + 1;
571                     } else {
572                         let start_glyph = BE::read_u32(&group[8..]);
573                         if format == 12 {
574                             return start_glyph + unicode_codepoint - start_char;
575                         } else {
576                             return start_glyph;
577                         }
578                     }
579                 }
580 
581                 0
582             }
583             n => panic!("Index map format unsupported: {}", n),
584         }
585     }
586 
587     /// Returns the series of vertices encoding the shape of the glyph for this
588     /// codepoint.
589     ///
590     /// The shape is a series of countours. Each one starts with
591     /// a moveto, then consists of a series of mixed
592     /// lineto and curveto segments. A lineto
593     /// draws a line from previous endpoint to its x,y; a curveto
594     /// draws a quadratic bezier from previous endpoint to
595     /// its x,y, using cx,cy as the bezier control point.
get_codepoint_shape(&self, unicode_codepoint: u32) -> Option<Vec<Vertex>>596     pub fn get_codepoint_shape(&self, unicode_codepoint: u32) -> Option<Vec<Vertex>> {
597         self.get_glyph_shape(self.find_glyph_index(unicode_codepoint))
598     }
599 
get_glyf_offset(&self, glyph_index: u32) -> Option<u32>600     fn get_glyf_offset(&self, glyph_index: u32) -> Option<u32> {
601         if glyph_index >= self.num_glyphs || self.index_to_loc_format >= 2 {
602             // glyph index out of range or unknown index->glyph map format
603             return None;
604         }
605 
606         let [g1, g2] = if self.index_to_loc_format == 0 {
607             let d = &self.data[(self.loca + glyph_index * 2) as usize..];
608             let [g1, g2] = read_ints!(2, u16, d);
609             [g1 as u32 * 2, g2 as u32 * 2]
610         } else {
611             read_ints!(2, u32, &self.data[(self.loca + glyph_index * 4) as usize..])
612         };
613         if g1 == g2 {
614             None
615         } else {
616             Some(self.glyf + g1)
617         }
618     }
619 
620     /// Like `get_codepoint_box`, but takes a glyph index. Use this if you have
621     /// cached the glyph index for a codepoint.
get_glyph_box(&self, glyph_index: u32) -> Option<Rect<i16>>622     pub fn get_glyph_box(&self, glyph_index: u32) -> Option<Rect<i16>> {
623         let g = self.get_glyf_offset(glyph_index)? as usize;
624         let [x0, y0, x1, y1] = read_ints!(4, i16, &self.data[g + 2..]);
625         Some(Rect { x0, y0, x1, y1 })
626     }
627 
628     /// Gets the bounding box of the visible part of the glyph, in unscaled
629     /// coordinates
get_codepoint_box(&self, codepoint: u32) -> Option<Rect<i16>>630     pub fn get_codepoint_box(&self, codepoint: u32) -> Option<Rect<i16>> {
631         self.get_glyph_box(self.find_glyph_index(codepoint))
632     }
633 
634     /// returns true if nothing is drawn for this glyph
is_glyph_empty(&self, glyph_index: u32) -> bool635     pub fn is_glyph_empty(&self, glyph_index: u32) -> bool {
636         match self.get_glyf_offset(glyph_index) {
637             Some(g) => {
638                 let number_of_contours = BE::read_i16(&self.data[g as usize..]);
639                 number_of_contours == 0
640             }
641             None => true,
642         }
643     }
644 
645     /// Like `get_codepoint_shape`, but takes a glyph index instead. Use this
646     /// if you have cached the glyph index for a codepoint.
get_glyph_shape(&self, glyph_index: u32) -> Option<Vec<Vertex>>647     pub fn get_glyph_shape(&self, glyph_index: u32) -> Option<Vec<Vertex>> {
648         let g = match self.get_glyf_offset(glyph_index) {
649             Some(g) => &self.data[g as usize..],
650             None => return None,
651         };
652 
653         let number_of_contours = BE::read_i16(g);
654         let vertices: Vec<Vertex> = if number_of_contours > 0 {
655             self.glyph_shape_positive_contours(g, number_of_contours as usize)
656         } else if number_of_contours == -1 {
657             // Compound shapes
658             let mut more = true;
659             let mut comp = &g[10..];
660             let mut vertices = Vec::new();
661             while more {
662                 let mut mtx = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0];
663 
664                 let [flags, gidx] = read_ints!(2, i16, comp);
665                 comp = &comp[4..];
666                 let gidx = gidx as u16;
667 
668                 if flags & 2 != 0 {
669                     // XY values
670                     if flags & 1 != 0 {
671                         // shorts
672                         let [a, b] = read_ints!(2, i16, comp);
673                         comp = &comp[4..];
674                         mtx[4] = a as f32;
675                         mtx[5] = b as f32;
676                     } else {
677                         mtx[4] = (comp[0] as i8) as f32;
678                         mtx[5] = (comp[1] as i8) as f32;
679                         comp = &comp[2..];
680                     }
681                 } else {
682                     panic!("Matching points not supported.");
683                 }
684                 if flags & (1 << 3) != 0 {
685                     // WE_HAVE_A_SCALE
686                     mtx[0] = BE::read_i16(comp) as f32 / 16384.0;
687                     comp = &comp[2..];
688                     mtx[1] = 0.0;
689                     mtx[2] = 0.0;
690                     mtx[3] = mtx[0];
691                 } else if flags & (1 << 6) != 0 {
692                     // WE_HAVE_AN_X_AND_YSCALE
693                     let [a, b] = read_ints!(2, i16, comp);
694                     comp = &comp[4..];
695                     mtx[0] = a as f32 / 16384.0;
696                     mtx[1] = 0.0;
697                     mtx[2] = 0.0;
698                     mtx[3] = b as f32 / 16384.0;
699                 } else if flags & (1 << 7) != 0 {
700                     // WE_HAVE_A_TWO_BY_TWO
701                     let [a, b, c, d] = read_ints!(4, i16, comp);
702                     comp = &comp[8..];
703                     mtx[0] = a as f32 / 16384.0;
704                     mtx[1] = b as f32 / 16384.0;
705                     mtx[2] = c as f32 / 16384.0;
706                     mtx[3] = d as f32 / 16384.0;
707                 }
708 
709                 // Find transformation scales.
710                 let m = (mtx[0] * mtx[0] + mtx[1] * mtx[1]).sqrt();
711                 let n = (mtx[2] * mtx[2] + mtx[3] * mtx[3]).sqrt();
712 
713                 // Get indexed glyph.
714                 let mut comp_verts = self.get_glyph_shape(gidx as u32).unwrap_or_else(Vec::new);
715                 if !comp_verts.is_empty() {
716                     // Transform vertices
717                     for v in &mut *comp_verts {
718                         let (x, y, cx, cy) = (v.x as f32, v.y as f32, v.cx as f32, v.cy as f32);
719                         *v = Vertex {
720                             type_: v.type_,
721                             x: (m * (mtx[0] * x + mtx[2] * y + mtx[4])) as i16,
722                             y: (n * (mtx[1] * x + mtx[3] * y + mtx[5])) as i16,
723                             cx: (m * (mtx[0] * cx + mtx[2] * cy + mtx[4])) as i16,
724                             cy: (n * (mtx[1] * cx + mtx[3] * cy + mtx[5])) as i16,
725                         };
726                     }
727                     // Append vertices.
728                     vertices.append(&mut comp_verts);
729                 }
730                 // More components ?
731                 more = flags & (1 << 5) != 0;
732             }
733             vertices
734         } else if number_of_contours < 0 {
735             panic!("Contour format not supported.")
736         } else {
737             return None;
738         };
739         Some(vertices)
740     }
741 
742     #[inline]
glyph_shape_positive_contours( &self, glyph_data: &[u8], number_of_contours: usize, ) -> Vec<Vertex>743     fn glyph_shape_positive_contours(
744         &self,
745         glyph_data: &[u8],
746         number_of_contours: usize,
747     ) -> Vec<Vertex> {
748         use VertexType::*;
749 
750         struct FlagData {
751             flags: u8,
752             x: i16,
753             y: i16,
754         }
755 
756         #[inline]
757         fn close_shape(
758             vertices: &mut Vec<Vertex>,
759             was_off: bool,
760             start_off: bool,
761             sx: i16,
762             sy: i16,
763             scx: i16,
764             scy: i16,
765             cx: i16,
766             cy: i16,
767         ) {
768             if start_off {
769                 if was_off {
770                     vertices.push(Vertex {
771                         type_: CurveTo as u8,
772                         x: (cx + scx) >> 1,
773                         y: (cy + scy) >> 1,
774                         cx,
775                         cy,
776                     });
777                 }
778                 vertices.push(Vertex {
779                     type_: CurveTo as u8,
780                     x: sx,
781                     y: sy,
782                     cx: scx,
783                     cy: scy,
784                 });
785             } else {
786                 vertices.push(if was_off {
787                     Vertex {
788                         type_: CurveTo as u8,
789                         x: sx,
790                         y: sy,
791                         cx,
792                         cy,
793                     }
794                 } else {
795                     Vertex {
796                         type_: LineTo as u8,
797                         x: sx,
798                         y: sy,
799                         cx: 0,
800                         cy: 0,
801                     }
802                 });
803             }
804         }
805 
806         let number_of_contours = number_of_contours as usize;
807         let mut start_off = false;
808         let mut was_off = false;
809         let end_points_of_contours = &glyph_data[10..];
810         let ins = BE::read_u16(&glyph_data[10 + number_of_contours * 2..]) as usize;
811         let mut points = &glyph_data[10 + number_of_contours * 2 + 2 + ins..];
812 
813         let n = 1 + BE::read_u16(&end_points_of_contours[number_of_contours * 2 - 2..]) as usize;
814 
815         let m = n + 2 * number_of_contours; // a loose bound on how many vertices we might need
816         let mut vertices: Vec<Vertex> = Vec::with_capacity(m);
817 
818         let mut flag_data = Vec::with_capacity(n);
819 
820         let mut next_move = 0;
821 
822         // in first pass, we load uninterpreted data into the allocated array above
823 
824         // first load flags
825         {
826             let mut flagcount = 0;
827             let mut flags = 0;
828             for _ in 0..n {
829                 if flagcount == 0 {
830                     flags = points[0];
831                     if flags & 8 != 0 {
832                         flagcount = points[1];
833                         points = &points[2..];
834                     } else {
835                         points = &points[1..];
836                     }
837                 } else {
838                     flagcount -= 1;
839                 }
840                 flag_data.push(FlagData { flags, x: 0, y: 0 });
841             }
842         }
843 
844         // now load x coordinates
845         let mut x_coord = 0_i16;
846         for flag_data in &mut flag_data {
847             let flags = flag_data.flags;
848             if flags & 2 != 0 {
849                 let dx = i16::from(points[0]);
850                 points = &points[1..];
851                 if flags & 16 != 0 {
852                     // ???
853                     x_coord += dx;
854                 } else {
855                     x_coord -= dx;
856                 }
857             } else if flags & 16 == 0 {
858                 x_coord += BE::read_i16(points);
859                 points = &points[2..];
860             }
861             flag_data.x = x_coord;
862         }
863 
864         // now load y coordinates
865         let mut y_coord = 0_i16;
866         for flag_data in &mut flag_data {
867             let flags = flag_data.flags;
868             if flags & 4 != 0 {
869                 let dy = i16::from(points[0]);
870                 points = &points[1..];
871                 if flags & 32 != 0 {
872                     y_coord += dy;
873                 } else {
874                     y_coord -= dy;
875                 }
876             } else if flags & 32 == 0 {
877                 y_coord += BE::read_i16(points);
878                 points = &points[2..];
879             }
880             flag_data.y = y_coord;
881         }
882 
883         // now convert them to our format
884         let mut sx = 0;
885         let mut sy = 0;
886         let mut cx = 0;
887         let mut cy = 0;
888         let mut scx = 0;
889         let mut scy = 0;
890         let mut j = 0;
891 
892         let mut iter = flag_data.into_iter().enumerate().peekable();
893 
894         while let Some((index, FlagData { flags, x, y })) = iter.next() {
895             if next_move == index {
896                 if index != 0 {
897                     close_shape(&mut vertices, was_off, start_off, sx, sy, scx, scy, cx, cy);
898                 }
899 
900                 // now start the new one
901                 start_off = flags & 1 == 0;
902                 if start_off {
903                     // if we start off with an off-curve point, then when we need to find a
904                     // point on the curve where we can start, and we
905                     // need to save some state for
906                     // when we wraparound.
907                     scx = x;
908                     scy = y;
909 
910                     let (next_flags, next_x, next_y) = {
911                         let peek = &iter.peek().unwrap().1;
912                         (peek.flags, peek.x, peek.y)
913                     };
914 
915                     if next_flags & 1 == 0 {
916                         // next point is also a curve point, so interpolate an on-point curve
917                         sx = (x + next_x) >> 1;
918                         sy = (y + next_y) >> 1;
919                     } else {
920                         // otherwise just use the next point as our start point
921                         sx = next_x;
922                         sy = next_y;
923 
924                         // we're using point i+1 as the starting point, so skip it
925                         let _ = iter.next();
926                     }
927                 } else {
928                     sx = x;
929                     sy = y;
930                 }
931                 vertices.push(Vertex {
932                     type_: MoveTo as u8,
933                     x: sx,
934                     y: sy,
935                     cx: 0,
936                     cy: 0,
937                 });
938                 was_off = false;
939                 next_move = 1 + BE::read_u16(&end_points_of_contours[j * 2..]) as usize;
940                 j += 1;
941             } else if flags & 1 == 0 {
942                 // if it's a curve
943                 if was_off {
944                     // two off-curve control points in a row means interpolate an on-curve
945                     // midpoint
946                     vertices.push(Vertex {
947                         type_: CurveTo as u8,
948                         x: ((cx + x) >> 1),
949                         y: ((cy + y) >> 1),
950                         cx,
951                         cy,
952                     });
953                 }
954                 cx = x;
955                 cy = y;
956                 was_off = true;
957             } else {
958                 vertices.push(if was_off {
959                     Vertex {
960                         type_: CurveTo as u8,
961                         x,
962                         y,
963                         cx,
964                         cy,
965                     }
966                 } else {
967                     Vertex {
968                         type_: LineTo as u8,
969                         x,
970                         y,
971                         cx: 0,
972                         cy: 0,
973                     }
974                 });
975                 was_off = false;
976             }
977         }
978         close_shape(
979             &mut vertices,
980             // &mut num_vertices,
981             was_off,
982             start_off,
983             sx,
984             sy,
985             scx,
986             scy,
987             cx,
988             cy,
989         );
990 
991         vertices
992     }
993 
994     /// like `get_codepoint_h_metrics`, but takes a glyph index instead. Use
995     /// this if you have cached the glyph index for a codepoint.
get_glyph_h_metrics(&self, glyph_index: u32) -> HMetrics996     pub fn get_glyph_h_metrics(&self, glyph_index: u32) -> HMetrics {
997         let num_of_long_hor_metrics = BE::read_u16(&self.data[self.hhea as usize + 34..]) as usize;
998         let glyph_index = glyph_index as usize;
999         if glyph_index < num_of_long_hor_metrics {
1000             let data = &self.data[self.hmtx as usize + 4 * glyph_index..];
1001             let [advance_width, left_side_bearing] = read_ints!(2, i16, data);
1002             HMetrics {
1003                 advance_width: i32::from(advance_width),
1004                 left_side_bearing: i32::from(left_side_bearing),
1005             }
1006         } else {
1007             HMetrics {
1008                 advance_width: BE::read_i16(
1009                     &self.data[self.hmtx as usize + 4 * (num_of_long_hor_metrics - 1)..],
1010                 ) as i32,
1011                 left_side_bearing: BE::read_i16(
1012                     &self.data[self.hmtx as usize
1013                                    + 4 * num_of_long_hor_metrics
1014                                    + 2 * (glyph_index as isize - num_of_long_hor_metrics as isize)
1015                                        as usize..],
1016                 ) as i32,
1017             }
1018         }
1019     }
1020 
1021     /// like `get_codepoint_kern_advance`, but takes glyph indices instead. Use
1022     /// this if you have cached the glyph indices for the codepoints.
get_glyph_kern_advance(&self, glyph_1: u32, glyph_2: u32) -> i321023     pub fn get_glyph_kern_advance(&self, glyph_1: u32, glyph_2: u32) -> i32 {
1024         let kern = &self.data[self.kern as usize..];
1025         // we only look at the first table. it must be 'horizontal' and format 0
1026         if self.kern == 0 || BE::read_u16(&kern[2..]) < 1 || BE::read_u16(&kern[8..]) != 1 {
1027             // kern not present, OR
1028             // no tables (need at least one), OR
1029             // horizontal flag not set in format
1030             return 0;
1031         }
1032 
1033         let mut l: i32 = 0;
1034         let mut r: i32 = BE::read_u16(&kern[10..]) as i32 - 1;
1035         let needle = glyph_1 << 16 | glyph_2;
1036         while l <= r {
1037             let m = (l + r) >> 1;
1038             let straw = BE::read_u32(&kern[18 + (m as usize) * 6..]); // note: unaligned read
1039             if needle < straw {
1040                 r = m - 1;
1041             } else if needle > straw {
1042                 l = m + 1;
1043             } else {
1044                 return BE::read_i16(&kern[22 + (m as usize) * 6..]) as i32;
1045             }
1046         }
1047         0
1048     }
1049 
1050     /// an additional amount to add to the 'advance' value between cp1 and cp2
get_codepoint_kern_advance(&self, cp1: u32, cp2: u32) -> i321051     pub fn get_codepoint_kern_advance(&self, cp1: u32, cp2: u32) -> i32 {
1052         if self.kern == 0 {
1053             // if no kerning table, don't waste time looking up both codepoint->glyphs
1054             0
1055         } else {
1056             self.get_glyph_kern_advance(self.find_glyph_index(cp1), self.find_glyph_index(cp2))
1057         }
1058     }
1059 
1060     /// `left_side_bearing` is the offset from the current horizontal position
1061     /// to the left edge of the character `advance_width` is the offset
1062     /// from the current horizontal position to the next horizontal
1063     /// position these are
1064     /// expressed in unscaled
1065     /// coordinates
get_codepoint_h_metrics(&self, codepoint: u32) -> HMetrics1066     pub fn get_codepoint_h_metrics(&self, codepoint: u32) -> HMetrics {
1067         self.get_glyph_h_metrics(self.find_glyph_index(codepoint))
1068     }
1069 
1070     /// `ascent` is the coordinate above the baseline the font extends; descent
1071     /// is the coordinate below the baseline the font extends (i.e. it is
1072     /// typically negative) `line_gap` is the spacing between one row's
1073     /// descent and the next row's ascent... so you should advance the
1074     /// vertical position by `ascent -
1075     /// descent + line_gap` these are expressed in unscaled coordinates, so
1076     /// you must multiply by the scale factor for a given size
get_v_metrics(&self) -> VMetrics1077     pub fn get_v_metrics(&self) -> VMetrics {
1078         let hhea = &self.data[self.hhea as usize..];
1079         let [ascent, descent, line_gap] = read_ints!(3, i16, &hhea[4..]);
1080         VMetrics {
1081             ascent: i32::from(ascent),
1082             descent: i32::from(descent),
1083             line_gap: i32::from(line_gap),
1084         }
1085     }
1086 
1087     /// the bounding box around all possible characters
get_bounding_box(&self) -> Rect<i16>1088     pub fn get_bounding_box(&self) -> Rect<i16> {
1089         let head = &self.data[self.head as usize..];
1090         Rect {
1091             x0: BE::read_i16(&head[36..]),
1092             y0: BE::read_i16(&head[38..]),
1093             x1: BE::read_i16(&head[40..]),
1094             y1: BE::read_i16(&head[42..]),
1095         }
1096     }
1097 
1098     /// computes a scale factor to produce a font whose "height" is 'pixels'
1099     /// tall. Height is measured as the distance from the highest ascender
1100     /// to the lowest descender; in other words, it's equivalent to calling
1101     /// GetFontVMetrics and computing:
1102     ///       scale = pixels / (ascent - descent)
1103     /// so if you prefer to measure height by the ascent only, use a similar
1104     /// calculation.
scale_for_pixel_height(&self, height: f32) -> f321105     pub fn scale_for_pixel_height(&self, height: f32) -> f32 {
1106         let hhea = &self.data[self.hhea as usize..];
1107         let fheight = {
1108             let [a, b] = read_ints!(2, i16, &hhea[4..]);
1109             f32::from(a) - f32::from(b)
1110         };
1111         height / fheight
1112     }
1113 
1114     /// Returns the units per EM square of this font.
units_per_em(&self) -> u161115     pub fn units_per_em(&self) -> u16 {
1116         BE::read_u16(&self.data[self.head as usize + 18..])
1117     }
1118 
1119     /// computes a scale factor to produce a font whose EM size is mapped to
1120     /// `pixels` tall. This is probably what traditional APIs compute, but
1121     /// I'm not positive.
scale_for_mapping_em_to_pixels(&self, pixels: f32) -> f321122     pub fn scale_for_mapping_em_to_pixels(&self, pixels: f32) -> f32 {
1123         pixels / (self.units_per_em() as f32)
1124     }
1125 
1126     /// like `get_codepoint_bitmap_box_subpixel`, but takes a glyph index
1127     /// instead of a codepoint.
get_glyph_bitmap_box_subpixel( &self, glyph: u32, scale_x: f32, scale_y: f32, shift_x: f32, shift_y: f32, ) -> Option<Rect<i32>>1128     pub fn get_glyph_bitmap_box_subpixel(
1129         &self,
1130         glyph: u32,
1131         scale_x: f32,
1132         scale_y: f32,
1133         shift_x: f32,
1134         shift_y: f32,
1135     ) -> Option<Rect<i32>> {
1136         if let Some(glyph_box) = self.get_glyph_box(glyph) {
1137             // move to integral bboxes (treating pixels as little squares, what pixels get
1138             // touched?)
1139             Some(Rect {
1140                 x0: (glyph_box.x0 as f32 * scale_x + shift_x).floor() as i32,
1141                 y0: (-glyph_box.y1 as f32 * scale_y + shift_y).floor() as i32,
1142                 x1: (glyph_box.x1 as f32 * scale_x + shift_x).ceil() as i32,
1143                 y1: (-glyph_box.y0 as f32 * scale_y + shift_y).ceil() as i32,
1144             })
1145         } else {
1146             // e.g. space character
1147             None
1148         }
1149     }
1150 
1151     /// like `get_codepoint_bitmap_box`, but takes a glyph index instead of a
1152     /// codepoint.
get_glyph_bitmap_box( &self, glyph: u32, scale_x: f32, scale_y: f32, ) -> Option<Rect<i32>>1153     pub fn get_glyph_bitmap_box(
1154         &self,
1155         glyph: u32,
1156         scale_x: f32,
1157         scale_y: f32,
1158     ) -> Option<Rect<i32>> {
1159         self.get_glyph_bitmap_box_subpixel(glyph, scale_x, scale_y, 0.0, 0.0)
1160     }
1161 
1162     /// same as get_codepoint_bitmap_box, but you can specify a subpixel
1163     /// shift for the character
get_codepoint_bitmap_box_subpixel( &self, codepoint: u32, scale_x: f32, scale_y: f32, shift_x: f32, shift_y: f32, ) -> Option<Rect<i32>>1164     pub fn get_codepoint_bitmap_box_subpixel(
1165         &self,
1166         codepoint: u32,
1167         scale_x: f32,
1168         scale_y: f32,
1169         shift_x: f32,
1170         shift_y: f32,
1171     ) -> Option<Rect<i32>> {
1172         self.get_glyph_bitmap_box_subpixel(
1173             self.find_glyph_index(codepoint),
1174             scale_x,
1175             scale_y,
1176             shift_x,
1177             shift_y,
1178         )
1179     }
1180 
1181     /// get the bounding box of the bitmap centered around the glyph origin; so
1182     /// the bitmap width is x1-x0, height is y1-y0, and location to place
1183     /// the bitmap top left is (left_side_bearing*scale, y0).
1184     /// (Note that the bitmap uses y-increases-down, but the shape uses
1185     /// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
get_codepoint_bitmap_box( &self, codepoint: u32, scale_x: f32, scale_y: f32, ) -> Option<Rect<i32>>1186     pub fn get_codepoint_bitmap_box(
1187         &self,
1188         codepoint: u32,
1189         scale_x: f32,
1190         scale_y: f32,
1191     ) -> Option<Rect<i32>> {
1192         self.get_codepoint_bitmap_box_subpixel(codepoint, scale_x, scale_y, 0.0, 0.0)
1193     }
1194 
get_font_name_strings(&self) -> FontNameIter<Data>1195     pub fn get_font_name_strings(&self) -> FontNameIter<Data> {
1196         let nm = self.name as usize;
1197         if nm == 0 {
1198             return FontNameIter {
1199                 font_info: &self,
1200                 string_offset: 0,
1201                 index: 0,
1202                 count: 0,
1203             };
1204         }
1205         let count = BE::read_u16(&self.data[nm + 2..]) as usize;
1206         let string_offset = nm + BE::read_u16(&self.data[nm + 4..]) as usize;
1207 
1208         FontNameIter {
1209             font_info: &self,
1210             string_offset,
1211             index: 0,
1212             count,
1213         }
1214     }
1215 }
1216 
1217 #[derive(Clone, Copy)]
1218 pub struct FontNameIter<'a, Data: 'a + Deref<Target = [u8]>> {
1219     /// Font info.
1220     font_info: &'a FontInfo<Data>,
1221     string_offset: usize,
1222     /// Next index.
1223     index: usize,
1224     /// Number of name strings.
1225     count: usize,
1226 }
1227 
1228 impl<'a, Data: 'a + Deref<Target = [u8]>> Iterator for FontNameIter<'a, Data> {
1229     type Item = (&'a [u8], Option<PlatformEncodingLanguageId>, u16);
1230 
next(&mut self) -> Option<Self::Item>1231     fn next(&mut self) -> Option<Self::Item> {
1232         if self.index >= self.count {
1233             return None;
1234         }
1235 
1236         let loc = self.font_info.name as usize + 6 + 12 * self.index;
1237 
1238         let pl_id = platform_id(BE::read_u16(&self.font_info.data[loc..]));
1239         let platform_encoding_language_id = pl_id.map(|pl_id| {
1240             let encoding_id = BE::read_u16(&self.font_info.data[loc + 2..]);
1241             let language_id = BE::read_u16(&self.font_info.data[loc + 4..]);
1242             platform_encoding_id(pl_id, Some(encoding_id), Some(language_id))
1243         });
1244         // @TODO: Define an enum type for Name ID.
1245         //        See https://www.microsoft.com/typography/otspec/name.htm, "Name IDs" section.
1246         let name_id = BE::read_u16(&self.font_info.data[loc + 6..]);
1247         let length = BE::read_u16(&self.font_info.data[loc + 8..]) as usize;
1248         let offset = self.string_offset + BE::read_u16(&self.font_info.data[loc + 10..]) as usize;
1249 
1250         self.index += 1;
1251 
1252         Some((
1253             &self.font_info.data[offset..offset + length],
1254             platform_encoding_language_id,
1255             name_id,
1256         ))
1257     }
1258 
size_hint(&self) -> (usize, Option<usize>)1259     fn size_hint(&self) -> (usize, Option<usize>) {
1260         let remaining = self.count - self.index;
1261         (remaining, Some(remaining))
1262     }
1263 
count(self) -> usize1264     fn count(self) -> usize {
1265         self.count - self.index
1266     }
1267 
last(mut self) -> Option<Self::Item>1268     fn last(mut self) -> Option<Self::Item> {
1269         if self.index >= self.count || self.count == 0 {
1270             return None;
1271         }
1272         self.index = self.count - 1;
1273         self.next()
1274     }
1275 
nth(&mut self, n: usize) -> Option<Self::Item>1276     fn nth(&mut self, n: usize) -> Option<Self::Item> {
1277         if n > self.count - self.index {
1278             self.index = self.count;
1279             return None;
1280         }
1281         self.index += n;
1282         self.next()
1283     }
1284 }
1285