1use std::cmp::{Ordering, PartialOrd};
6use std::iter::once;
7use std::sync::Arc;
8use std::vec::Vec;
9use std::{fmt, mem};
10
11use app_units::Au;
12use euclid::default::Point2D;
13use euclid::num::Zero;
14pub(crate) use fonts_traits::ByteIndex;
15use itertools::Either;
16use log::debug;
17use malloc_size_of_derive::MallocSizeOf;
18use range::{self, Range, RangeIndex};
19use serde::{Deserialize, Serialize};
20
21#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
30pub(crate) struct GlyphEntry {
31 value: u32,
32}
33
34impl GlyphEntry {
35 fn new(value: u32) -> GlyphEntry {
36 GlyphEntry { value }
37 }
38
39 fn initial() -> GlyphEntry {
40 GlyphEntry::new(0)
41 }
42
43 fn simple(id: GlyphId, advance: Au) -> GlyphEntry {
45 assert!(is_simple_glyph_id(id));
46 assert!(is_simple_advance(advance));
47
48 let id_mask = id;
49 let Au(advance) = advance;
50 let advance_mask = (advance as u32) << GLYPH_ADVANCE_SHIFT;
51
52 GlyphEntry::new(id_mask | advance_mask | FLAG_IS_SIMPLE_GLYPH)
53 }
54
55 fn complex(starts_cluster: bool, starts_ligature: bool, glyph_count: usize) -> GlyphEntry {
58 assert!(glyph_count <= u16::MAX as usize);
59
60 debug!(
61 "creating complex glyph entry: starts_cluster={}, starts_ligature={}, \
62 glyph_count={}",
63 starts_cluster, starts_ligature, glyph_count
64 );
65
66 GlyphEntry::new(glyph_count as u32)
67 }
68
69 fn is_initial(&self) -> bool {
70 *self == GlyphEntry::initial()
71 }
72}
73
74pub(crate) type GlyphId = u32;
76
77const FLAG_CHAR_IS_WORD_SEPARATOR: u32 = 0x40000000;
80const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
81
82const GLYPH_ADVANCE_MASK: u32 = 0x3FFF0000;
84const GLYPH_ADVANCE_SHIFT: u32 = 16;
85const GLYPH_ID_MASK: u32 = 0x0000FFFF;
86
87const GLYPH_COUNT_MASK: u32 = 0x0000FFFF;
95
96fn is_simple_glyph_id(id: GlyphId) -> bool {
97 (id & GLYPH_ID_MASK) == id
98}
99
100fn is_simple_advance(advance: Au) -> bool {
101 advance >= Au::zero() && {
102 let unsigned_au = advance.0 as u32;
103 (unsigned_au & (GLYPH_ADVANCE_MASK >> GLYPH_ADVANCE_SHIFT)) == unsigned_au
104 }
105}
106
107impl GlyphEntry {
110 #[inline(always)]
111 fn advance(&self) -> Au {
112 Au::new(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32)
113 }
114
115 #[inline]
116 fn id(&self) -> GlyphId {
117 self.value & GLYPH_ID_MASK
118 }
119
120 fn char_is_word_separator(&self) -> bool {
127 self.has_flag(FLAG_CHAR_IS_WORD_SEPARATOR)
128 }
129
130 #[inline(always)]
131 fn set_char_is_word_separator(&mut self) {
132 self.value |= FLAG_CHAR_IS_WORD_SEPARATOR;
133 }
134
135 fn glyph_count(&self) -> u16 {
136 assert!(!self.is_simple());
137 (self.value & GLYPH_COUNT_MASK) as u16
138 }
139
140 #[inline(always)]
141 fn is_simple(&self) -> bool {
142 self.has_flag(FLAG_IS_SIMPLE_GLYPH)
143 }
144
145 #[inline(always)]
146 fn has_flag(&self, flag: u32) -> bool {
147 (self.value & flag) != 0
148 }
149}
150
151#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize)]
154struct DetailedGlyph {
155 id: GlyphId,
156 advance: Au,
158 offset: Point2D<Au>,
160}
161
162impl DetailedGlyph {
163 fn new(id: GlyphId, advance: Au, offset: Point2D<Au>) -> DetailedGlyph {
164 DetailedGlyph {
165 id,
166 advance,
167 offset,
168 }
169 }
170}
171
172#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
173struct DetailedGlyphRecord {
174 entry_offset: ByteIndex,
176 detail_offset: usize,
178}
179
180impl Ord for DetailedGlyphRecord {
181 fn cmp(&self, other: &DetailedGlyphRecord) -> Ordering {
182 self.entry_offset.cmp(&other.entry_offset)
183 }
184}
185
186impl PartialOrd for DetailedGlyphRecord {
187 fn partial_cmp(&self, other: &DetailedGlyphRecord) -> Option<Ordering> {
188 Some(self.cmp(other))
189 }
190}
191
192#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
197struct DetailedGlyphStore {
198 detail_buffer: Vec<DetailedGlyph>,
201 detail_lookup: Vec<DetailedGlyphRecord>,
204 lookup_is_sorted: bool,
205}
206
207impl<'a> DetailedGlyphStore {
208 fn new() -> DetailedGlyphStore {
209 DetailedGlyphStore {
210 detail_buffer: vec![], detail_lookup: vec![],
212 lookup_is_sorted: false,
213 }
214 }
215
216 fn add_detailed_glyphs_for_entry(&mut self, entry_offset: ByteIndex, glyphs: &[DetailedGlyph]) {
217 let entry = DetailedGlyphRecord {
218 entry_offset,
219 detail_offset: self.detail_buffer.len(),
220 };
221
222 debug!(
223 "Adding entry[off={:?}] for detailed glyphs: {:?}",
224 entry_offset, glyphs
225 );
226
227 debug_assert!(!self.detail_lookup.contains(&entry));
228 self.detail_lookup.push(entry);
229 self.detail_buffer.extend_from_slice(glyphs);
230 self.lookup_is_sorted = false;
231 }
232
233 fn detailed_glyphs_for_entry(
234 &'a self,
235 entry_offset: ByteIndex,
236 count: u16,
237 ) -> &'a [DetailedGlyph] {
238 debug!(
239 "Requesting detailed glyphs[n={}] for entry[off={:?}]",
240 count, entry_offset
241 );
242
243 if count == 0 {
246 return &self.detail_buffer[0..0];
247 }
248
249 assert!((count as usize) <= self.detail_buffer.len());
250 assert!(self.lookup_is_sorted);
251
252 let key = DetailedGlyphRecord {
253 entry_offset,
254 detail_offset: 0, };
256
257 let i = self
258 .detail_lookup
259 .binary_search(&key)
260 .expect("Invalid index not found in detailed glyph lookup table!");
261 let main_detail_offset = self.detail_lookup[i].detail_offset;
262 assert!(main_detail_offset + (count as usize) <= self.detail_buffer.len());
263 &self.detail_buffer[main_detail_offset..main_detail_offset + count as usize]
265 }
266
267 fn detailed_glyph_with_index(
268 &'a self,
269 entry_offset: ByteIndex,
270 detail_offset: u16,
271 ) -> &'a DetailedGlyph {
272 assert!((detail_offset as usize) <= self.detail_buffer.len());
273 assert!(self.lookup_is_sorted);
274
275 let key = DetailedGlyphRecord {
276 entry_offset,
277 detail_offset: 0, };
279
280 let i = self
281 .detail_lookup
282 .binary_search(&key)
283 .expect("Invalid index not found in detailed glyph lookup table!");
284 let main_detail_offset = self.detail_lookup[i].detail_offset;
285 assert!(main_detail_offset + (detail_offset as usize) < self.detail_buffer.len());
286 &self.detail_buffer[main_detail_offset + (detail_offset as usize)]
287 }
288
289 fn ensure_sorted(&mut self) {
290 if self.lookup_is_sorted {
291 return;
292 }
293
294 let mut unsorted_records: Vec<DetailedGlyphRecord> = vec![];
300 mem::swap(&mut self.detail_lookup, &mut unsorted_records);
301 let mut mut_records: Vec<DetailedGlyphRecord> = unsorted_records;
302 mut_records.sort_by(|a, b| {
303 if a < b {
304 Ordering::Less
305 } else {
306 Ordering::Greater
307 }
308 });
309 let mut sorted_records = mut_records;
310 mem::swap(&mut self.detail_lookup, &mut sorted_records);
311
312 self.lookup_is_sorted = true;
313 }
314}
315
316#[derive(Clone, Copy, Debug)]
319pub(crate) struct GlyphData {
320 id: GlyphId,
321 advance: Au,
322 offset: Point2D<Au>,
323 cluster_start: bool,
324 ligature_start: bool,
325}
326
327impl GlyphData {
328 pub(crate) fn new(
330 id: GlyphId,
331 advance: Au,
332 offset: Option<Point2D<Au>>,
333 cluster_start: bool,
334 ligature_start: bool,
335 ) -> GlyphData {
336 GlyphData {
337 id,
338 advance,
339 offset: offset.unwrap_or(Point2D::zero()),
340 cluster_start,
341 ligature_start,
342 }
343 }
344}
345
346#[derive(Clone, Copy)]
351pub enum GlyphInfo<'a> {
352 Simple(&'a GlyphStore, ByteIndex),
353 Detail(&'a GlyphStore, ByteIndex, u16),
354}
355
356impl GlyphInfo<'_> {
357 pub fn id(self) -> GlyphId {
358 match self {
359 GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].id(),
360 GlyphInfo::Detail(store, entry_i, detail_j) => {
361 store
362 .detail_store
363 .detailed_glyph_with_index(entry_i, detail_j)
364 .id
365 },
366 }
367 }
368
369 #[inline(always)]
370 pub fn advance(self) -> Au {
371 match self {
372 GlyphInfo::Simple(store, entry_i) => store.entry_buffer[entry_i.to_usize()].advance(),
373 GlyphInfo::Detail(store, entry_i, detail_j) => {
374 store
375 .detail_store
376 .detailed_glyph_with_index(entry_i, detail_j)
377 .advance
378 },
379 }
380 }
381
382 #[inline]
383 pub fn offset(self) -> Option<Point2D<Au>> {
384 match self {
385 GlyphInfo::Simple(_, _) => None,
386 GlyphInfo::Detail(store, entry_i, detail_j) => Some(
387 store
388 .detail_store
389 .detailed_glyph_with_index(entry_i, detail_j)
390 .offset,
391 ),
392 }
393 }
394
395 pub fn char_is_word_separator(self) -> bool {
396 let (store, entry_i) = match self {
397 GlyphInfo::Simple(store, entry_i) => (store, entry_i),
398 GlyphInfo::Detail(store, entry_i, _) => (store, entry_i),
399 };
400
401 store.char_is_word_separator(entry_i)
402 }
403}
404
405#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
424pub struct GlyphStore {
425 entry_buffer: Vec<GlyphEntry>,
432 detail_store: DetailedGlyphStore,
435
436 total_advance: Au,
438
439 total_word_separators: usize,
442
443 has_detailed_glyphs: bool,
445
446 is_whitespace: bool,
448
449 ends_with_whitespace: bool,
453
454 is_single_preserved_newline: bool,
457
458 is_rtl: bool,
459}
460
461impl GlyphStore {
462 pub(crate) fn new(
466 length: usize,
467 is_whitespace: bool,
468 ends_with_whitespace: bool,
469 is_single_preserved_newline: bool,
470 is_rtl: bool,
471 ) -> GlyphStore {
472 assert!(length > 0);
473
474 GlyphStore {
475 entry_buffer: vec![GlyphEntry::initial(); length],
476 detail_store: DetailedGlyphStore::new(),
477 total_advance: Au::zero(),
478 total_word_separators: 0,
479 has_detailed_glyphs: false,
480 is_whitespace,
481 ends_with_whitespace,
482 is_single_preserved_newline,
483 is_rtl,
484 }
485 }
486
487 #[inline]
488 pub fn total_advance(&self) -> Au {
489 self.total_advance
490 }
491
492 #[inline]
493 pub fn len(&self) -> ByteIndex {
494 ByteIndex(self.entry_buffer.len() as isize)
495 }
496
497 #[inline]
498 pub fn is_whitespace(&self) -> bool {
499 self.is_whitespace
500 }
501
502 #[inline]
503 pub fn ends_with_whitespace(&self) -> bool {
504 self.ends_with_whitespace
505 }
506
507 #[inline]
508 pub fn total_word_separators(&self) -> usize {
509 self.total_word_separators
510 }
511
512 pub(crate) fn finalize_changes(&mut self) {
513 self.detail_store.ensure_sorted();
514 self.cache_total_advance_and_word_separators()
515 }
516
517 #[inline(never)]
518 fn cache_total_advance_and_word_separators(&mut self) {
519 let mut total_advance = Au::zero();
520 let mut total_word_separators = 0;
521 for glyph in self.iter_glyphs_for_byte_range(&Range::new(ByteIndex(0), self.len())) {
522 total_advance += glyph.advance();
523 if glyph.char_is_word_separator() {
524 total_word_separators += 1;
525 }
526 }
527 self.total_advance = total_advance;
528 self.total_word_separators = total_word_separators;
529 }
530
531 pub(crate) fn add_glyph_for_byte_index(
533 &mut self,
534 i: ByteIndex,
535 character: char,
536 data: &GlyphData,
537 ) {
538 let glyph_is_compressible = is_simple_glyph_id(data.id) &&
539 is_simple_advance(data.advance) &&
540 data.offset == Point2D::zero() &&
541 data.cluster_start; debug_assert!(data.ligature_start); debug_assert!(i < self.len());
545
546 let mut entry = if glyph_is_compressible {
547 GlyphEntry::simple(data.id, data.advance)
548 } else {
549 let glyph = &[DetailedGlyph::new(data.id, data.advance, data.offset)];
550 self.has_detailed_glyphs = true;
551 self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
552 GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
553 };
554
555 if matches!(
559 character,
560 ' ' |
561 '\u{00A0}' | '\u{1361}' | '\u{10100}' | '\u{10101}' | '\u{1039F}' | '\u{1091F}' ) {
568 entry.set_char_is_word_separator();
569 }
570
571 self.entry_buffer[i.to_usize()] = entry;
572 }
573
574 pub(crate) fn add_glyphs_for_byte_index(
575 &mut self,
576 i: ByteIndex,
577 data_for_glyphs: &[GlyphData],
578 ) {
579 assert!(i < self.len());
580 assert!(!data_for_glyphs.is_empty());
581
582 let glyph_count = data_for_glyphs.len();
583
584 let first_glyph_data = data_for_glyphs[0];
585 let glyphs_vec: Vec<DetailedGlyph> = (0..glyph_count)
586 .map(|i| {
587 DetailedGlyph::new(
588 data_for_glyphs[i].id,
589 data_for_glyphs[i].advance,
590 data_for_glyphs[i].offset,
591 )
592 })
593 .collect();
594
595 self.has_detailed_glyphs = true;
596 self.detail_store
597 .add_detailed_glyphs_for_entry(i, &glyphs_vec);
598
599 let entry = GlyphEntry::complex(
600 first_glyph_data.cluster_start,
601 first_glyph_data.ligature_start,
602 glyph_count,
603 );
604
605 debug!(
606 "Adding multiple glyphs[idx={:?}, count={}]: {:?}",
607 i, glyph_count, entry
608 );
609
610 self.entry_buffer[i.to_usize()] = entry;
611 }
612
613 #[inline]
614 pub fn iter_glyphs_for_byte_range(
615 &self,
616 range: &Range<ByteIndex>,
617 ) -> impl Iterator<Item = GlyphInfo<'_>> + use<'_> {
618 if range.begin() >= self.len() {
619 panic!("iter_glyphs_for_range: range.begin beyond length!");
620 }
621 if range.end() > self.len() {
622 panic!("iter_glyphs_for_range: range.end beyond length!");
623 }
624
625 let range_it = if self.is_rtl {
626 Either::Left(range.each_index().rev())
627 } else {
628 Either::Right(range.each_index())
629 };
630 range_it.into_iter().flat_map(move |range_idx| {
631 let entry = self.entry_buffer[range_idx.to_usize()];
632 let result = if entry.is_simple() {
633 Either::Left(once(GlyphInfo::Simple(self, range_idx)))
634 } else {
635 let glyphs = self.detail_store.detailed_glyphs_for_entry(
637 range_idx,
638 self.entry_buffer[range_idx.to_usize()].glyph_count(),
639 );
640
641 let complex_glyph_range =
642 range::each_index(ByteIndex(0), ByteIndex(glyphs.len() as isize));
643 Either::Right(complex_glyph_range.map(move |i| {
644 GlyphInfo::Detail(self, range_idx, i.get() as u16 )
645 }))
646 };
647
648 result.into_iter()
649 })
650 }
651
652 #[inline]
653 pub fn advance_for_byte_range(&self, range: &Range<ByteIndex>, extra_word_spacing: Au) -> Au {
654 if range.begin() == ByteIndex(0) && range.end() == self.len() {
655 self.total_advance + extra_word_spacing * (self.total_word_separators as i32)
656 } else {
657 self.advance_for_byte_range_simple_glyphs(range, extra_word_spacing)
658 }
659 }
660
661 #[inline]
662 pub(crate) fn advance_for_byte_range_simple_glyphs(
663 &self,
664 range: &Range<ByteIndex>,
665 extra_word_spacing: Au,
666 ) -> Au {
667 self.iter_glyphs_for_byte_range(range)
668 .fold(Au::zero(), |advance, glyph| {
669 if glyph.char_is_word_separator() {
670 advance + glyph.advance() + extra_word_spacing
671 } else {
672 advance + glyph.advance()
673 }
674 })
675 }
676
677 pub(crate) fn char_is_word_separator(&self, i: ByteIndex) -> bool {
678 assert!(i < self.len());
679 self.entry_buffer[i.to_usize()].char_is_word_separator()
680 }
681}
682
683impl fmt::Debug for GlyphStore {
684 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
685 writeln!(formatter, "GlyphStore:")?;
686 let mut detailed_buffer = self.detail_store.detail_buffer.iter();
687 for entry in self.entry_buffer.iter() {
688 if entry.is_simple() {
689 writeln!(
690 formatter,
691 " simple id={:?} advance={:?}",
692 entry.id(),
693 entry.advance()
694 )?;
695 continue;
696 }
697 if entry.is_initial() {
698 continue;
699 }
700 write!(formatter, " complex...")?;
701 if detailed_buffer.next().is_none() {
702 continue;
703 }
704 writeln!(
705 formatter,
706 " detailed id={:?} advance={:?}",
707 entry.id(),
708 entry.advance()
709 )?;
710 }
711 Ok(())
712 }
713}
714
715#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
717pub struct GlyphRun {
718 #[conditional_malloc_size_of]
720 pub glyph_store: Arc<GlyphStore>,
721 pub range: Range<ByteIndex>,
723}
724
725impl GlyphRun {
726 #[inline]
727 pub fn is_single_preserved_newline(&self) -> bool {
728 self.glyph_store.is_single_preserved_newline
729 }
730}