1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use app_units::Au;
6 use euclid::Point2D;
7 use range::{self, EachIndex, Range, RangeIndex};
8 #[cfg(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon")))]
9 use simd::u32x4;
10 use std::{fmt, mem, u16};
11 use std::cmp::{Ordering, PartialOrd};
12 use std::vec::Vec;
13 
14 pub use gfx_traits::ByteIndex;
15 
16 /// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
17 ///
18 /// In the common case (reasonable glyph advances, no offsets from the font em-box, and one glyph
19 /// per character), we pack glyph advance, glyph id, and some flags into a single u32.
20 ///
21 /// In the uncommon case (multiple glyphs per unicode character, large glyph index/advance, or
22 /// glyph offsets), we pack the glyph count into GlyphEntry, and store the other glyph information
23 /// in DetailedGlyphStore.
24 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
25 pub struct GlyphEntry {
26     value: u32,
27 }
28 
29 impl GlyphEntry {
new(value: u32) -> GlyphEntry30     fn new(value: u32) -> GlyphEntry {
31         GlyphEntry {
32             value: value,
33         }
34     }
35 
initial() -> GlyphEntry36     fn initial() -> GlyphEntry {
37         GlyphEntry::new(0)
38     }
39 
40     // Creates a GlyphEntry for the common case
simple(id: GlyphId, advance: Au) -> GlyphEntry41     fn simple(id: GlyphId, advance: Au) -> GlyphEntry {
42         assert!(is_simple_glyph_id(id));
43         assert!(is_simple_advance(advance));
44 
45         let id_mask = id as u32;
46         let Au(advance) = advance;
47         let advance_mask = (advance as u32) << GLYPH_ADVANCE_SHIFT;
48 
49         GlyphEntry::new(id_mask | advance_mask | FLAG_IS_SIMPLE_GLYPH)
50     }
51 
52     // Create a GlyphEntry for uncommon case; should be accompanied by
53     // initialization of the actual DetailedGlyph data in DetailedGlyphStore
complex(starts_cluster: bool, starts_ligature: bool, glyph_count: usize) -> GlyphEntry54     fn complex(starts_cluster: bool, starts_ligature: bool, glyph_count: usize) -> GlyphEntry {
55         assert!(glyph_count <= u16::MAX as usize);
56 
57         debug!("creating complex glyph entry: starts_cluster={}, starts_ligature={}, \
58                 glyph_count={}",
59                starts_cluster,
60                starts_ligature,
61                glyph_count);
62 
63         GlyphEntry::new(glyph_count as u32)
64     }
65 
is_initial(&self) -> bool66     fn is_initial(&self) -> bool {
67         *self == GlyphEntry::initial()
68     }
69 }
70 
71 /// The id of a particular glyph within a font
72 pub type GlyphId = u32;
73 
74 // TODO: make this more type-safe.
75 
76 const FLAG_CHAR_IS_SPACE: u32       = 0x40000000;
77 #[cfg(feature = "unstable")]
78 #[cfg(any(target_feature = "sse2", target_feature = "neon"))]
79 const FLAG_CHAR_IS_SPACE_SHIFT: u32 = 30;
80 const FLAG_IS_SIMPLE_GLYPH: u32     = 0x80000000;
81 
82 // glyph advance; in Au's.
83 const GLYPH_ADVANCE_MASK: u32       = 0x3FFF0000;
84 const GLYPH_ADVANCE_SHIFT: u32      = 16;
85 const GLYPH_ID_MASK: u32            = 0x0000FFFF;
86 
87 // Non-simple glyphs (more than one glyph per char; missing glyph,
88 // newline, tab, large advance, or nonzero x/y offsets) may have one
89 // or more detailed glyphs associated with them. They are stored in a
90 // side array so that there is a 1:1 mapping of GlyphEntry to
91 // unicode char.
92 
93 // The number of detailed glyphs for this char.
94 const GLYPH_COUNT_MASK:              u32 = 0x0000FFFF;
95 
is_simple_glyph_id(id: GlyphId) -> bool96 fn is_simple_glyph_id(id: GlyphId) -> bool {
97     ((id as u32) & GLYPH_ID_MASK) == id
98 }
99 
is_simple_advance(advance: Au) -> bool100 fn is_simple_advance(advance: Au) -> bool {
101     advance >= Au(0) && {
102         let unsigned_au = advance.0 as u32;
103         (unsigned_au & (GLYPH_ADVANCE_MASK >> GLYPH_ADVANCE_SHIFT)) == unsigned_au
104     }
105 }
106 
107 pub type DetailedGlyphCount = u16;
108 
109 // Getters and setters for GlyphEntry. Setter methods are functional,
110 // because GlyphEntry is immutable and only a u32 in size.
111 impl GlyphEntry {
112     #[inline(always)]
advance(&self) -> Au113     fn advance(&self) -> Au {
114         Au::new(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32)
115     }
116 
117     #[inline]
id(&self) -> GlyphId118     fn id(&self) -> GlyphId {
119         self.value & GLYPH_ID_MASK
120     }
121 
122     /// True if original char was normal (U+0020) space. Other chars may
123     /// map to space glyph, but this does not account for them.
char_is_space(&self) -> bool124     fn char_is_space(&self) -> bool {
125         self.has_flag(FLAG_CHAR_IS_SPACE)
126     }
127 
128     #[inline(always)]
set_char_is_space(&mut self)129     fn set_char_is_space(&mut self) {
130         self.value |= FLAG_CHAR_IS_SPACE;
131     }
132 
glyph_count(&self) -> u16133     fn glyph_count(&self) -> u16 {
134         assert!(!self.is_simple());
135         (self.value & GLYPH_COUNT_MASK) as u16
136     }
137 
138     #[inline(always)]
is_simple(&self) -> bool139     fn is_simple(&self) -> bool {
140         self.has_flag(FLAG_IS_SIMPLE_GLYPH)
141     }
142 
143     #[inline(always)]
has_flag(&self, flag: u32) -> bool144     fn has_flag(&self, flag: u32) -> bool {
145         (self.value & flag) != 0
146     }
147 }
148 
149 // Stores data for a detailed glyph, in the case that several glyphs
150 // correspond to one character, or the glyph's data couldn't be packed.
151 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
152 struct DetailedGlyph {
153     id: GlyphId,
154     // glyph's advance, in the text's direction (LTR or RTL)
155     advance: Au,
156     // glyph's offset from the font's em-box (from top-left)
157     offset: Point2D<Au>,
158 }
159 
160 impl DetailedGlyph {
new(id: GlyphId, advance: Au, offset: Point2D<Au>) -> DetailedGlyph161     fn new(id: GlyphId, advance: Au, offset: Point2D<Au>) -> DetailedGlyph {
162         DetailedGlyph {
163             id: id,
164             advance: advance,
165             offset: offset,
166         }
167     }
168 }
169 
170 #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
171 struct DetailedGlyphRecord {
172     // source string offset/GlyphEntry offset in the TextRun
173     entry_offset: ByteIndex,
174     // offset into the detailed glyphs buffer
175     detail_offset: usize,
176 }
177 
178 impl PartialOrd for DetailedGlyphRecord {
partial_cmp(&self, other: &DetailedGlyphRecord) -> Option<Ordering>179     fn partial_cmp(&self, other: &DetailedGlyphRecord) -> Option<Ordering> {
180         self.entry_offset.partial_cmp(&other.entry_offset)
181     }
182 }
183 
184 impl Ord for DetailedGlyphRecord {
cmp(&self, other: &DetailedGlyphRecord) -> Ordering185     fn cmp(&self, other: &DetailedGlyphRecord) -> Ordering {
186         self.entry_offset.cmp(&other.entry_offset)
187     }
188 }
189 
190 // Manages the lookup table for detailed glyphs. Sorting is deferred
191 // until a lookup is actually performed; this matches the expected
192 // usage pattern of setting/appending all the detailed glyphs, and
193 // then querying without setting.
194 #[derive(Clone, Deserialize, Serialize)]
195 struct DetailedGlyphStore {
196     // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector
197     // optimization.
198     detail_buffer: Vec<DetailedGlyph>,
199     // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector
200     // optimization.
201     detail_lookup: Vec<DetailedGlyphRecord>,
202     lookup_is_sorted: bool,
203 }
204 
205 impl<'a> DetailedGlyphStore {
new() -> DetailedGlyphStore206     fn new() -> DetailedGlyphStore {
207         DetailedGlyphStore {
208             detail_buffer: vec!(), // TODO: default size?
209             detail_lookup: vec!(),
210             lookup_is_sorted: false,
211         }
212     }
213 
add_detailed_glyphs_for_entry(&mut self, entry_offset: ByteIndex, glyphs: &[DetailedGlyph])214     fn add_detailed_glyphs_for_entry(&mut self, entry_offset: ByteIndex, glyphs: &[DetailedGlyph]) {
215         let entry = DetailedGlyphRecord {
216             entry_offset: entry_offset,
217             detail_offset: self.detail_buffer.len(),
218         };
219 
220         debug!("Adding entry[off={:?}] for detailed glyphs: {:?}", entry_offset, glyphs);
221 
222         /* TODO: don't actually assert this until asserts are compiled
223         in/out based on severity, debug/release, etc. This assertion
224         would wreck the complexity of the lookup.
225 
226         See Rust Issue #3647, #2228, #3627 for related information.
227 
228         do self.detail_lookup.borrow |arr| {
229             assert !arr.contains(entry)
230         }
231         */
232 
233         self.detail_lookup.push(entry);
234         self.detail_buffer.extend_from_slice(glyphs);
235         self.lookup_is_sorted = false;
236     }
237 
detailed_glyphs_for_entry(&'a self, entry_offset: ByteIndex, count: u16) -> &'a [DetailedGlyph]238     fn detailed_glyphs_for_entry(&'a self, entry_offset: ByteIndex, count: u16)
239                                   -> &'a [DetailedGlyph] {
240         debug!("Requesting detailed glyphs[n={}] for entry[off={:?}]", count, entry_offset);
241 
242         // FIXME: Is this right? --pcwalton
243         // TODO: should fix this somewhere else
244         if count == 0 {
245             return &self.detail_buffer[0..0];
246         }
247 
248         assert!((count as usize) <= self.detail_buffer.len());
249         assert!(self.lookup_is_sorted);
250 
251         let key = DetailedGlyphRecord {
252             entry_offset: entry_offset,
253             detail_offset: 0, // unused
254         };
255 
256         let i = self.detail_lookup.binary_search(&key)
257             .expect("Invalid index not found in detailed glyph lookup table!");
258         let main_detail_offset = self.detail_lookup[i].detail_offset;
259         assert!(main_detail_offset + (count as usize) <= self.detail_buffer.len());
260         // return a slice into the buffer
261         &self.detail_buffer[main_detail_offset .. main_detail_offset + count as usize]
262     }
263 
detailed_glyph_with_index(&'a self, entry_offset: ByteIndex, detail_offset: u16) -> &'a DetailedGlyph264     fn detailed_glyph_with_index(&'a self,
265                                      entry_offset: ByteIndex,
266                                      detail_offset: u16)
267             -> &'a DetailedGlyph {
268         assert!((detail_offset as usize) <= self.detail_buffer.len());
269         assert!(self.lookup_is_sorted);
270 
271         let key = DetailedGlyphRecord {
272             entry_offset: entry_offset,
273             detail_offset: 0, // unused
274         };
275 
276         let i = self.detail_lookup.binary_search(&key)
277             .expect("Invalid index not found in detailed glyph lookup table!");
278         let main_detail_offset = self.detail_lookup[i].detail_offset;
279         assert!(main_detail_offset + (detail_offset as usize) < self.detail_buffer.len());
280         &self.detail_buffer[main_detail_offset + (detail_offset as usize)]
281     }
282 
ensure_sorted(&mut self)283     fn ensure_sorted(&mut self) {
284         if self.lookup_is_sorted {
285             return;
286         }
287 
288         // Sorting a unique vector is surprisingly hard. The following
289         // code is a good argument for using DVecs, but they require
290         // immutable locations thus don't play well with freezing.
291 
292         // Thar be dragons here. You have been warned. (Tips accepted.)
293         let mut unsorted_records: Vec<DetailedGlyphRecord> = vec!();
294         mem::swap(&mut self.detail_lookup, &mut unsorted_records);
295         let mut mut_records: Vec<DetailedGlyphRecord> = unsorted_records;
296         mut_records.sort_by(|a, b| {
297             if a < b {
298                 Ordering::Less
299             } else {
300                 Ordering::Greater
301             }
302         });
303         let mut sorted_records = mut_records;
304         mem::swap(&mut self.detail_lookup, &mut sorted_records);
305 
306         self.lookup_is_sorted = true;
307     }
308 }
309 
310 // This struct is used by GlyphStore clients to provide new glyph data.
311 // It should be allocated on the stack and passed by reference to GlyphStore.
312 #[derive(Clone, Copy)]
313 pub struct GlyphData {
314     id: GlyphId,
315     advance: Au,
316     offset: Point2D<Au>,
317     cluster_start: bool,
318     ligature_start: bool,
319 }
320 
321 impl GlyphData {
322     /// Creates a new entry for one glyph.
new(id: GlyphId, advance: Au, offset: Option<Point2D<Au>>, cluster_start: bool, ligature_start: bool) -> GlyphData323     pub fn new(id: GlyphId,
324                advance: Au,
325                offset: Option<Point2D<Au>>,
326                cluster_start: bool,
327                ligature_start: bool)
328             -> GlyphData {
329         GlyphData {
330             id: id,
331             advance: advance,
332             offset: offset.unwrap_or(Point2D::zero()),
333             cluster_start: cluster_start,
334             ligature_start: ligature_start,
335         }
336     }
337 }
338 
339 // This enum is a proxy that's provided to GlyphStore clients when iterating
340 // through glyphs (either for a particular TextRun offset, or all glyphs).
341 // Rather than eagerly assembling and copying glyph data, it only retrieves
342 // values as they are needed from the GlyphStore, using provided offsets.
343 #[derive(Clone, Copy)]
344 pub enum GlyphInfo<'a> {
345     Simple(&'a GlyphStore, ByteIndex),
346     Detail(&'a GlyphStore, ByteIndex, u16),
347 }
348 
349 impl<'a> GlyphInfo<'a> {
id(self) -> GlyphId350     pub fn id(self) -> GlyphId {
351         match self {
352             GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].id(),
353             GlyphInfo::Detail(store, entry_i, detail_j) => {
354                 store.detail_store.detailed_glyph_with_index(entry_i, detail_j).id
355             }
356         }
357     }
358 
359     #[inline(always)]
360     // FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
advance(self) -> Au361     pub fn advance(self) -> Au {
362         match self {
363             GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].advance(),
364             GlyphInfo::Detail(store, entry_i, detail_j) => {
365                 store.detail_store.detailed_glyph_with_index(entry_i, detail_j).advance
366             }
367         }
368     }
369 
370     #[inline]
offset(self) -> Option<Point2D<Au>>371     pub fn offset(self) -> Option<Point2D<Au>> {
372         match self {
373             GlyphInfo::Simple(_, _) => None,
374             GlyphInfo::Detail(store, entry_i, detail_j) => {
375                 Some(store.detail_store.detailed_glyph_with_index(entry_i, detail_j).offset)
376             }
377         }
378     }
379 
char_is_space(self) -> bool380     pub fn char_is_space(self) -> bool {
381         let (store, entry_i) = match self {
382             GlyphInfo::Simple(store, entry_i) => (store, entry_i),
383             GlyphInfo::Detail(store, entry_i, _) => (store, entry_i),
384         };
385 
386         store.char_is_space(entry_i)
387     }
388 }
389 
390 /// Stores the glyph data belonging to a text run.
391 ///
392 /// Simple glyphs are stored inline in the `entry_buffer`, detailed glyphs are
393 /// stored as pointers into the `detail_store`.
394 ///
395 /// ~~~ascii
396 /// +- GlyphStore --------------------------------+
397 /// |               +---+---+---+---+---+---+---+ |
398 /// | entry_buffer: |   | s |   | s |   | s | s | |  d = detailed
399 /// |               +-|-+---+-|-+---+-|-+---+---+ |  s = simple
400 /// |                 |       |       |           |
401 /// |                 |   +---+-------+           |
402 /// |                 |   |                       |
403 /// |               +-V-+-V-+                     |
404 /// | detail_store: | d | d |                     |
405 /// |               +---+---+                     |
406 /// +---------------------------------------------+
407 /// ~~~
408 #[derive(Clone, Deserialize, Serialize)]
409 pub struct GlyphStore {
410     // TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector
411     // optimization.
412     /// A buffer of glyphs within the text run, in the order in which they
413     /// appear in the input text.
414     /// Any changes will also need to be reflected in
415     /// transmute_entry_buffer_to_u32_buffer().
416     entry_buffer: Vec<GlyphEntry>,
417     /// A store of the detailed glyph data. Detailed glyphs contained in the
418     /// `entry_buffer` point to locations in this data structure.
419     detail_store: DetailedGlyphStore,
420 
421     /// A cache of the advance of the entire glyph store.
422     total_advance: Au,
423     /// A cache of the number of spaces in the entire glyph store.
424     total_spaces: i32,
425 
426     /// Used to check if fast path should be used in glyph iteration.
427     has_detailed_glyphs: bool,
428     is_whitespace: bool,
429     is_rtl: bool,
430 }
431 
432 impl<'a> GlyphStore {
433     /// Initializes the glyph store, but doesn't actually shape anything.
434     ///
435     /// Use the `add_*` methods to store glyph data.
new(length: usize, is_whitespace: bool, is_rtl: bool) -> GlyphStore436     pub fn new(length: usize, is_whitespace: bool, is_rtl: bool) -> GlyphStore {
437         assert!(length > 0);
438 
439         GlyphStore {
440             entry_buffer: vec![GlyphEntry::initial(); length],
441             detail_store: DetailedGlyphStore::new(),
442             total_advance: Au(0),
443             total_spaces: 0,
444             has_detailed_glyphs: false,
445             is_whitespace: is_whitespace,
446             is_rtl: is_rtl,
447         }
448     }
449 
450     #[inline]
len(&self) -> ByteIndex451     pub fn len(&self) -> ByteIndex {
452         ByteIndex(self.entry_buffer.len() as isize)
453     }
454 
455     #[inline]
is_whitespace(&self) -> bool456     pub fn is_whitespace(&self) -> bool {
457         self.is_whitespace
458     }
459 
finalize_changes(&mut self)460     pub fn finalize_changes(&mut self) {
461         self.detail_store.ensure_sorted();
462         self.cache_total_advance_and_spaces()
463     }
464 
465     #[inline(never)]
cache_total_advance_and_spaces(&mut self)466     fn cache_total_advance_and_spaces(&mut self) {
467         let mut total_advance = Au(0);
468         let mut total_spaces = 0;
469         for glyph in self.iter_glyphs_for_byte_range(&Range::new(ByteIndex(0), self.len())) {
470             total_advance = total_advance + glyph.advance();
471             if glyph.char_is_space() {
472                 total_spaces += 1;
473             }
474         }
475         self.total_advance = total_advance;
476         self.total_spaces = total_spaces;
477     }
478 
479     /// Adds a single glyph.
add_glyph_for_byte_index(&mut self, i: ByteIndex, character: char, data: &GlyphData)480     pub fn add_glyph_for_byte_index(&mut self,
481                                     i: ByteIndex,
482                                     character: char,
483                                     data: &GlyphData) {
484         let glyph_is_compressible = is_simple_glyph_id(data.id) &&
485             is_simple_advance(data.advance) &&
486                 data.offset == Point2D::zero() &&
487                 data.cluster_start;  // others are stored in detail buffer
488 
489         debug_assert!(data.ligature_start); // can't compress ligature continuation glyphs.
490         debug_assert!(i < self.len());
491 
492         let mut entry = if glyph_is_compressible {
493             GlyphEntry::simple(data.id, data.advance)
494         } else {
495             let glyph = &[DetailedGlyph::new(data.id, data.advance, data.offset)];
496             self.has_detailed_glyphs = true;
497             self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
498             GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
499         };
500 
501         if character == ' ' {
502             entry.set_char_is_space()
503         }
504 
505         self.entry_buffer[i.to_usize()] = entry;
506     }
507 
add_glyphs_for_byte_index(&mut self, i: ByteIndex, data_for_glyphs: &[GlyphData])508     pub fn add_glyphs_for_byte_index(&mut self, i: ByteIndex, data_for_glyphs: &[GlyphData]) {
509         assert!(i < self.len());
510         assert!(data_for_glyphs.len() > 0);
511 
512         let glyph_count = data_for_glyphs.len();
513 
514         let first_glyph_data = data_for_glyphs[0];
515         let glyphs_vec: Vec<DetailedGlyph> = (0..glyph_count).map(|i| {
516             DetailedGlyph::new(data_for_glyphs[i].id,
517                                data_for_glyphs[i].advance,
518                                data_for_glyphs[i].offset)
519         }).collect();
520 
521         self.has_detailed_glyphs = true;
522         self.detail_store.add_detailed_glyphs_for_entry(i, &glyphs_vec);
523 
524         let entry = GlyphEntry::complex(first_glyph_data.cluster_start,
525                                         first_glyph_data.ligature_start,
526                                         glyph_count);
527 
528         debug!("Adding multiple glyphs[idx={:?}, count={}]: {:?}", i, glyph_count, entry);
529 
530         self.entry_buffer[i.to_usize()] = entry;
531     }
532 
533     #[inline]
iter_glyphs_for_byte_range(&'a self, range: &Range<ByteIndex>) -> GlyphIterator<'a>534     pub fn iter_glyphs_for_byte_range(&'a self, range: &Range<ByteIndex>) -> GlyphIterator<'a> {
535         if range.begin() >= self.len() {
536             panic!("iter_glyphs_for_range: range.begin beyond length!");
537         }
538         if range.end() > self.len() {
539             panic!("iter_glyphs_for_range: range.end beyond length!");
540         }
541 
542         GlyphIterator {
543             store:       self,
544             byte_index:  if self.is_rtl { range.end() } else { range.begin() - ByteIndex(1) },
545             byte_range:  *range,
546             glyph_range: None,
547         }
548     }
549 
550     // Scan the glyphs for a given range until we reach a given advance. Returns the index
551     // and advance of the glyph in the range at the given advance, if reached. Otherwise, returns the
552     // the number of glyphs and the advance for the given range.
553     #[inline]
range_index_of_advance(&self, range: &Range<ByteIndex>, advance: Au, extra_word_spacing: Au) -> (usize, Au)554     pub fn range_index_of_advance(&self, range: &Range<ByteIndex>, advance: Au, extra_word_spacing: Au) -> (usize, Au) {
555         let mut index = 0;
556         let mut current_advance = Au(0);
557         for glyph in self.iter_glyphs_for_byte_range(range) {
558             if glyph.char_is_space() {
559                 current_advance += glyph.advance() + extra_word_spacing
560             } else {
561                 current_advance += glyph.advance()
562             }
563             if current_advance > advance {
564                 break;
565             }
566             index += 1;
567         }
568         (index, current_advance)
569     }
570 
571     #[inline]
advance_for_byte_range(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au572     pub fn advance_for_byte_range(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
573         if range.begin() == ByteIndex(0) && range.end() == self.len() {
574             self.total_advance + extra_word_spacing * self.total_spaces
575         } else if !self.has_detailed_glyphs {
576             self.advance_for_byte_range_simple_glyphs(range, extra_word_spacing)
577         } else {
578             self.advance_for_byte_range_slow_path(range, extra_word_spacing)
579         }
580     }
581 
582     #[inline]
advance_for_byte_range_slow_path(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au583     pub fn advance_for_byte_range_slow_path(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
584         self.iter_glyphs_for_byte_range(range)
585             .fold(Au(0), |advance, glyph| {
586                 if glyph.char_is_space() {
587                     advance + glyph.advance() + extra_word_spacing
588                 } else {
589                     advance + glyph.advance()
590                 }
591             })
592     }
593 
594     #[inline]
595     #[cfg(feature = "unstable")]
596     #[cfg(any(target_feature = "sse2", target_feature = "neon"))]
advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au597     fn advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
598         let advance_mask = u32x4::splat(GLYPH_ADVANCE_MASK);
599         let space_flag_mask = u32x4::splat(FLAG_CHAR_IS_SPACE);
600         let mut simd_advance = u32x4::splat(0);
601         let mut simd_spaces = u32x4::splat(0);
602         let begin = range.begin().to_usize();
603         let len = range.length().to_usize();
604         let num_simd_iterations = len / 4;
605         let leftover_entries = range.end().to_usize() - (len - num_simd_iterations * 4);
606         let buf = self.transmute_entry_buffer_to_u32_buffer();
607 
608         for i in 0..num_simd_iterations {
609             let v = u32x4::load(buf, begin + i * 4);
610             let advance = (v & advance_mask) >> GLYPH_ADVANCE_SHIFT;
611             let spaces = (v & space_flag_mask) >> FLAG_CHAR_IS_SPACE_SHIFT;
612             simd_advance = simd_advance + advance;
613             simd_spaces = simd_spaces + spaces;
614         }
615 
616         let advance =
617             (simd_advance.extract(0) +
618              simd_advance.extract(1) +
619              simd_advance.extract(2) +
620              simd_advance.extract(3)) as i32;
621         let spaces =
622             (simd_spaces.extract(0) +
623              simd_spaces.extract(1) +
624              simd_spaces.extract(2) +
625              simd_spaces.extract(3)) as i32;
626         let mut leftover_advance = Au(0);
627         let mut leftover_spaces = 0;
628         for i in leftover_entries..range.end().to_usize() {
629             leftover_advance = leftover_advance + self.entry_buffer[i].advance();
630             if self.entry_buffer[i].char_is_space() {
631                 leftover_spaces += 1;
632             }
633         }
634         Au::new(advance) + leftover_advance + extra_word_spacing * (spaces + leftover_spaces)
635     }
636 
637     /// When SIMD isn't available, fallback to the slow path.
638     #[inline]
639     #[cfg(not(all(feature = "unstable", any(target_feature = "sse2", target_feature = "neon"))))]
advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au640     fn advance_for_byte_range_simple_glyphs(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
641         self.advance_for_byte_range_slow_path(range, extra_word_spacing)
642     }
643 
644     /// Used for SIMD.
645     #[inline]
646     #[cfg(feature = "unstable")]
647     #[cfg(any(target_feature = "sse2", target_feature = "neon"))]
648     #[allow(unsafe_code)]
transmute_entry_buffer_to_u32_buffer(&self) -> &[u32]649     fn transmute_entry_buffer_to_u32_buffer(&self) -> &[u32] {
650         unsafe { mem::transmute(self.entry_buffer.as_slice()) }
651     }
652 
char_is_space(&self, i: ByteIndex) -> bool653     pub fn char_is_space(&self, i: ByteIndex) -> bool {
654         assert!(i < self.len());
655         self.entry_buffer[i.to_usize()].char_is_space()
656     }
657 
space_count_in_range(&self, range: &Range<ByteIndex>) -> u32658     pub fn space_count_in_range(&self, range: &Range<ByteIndex>) -> u32 {
659         let mut spaces = 0;
660         for index in range.each_index() {
661             if self.char_is_space(index) {
662                 spaces += 1
663             }
664         }
665         spaces
666     }
667 }
668 
669 impl fmt::Debug for GlyphStore {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result670     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
671         write!(formatter, "GlyphStore:\n")?;
672         let mut detailed_buffer = self.detail_store.detail_buffer.iter();
673         for entry in self.entry_buffer.iter() {
674             if entry.is_simple() {
675                 write!(formatter,
676                             "  simple id={:?} advance={:?}\n",
677                             entry.id(),
678                             entry.advance())?;
679                 continue
680             }
681             if entry.is_initial() {
682                 continue
683             }
684             write!(formatter, "  complex...")?;
685             if detailed_buffer.next().is_none() {
686                 continue
687             }
688             write!(formatter,
689                         "  detailed id={:?} advance={:?}\n",
690                         entry.id(),
691                         entry.advance())?;
692         }
693         Ok(())
694     }
695 }
696 
697 /// An iterator over the glyphs in a byte range in a `GlyphStore`.
698 pub struct GlyphIterator<'a> {
699     store: &'a GlyphStore,
700     byte_index: ByteIndex,
701     byte_range: Range<ByteIndex>,
702     glyph_range: Option<EachIndex<ByteIndex>>,
703 }
704 
705 impl<'a> GlyphIterator<'a> {
706     // Slow path when there is a glyph range.
707     #[inline(never)]
next_glyph_range(&mut self) -> Option<GlyphInfo<'a>>708     fn next_glyph_range(&mut self) -> Option<GlyphInfo<'a>> {
709         match self.glyph_range.as_mut().unwrap().next() {
710             Some(j) => {
711                 Some(GlyphInfo::Detail(self.store, self.byte_index, j.get() as u16 /* ??? */))
712             }
713             None => {
714                 // No more glyphs for current character.  Try to get another.
715                 self.glyph_range = None;
716                 self.next()
717             }
718         }
719     }
720 
721     // Slow path when there is a complex glyph.
722     #[inline(never)]
next_complex_glyph(&mut self, entry: &GlyphEntry, i: ByteIndex) -> Option<GlyphInfo<'a>>723     fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: ByteIndex) -> Option<GlyphInfo<'a>> {
724         let glyphs = self.store.detail_store.detailed_glyphs_for_entry(i, entry.glyph_count());
725         self.glyph_range = Some(range::each_index(ByteIndex(0), ByteIndex(glyphs.len() as isize)));
726         self.next()
727     }
728 }
729 
730 impl<'a> Iterator for GlyphIterator<'a> {
731     type Item  = GlyphInfo<'a>;
732 
733     // I tried to start with something simpler and apply FlatMap, but the
734     // inability to store free variables in the FlatMap struct was problematic.
735     //
736     // This function consists of the fast path and is designed to be inlined into its caller. The
737     // slow paths, which should not be inlined, are `next_glyph_range()` and
738     // `next_complex_glyph()`.
739     #[inline(always)]
next(&mut self) -> Option<GlyphInfo<'a>>740     fn next(&mut self) -> Option<GlyphInfo<'a>> {
741         // Would use 'match' here but it borrows contents in a way that interferes with mutation.
742         if self.glyph_range.is_some() {
743             return self.next_glyph_range()
744         }
745 
746         // No glyph range. Look at next byte.
747         self.byte_index = self.byte_index + if self.store.is_rtl {
748             ByteIndex(-1)
749         } else {
750             ByteIndex(1)
751         };
752         let i = self.byte_index;
753         if !self.byte_range.contains(i) {
754             return None
755         }
756         debug_assert!(i < self.store.len());
757         let entry = self.store.entry_buffer[i.to_usize()];
758         if entry.is_simple() {
759             Some(GlyphInfo::Simple(self.store, i))
760         } else {
761             // Fall back to the slow path.
762             self.next_complex_glyph(&entry, i)
763         }
764     }
765 }
766