/src/harfbuzz/src/hb-set-digest.hh
Line  | Count  | Source  | 
1  |  | /*  | 
2  |  |  * Copyright © 2012  Google, Inc.  | 
3  |  |  *  | 
4  |  |  *  This is part of HarfBuzz, a text shaping library.  | 
5  |  |  *  | 
6  |  |  * Permission is hereby granted, without written agreement and without  | 
7  |  |  * license or royalty fees, to use, copy, modify, and distribute this  | 
8  |  |  * software and its documentation for any purpose, provided that the  | 
9  |  |  * above copyright notice and the following two paragraphs appear in  | 
10  |  |  * all copies of this software.  | 
11  |  |  *  | 
12  |  |  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR  | 
13  |  |  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES  | 
14  |  |  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN  | 
15  |  |  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH  | 
16  |  |  * DAMAGE.  | 
17  |  |  *  | 
18  |  |  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,  | 
19  |  |  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  | 
20  |  |  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS  | 
21  |  |  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO  | 
22  |  |  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.  | 
23  |  |  *  | 
24  |  |  * Google Author(s): Behdad Esfahbod  | 
25  |  |  */  | 
26  |  |  | 
27  |  | #ifndef HB_SET_DIGEST_HH  | 
28  |  | #define HB_SET_DIGEST_HH  | 
29  |  |  | 
30  |  | #include "hb.hh"  | 
31  |  | #include "hb-machinery.hh"  | 
32  |  |  | 
33  |  | /*  | 
34  |  |  * The set-digests here implement various "filters" that support  | 
35  |  |  * "approximate member query".  Conceptually these are like Bloom  | 
36  |  |  * Filter and Quotient Filter, however, much smaller, faster, and  | 
37  |  |  * designed to fit the requirements of our uses for glyph coverage  | 
38  |  |  * queries.  | 
39  |  |  *  | 
40  |  |  * Our filters are highly accurate if the lookup covers fairly local  | 
41  |  |  * set of glyphs, but fully flooded and ineffective if coverage is  | 
42  |  |  * all over the place.  | 
43  |  |  *  | 
44  |  |  * The way these are used is that the filter is first populated by  | 
45  |  |  * a lookup's or subtable's Coverage table(s), and then when we  | 
46  |  |  * want to apply the lookup or subtable to a glyph, before trying  | 
47  |  |  * to apply, we ask the filter if the glyph may be covered. If it's  | 
48  |  |  * not, we return early.  | 
49  |  |  *  | 
50  |  |  * We use these filters both at the lookup-level, and then again,  | 
51  |  |  * at the subtable-level. Both have performance win.  | 
52  |  |  *  | 
53  |  |  * The main filter we use is a combination of three bits-pattern  | 
54  |  |  * filters. A bits-pattern filter checks a number of bits (5 or 6)  | 
55  |  |  * of the input number (glyph-id in this case) and checks whether  | 
56  |  |  * its pattern is amongst the patterns of any of the accepted values.  | 
57  |  |  * The accepted patterns are represented as a "long" integer. The  | 
58  |  |  * check is done using four bitwise operations only.  | 
59  |  |  */  | 
60  |  |  | 
61  |  | template <typename mask_t, unsigned int shift>  | 
62  |  | struct hb_set_digest_bits_pattern_t  | 
63  |  | { | 
64  |  |   static constexpr unsigned mask_bytes = sizeof (mask_t);  | 
65  |  |   static constexpr unsigned mask_bits = sizeof (mask_t) * 8;  | 
66  |  |   static constexpr unsigned num_bits = 0  | 
67  |  |              + (mask_bytes >= 1 ? 3 : 0)  | 
68  |  |              + (mask_bytes >= 2 ? 1 : 0)  | 
69  |  |              + (mask_bytes >= 4 ? 1 : 0)  | 
70  |  |              + (mask_bytes >= 8 ? 1 : 0)  | 
71  |  |              + (mask_bytes >= 16? 1 : 0)  | 
72  |  |              + 0;  | 
73  |  |  | 
74  |  |   static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");  | 
75  |  |   static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");  | 
76  |  |  | 
77  | 1.89M  |   void init () { mask = 0; }hb_set_digest_bits_pattern_t<unsigned long, 4u>::init() Line  | Count  | Source  |  77  | 631k  |   void init () { mask = 0; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::init() Line  | Count  | Source  |  77  | 631k  |   void init () { mask = 0; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::init() Line  | Count  | Source  |  77  | 631k  |   void init () { mask = 0; } |  
  | 
78  |  |  | 
79  | 171k  |   void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; }hb_set_digest_bits_pattern_t<unsigned long, 4u>::add(hb_set_digest_bits_pattern_t<unsigned long, 4u> const&) Line  | Count  | Source  |  79  | 57.1k  |   void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::add(hb_set_digest_bits_pattern_t<unsigned long, 0u> const&) Line  | Count  | Source  |  79  | 57.1k  |   void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::add(hb_set_digest_bits_pattern_t<unsigned long, 9u> const&) Line  | Count  | Source  |  79  | 57.1k  |   void add (const hb_set_digest_bits_pattern_t &o) { mask |= o.mask; } |  
  | 
80  |  |  | 
81  | 22.6M  |   void add (hb_codepoint_t g) { mask |= mask_for (g); }hb_set_digest_bits_pattern_t<unsigned long, 4u>::add(unsigned int) Line  | Count  | Source  |  81  | 7.55M  |   void add (hb_codepoint_t g) { mask |= mask_for (g); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::add(unsigned int) Line  | Count  | Source  |  81  | 7.55M  |   void add (hb_codepoint_t g) { mask |= mask_for (g); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::add(unsigned int) Line  | Count  | Source  |  81  | 7.55M  |   void add (hb_codepoint_t g) { mask |= mask_for (g); } |  
  | 
82  |  |  | 
83  |  |   bool add_range (hb_codepoint_t a, hb_codepoint_t b)  | 
84  | 3.20M  |   { | 
85  | 3.20M  |     if ((b >> shift) - (a >> shift) >= mask_bits - 1)  | 
86  | 1.70M  |       mask = (mask_t) -1;  | 
87  | 1.50M  |     else { | 
88  | 1.50M  |       mask_t ma = mask_for (a);  | 
89  | 1.50M  |       mask_t mb = mask_for (b);  | 
90  | 1.50M  |       mask |= mb + (mb - ma) - (mb < ma);  | 
91  | 1.50M  |     }  | 
92  | 3.20M  |     return true;  | 
93  | 3.20M  |   } hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_range(unsigned int, unsigned int) Line  | Count  | Source  |  84  | 1.06M  |   { |  85  | 1.06M  |     if ((b >> shift) - (a >> shift) >= mask_bits - 1)  |  86  | 603k  |       mask = (mask_t) -1;  |  87  | 465k  |     else { |  88  | 465k  |       mask_t ma = mask_for (a);  |  89  | 465k  |       mask_t mb = mask_for (b);  |  90  | 465k  |       mask |= mb + (mb - ma) - (mb < ma);  |  91  | 465k  |     }  |  92  | 1.06M  |     return true;  |  93  | 1.06M  |   }  |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_range(unsigned int, unsigned int) Line  | Count  | Source  |  84  | 1.06M  |   { |  85  | 1.06M  |     if ((b >> shift) - (a >> shift) >= mask_bits - 1)  |  86  | 694k  |       mask = (mask_t) -1;  |  87  | 373k  |     else { |  88  | 373k  |       mask_t ma = mask_for (a);  |  89  | 373k  |       mask_t mb = mask_for (b);  |  90  | 373k  |       mask |= mb + (mb - ma) - (mb < ma);  |  91  | 373k  |     }  |  92  | 1.06M  |     return true;  |  93  | 1.06M  |   }  |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_range(unsigned int, unsigned int) Line  | Count  | Source  |  84  | 1.06M  |   { |  85  | 1.06M  |     if ((b >> shift) - (a >> shift) >= mask_bits - 1)  |  86  | 402k  |       mask = (mask_t) -1;  |  87  | 666k  |     else { |  88  | 666k  |       mask_t ma = mask_for (a);  |  89  | 666k  |       mask_t mb = mask_for (b);  |  90  | 666k  |       mask |= mb + (mb - ma) - (mb < ma);  |  91  | 666k  |     }  |  92  | 1.06M  |     return true;  |  93  | 1.06M  |   }  |  
  | 
94  |  |  | 
95  |  |   template <typename T>  | 
96  |  |   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))  | 
97  | 1.21M  |   { | 
98  | 10.5M  |     for (unsigned int i = 0; i < count; i++)  | 
99  | 9.29M  |     { | 
100  | 9.29M  |       add (*array);  | 
101  | 9.29M  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  | 
102  | 9.29M  |     }  | 
103  | 1.21M  |   } void hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_array<unsigned int>(unsigned int const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 397k  |   { |  98  | 2.72M  |     for (unsigned int i = 0; i < count; i++)  |  99  | 2.32M  |     { |  100  | 2.32M  |       add (*array);  |  101  | 2.32M  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 2.32M  |     }  |  103  | 397k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_array<unsigned int>(unsigned int const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 397k  |   { |  98  | 2.72M  |     for (unsigned int i = 0; i < count; i++)  |  99  | 2.32M  |     { |  100  | 2.32M  |       add (*array);  |  101  | 2.32M  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 2.32M  |     }  |  103  | 397k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_array<unsigned int>(unsigned int const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 397k  |   { |  98  | 2.72M  |     for (unsigned int i = 0; i < count; i++)  |  99  | 2.32M  |     { |  100  | 2.32M  |       add (*array);  |  101  | 2.32M  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 2.32M  |     }  |  103  | 397k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 6.15k  |   { |  98  | 623k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 617k  |     { |  100  | 617k  |       add (*array);  |  101  | 617k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 617k  |     }  |  103  | 6.15k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 6.15k  |   { |  98  | 623k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 617k  |     { |  100  | 617k  |       add (*array);  |  101  | 617k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 617k  |     }  |  103  | 6.15k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 6.15k  |   { |  98  | 623k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 617k  |     { |  100  | 617k  |       add (*array);  |  101  | 617k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 617k  |     }  |  103  | 6.15k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 1.11k  |   { |  98  | 156k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 155k  |     { |  100  | 155k  |       add (*array);  |  101  | 155k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 155k  |     }  |  103  | 1.11k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 1.11k  |   { |  98  | 156k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 155k  |     { |  100  | 155k  |       add (*array);  |  101  | 155k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 155k  |     }  |  103  | 1.11k  |   }  |  
 void hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  97  | 1.11k  |   { |  98  | 156k  |     for (unsigned int i = 0; i < count; i++)  |  99  | 155k  |     { |  100  | 155k  |       add (*array);  |  101  | 155k  |       array = &StructAtOffsetUnaligned<T> ((const void *) array, stride);  |  102  | 155k  |     }  |  103  | 1.11k  |   }  |  
  | 
104  |  |   template <typename T>  | 
105  |  |   void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } | 
106  |  |   template <typename T>  | 
107  |  |   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))  | 
108  | 21.7k  |   { | 
109  | 21.7k  |     add_array (array, count, stride);  | 
110  | 21.7k  |     return true;  | 
111  | 21.7k  |   } bool hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_sorted_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 6.15k  |   { |  109  | 6.15k  |     add_array (array, count, stride);  |  110  | 6.15k  |     return true;  |  111  | 6.15k  |   }  |  
 bool hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_sorted_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 6.15k  |   { |  109  | 6.15k  |     add_array (array, count, stride);  |  110  | 6.15k  |     return true;  |  111  | 6.15k  |   }  |  
 bool hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_sorted_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 6.15k  |   { |  109  | 6.15k  |     add_array (array, count, stride);  |  110  | 6.15k  |     return true;  |  111  | 6.15k  |   }  |  
 bool hb_set_digest_bits_pattern_t<unsigned long, 4u>::add_sorted_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 1.11k  |   { |  109  | 1.11k  |     add_array (array, count, stride);  |  110  | 1.11k  |     return true;  |  111  | 1.11k  |   }  |  
 bool hb_set_digest_bits_pattern_t<unsigned long, 0u>::add_sorted_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 1.11k  |   { |  109  | 1.11k  |     add_array (array, count, stride);  |  110  | 1.11k  |     return true;  |  111  | 1.11k  |   }  |  
 bool hb_set_digest_bits_pattern_t<unsigned long, 9u>::add_sorted_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  108  | 1.11k  |   { |  109  | 1.11k  |     add_array (array, count, stride);  |  110  | 1.11k  |     return true;  |  111  | 1.11k  |   }  |  
  | 
112  |  |   template <typename T>  | 
113  |  |   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } | 
114  |  |  | 
115  |  |   bool may_have (const hb_set_digest_bits_pattern_t &o) const  | 
116  | 830k  |   { return mask & o.mask; }hb_set_digest_bits_pattern_t<unsigned long, 4u>::may_have(hb_set_digest_bits_pattern_t<unsigned long, 4u> const&) const Line  | Count  | Source  |  116  | 774k  |   { return mask & o.mask; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::may_have(hb_set_digest_bits_pattern_t<unsigned long, 0u> const&) const Line  | Count  | Source  |  116  | 29.6k  |   { return mask & o.mask; } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::may_have(hb_set_digest_bits_pattern_t<unsigned long, 9u> const&) const Line  | Count  | Source  |  116  | 25.7k  |   { return mask & o.mask; } |  
  | 
117  |  |  | 
118  |  |   bool may_have (hb_codepoint_t g) const  | 
119  | 25.1M  |   { return mask & mask_for (g); }hb_set_digest_bits_pattern_t<unsigned long, 4u>::may_have(unsigned int) const Line  | Count  | Source  |  119  | 8.49M  |   { return mask & mask_for (g); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::may_have(unsigned int) const Line  | Count  | Source  |  119  | 8.36M  |   { return mask & mask_for (g); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::may_have(unsigned int) const Line  | Count  | Source  |  119  | 8.31M  |   { return mask & mask_for (g); } |  
  | 
120  |  |  | 
121  |  |   private:  | 
122  |  |  | 
123  |  |   static mask_t mask_for (hb_codepoint_t g)  | 
124  | 50.8M  |   { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }hb_set_digest_bits_pattern_t<unsigned long, 4u>::mask_for(unsigned int) Line  | Count  | Source  |  124  | 16.9M  |   { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 0u>::mask_for(unsigned int) Line  | Count  | Source  |  124  | 16.6M  |   { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); } |  
 hb_set_digest_bits_pattern_t<unsigned long, 9u>::mask_for(unsigned int) Line  | Count  | Source  |  124  | 17.2M  |   { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); } |  
  | 
125  |  |   mask_t mask;  | 
126  |  | };  | 
127  |  |  | 
128  |  | template <typename head_t, typename tail_t>  | 
129  |  | struct hb_set_digest_combiner_t  | 
130  |  | { | 
131  |  |   void init ()  | 
132  | 1.26M  |   { | 
133  | 1.26M  |     head.init ();  | 
134  | 1.26M  |     tail.init ();  | 
135  | 1.26M  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::init() Line  | Count  | Source  |  132  | 631k  |   { |  133  | 631k  |     head.init ();  |  134  | 631k  |     tail.init ();  |  135  | 631k  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::init() Line  | Count  | Source  |  132  | 631k  |   { |  133  | 631k  |     head.init ();  |  134  | 631k  |     tail.init ();  |  135  | 631k  |   }  |  
  | 
136  |  |  | 
137  |  |   void add (const hb_set_digest_combiner_t &o)  | 
138  | 114k  |   { | 
139  | 114k  |     head.add (o.head);  | 
140  | 114k  |     tail.add (o.tail);  | 
141  | 114k  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add(hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > > const&) Line  | Count  | Source  |  138  | 57.1k  |   { |  139  | 57.1k  |     head.add (o.head);  |  140  | 57.1k  |     tail.add (o.tail);  |  141  | 57.1k  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add(hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > const&) Line  | Count  | Source  |  138  | 57.1k  |   { |  139  | 57.1k  |     head.add (o.head);  |  140  | 57.1k  |     tail.add (o.tail);  |  141  | 57.1k  |   }  |  
  | 
142  |  |  | 
143  |  |   void add (hb_codepoint_t g)  | 
144  | 8.91M  |   { | 
145  | 8.91M  |     head.add (g);  | 
146  | 8.91M  |     tail.add (g);  | 
147  | 8.91M  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add(unsigned int) Line  | Count  | Source  |  144  | 4.45M  |   { |  145  | 4.45M  |     head.add (g);  |  146  | 4.45M  |     tail.add (g);  |  147  | 4.45M  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add(unsigned int) Line  | Count  | Source  |  144  | 4.45M  |   { |  145  | 4.45M  |     head.add (g);  |  146  | 4.45M  |     tail.add (g);  |  147  | 4.45M  |   }  |  
  | 
148  |  |  | 
149  |  |   bool add_range (hb_codepoint_t a, hb_codepoint_t b)  | 
150  | 2.13M  |   { | 
151  | 2.13M  |     return head.add_range (a, b) &&  | 
152  | 2.13M  |      tail.add_range (a, b);  | 
153  | 2.13M  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_range(unsigned int, unsigned int) Line  | Count  | Source  |  150  | 1.06M  |   { |  151  | 1.06M  |     return head.add_range (a, b) &&  |  152  | 1.06M  |      tail.add_range (a, b);  |  153  | 1.06M  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add_range(unsigned int, unsigned int) Line  | Count  | Source  |  150  | 1.06M  |   { |  151  | 1.06M  |     return head.add_range (a, b) &&  |  152  | 1.06M  |      tail.add_range (a, b);  |  153  | 1.06M  |   }  |  
  | 
154  |  |   template <typename T>  | 
155  |  |   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))  | 
156  | 795k  |   { | 
157  | 795k  |     head.add_array (array, count, stride);  | 
158  | 795k  |     tail.add_array (array, count, stride);  | 
159  | 795k  |   } void hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_array<unsigned int>(unsigned int const*, unsigned int, unsigned int) Line  | Count  | Source  |  156  | 397k  |   { |  157  | 397k  |     head.add_array (array, count, stride);  |  158  | 397k  |     tail.add_array (array, count, stride);  |  159  | 397k  |   }  |  
 void hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add_array<unsigned int>(unsigned int const*, unsigned int, unsigned int) Line  | Count  | Source  |  156  | 397k  |   { |  157  | 397k  |     head.add_array (array, count, stride);  |  158  | 397k  |     tail.add_array (array, count, stride);  |  159  | 397k  |   }  |  
  | 
160  |  |   template <typename T>  | 
161  |  |   void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } | 
162  |  |   template <typename T>  | 
163  |  |   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))  | 
164  | 14.5k  |   { | 
165  | 14.5k  |     return head.add_sorted_array (array, count, stride) &&  | 
166  | 14.5k  |      tail.add_sorted_array (array, count, stride);  | 
167  | 14.5k  |   } bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_sorted_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  164  | 6.15k  |   { |  165  | 6.15k  |     return head.add_sorted_array (array, count, stride) &&  |  166  | 6.15k  |      tail.add_sorted_array (array, count, stride);  |  167  | 6.15k  |   }  |  
 bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add_sorted_array<OT::HBGlyphID16>(OT::HBGlyphID16 const*, unsigned int, unsigned int) Line  | Count  | Source  |  164  | 6.15k  |   { |  165  | 6.15k  |     return head.add_sorted_array (array, count, stride) &&  |  166  | 6.15k  |      tail.add_sorted_array (array, count, stride);  |  167  | 6.15k  |   }  |  
 bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_sorted_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  164  | 1.11k  |   { |  165  | 1.11k  |     return head.add_sorted_array (array, count, stride) &&  |  166  | 1.11k  |      tail.add_sorted_array (array, count, stride);  |  167  | 1.11k  |   }  |  
 bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::add_sorted_array<OT::HBGlyphID24>(OT::HBGlyphID24 const*, unsigned int, unsigned int) Line  | Count  | Source  |  164  | 1.11k  |   { |  165  | 1.11k  |     return head.add_sorted_array (array, count, stride) &&  |  166  | 1.11k  |      tail.add_sorted_array (array, count, stride);  |  167  | 1.11k  |   }  |  
  | 
168  |  |   template <typename T>  | 
169  | 7.26k  |   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_sorted_array<OT::HBGlyphID16>(hb_sorted_array_t<OT::HBGlyphID16 const> const&) Line  | Count  | Source  |  169  | 6.15k  |   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } |  
 bool hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::add_sorted_array<OT::HBGlyphID24>(hb_sorted_array_t<OT::HBGlyphID24 const> const&) Line  | Count  | Source  |  169  | 1.11k  |   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } |  
  | 
170  |  |  | 
171  |  |   bool may_have (const hb_set_digest_combiner_t &o) const  | 
172  | 804k  |   { | 
173  | 804k  |     return head.may_have (o.head) && tail.may_have (o.tail);  | 
174  | 804k  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::may_have(hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > > const&) const Line  | Count  | Source  |  172  | 774k  |   { |  173  | 774k  |     return head.may_have (o.head) && tail.may_have (o.tail);  |  174  | 774k  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::may_have(hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > const&) const Line  | Count  | Source  |  172  | 29.6k  |   { |  173  | 29.6k  |     return head.may_have (o.head) && tail.may_have (o.tail);  |  174  | 29.6k  |   }  |  
  | 
175  |  |  | 
176  |  |   bool may_have (hb_codepoint_t g) const  | 
177  | 16.8M  |   { | 
178  | 16.8M  |     return head.may_have (g) && tail.may_have (g);  | 
179  | 16.8M  |   } hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 4u>, hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> > >::may_have(unsigned int) const Line  | Count  | Source  |  177  | 8.49M  |   { |  178  | 8.49M  |     return head.may_have (g) && tail.may_have (g);  |  179  | 8.49M  |   }  |  
 hb_set_digest_combiner_t<hb_set_digest_bits_pattern_t<unsigned long, 0u>, hb_set_digest_bits_pattern_t<unsigned long, 9u> >::may_have(unsigned int) const Line  | Count  | Source  |  177  | 8.36M  |   { |  178  | 8.36M  |     return head.may_have (g) && tail.may_have (g);  |  179  | 8.36M  |   }  |  
  | 
180  |  |  | 
181  |  |   private:  | 
182  |  |   head_t head;  | 
183  |  |   tail_t tail;  | 
184  |  | };  | 
185  |  |  | 
186  |  |  | 
187  |  | /*  | 
188  |  |  * hb_set_digest_t  | 
189  |  |  *  | 
190  |  |  * This is a combination of digests that performs "best".  | 
191  |  |  * There is not much science to this: it's a result of intuition  | 
192  |  |  * and testing.  | 
193  |  |  */  | 
194  |  | using hb_set_digest_t =  | 
195  |  |   hb_set_digest_combiner_t  | 
196  |  |   <  | 
197  |  |     hb_set_digest_bits_pattern_t<unsigned long, 4>,  | 
198  |  |     hb_set_digest_combiner_t  | 
199  |  |     <  | 
200  |  |       hb_set_digest_bits_pattern_t<unsigned long, 0>,  | 
201  |  |       hb_set_digest_bits_pattern_t<unsigned long, 9>  | 
202  |  |     >  | 
203  |  |   >  | 
204  |  | ;  | 
205  |  |  | 
206  |  |  | 
207  |  | #endif /* HB_SET_DIGEST_HH */  |