CoverageFormat2.hh (6766B)
1 /* 2 * Copyright © 2007,2008,2009 Red Hat, Inc. 3 * Copyright © 2010,2012 Google, Inc. 4 * 5 * This is part of HarfBuzz, a text shaping library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 * 25 * Red Hat Author(s): Behdad Esfahbod 26 * Google Author(s): Behdad Esfahbod, Garret Rieger 27 */ 28 29 #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH 30 #define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH 31 32 #include "RangeRecord.hh" 33 34 namespace OT { 35 namespace Layout { 36 namespace Common { 37 38 template <typename Types> 39 struct CoverageFormat2_4 40 { 41 friend struct Coverage; 42 43 public: 44 HBUINT16 coverageFormat; /* Format identifier--format = 2 */ 45 SortedArray16Of<RangeRecord<Types>> 46 rangeRecord; /* Array of glyph ranges--ordered by 47 * Start GlyphID. rangeCount entries 48 * long */ 49 public: 50 DEFINE_SIZE_ARRAY (4, rangeRecord); 51 52 private: 53 54 bool sanitize (hb_sanitize_context_t *c) const 55 { 56 TRACE_SANITIZE (this); 57 return_trace (rangeRecord.sanitize (c)); 58 } 59 60 unsigned int get_coverage (hb_codepoint_t glyph_id) const 61 { 62 const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id); 63 return likely (range.first <= range.last) 64 ? (unsigned int) range.value + (glyph_id - range.first) 65 : NOT_COVERED; 66 } 67 68 unsigned get_population () const 69 { 70 typename Types::large_int ret = 0; 71 for (const auto &r : rangeRecord) 72 ret += r.get_population (); 73 return ret > UINT_MAX ? UINT_MAX : (unsigned) ret; 74 } 75 76 template <typename Iterator, 77 hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))> 78 bool serialize (hb_serialize_context_t *c, Iterator glyphs) 79 { 80 TRACE_SERIALIZE (this); 81 if (unlikely (!c->extend_min (this))) return_trace (false); 82 83 unsigned num_ranges = 0; 84 hb_codepoint_t last = (hb_codepoint_t) -2; 85 for (auto g: glyphs) 86 { 87 if (last + 1 != g) 88 num_ranges++; 89 last = g; 90 } 91 92 if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false); 93 if (!num_ranges) return_trace (true); 94 95 unsigned count = 0; 96 unsigned range = (unsigned) -1; 97 last = (hb_codepoint_t) -2; 98 unsigned unsorted = false; 99 for (auto g: glyphs) 100 { 101 if (last + 1 != g) 102 { 103 if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g)) 104 unsorted = true; 105 106 range++; 107 rangeRecord.arrayZ[range].first = g; 108 rangeRecord.arrayZ[range].value = count; 109 } 110 rangeRecord.arrayZ[range].last = g; 111 last = g; 112 count++; 113 } 114 115 if (unlikely (unsorted)) 116 rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range); 117 118 return_trace (true); 119 } 120 121 bool intersects (const hb_set_t *glyphs) const 122 { 123 if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len)) 124 { 125 for (auto g : *glyphs) 126 if (get_coverage (g) != NOT_COVERED) 127 return true; 128 return false; 129 } 130 131 return hb_any (+ hb_iter (rangeRecord) 132 | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); })); 133 } 134 bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const 135 { 136 auto *range = rangeRecord.as_array ().bsearch (index); 137 if (range) 138 return range->intersects (*glyphs); 139 return false; 140 } 141 142 template <typename IterableOut, 143 hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))> 144 void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const 145 { 146 /* Break out of loop for overlapping, broken, tables, 147 * to avoid fuzzer timouts. */ 148 hb_codepoint_t last = 0; 149 for (const auto& range : rangeRecord) 150 { 151 if (unlikely (range.first < last)) 152 break; 153 last = range.last; 154 for (hb_codepoint_t g = range.first - 1; 155 glyphs.next (&g) && g <= last;) 156 intersect_glyphs << g; 157 } 158 } 159 160 unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ } 161 162 template <typename set_t> 163 bool collect_coverage (set_t *glyphs) const 164 { 165 for (const auto& range: rangeRecord) 166 if (unlikely (!range.collect_coverage (glyphs))) 167 return false; 168 return true; 169 } 170 171 public: 172 /* Older compilers need this to be public. */ 173 struct iter_t 174 { 175 void init (const CoverageFormat2_4 &c_) 176 { 177 c = &c_; 178 coverage = 0; 179 i = 0; 180 j = c->rangeRecord.len ? c->rangeRecord[0].first : 0; 181 if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last)) 182 { 183 /* Broken table. Skip. */ 184 i = c->rangeRecord.len; 185 j = 0; 186 } 187 } 188 bool __more__ () const { return i < c->rangeRecord.len; } 189 void __next__ () 190 { 191 if (j >= c->rangeRecord[i].last) 192 { 193 i++; 194 if (__more__ ()) 195 { 196 unsigned int old = coverage; 197 j = c->rangeRecord.arrayZ[i].first; 198 coverage = c->rangeRecord.arrayZ[i].value; 199 if (unlikely (coverage != old + 1)) 200 { 201 /* Broken table. Skip. Important to avoid DoS. 202 * Also, our callers depend on coverage being 203 * consecutive and monotonically increasing, 204 * ie. iota(). */ 205 i = c->rangeRecord.len; 206 j = 0; 207 return; 208 } 209 } 210 else 211 j = 0; 212 return; 213 } 214 coverage++; 215 j++; 216 } 217 hb_codepoint_t get_glyph () const { return j; } 218 bool operator != (const iter_t& o) const 219 { return i != o.i || j != o.j; } 220 iter_t __end__ () const 221 { 222 iter_t it; 223 it.init (*c); 224 it.i = c->rangeRecord.len; 225 it.j = 0; 226 return it; 227 } 228 229 private: 230 const struct CoverageFormat2_4 *c; 231 unsigned int i, coverage; 232 hb_codepoint_t j; 233 }; 234 private: 235 }; 236 237 } 238 } 239 } 240 241 #endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH