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 39 40 struct hb_ot_face_metrics_accelerator_t 41 { 42 unsigned int num_metrics; 43 unsigned int num_advances; 44 unsigned int default_advance; 45 const OT::_mtx *table; 46 hb_blob_t *blob; 47 48 inline void init (hb_face_t *face, 49 hb_tag_t _hea_tag, hb_tag_t _mtx_tag, 50 unsigned int default_advance_) 51 { 52 this->default_advance = default_advance_; 53 this->num_metrics = face->get_num_glyphs (); 54 55 hb_blob_t *_hea_blob = OT::Sanitizer<OT::_hea>::sanitize (face->reference_table (_hea_tag)); 56 const OT::_hea *_hea = OT::Sanitizer<OT::_hea>::lock_instance (_hea_blob); 57 this->num_advances = _hea->numberOfLongMetrics; 58 hb_blob_destroy (_hea_blob); 59 60 this->blob = OT::Sanitizer<OT::_mtx>::sanitize (face->reference_table (_mtx_tag)); 61 if (unlikely (!this->num_advances || 62 2 * (this->num_advances + this->num_metrics) > hb_blob_get_length (this->blob))) 63 { 64 this->num_metrics = this->num_advances = 0; 65 hb_blob_destroy (this->blob); 66 this->blob = hb_blob_get_empty (); 67 } 68 this->table = OT::Sanitizer<OT::_mtx>::lock_instance (this->blob); 69 } 70 71 inline void fini (void) 72 { 73 hb_blob_destroy (this->blob); 74 } 75 76 inline unsigned int get_advance (hb_codepoint_t glyph) const 77 { 78 if (unlikely (glyph >= this->num_metrics)) 79 { 80 /* If this->num_metrics is zero, it means we don't have the metrics table 81 * for this direction: return default advance. Otherwise, it means that the 82 * glyph index is out of bound: return zero. */ 83 if (this->num_metrics) 84 return 0; 85 else 86 return this->default_advance; 87 } 88 89 if (glyph >= this->num_advances) 90 glyph = this->num_advances - 1; 91 92 return this->table->longMetric[glyph].advance; 93 } 94 }; 95 96 struct hb_ot_face_glyf_accelerator_t 97 { 98 bool short_offset; 99 unsigned int num_glyphs; 100 const OT::loca *loca; 101 const OT::glyf *glyf; 102 hb_blob_t *loca_blob; 103 hb_blob_t *glyf_blob; 104 unsigned int glyf_len; 105 106 inline void init (hb_face_t *face) 107 { 108 hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (face->reference_table (HB_OT_TAG_head)); 109 const OT::head *head = OT::Sanitizer<OT::head>::lock_instance (head_blob); 110 if ((unsigned int) head->indexToLocFormat > 1 || head->glyphDataFormat != 0) 111 { 112 /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ 113 hb_blob_destroy (head_blob); 114 return; 115 } 116 this->short_offset = 0 == head->indexToLocFormat; 117 hb_blob_destroy (head_blob); 118 119 this->loca_blob = OT::Sanitizer<OT::loca>::sanitize (face->reference_table (HB_OT_TAG_loca)); 120 this->loca = OT::Sanitizer<OT::loca>::lock_instance (this->loca_blob); 121 this->glyf_blob = OT::Sanitizer<OT::glyf>::sanitize (face->reference_table (HB_OT_TAG_glyf)); 122 this->glyf = OT::Sanitizer<OT::glyf>::lock_instance (this->glyf_blob); 123 124 this->num_glyphs = MAX (1u, hb_blob_get_length (this->loca_blob) / (this->short_offset ? 2 : 4)) - 1; 125 this->glyf_len = hb_blob_get_length (this->glyf_blob); 126 } 127 128 inline void fini (void) 129 { 130 hb_blob_destroy (this->loca_blob); 131 hb_blob_destroy (this->glyf_blob); 132 } 133 134 inline bool get_extents (hb_codepoint_t glyph, 135 hb_glyph_extents_t *extents) const 136 { 137 if (unlikely (glyph >= this->num_glyphs)) 138 return false; 139 140 unsigned int start_offset, end_offset; 141 if (this->short_offset) 142 { 143 start_offset = 2 * this->loca->u.shortsZ[glyph]; 144 end_offset = 2 * this->loca->u.shortsZ[glyph + 1]; 145 } 146 else 147 { 148 start_offset = this->loca->u.longsZ[glyph]; 149 end_offset = this->loca->u.longsZ[glyph + 1]; 150 } 151 152 if (start_offset > end_offset || end_offset > this->glyf_len) 153 return false; 154 155 if (end_offset - start_offset < OT::glyfGlyphHeader::static_size) 156 return true; /* Empty glyph; zero extents. */ 157 158 const OT::glyfGlyphHeader &glyph_header = OT::StructAtOffset<OT::glyfGlyphHeader> (this->glyf, start_offset); 159 160 extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax); 161 extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax); 162 extents->width = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing; 163 extents->height = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing; 164 165 return true; 166 } 167 }; 168 169 struct hb_ot_face_cmap_accelerator_t 170 { 171 const OT::CmapSubtable *table; 172 const OT::CmapSubtable *uvs_table; 173 hb_blob_t *blob; 174 175 inline void init (hb_face_t *face) 176 { 177 this->blob = OT::Sanitizer<OT::cmap>::sanitize (face->reference_table (HB_OT_TAG_cmap)); 178 const OT::cmap *cmap = OT::Sanitizer<OT::cmap>::lock_instance (this->blob); 179 const OT::CmapSubtable *subtable = NULL; 180 const OT::CmapSubtable *subtable_uvs = NULL; 181 182 /* 32-bit subtables. */ 183 if (!subtable) subtable = cmap->find_subtable (3, 10); 184 if (!subtable) subtable = cmap->find_subtable (0, 6); 185 if (!subtable) subtable = cmap->find_subtable (0, 4); 186 /* 16-bit subtables. */ 187 if (!subtable) subtable = cmap->find_subtable (3, 1); 188 if (!subtable) subtable = cmap->find_subtable (0, 3); 189 if (!subtable) subtable = cmap->find_subtable (0, 2); 190 if (!subtable) subtable = cmap->find_subtable (0, 1); 191 if (!subtable) subtable = cmap->find_subtable (0, 0); 192 if (!subtable) subtable = cmap->find_subtable (3, 0); 193 /* Meh. */ 194 if (!subtable) subtable = &OT::Null(OT::CmapSubtable); 195 196 /* UVS subtable. */ 197 if (!subtable_uvs) subtable_uvs = cmap->find_subtable (0, 5); 198 /* Meh. */ 199 if (!subtable_uvs) subtable_uvs = &OT::Null(OT::CmapSubtable); 200 201 this->table = subtable; 202 this->uvs_table = subtable_uvs; 203 } 204 205 inline void fini (void) 206 { 207 hb_blob_destroy (this->blob); 208 } 209 210 inline bool get_glyph (hb_codepoint_t unicode, 211 hb_codepoint_t variation_selector, 212 hb_codepoint_t *glyph) const 213 { 214 if (unlikely (variation_selector)) 215 { 216 switch (this->uvs_table->get_glyph_variant (unicode, 217 variation_selector, 218 glyph)) 219 { 220 case OT::GLYPH_VARIANT_NOT_FOUND: return false; 221 case OT::GLYPH_VARIANT_FOUND: return true; 222 case OT::GLYPH_VARIANT_USE_DEFAULT: break; 223 } 224 } 225 226 return this->table->get_glyph (unicode, glyph); 227 } 228 }; 229 230 231 struct hb_ot_font_t 232 { 233 hb_ot_face_cmap_accelerator_t cmap; 234 hb_ot_face_metrics_accelerator_t h_metrics; 235 hb_ot_face_metrics_accelerator_t v_metrics; 236 hb_ot_face_glyf_accelerator_t glyf; 237 }; 238 239 240 static hb_ot_font_t * 241 _hb_ot_font_create (hb_face_t *face) 242 { 243 hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t)); 244 245 if (unlikely (!ot_font)) 246 return NULL; 247 248 unsigned int upem = face->get_upem (); 249 250 ot_font->cmap.init (face); 251 ot_font->h_metrics.init (face, HB_OT_TAG_hhea, HB_OT_TAG_hmtx, upem>>1); 252 ot_font->v_metrics.init (face, HB_OT_TAG_vhea, HB_OT_TAG_vmtx, upem); /* TODO Can we do this lazily? */ 253 ot_font->glyf.init (face); 254 255 return ot_font; 256 } 257 258 static void 259 _hb_ot_font_destroy (hb_ot_font_t *ot_font) 260 { 261 ot_font->cmap.fini (); 262 ot_font->h_metrics.fini (); 263 ot_font->v_metrics.fini (); 264 ot_font->glyf.fini (); 265 266 free (ot_font); 267 } 268 269 270 static hb_bool_t 271 hb_ot_get_glyph (hb_font_t *font HB_UNUSED, 272 void *font_data, 273 hb_codepoint_t unicode, 274 hb_codepoint_t variation_selector, 275 hb_codepoint_t *glyph, 276 void *user_data HB_UNUSED) 277 278 { 279 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 280 return ot_font->cmap.get_glyph (unicode, variation_selector, glyph); 281 } 282 283 static hb_position_t 284 hb_ot_get_glyph_h_advance (hb_font_t *font HB_UNUSED, 285 void *font_data, 286 hb_codepoint_t glyph, 287 void *user_data HB_UNUSED) 288 { 289 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 290 return font->em_scale_x (ot_font->h_metrics.get_advance (glyph)); 291 } 292 293 static hb_position_t 294 hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, 295 void *font_data, 296 hb_codepoint_t glyph, 297 void *user_data HB_UNUSED) 298 { 299 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 300 return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph)); 301 } 302 303 static hb_bool_t 304 hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, 305 void *font_data HB_UNUSED, 306 hb_codepoint_t glyph HB_UNUSED, 307 hb_position_t *x HB_UNUSED, 308 hb_position_t *y HB_UNUSED, 309 void *user_data HB_UNUSED) 310 { 311 /* We always work in the horizontal coordinates. */ 312 return true; 313 } 314 315 static hb_bool_t 316 hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, 317 void *font_data, 318 hb_codepoint_t glyph, 319 hb_position_t *x, 320 hb_position_t *y, 321 void *user_data HB_UNUSED) 322 { 323 /* TODO */ 324 return false; 325 } 326 327 static hb_position_t 328 hb_ot_get_glyph_h_kerning (hb_font_t *font, 329 void *font_data, 330 hb_codepoint_t left_glyph, 331 hb_codepoint_t right_glyph, 332 void *user_data HB_UNUSED) 333 { 334 /* TODO */ 335 return 0; 336 } 337 338 static hb_position_t 339 hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, 340 void *font_data HB_UNUSED, 341 hb_codepoint_t top_glyph HB_UNUSED, 342 hb_codepoint_t bottom_glyph HB_UNUSED, 343 void *user_data HB_UNUSED) 344 { 345 /* OpenType doesn't have vertical-kerning other than GPOS. */ 346 return 0; 347 } 348 349 static hb_bool_t 350 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, 351 void *font_data, 352 hb_codepoint_t glyph, 353 hb_glyph_extents_t *extents, 354 void *user_data HB_UNUSED) 355 { 356 const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data; 357 bool ret = ot_font->glyf.get_extents (glyph, extents); 358 extents->x_bearing = font->em_scale_x (extents->x_bearing); 359 extents->y_bearing = font->em_scale_y (extents->y_bearing); 360 extents->width = font->em_scale_x (extents->width); 361 extents->height = font->em_scale_y (extents->height); 362 return ret; 363 } 364 365 static hb_bool_t 366 hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, 367 void *font_data, 368 hb_codepoint_t glyph, 369 unsigned int point_index, 370 hb_position_t *x, 371 hb_position_t *y, 372 void *user_data HB_UNUSED) 373 { 374 /* TODO */ 375 return false; 376 } 377 378 static hb_bool_t 379 hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, 380 void *font_data, 381 hb_codepoint_t glyph, 382 char *name, unsigned int size, 383 void *user_data HB_UNUSED) 384 { 385 /* TODO */ 386 return false; 387 } 388 389 static hb_bool_t 390 hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, 391 void *font_data, 392 const char *name, int len, /* -1 means nul-terminated */ 393 hb_codepoint_t *glyph, 394 void *user_data HB_UNUSED) 395 { 396 /* TODO */ 397 return false; 398 } 399 400 401 static hb_font_funcs_t * 402 _hb_ot_get_font_funcs (void) 403 { 404 static const hb_font_funcs_t ot_ffuncs = { 405 HB_OBJECT_HEADER_STATIC, 406 407 true, /* immutable */ 408 409 { 410 #define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, 411 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 412 #undef HB_FONT_FUNC_IMPLEMENT 413 } 414 }; 415 416 return const_cast<hb_font_funcs_t *> (&ot_ffuncs); 417 } 418 419 420 /** 421 * Since: 0.9.28 422 **/ 423 void 424 hb_ot_font_set_funcs (hb_font_t *font) 425 { 426 hb_ot_font_t *ot_font = _hb_ot_font_create (font->face); 427 if (unlikely (!ot_font)) 428 return; 429 430 hb_font_set_funcs (font, 431 _hb_ot_get_font_funcs (), 432 ot_font, 433 (hb_destroy_func_t) _hb_ot_font_destroy); 434 }