1 /* 2 * Copyright © 2011,2014 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, Roozbeh Pournader 25 */ 26 27 #include "hb-private.hh" 28 29 #include "hb-ot.h" 30 31 #include "hb-font-private.hh" 32 33 #include "hb-ot-cmap-table.hh" 34 #include "hb-ot-glyf-table.hh" 35 #include "hb-ot-head-table.hh" 36 #include "hb-ot-hhea-table.hh" 37 #include "hb-ot-hmtx-table.hh" 38 #include "hb-ot-os2-table.hh" 39 //#include "hb-ot-post-table.hh" 40 41 42 struct hb_ot_face_metrics_accelerator_t 43 { 44 unsigned int num_metrics; 45 unsigned int num_advances; 46 unsigned int default_advance; 47 unsigned short ascender; 48 unsigned short descender; 49 unsigned short line_gap; 50 51 const OT::_mtx *table; 52 hb_blob_t *blob; 53 54 inline void init (hb_face_t *face, 55 hb_tag_t _hea_tag, 56 hb_tag_t _mtx_tag, 57 hb_tag_t os2_tag) 58 { 59 this->default_advance = face->get_upem (); 60 61 bool got_font_extents = false; 62 if (os2_tag) 63 { 64 hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>::sanitize (face->reference_table (os2_tag)); 65 const OT::os2 *os2 = OT::Sanitizer<OT::os2>::lock_instance (os2_blob); 66 #define USE_TYPO_METRICS (1u<<7) 67 if (0 != (os2->fsSelection & USE_TYPO_METRICS)) 68 { 69 this->ascender = os2->sTypoAscender; 70 this->descender = os2->sTypoDescender; 71 this->line_gap = os2->sTypoLineGap; 72 got_font_extents = (this->ascender | this->descender) != 0; 73 } 74 hb_blob_destroy (os2_blob); 75 } 76 77 hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); 78 const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob); 79 this->num_advances = _hea->numberOfLongMetrics; 80 if (!got_font_extents) 81 { 82 this->ascender = _hea->ascender; 83 this->descender = _hea->descender; 84 this->line_gap = _hea->lineGap; 85 } 86 hb_blob_destroy (_hea_blob); 87 88 this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag)); 89 90 /* Cap num_metrics() and num_advances() based on table length. */ 91 unsigned int len = hb_blob_get_length (this->blob); 92 if (unlikely (this->num_advances * 4 > len)) 93 this->num_advances = len / 4; 94 this->num_metrics = this->num_advances + (len - 4 * this->num_advances) / 2; 95 96 /* We MUST set num_metrics to zero if num_advances is zero. 97 * Our get_advance() depends on that. */ 98 if (unlikely (!this->num_advances)) 99 { 100 this->num_metrics = this->num_advances = 0; 101 hb_blob_destroy (this->blob); 102 this->blob = hb_blob_get_empty (); 103 } 104 this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob); 105 } 106 107 inline void fini (void) 108 { 109 hb_blob_destroy (this->blob); 110 } 111 112 inline unsigned int get_advance (hb_codepoint_t glyph) const 113 { 114 if (unlikely (glyph >= this->num_metrics)) 115 { 116 /* If this->num_metrics is zero, it means we don't have the metrics table 117 * for this direction: return default advance. Otherwise, it means that the 118 * glyph index is out of bound: return zero. */ 119 if (this->num_metrics) 120 return 0; 121 else 122 return this->default_advance; 123 } 124 125 if (glyph >= this->num_advances) 126 glyph = this->num_advances - 1; 127 128 return this->table->longMetric[glyph].advance; 129 } 130 }; 131 132 struct hb_ot_face_glyf_accelerator_t 133 { 134 bool short_offset; 135 unsigned int num_glyphs; 136 const OT::loca *loca; 137 const OT::glyf *glyf; 138 hb_blob_t *loca_blob; 139 hb_blob_t *glyf_blob; 140 unsigned int glyf_len; 141 142 inline void init (hb_face_t *face) 143 { 144 hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head)); 145 const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob); 146 if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0) 147 { 148 /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ 149 hb_blob_destroy (head_blob); 150 return; 151 } 152 this->short_offset = 0 == head->indexToLocFormat; 153 hb_blob_destroy (head_blob); 154 155 this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); 156 this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob); 157 this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); 158 this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob); 159 160 this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1; 161 this->glyf_len = hb_blob_get_length (this->glyf_blob); 162 } 163 164 inline void fini (void) 165 { 166 hb_blob_destroy (this->loca_blob); 167 hb_blob_destroy (this->glyf_blob); 168 } 169 170 inline bool get_extents (hb_codepoint_t glyph, 171 hb_glyph_extents_t *extents) const 172 { 173 if (unlikely (glyph >= this->num_glyphs)) 174 return false; 175 176 unsigned int start_offset, end_offset; 177 if (this->short_offset) 178 { 179 start_offset = 2 * this->loca->u.shortsZ[glyph]; 180 end_offset = 2 * this->loca->u.shortsZ[glyph + 1]; 181 } 182 else 183 { 184 start_offset = this->loca->u.longsZ[glyph]; 185 end_offset = this->loca->u.longsZ[glyph + 1]; 186 } 187 188 if (start_offset > end_offset || end_offset > this->glyf_len) 189 return false; 190 191 if (end_offset - start_offset < OT::glyfGlyphHeader::static_size) 192 return true; /* Empty glyph; zero extents. */ 193 194 const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset); 195 196 extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); 197 extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); 198 extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; 199 extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; 200 201 return true; 202 } 203 }; 204 205 typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj, 206 hb_codepoint_t codepoint, 207 hb_codepoint_t *glyph); 208 209 template <typename Type> 210 static inline bool get_glyph_from (const void *obj, 211 hb_codepoint_t codepoint, 212 hb_codepoint_t *glyph) 213 { 214 const Type *typed_obj = (const Type *) obj; 215 return typed_obj->get_glyph (codepoint, glyph); 216 } 217 218 template <typename Type> 219 static inline bool get_glyph_from_symbol (const void *obj, 220 hb_codepoint_t codepoint, 221 hb_codepoint_t *glyph) 222 { 223 const Type *typed_obj = (const Type *) obj; 224 if (likely (typed_obj->get_glyph (codepoint, glyph))) 225 return true; 226 227 if (codepoint <= 0x00FFu) 228 { 229 /* For symbol-encoded OpenType fonts, we duplicate the 230 * U+F000..F0FF range at U+0000..U+00FF. That's what 231 * Windows seems to do, and that's hinted about at: 232 * http://www.microsoft.com/typography/otspec/recom.htm 233 * under "Non-Standard (Symbol) Fonts". */ 234 return typed_obj->get_glyph (0xF000u + codepoint, glyph); 235 } 236 237 return false; 238 } 239 240 struct hb_ot_face_cmap_accelerator_t 241 { 242 hb_cmap_get_glyph_func_t get_glyph_func; 243 const void *get_glyph_data; 244 OT::CmapSubtableFormat4::accelerator_t format4_accel; 245 246 const OT::CmapSubtableFormat14 *uvs_table; 247 hb_blob_t *blob; 248 249 inline void init (hb_face_t *face) 250 { 251 this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap)); 252 const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob); 253 const OT::CmapSubtable *subtable = NULL; 254 const OT::CmapSubtableFormat14 *subtable_uvs = NULL; 255 256 bool symbol = false; 257 /* 32-bit subtables. */ 258 if (!subtable) subtable = cmap->find_subtable (3, 10); 259 if (!subtable) subtable = cmap->find_subtable (0, 6); 260 if (!subtable) subtable = cmap->find_subtable (0, 4); 261 /* 16-bit subtables. */ 262 if (!subtable) subtable = cmap->find_subtable (3, 1); 263 if (!subtable) subtable = cmap->find_subtable (0, 3); 264 if (!subtable) subtable = cmap->find_subtable (0, 2); 265 if (!subtable) subtable = cmap->find_subtable (0, 1); 266 if (!subtable) subtable = cmap->find_subtable (0, 0); 267 if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true); 268 /* Meh. */ 269 if (!subtable) subtable = &OT::Null(OT::CmapSubtable); 270 271 /* UVS subtable. */ 272 if (!subtable_uvs) 273 { 274 const OT::CmapSubtable *st = cmap->find_subtable (0, 5); 275 if (st && st->u.format == 14) 276 subtable_uvs = &st->u.format14; 277 } 278 /* Meh. */ 279 if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtableFormat14); 280 281 this->uvs_table = subtable_uvs; 282 283 this->get_glyph_data = subtable; 284 if (unlikely (symbol)) 285 this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>; 286 else 287 switch (subtable->u.format) { 288 /* Accelerate format 4 and format 12. */ 289 default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>; break; 290 case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>; break; 291 case 4: 292 { 293 this->format4_accel.init (&subtable->u.format4); 294 this->get_glyph_data = &this->format4_accel; 295 this->get_glyph_func = this->format4_accel.get_glyph_func; 296 } 297 break; 298 } 299 } 300 301 inline void fini (void) 302 { 303 hb_blob_destroy (this->blob); 304 } 305 306 inline bool get_nominal_glyph (hb_codepoint_t unicode, 307 hb_codepoint_t *glyph) const 308 { 309 return this->get_glyph_func (this->get_glyph_data, unicode, glyph); 310 } 311 312 inline bool get_variation_glyph (hb_codepoint_t unicode, 313 hb_codepoint_t variation_selector, 314 hb_codepoint_t *glyph) const 315 { 316 switch (this->uvs_table->get_glyph_variant (unicode, 317 variation_selector, 318 glyph)) 319 { 320 case OT::GLYPH_VARIANT_NOT_FOUND: return false; 321 case OT::GLYPH_VARIANT_FOUND: return true; 322 case OT::GLYPH_VARIANT_USE_DEFAULT: break; 323 } 324 325 return get_nominal_glyph (unicode, glyph); 326 } 327 }; 328 329 template <typename T> 330 struct hb_lazy_loader_t 331 { 332 inline void init (hb_face_t *face_) 333 { 334 face = face_; 335 instance = NULL; 336 } 337 338 inline void fini (void) 339 { 340 if (instance && instance != &OT::Null(T)) 341 { 342 instance->fini(); 343 free (instance); 344 } 345 } 346 347 inline const T* operator-> (void) const 348 { 349 retry: 350 T *p = (T *) hb_atomic_ptr_get (&instance); 351 if (unlikely (!p)) 352 { 353 p = (T *) calloc (1, sizeof (T)); 354 if (unlikely (!p)) 355 return &OT::Null(T); 356 p->init (face); 357 if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), NULL, p))) 358 { 359 p->fini (); 360 goto retry; 361 } 362 } 363 return p; 364 } 365 366 private: 367 hb_face_t *face; 368 T *instance; 369 }; 370 371 struct hb_ot_font_t 372 { 373 hb_ot_face_cmap_accelerator_t cmap; 374 hb_ot_face_metrics_accelerator_t h_metrics; 375 hb_ot_face_metrics_accelerator_t v_metrics; 376 hb_lazy_loader_t<hb_ot_face_glyf_accelerator_t> glyf; 377 }; 378 379 380 static hb_ot_font_t * 381 _hb_ot_font_create (hb_face_t *face) 382 { 383 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); 384 385 if (unlikely (!ot_font)) 386 return NULL; 387 388 ot_font->cmap.init (face); 389 ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, HB_OT_TAG_os2); 390 ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, HB_TAG_NONE); /* TODO Can we do this lazily? */ 391 ot_font->glyf.init (face); 392 393 return ot_font; 394 } 395 396 static void 397 _hb_ot_font_destroy (hb_ot_font_t *ot_font) 398 { 399 ot_font->cmap.fini (); 400 ot_font->h_metrics.fini (); 401 ot_font->v_metrics.fini (); 402 ot_font->glyf.fini (); 403 404 free (ot_font); 405 } 406 407 408 static hb_bool_t 409 hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, 410 void *font_data, 411 hb_codepoint_t unicode, 412 hb_codepoint_t *glyph, 413 void *user_data HB_UNUSED) 414 415 { 416 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 417 return ot_font->cmap.get_nominal_glyph (unicode, glyph); 418 } 419 420 static hb_bool_t 421 hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, 422 void *font_data, 423 hb_codepoint_t unicode, 424 hb_codepoint_t variation_selector, 425 hb_codepoint_t *glyph, 426 void *user_data HB_UNUSED) 427 { 428 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 429 return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph); 430 } 431 432 static hb_position_t 433 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, 434 void *font_data, 435 hb_codepoint_t glyph, 436 void *user_data HB_UNUSED) 437 { 438 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 439 return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); 440 } 441 442 static hb_position_t 443 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, 444 void *font_data, 445 hb_codepoint_t glyph, 446 void *user_data HB_UNUSED) 447 { 448 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 449 return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); 450 } 451 452 static hb_bool_t 453 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, 454 void *font_data, 455 hb_codepoint_t glyph, 456 hb_glyph_extents_t *extents, 457 void *user_data HB_UNUSED) 458 { 459 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 460 bool ret = ot_font->glyf->get_extents (glyph, extents); 461 extents->x_bearing = font->em_scale_x (extents->x_bearing); 462 extents->y_bearing = font->em_scale_y (extents->y_bearing); 463 extents->width = font->em_scale_x (extents->width); 464 extents->height = font->em_scale_y (extents->height); 465 return ret; 466 } 467 468 static hb_bool_t 469 hb_ot_get_font_h_extents (hb_font_t *font HB_UNUSED, 470 void *font_data, 471 hb_font_extents_t *metrics, 472 void *user_data HB_UNUSED) 473 { 474 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 475 metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender); 476 metrics->descender = font->em_scale_y (ot_font->h_metrics.descender); 477 metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap); 478 return true; 479 } 480 481 static hb_bool_t 482 hb_ot_get_font_v_extents (hb_font_t *font HB_UNUSED, 483 void *font_data, 484 hb_font_extents_t *metrics, 485 void *user_data HB_UNUSED) 486 { 487 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 488 metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender); 489 metrics->descender = font->em_scale_x (ot_font->v_metrics.descender); 490 metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap); 491 return true; 492 } 493 494 static hb_font_funcs_t *static_ot_funcs = NULL; 495 496 #ifdef HB_USE_ATEXIT 497 static 498 void free_static_ot_funcs (void) 499 { 500 hb_font_funcs_destroy (static_ot_funcs); 501 } 502 #endif 503 504 static hb_font_funcs_t * 505 _hb_ot_get_font_funcs (void) 506 { 507 retry: 508 hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); 509 510 if (unlikely (!funcs)) 511 { 512 funcs = hb_font_funcs_create (); 513 514 hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, NULL, NULL); 515 hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, NULL, NULL); 516 hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, NULL, NULL); 517 hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, NULL, NULL); 518 hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); 519 hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); 520 //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); 521 //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); 522 //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO 523 //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); 524 hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); 525 //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO 526 //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO 527 //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO 528 529 hb_font_funcs_make_immutable (funcs); 530 531 if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) { 532 hb_font_funcs_destroy (funcs); 533 goto retry; 534 } 535 536 #ifdef HB_USE_ATEXIT 537 atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ 538 #endif 539 }; 540 541 return funcs; 542 } 543 544 545 /** 546 * hb_ot_font_set_funcs: 547 * 548 * Since: 0.9.28 549 **/ 550 void 551 hb_ot_font_set_funcs (hb_font_t *font) 552 { 553 hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); 554 if (unlikely (!ot_font)) 555 return; 556 557 hb_font_set_funcs (font, 558 _hb_ot_get_font_funcs (), 559 ot_font, 560 (hb_destroy_func_t) _hb_ot_font_destroy); 561 }