1
+
1
2
/* This Source Code Form is subject to the terms of the Mozilla Public
2
3
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
4
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
5
6
use euclid:: point:: Point2D ;
6
7
use std:: cmp:: { Ordering , PartialOrd } ;
7
8
use std:: mem;
9
+ use std:: ops:: { BitAnd , Shr } ;
8
10
use std:: u16;
9
11
use std:: vec:: Vec ;
10
12
use util:: geometry:: Au ;
11
13
use util:: range:: { self , Range , RangeIndex , EachIndex } ;
12
14
use util:: vec:: * ;
15
+ use simd:: u32x4;
16
+
13
17
14
18
/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
15
19
///
@@ -511,6 +515,8 @@ pub struct GlyphStore {
511
515
/// `entry_buffer` point to locations in this data structure.
512
516
detail_store : DetailedGlyphStore ,
513
517
518
+ has_detailed_glyphs : bool ,
519
+
514
520
is_whitespace : bool ,
515
521
is_rtl : bool ,
516
522
}
@@ -533,6 +539,7 @@ impl<'a> GlyphStore {
533
539
GlyphStore {
534
540
entry_buffer : vec ! [ GlyphEntry :: initial( ) ; length] ,
535
541
detail_store : DetailedGlyphStore :: new ( ) ,
542
+ has_detailed_glyphs : false ,
536
543
is_whitespace : is_whitespace,
537
544
is_rtl : is_rtl,
538
545
}
@@ -571,6 +578,7 @@ impl<'a> GlyphStore {
571
578
( false , true ) => GlyphEntry :: simple ( data. id , data. advance ) ,
572
579
( false , false ) => {
573
580
let glyph = & [ DetailedGlyph :: new ( data. id , data. advance , data. offset ) ] ;
581
+ self . has_detailed_glyphs = true ;
574
582
self . detail_store . add_detailed_glyphs_for_entry ( i, glyph) ;
575
583
GlyphEntry :: complex ( data. cluster_start , data. ligature_start , 1 )
576
584
}
@@ -601,7 +609,7 @@ impl<'a> GlyphStore {
601
609
data_for_glyphs[ i] . advance ,
602
610
data_for_glyphs[ i] . offset )
603
611
} ) . collect ( ) ;
604
-
612
+ self . has_detailed_glyphs = true ;
605
613
self . detail_store . add_detailed_glyphs_for_entry ( i, & glyphs_vec) ;
606
614
GlyphEntry :: complex ( first_glyph_data. cluster_start ,
607
615
first_glyph_data. ligature_start ,
@@ -643,10 +651,66 @@ impl<'a> GlyphStore {
643
651
644
652
#[ inline]
645
653
pub fn advance_for_char_range ( & self , rang : & Range < CharIndex > ) -> Au {
646
- self . iter_glyphs_for_char_range ( rang)
647
- . fold ( Au ( 0 ) , |advance, ( _, glyph) | advance + glyph. advance ( ) )
654
+ //println!("advance_for_char_range - has_detailed_glyphs: {}", self.has_detailed_glyphs);
655
+ if !self . has_detailed_glyphs {
656
+ self . advance_for_char_range_simple_glyphs ( rang)
657
+ } else {
658
+ self . iter_glyphs_for_char_range ( rang)
659
+ . fold ( Au ( 0 ) , |advance, ( _, glyph) | advance + glyph. advance ( ) )
660
+ }
648
661
}
649
662
663
+ #[ inline]
664
+ fn advance_for_char_range_simple_glyphs ( & self , rang : & Range < CharIndex > ) -> Au {
665
+ //println!("advance_for_char_range_simple_glyphs");
666
+ let begin = rang. begin ( ) . to_usize ( ) ;
667
+ let len = rang. length ( ) . to_usize ( ) ;
668
+ let num: usize = len / 4 ;
669
+ let leftover = len - num * 4 ;
670
+ let mut advance: u32x4 = u32x4:: splat ( 0 ) ;
671
+ let mask = u32x4:: splat ( GLYPH_ADVANCE_MASK ) ;
672
+
673
+ let entry_buf_slice: & [ GlyphEntry ] = self . entry_buffer . as_slice ( ) ;
674
+ let buf: & [ u32 ] = unsafe { mem:: transmute ( entry_buf_slice) } ;
675
+ //println!("begin, len, num, leftover: ({:?}, {:?}, {:?}, {:?})",
676
+ //begin, len, num, leftover);
677
+ for i in 0 ..num {
678
+ let mut v = u32x4:: load ( buf, begin + i * 4 ) ;
679
+ v = v. bitand ( mask) ;
680
+ v = v. shr ( GLYPH_ADVANCE_SHIFT ) ;
681
+ advance = advance + v;
682
+ }
683
+
684
+ let left = match leftover {
685
+ 0 => 0 ,
686
+ 1 =>
687
+ ( ( self . entry_buffer [ begin + len - 1 ] . value &
688
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ,
689
+
690
+ 2 =>
691
+ ( ( ( self . entry_buffer [ begin + len - 1 ] . value &
692
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ) +
693
+ ( ( ( self . entry_buffer [ begin + len - 2 ] . value &
694
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ) ,
695
+
696
+ 3 => ( ( ( self . entry_buffer [ begin + len - 1 ] . value &
697
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ) +
698
+ ( ( ( self . entry_buffer [ begin + len - 2 ] . value &
699
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ) +
700
+ ( ( ( self . entry_buffer [ begin + len - 3 ] . value &
701
+ GLYPH_ADVANCE_MASK ) ) >> GLYPH_ADVANCE_SHIFT ) ,
702
+ _ => panic ! ( "Error leftover should never be > 3" ) ,
703
+ } ;
704
+
705
+ let adv =
706
+ advance. extract ( 0 ) +
707
+ advance. extract ( 1 ) +
708
+ advance. extract ( 2 ) +
709
+ advance. extract ( 3 ) ;
710
+
711
+ Au ( ( adv + left) as i32 )
712
+ }
713
+
650
714
// getter methods
651
715
pub fn char_is_space ( & self , i : CharIndex ) -> bool {
652
716
assert ! ( i < self . char_len( ) ) ;
0 commit comments