Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright © 2007,2008,2009 Red Hat, Inc. | |
| 3 * Copyright © 2010,2011,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 | |
| 27 */ | |
| 28 | |
| 29 #ifndef HB_OT_LAYOUT_GDEF_TABLE_HH | |
| 30 #define HB_OT_LAYOUT_GDEF_TABLE_HH | |
| 31 | |
| 32 #include "hb-ot-layout-common.hh" | |
| 33 | |
| 34 #include "hb-font.hh" | |
| 35 | |
| 36 | |
| 37 namespace OT { | |
| 38 | |
| 39 | |
| 40 /* | |
| 41 * Attachment List Table | |
| 42 */ | |
| 43 | |
| 44 /* Array of contour point indices--in increasing numerical order */ | |
| 45 struct AttachPoint : Array16Of<HBUINT16> | |
| 46 { | |
| 47 bool subset (hb_subset_context_t *c) const | |
| 48 { | |
| 49 TRACE_SUBSET (this); | |
| 50 auto *out = c->serializer->start_embed (*this); | |
| 51 if (unlikely (!out)) return_trace (false); | |
| 52 | |
| 53 return_trace (out->serialize (c->serializer, + iter ())); | |
| 54 } | |
| 55 }; | |
| 56 | |
| 57 struct AttachList | |
| 58 { | |
| 59 unsigned int get_attach_points (hb_codepoint_t glyph_id, | |
| 60 unsigned int start_offset, | |
| 61 unsigned int *point_count /* IN/OUT */, | |
| 62 unsigned int *point_array /* OUT */) const | |
| 63 { | |
| 64 unsigned int index = (this+coverage).get_coverage (glyph_id); | |
| 65 if (index == NOT_COVERED) | |
| 66 { | |
| 67 if (point_count) | |
| 68 *point_count = 0; | |
| 69 return 0; | |
| 70 } | |
| 71 | |
| 72 const AttachPoint &points = this+attachPoint[index]; | |
| 73 | |
| 74 if (point_count) | |
| 75 { | |
| 76 + points.as_array ().sub_array (start_offset, point_count) | |
| 77 | hb_sink (hb_array (point_array, *point_count)) | |
| 78 ; | |
| 79 } | |
| 80 | |
| 81 return points.len; | |
| 82 } | |
| 83 | |
| 84 bool subset (hb_subset_context_t *c) const | |
| 85 { | |
| 86 TRACE_SUBSET (this); | |
| 87 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); | |
| 88 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 89 | |
| 90 auto *out = c->serializer->start_embed (*this); | |
| 91 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 92 | |
| 93 hb_sorted_vector_t<hb_codepoint_t> new_coverage; | |
| 94 + hb_zip (this+coverage, attachPoint) | |
| 95 | hb_filter (glyphset, hb_first) | |
| 96 | hb_filter (subset_offset_array (c, out->attachPoint, this), hb_second) | |
| 97 | hb_map (hb_first) | |
| 98 | hb_map (glyph_map) | |
| 99 | hb_sink (new_coverage) | |
| 100 ; | |
| 101 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); | |
| 102 return_trace (bool (new_coverage)); | |
| 103 } | |
| 104 | |
| 105 bool sanitize (hb_sanitize_context_t *c) const | |
| 106 { | |
| 107 TRACE_SANITIZE (this); | |
| 108 return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this)); | |
| 109 } | |
| 110 | |
| 111 protected: | |
| 112 Offset16To<Coverage> | |
| 113 coverage; /* Offset to Coverage table -- from | |
| 114 * beginning of AttachList table */ | |
| 115 Array16OfOffset16To<AttachPoint> | |
| 116 attachPoint; /* Array of AttachPoint tables | |
| 117 * in Coverage Index order */ | |
| 118 public: | |
| 119 DEFINE_SIZE_ARRAY (4, attachPoint); | |
| 120 }; | |
| 121 | |
| 122 /* | |
| 123 * Ligature Caret Table | |
| 124 */ | |
| 125 | |
| 126 struct CaretValueFormat1 | |
| 127 { | |
| 128 friend struct CaretValue; | |
| 129 bool subset (hb_subset_context_t *c) const | |
| 130 { | |
| 131 TRACE_SUBSET (this); | |
| 132 auto *out = c->serializer->embed (this); | |
| 133 if (unlikely (!out)) return_trace (false); | |
| 134 return_trace (true); | |
| 135 } | |
| 136 | |
| 137 private: | |
| 138 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const | |
| 139 { | |
| 140 return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate); | |
| 141 } | |
| 142 | |
| 143 bool sanitize (hb_sanitize_context_t *c) const | |
| 144 { | |
| 145 TRACE_SANITIZE (this); | |
| 146 return_trace (c->check_struct (this)); | |
| 147 } | |
| 148 | |
| 149 protected: | |
| 150 HBUINT16 caretValueFormat; /* Format identifier--format = 1 */ | |
| 151 FWORD coordinate; /* X or Y value, in design units */ | |
| 152 public: | |
| 153 DEFINE_SIZE_STATIC (4); | |
| 154 }; | |
| 155 | |
| 156 struct CaretValueFormat2 | |
| 157 { | |
| 158 friend struct CaretValue; | |
| 159 bool subset (hb_subset_context_t *c) const | |
| 160 { | |
| 161 TRACE_SUBSET (this); | |
| 162 auto *out = c->serializer->embed (this); | |
| 163 if (unlikely (!out)) return_trace (false); | |
| 164 return_trace (true); | |
| 165 } | |
| 166 | |
| 167 private: | |
| 168 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const | |
| 169 { | |
| 170 hb_position_t x, y; | |
| 171 font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y); | |
| 172 return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y; | |
| 173 } | |
| 174 | |
| 175 bool sanitize (hb_sanitize_context_t *c) const | |
| 176 { | |
| 177 TRACE_SANITIZE (this); | |
| 178 return_trace (c->check_struct (this)); | |
| 179 } | |
| 180 | |
| 181 protected: | |
| 182 HBUINT16 caretValueFormat; /* Format identifier--format = 2 */ | |
| 183 HBUINT16 caretValuePoint; /* Contour point index on glyph */ | |
| 184 public: | |
| 185 DEFINE_SIZE_STATIC (4); | |
| 186 }; | |
| 187 | |
| 188 struct CaretValueFormat3 | |
| 189 { | |
| 190 friend struct CaretValue; | |
| 191 | |
| 192 hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, | |
| 193 const VariationStore &var_store) const | |
| 194 { | |
| 195 return HB_DIRECTION_IS_HORIZONTAL (direction) ? | |
| 196 font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) : | |
| 197 font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store); | |
| 198 } | |
| 199 | |
| 200 bool subset (hb_subset_context_t *c) const | |
| 201 { | |
| 202 TRACE_SUBSET (this); | |
| 203 auto *out = c->serializer->start_embed (*this); | |
| 204 if (unlikely (!out)) return_trace (false); | |
| 205 if (!c->serializer->embed (caretValueFormat)) return_trace (false); | |
| 206 if (!c->serializer->embed (coordinate)) return_trace (false); | |
| 207 | |
| 208 unsigned varidx = (this+deviceTable).get_variation_index (); | |
| 209 if (c->plan->layout_variation_idx_delta_map->has (varidx)) | |
| 210 { | |
| 211 int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (varidx)); | |
| 212 if (delta != 0) | |
| 213 { | |
| 214 if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) | |
| 215 return_trace (false); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 if (c->plan->all_axes_pinned) | |
| 220 return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); | |
| 221 | |
| 222 if (!c->serializer->embed (deviceTable)) | |
| 223 return_trace (false); | |
| 224 | |
| 225 return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out), | |
| 226 hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map)); | |
| 227 } | |
| 228 | |
| 229 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const | |
| 230 { (this+deviceTable).collect_variation_indices (c); } | |
| 231 | |
| 232 bool sanitize (hb_sanitize_context_t *c) const | |
| 233 { | |
| 234 TRACE_SANITIZE (this); | |
| 235 return_trace (c->check_struct (this) && deviceTable.sanitize (c, this)); | |
| 236 } | |
| 237 | |
| 238 protected: | |
| 239 HBUINT16 caretValueFormat; /* Format identifier--format = 3 */ | |
| 240 FWORD coordinate; /* X or Y value, in design units */ | |
| 241 Offset16To<Device> | |
| 242 deviceTable; /* Offset to Device table for X or Y | |
| 243 * value--from beginning of CaretValue | |
| 244 * table */ | |
| 245 public: | |
| 246 DEFINE_SIZE_STATIC (6); | |
| 247 }; | |
| 248 | |
| 249 struct CaretValue | |
| 250 { | |
| 251 hb_position_t get_caret_value (hb_font_t *font, | |
| 252 hb_direction_t direction, | |
| 253 hb_codepoint_t glyph_id, | |
| 254 const VariationStore &var_store) const | |
| 255 { | |
| 256 switch (u.format) { | |
| 257 case 1: return u.format1.get_caret_value (font, direction); | |
| 258 case 2: return u.format2.get_caret_value (font, direction, glyph_id); | |
| 259 case 3: return u.format3.get_caret_value (font, direction, var_store); | |
| 260 default:return 0; | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 template <typename context_t, typename ...Ts> | |
| 265 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const | |
| 266 { | |
| 267 TRACE_DISPATCH (this, u.format); | |
| 268 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ()); | |
| 269 switch (u.format) { | |
| 270 case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...)); | |
| 271 case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...)); | |
| 272 case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...)); | |
| 273 default:return_trace (c->default_return_value ()); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const | |
| 278 { | |
| 279 switch (u.format) { | |
| 280 case 1: | |
| 281 case 2: | |
| 282 return; | |
| 283 case 3: | |
| 284 u.format3.collect_variation_indices (c); | |
| 285 return; | |
| 286 default: return; | |
| 287 } | |
| 288 } | |
| 289 | |
| 290 bool sanitize (hb_sanitize_context_t *c) const | |
| 291 { | |
| 292 TRACE_SANITIZE (this); | |
| 293 if (!u.format.sanitize (c)) return_trace (false); | |
| 294 switch (u.format) { | |
| 295 case 1: return_trace (u.format1.sanitize (c)); | |
| 296 case 2: return_trace (u.format2.sanitize (c)); | |
| 297 case 3: return_trace (u.format3.sanitize (c)); | |
| 298 default:return_trace (true); | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 protected: | |
| 303 union { | |
| 304 HBUINT16 format; /* Format identifier */ | |
| 305 CaretValueFormat1 format1; | |
| 306 CaretValueFormat2 format2; | |
| 307 CaretValueFormat3 format3; | |
| 308 } u; | |
| 309 public: | |
| 310 DEFINE_SIZE_UNION (2, format); | |
| 311 }; | |
| 312 | |
| 313 struct LigGlyph | |
| 314 { | |
| 315 unsigned get_lig_carets (hb_font_t *font, | |
| 316 hb_direction_t direction, | |
| 317 hb_codepoint_t glyph_id, | |
| 318 const VariationStore &var_store, | |
| 319 unsigned start_offset, | |
| 320 unsigned *caret_count /* IN/OUT */, | |
| 321 hb_position_t *caret_array /* OUT */) const | |
| 322 { | |
| 323 if (caret_count) | |
| 324 { | |
| 325 + carets.as_array ().sub_array (start_offset, caret_count) | |
| 326 | hb_map (hb_add (this)) | |
| 327 | hb_map ([&] (const CaretValue &value) { return value.get_caret_value (font, direction, glyph_id, var_store); }) | |
| 328 | hb_sink (hb_array (caret_array, *caret_count)) | |
| 329 ; | |
| 330 } | |
| 331 | |
| 332 return carets.len; | |
| 333 } | |
| 334 | |
| 335 bool subset (hb_subset_context_t *c) const | |
| 336 { | |
| 337 TRACE_SUBSET (this); | |
| 338 auto *out = c->serializer->start_embed (*this); | |
| 339 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 340 | |
| 341 + hb_iter (carets) | |
| 342 | hb_apply (subset_offset_array (c, out->carets, this)) | |
| 343 ; | |
| 344 | |
| 345 return_trace (bool (out->carets)); | |
| 346 } | |
| 347 | |
| 348 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const | |
| 349 { | |
| 350 for (const Offset16To<CaretValue>& offset : carets.iter ()) | |
| 351 (this+offset).collect_variation_indices (c); | |
| 352 } | |
| 353 | |
| 354 bool sanitize (hb_sanitize_context_t *c) const | |
| 355 { | |
| 356 TRACE_SANITIZE (this); | |
| 357 return_trace (carets.sanitize (c, this)); | |
| 358 } | |
| 359 | |
| 360 protected: | |
| 361 Array16OfOffset16To<CaretValue> | |
| 362 carets; /* Offset array of CaretValue tables | |
| 363 * --from beginning of LigGlyph table | |
| 364 * --in increasing coordinate order */ | |
| 365 public: | |
| 366 DEFINE_SIZE_ARRAY (2, carets); | |
| 367 }; | |
| 368 | |
| 369 struct LigCaretList | |
| 370 { | |
| 371 unsigned int get_lig_carets (hb_font_t *font, | |
| 372 hb_direction_t direction, | |
| 373 hb_codepoint_t glyph_id, | |
| 374 const VariationStore &var_store, | |
| 375 unsigned int start_offset, | |
| 376 unsigned int *caret_count /* IN/OUT */, | |
| 377 hb_position_t *caret_array /* OUT */) const | |
| 378 { | |
| 379 unsigned int index = (this+coverage).get_coverage (glyph_id); | |
| 380 if (index == NOT_COVERED) | |
| 381 { | |
| 382 if (caret_count) | |
| 383 *caret_count = 0; | |
| 384 return 0; | |
| 385 } | |
| 386 const LigGlyph &lig_glyph = this+ligGlyph[index]; | |
| 387 return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array); | |
| 388 } | |
| 389 | |
| 390 bool subset (hb_subset_context_t *c) const | |
| 391 { | |
| 392 TRACE_SUBSET (this); | |
| 393 const hb_set_t &glyphset = *c->plan->glyphset_gsub (); | |
| 394 const hb_map_t &glyph_map = *c->plan->glyph_map; | |
| 395 | |
| 396 auto *out = c->serializer->start_embed (*this); | |
| 397 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 398 | |
| 399 hb_sorted_vector_t<hb_codepoint_t> new_coverage; | |
| 400 + hb_zip (this+coverage, ligGlyph) | |
| 401 | hb_filter (glyphset, hb_first) | |
| 402 | hb_filter (subset_offset_array (c, out->ligGlyph, this), hb_second) | |
| 403 | hb_map (hb_first) | |
| 404 | hb_map (glyph_map) | |
| 405 | hb_sink (new_coverage) | |
| 406 ; | |
| 407 out->coverage.serialize_serialize (c->serializer, new_coverage.iter ()); | |
| 408 return_trace (bool (new_coverage)); | |
| 409 } | |
| 410 | |
| 411 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const | |
| 412 { | |
| 413 + hb_zip (this+coverage, ligGlyph) | |
| 414 | hb_filter (c->glyph_set, hb_first) | |
| 415 | hb_map (hb_second) | |
| 416 | hb_map (hb_add (this)) | |
| 417 | hb_apply ([c] (const LigGlyph& _) { _.collect_variation_indices (c); }) | |
| 418 ; | |
| 419 } | |
| 420 | |
| 421 bool sanitize (hb_sanitize_context_t *c) const | |
| 422 { | |
| 423 TRACE_SANITIZE (this); | |
| 424 return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this)); | |
| 425 } | |
| 426 | |
| 427 protected: | |
| 428 Offset16To<Coverage> | |
| 429 coverage; /* Offset to Coverage table--from | |
| 430 * beginning of LigCaretList table */ | |
| 431 Array16OfOffset16To<LigGlyph> | |
| 432 ligGlyph; /* Array of LigGlyph tables | |
| 433 * in Coverage Index order */ | |
| 434 public: | |
| 435 DEFINE_SIZE_ARRAY (4, ligGlyph); | |
| 436 }; | |
| 437 | |
| 438 | |
| 439 struct MarkGlyphSetsFormat1 | |
| 440 { | |
| 441 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const | |
| 442 { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; } | |
| 443 | |
| 444 bool subset (hb_subset_context_t *c) const | |
| 445 { | |
| 446 TRACE_SUBSET (this); | |
| 447 auto *out = c->serializer->start_embed (*this); | |
| 448 if (unlikely (!c->serializer->extend_min (out))) return_trace (false); | |
| 449 out->format = format; | |
| 450 | |
| 451 bool ret = true; | |
| 452 for (const Offset32To<Coverage>& offset : coverage.iter ()) | |
| 453 { | |
| 454 auto *o = out->coverage.serialize_append (c->serializer); | |
| 455 if (unlikely (!o)) | |
| 456 { | |
| 457 ret = false; | |
| 458 break; | |
| 459 } | |
| 460 | |
| 461 //not using o->serialize_subset (c, offset, this, out) here because | |
| 462 //OTS doesn't allow null offset. | |
| 463 //See issue: https://github.com/khaledhosny/ots/issues/172 | |
| 464 c->serializer->push (); | |
| 465 c->dispatch (this+offset); | |
| 466 c->serializer->add_link (*o, c->serializer->pop_pack ()); | |
| 467 } | |
| 468 | |
| 469 return_trace (ret && out->coverage.len); | |
| 470 } | |
| 471 | |
| 472 bool sanitize (hb_sanitize_context_t *c) const | |
| 473 { | |
| 474 TRACE_SANITIZE (this); | |
| 475 return_trace (coverage.sanitize (c, this)); | |
| 476 } | |
| 477 | |
| 478 protected: | |
| 479 HBUINT16 format; /* Format identifier--format = 1 */ | |
| 480 Array16Of<Offset32To<Coverage>> | |
| 481 coverage; /* Array of long offsets to mark set | |
| 482 * coverage tables */ | |
| 483 public: | |
| 484 DEFINE_SIZE_ARRAY (4, coverage); | |
| 485 }; | |
| 486 | |
| 487 struct MarkGlyphSets | |
| 488 { | |
| 489 bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const | |
| 490 { | |
| 491 switch (u.format) { | |
| 492 case 1: return u.format1.covers (set_index, glyph_id); | |
| 493 default:return false; | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 bool subset (hb_subset_context_t *c) const | |
| 498 { | |
| 499 TRACE_SUBSET (this); | |
| 500 switch (u.format) { | |
| 501 case 1: return_trace (u.format1.subset (c)); | |
| 502 default:return_trace (false); | |
| 503 } | |
| 504 } | |
| 505 | |
| 506 bool sanitize (hb_sanitize_context_t *c) const | |
| 507 { | |
| 508 TRACE_SANITIZE (this); | |
| 509 if (!u.format.sanitize (c)) return_trace (false); | |
| 510 switch (u.format) { | |
| 511 case 1: return_trace (u.format1.sanitize (c)); | |
| 512 default:return_trace (true); | |
| 513 } | |
| 514 } | |
| 515 | |
| 516 protected: | |
| 517 union { | |
| 518 HBUINT16 format; /* Format identifier */ | |
| 519 MarkGlyphSetsFormat1 format1; | |
| 520 } u; | |
| 521 public: | |
| 522 DEFINE_SIZE_UNION (2, format); | |
| 523 }; | |
| 524 | |
| 525 | |
| 526 /* | |
| 527 * GDEF -- Glyph Definition | |
| 528 * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef | |
| 529 */ | |
| 530 | |
| 531 | |
| 532 template <typename Types> | |
| 533 struct GDEFVersion1_2 | |
| 534 { | |
| 535 friend struct GDEF; | |
| 536 | |
| 537 protected: | |
| 538 FixedVersion<>version; /* Version of the GDEF table--currently | |
| 539 * 0x00010003u */ | |
| 540 typename Types::template OffsetTo<ClassDef> | |
| 541 glyphClassDef; /* Offset to class definition table | |
| 542 * for glyph type--from beginning of | |
| 543 * GDEF header (may be Null) */ | |
| 544 typename Types::template OffsetTo<AttachList> | |
| 545 attachList; /* Offset to list of glyphs with | |
| 546 * attachment points--from beginning | |
| 547 * of GDEF header (may be Null) */ | |
| 548 typename Types::template OffsetTo<LigCaretList> | |
| 549 ligCaretList; /* Offset to list of positioning points | |
| 550 * for ligature carets--from beginning | |
| 551 * of GDEF header (may be Null) */ | |
| 552 typename Types::template OffsetTo<ClassDef> | |
| 553 markAttachClassDef; /* Offset to class definition table for | |
| 554 * mark attachment type--from beginning | |
| 555 * of GDEF header (may be Null) */ | |
| 556 typename Types::template OffsetTo<MarkGlyphSets> | |
| 557 markGlyphSetsDef; /* Offset to the table of mark set | |
| 558 * definitions--from beginning of GDEF | |
| 559 * header (may be NULL). Introduced | |
| 560 * in version 0x00010002. */ | |
| 561 Offset32To<VariationStore> | |
| 562 varStore; /* Offset to the table of Item Variation | |
| 563 * Store--from beginning of GDEF | |
| 564 * header (may be NULL). Introduced | |
| 565 * in version 0x00010003. */ | |
| 566 public: | |
| 567 DEFINE_SIZE_MIN (4 + 4 * Types::size); | |
| 568 | |
| 569 unsigned int get_size () const | |
| 570 { | |
| 571 return min_size + | |
| 572 (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) + | |
| 573 (version.to_int () >= 0x00010003u ? varStore.static_size : 0); | |
| 574 } | |
| 575 | |
| 576 bool sanitize (hb_sanitize_context_t *c) const | |
| 577 { | |
| 578 TRACE_SANITIZE (this); | |
| 579 return_trace (version.sanitize (c) && | |
| 580 glyphClassDef.sanitize (c, this) && | |
| 581 attachList.sanitize (c, this) && | |
| 582 ligCaretList.sanitize (c, this) && | |
| 583 markAttachClassDef.sanitize (c, this) && | |
| 584 (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) && | |
| 585 (version.to_int () < 0x00010003u || varStore.sanitize (c, this))); | |
| 586 } | |
| 587 | |
| 588 bool subset (hb_subset_context_t *c) const | |
| 589 { | |
| 590 TRACE_SUBSET (this); | |
| 591 auto *out = c->serializer->embed (*this); | |
| 592 if (unlikely (!out)) return_trace (false); | |
| 593 | |
| 594 bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true); | |
| 595 bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this); | |
| 596 bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this); | |
| 597 bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true); | |
| 598 | |
| 599 bool subset_markglyphsetsdef = false; | |
| 600 if (version.to_int () >= 0x00010002u) | |
| 601 { | |
| 602 subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this); | |
| 603 } | |
| 604 | |
| 605 bool subset_varstore = false; | |
| 606 if (version.to_int () >= 0x00010003u) | |
| 607 { | |
| 608 if (c->plan->all_axes_pinned) | |
| 609 out->varStore = 0; | |
| 610 else | |
| 611 subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); | |
| 612 } | |
| 613 | |
| 614 if (subset_varstore) | |
| 615 { | |
| 616 out->version.minor = 3; | |
| 617 } else if (subset_markglyphsetsdef) { | |
| 618 out->version.minor = 2; | |
| 619 } else { | |
| 620 out->version.minor = 0; | |
| 621 } | |
| 622 | |
| 623 return_trace (subset_glyphclassdef || subset_attachlist || | |
| 624 subset_ligcaretlist || subset_markattachclassdef || | |
| 625 (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) || | |
| 626 (out->version.to_int () >= 0x00010003u && subset_varstore)); | |
| 627 } | |
| 628 }; | |
| 629 | |
| 630 struct GDEF | |
| 631 { | |
| 632 static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF; | |
| 633 | |
| 634 enum GlyphClasses { | |
| 635 UnclassifiedGlyph = 0, | |
| 636 BaseGlyph = 1, | |
| 637 LigatureGlyph = 2, | |
| 638 MarkGlyph = 3, | |
| 639 ComponentGlyph = 4 | |
| 640 }; | |
| 641 | |
| 642 unsigned int get_size () const | |
| 643 { | |
| 644 switch (u.version.major) { | |
| 645 case 1: return u.version1.get_size (); | |
| 646 #ifndef HB_NO_BEYOND_64K | |
| 647 case 2: return u.version2.get_size (); | |
| 648 #endif | |
| 649 default: return u.version.static_size; | |
| 650 } | |
| 651 } | |
| 652 | |
| 653 bool sanitize (hb_sanitize_context_t *c) const | |
| 654 { | |
| 655 TRACE_SANITIZE (this); | |
| 656 if (unlikely (!u.version.sanitize (c))) return_trace (false); | |
| 657 switch (u.version.major) { | |
| 658 case 1: return_trace (u.version1.sanitize (c)); | |
| 659 #ifndef HB_NO_BEYOND_64K | |
| 660 case 2: return_trace (u.version2.sanitize (c)); | |
| 661 #endif | |
| 662 default: return_trace (true); | |
| 663 } | |
| 664 } | |
| 665 | |
| 666 bool subset (hb_subset_context_t *c) const | |
| 667 { | |
| 668 switch (u.version.major) { | |
| 669 case 1: return u.version1.subset (c); | |
| 670 #ifndef HB_NO_BEYOND_64K | |
| 671 case 2: return u.version2.subset (c); | |
| 672 #endif | |
| 673 default: return false; | |
| 674 } | |
| 675 } | |
| 676 | |
| 677 bool has_glyph_classes () const | |
| 678 { | |
| 679 switch (u.version.major) { | |
| 680 case 1: return u.version1.glyphClassDef != 0; | |
| 681 #ifndef HB_NO_BEYOND_64K | |
| 682 case 2: return u.version2.glyphClassDef != 0; | |
| 683 #endif | |
| 684 default: return false; | |
| 685 } | |
| 686 } | |
| 687 const ClassDef &get_glyph_class_def () const | |
| 688 { | |
| 689 switch (u.version.major) { | |
| 690 case 1: return this+u.version1.glyphClassDef; | |
| 691 #ifndef HB_NO_BEYOND_64K | |
| 692 case 2: return this+u.version2.glyphClassDef; | |
| 693 #endif | |
| 694 default: return Null(ClassDef); | |
| 695 } | |
| 696 } | |
| 697 bool has_attach_list () const | |
| 698 { | |
| 699 switch (u.version.major) { | |
| 700 case 1: return u.version1.attachList != 0; | |
| 701 #ifndef HB_NO_BEYOND_64K | |
| 702 case 2: return u.version2.attachList != 0; | |
| 703 #endif | |
| 704 default: return false; | |
| 705 } | |
| 706 } | |
| 707 const AttachList &get_attach_list () const | |
| 708 { | |
| 709 switch (u.version.major) { | |
| 710 case 1: return this+u.version1.attachList; | |
| 711 #ifndef HB_NO_BEYOND_64K | |
| 712 case 2: return this+u.version2.attachList; | |
| 713 #endif | |
| 714 default: return Null(AttachList); | |
| 715 } | |
| 716 } | |
| 717 bool has_lig_carets () const | |
| 718 { | |
| 719 switch (u.version.major) { | |
| 720 case 1: return u.version1.ligCaretList != 0; | |
| 721 #ifndef HB_NO_BEYOND_64K | |
| 722 case 2: return u.version2.ligCaretList != 0; | |
| 723 #endif | |
| 724 default: return false; | |
| 725 } | |
| 726 } | |
| 727 const LigCaretList &get_lig_caret_list () const | |
| 728 { | |
| 729 switch (u.version.major) { | |
| 730 case 1: return this+u.version1.ligCaretList; | |
| 731 #ifndef HB_NO_BEYOND_64K | |
| 732 case 2: return this+u.version2.ligCaretList; | |
| 733 #endif | |
| 734 default: return Null(LigCaretList); | |
| 735 } | |
| 736 } | |
| 737 bool has_mark_attachment_types () const | |
| 738 { | |
| 739 switch (u.version.major) { | |
| 740 case 1: return u.version1.markAttachClassDef != 0; | |
| 741 #ifndef HB_NO_BEYOND_64K | |
| 742 case 2: return u.version2.markAttachClassDef != 0; | |
| 743 #endif | |
| 744 default: return false; | |
| 745 } | |
| 746 } | |
| 747 const ClassDef &get_mark_attach_class_def () const | |
| 748 { | |
| 749 switch (u.version.major) { | |
| 750 case 1: return this+u.version1.markAttachClassDef; | |
| 751 #ifndef HB_NO_BEYOND_64K | |
| 752 case 2: return this+u.version2.markAttachClassDef; | |
| 753 #endif | |
| 754 default: return Null(ClassDef); | |
| 755 } | |
| 756 } | |
| 757 bool has_mark_glyph_sets () const | |
| 758 { | |
| 759 switch (u.version.major) { | |
| 760 case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0; | |
| 761 #ifndef HB_NO_BEYOND_64K | |
| 762 case 2: return u.version2.markGlyphSetsDef != 0; | |
| 763 #endif | |
| 764 default: return false; | |
| 765 } | |
| 766 } | |
| 767 const MarkGlyphSets &get_mark_glyph_sets () const | |
| 768 { | |
| 769 switch (u.version.major) { | |
| 770 case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets); | |
| 771 #ifndef HB_NO_BEYOND_64K | |
| 772 case 2: return this+u.version2.markGlyphSetsDef; | |
| 773 #endif | |
| 774 default: return Null(MarkGlyphSets); | |
| 775 } | |
| 776 } | |
| 777 bool has_var_store () const | |
| 778 { | |
| 779 switch (u.version.major) { | |
| 780 case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0; | |
| 781 #ifndef HB_NO_BEYOND_64K | |
| 782 case 2: return u.version2.varStore != 0; | |
| 783 #endif | |
| 784 default: return false; | |
| 785 } | |
| 786 } | |
| 787 const VariationStore &get_var_store () const | |
| 788 { | |
| 789 switch (u.version.major) { | |
| 790 case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore); | |
| 791 #ifndef HB_NO_BEYOND_64K | |
| 792 case 2: return this+u.version2.varStore; | |
| 793 #endif | |
| 794 default: return Null(VariationStore); | |
| 795 } | |
| 796 } | |
| 797 | |
| 798 | |
| 799 bool has_data () const { return u.version.to_int (); } | |
| 800 unsigned int get_glyph_class (hb_codepoint_t glyph) const | |
| 801 { return get_glyph_class_def ().get_class (glyph); } | |
| 802 void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const | |
| 803 { get_glyph_class_def ().collect_class (glyphs, klass); } | |
| 804 | |
| 805 unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const | |
| 806 { return get_mark_attach_class_def ().get_class (glyph); } | |
| 807 | |
| 808 unsigned int get_attach_points (hb_codepoint_t glyph_id, | |
| 809 unsigned int start_offset, | |
| 810 unsigned int *point_count /* IN/OUT */, | |
| 811 unsigned int *point_array /* OUT */) const | |
| 812 { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); } | |
| 813 | |
| 814 unsigned int get_lig_carets (hb_font_t *font, | |
| 815 hb_direction_t direction, | |
| 816 hb_codepoint_t glyph_id, | |
| 817 unsigned int start_offset, | |
| 818 unsigned int *caret_count /* IN/OUT */, | |
| 819 hb_position_t *caret_array /* OUT */) const | |
| 820 { return get_lig_caret_list ().get_lig_carets (font, | |
| 821 direction, glyph_id, get_var_store(), | |
| 822 start_offset, caret_count, caret_array); } | |
| 823 | |
| 824 bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const | |
| 825 { return get_mark_glyph_sets ().covers (set_index, glyph_id); } | |
| 826 | |
| 827 /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing | |
| 828 * glyph class and other bits, and high 8-bit the mark attachment type (if any). | |
| 829 * Not to be confused with lookup_props which is very similar. */ | |
| 830 unsigned int get_glyph_props (hb_codepoint_t glyph) const | |
| 831 { | |
| 832 unsigned int klass = get_glyph_class (glyph); | |
| 833 | |
| 834 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH == (unsigned int) LookupFlag::IgnoreBaseGlyphs), ""); | |
| 835 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE == (unsigned int) LookupFlag::IgnoreLigatures), ""); | |
| 836 static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), ""); | |
| 837 | |
| 838 switch (klass) { | |
| 839 default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; | |
| 840 case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; | |
| 841 case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE; | |
| 842 case MarkGlyph: | |
| 843 klass = get_mark_attachment_type (glyph); | |
| 844 return HB_OT_LAYOUT_GLYPH_PROPS_MARK | (klass << 8); | |
| 845 } | |
| 846 } | |
| 847 | |
| 848 HB_INTERNAL bool is_blocklisted (hb_blob_t *blob, | |
| 849 hb_face_t *face) const; | |
| 850 | |
| 851 struct accelerator_t | |
| 852 { | |
| 853 accelerator_t (hb_face_t *face) | |
| 854 { | |
| 855 table = hb_sanitize_context_t ().reference_table<GDEF> (face); | |
| 856 if (unlikely (table->is_blocklisted (table.get_blob (), face))) | |
| 857 { | |
| 858 hb_blob_destroy (table.get_blob ()); | |
| 859 table = hb_blob_get_empty (); | |
| 860 } | |
| 861 } | |
| 862 ~accelerator_t () { table.destroy (); } | |
| 863 | |
| 864 hb_blob_ptr_t<GDEF> table; | |
| 865 }; | |
| 866 | |
| 867 void collect_variation_indices (hb_collect_variation_indices_context_t *c) const | |
| 868 { get_lig_caret_list ().collect_variation_indices (c); } | |
| 869 | |
| 870 void remap_layout_variation_indices (const hb_set_t *layout_variation_indices, | |
| 871 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map /* OUT */) const | |
| 872 { | |
| 873 if (!has_var_store ()) return; | |
| 874 if (layout_variation_indices->is_empty ()) return; | |
| 875 | |
| 876 unsigned new_major = 0, new_minor = 0; | |
| 877 unsigned last_major = (layout_variation_indices->get_min ()) >> 16; | |
| 878 for (unsigned idx : layout_variation_indices->iter ()) | |
| 879 { | |
| 880 uint16_t major = idx >> 16; | |
| 881 if (major >= get_var_store ().get_sub_table_count ()) break; | |
| 882 if (major != last_major) | |
| 883 { | |
| 884 new_minor = 0; | |
| 885 ++new_major; | |
| 886 } | |
| 887 | |
| 888 unsigned new_idx = (new_major << 16) + new_minor; | |
| 889 if (!layout_variation_idx_delta_map->has (idx)) | |
| 890 continue; | |
| 891 int delta = hb_second (layout_variation_idx_delta_map->get (idx)); | |
| 892 | |
| 893 layout_variation_idx_delta_map->set (idx, hb_pair_t<unsigned, int> (new_idx, delta)); | |
| 894 ++new_minor; | |
| 895 last_major = major; | |
| 896 } | |
| 897 } | |
| 898 | |
| 899 protected: | |
| 900 union { | |
| 901 FixedVersion<> version; /* Version identifier */ | |
| 902 GDEFVersion1_2<SmallTypes> version1; | |
| 903 #ifndef HB_NO_BEYOND_64K | |
| 904 GDEFVersion1_2<MediumTypes> version2; | |
| 905 #endif | |
| 906 } u; | |
| 907 public: | |
| 908 DEFINE_SIZE_MIN (4); | |
| 909 }; | |
| 910 | |
| 911 struct GDEF_accelerator_t : GDEF::accelerator_t { | |
| 912 GDEF_accelerator_t (hb_face_t *face) : GDEF::accelerator_t (face) {} | |
| 913 }; | |
| 914 | |
| 915 } /* namespace OT */ | |
| 916 | |
| 917 | |
| 918 #endif /* HB_OT_LAYOUT_GDEF_TABLE_HH */ |
