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