1 /* 2 * Copyright © 2009 Red Hat, Inc. 3 * Copyright © 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 #include "hb-private.hh" 30 31 #include "hb-face-private.hh" 32 #include "hb-open-file-private.hh" 33 #include "hb-ot-head-table.hh" 34 #include "hb-ot-maxp-table.hh" 35 36 37 /* 38 * hb_face_t 39 */ 40 41 const hb_face_t _hb_face_nil = { 42 HB_OBJECT_HEADER_STATIC, 43 44 true, /* immutable */ 45 46 nullptr, /* reference_table_func */ 47 nullptr, /* user_data */ 48 nullptr, /* destroy */ 49 50 0, /* index */ 51 1000, /* upem */ 52 0, /* num_glyphs */ 53 54 { 55 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, 56 #include "hb-shaper-list.hh" 57 #undef HB_SHAPER_IMPLEMENT 58 }, 59 60 nullptr, /* shape_plans */ 61 }; 62 63 64 /** 65 * hb_face_create_for_tables: 66 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): 67 * @user_data: 68 * @destroy: 69 * 70 * 71 * 72 * Return value: (transfer full) 73 * 74 * Since: 0.9.2 75 **/ 76 hb_face_t * 77 hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, 78 void *user_data, 79 hb_destroy_func_t destroy) 80 { 81 hb_face_t *face; 82 83 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) { 84 if (destroy) 85 destroy (user_data); 86 return hb_face_get_empty (); 87 } 88 89 face->reference_table_func = reference_table_func; 90 face->user_data = user_data; 91 face->destroy = destroy; 92 93 face->upem = 0; 94 face->num_glyphs = (unsigned int) -1; 95 96 return face; 97 } 98 99 100 typedef struct hb_face_for_data_closure_t { 101 hb_blob_t *blob; 102 unsigned int index; 103 } hb_face_for_data_closure_t; 104 105 static hb_face_for_data_closure_t * 106 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) 107 { 108 hb_face_for_data_closure_t *closure; 109 110 closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); 111 if (unlikely (!closure)) 112 return nullptr; 113 114 closure->blob = blob; 115 closure->index = index; 116 117 return closure; 118 } 119 120 #ifdef __SUNPRO_CC 121 extern "C" { 122 #endif 123 static void 124 _hb_face_for_data_closure_destroy (void *data) 125 { 126 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data; 127 128 hb_blob_destroy (closure->blob); 129 free (closure); 130 } 131 #ifdef __SUNPRO_CC 132 } 133 #endif 134 135 static hb_blob_t * 136 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) 137 { 138 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; 139 140 if (tag == HB_TAG_NONE) 141 return hb_blob_reference (data->blob); 142 143 const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); 144 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); 145 146 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag); 147 148 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); 149 150 return blob; 151 } 152 153 /** 154 * hb_face_create: (Xconstructor) 155 * @blob: 156 * @index: 157 * 158 * 159 * 160 * Return value: (transfer full): 161 * 162 * Since: 0.9.2 163 **/ 164 hb_face_t * 165 hb_face_create (hb_blob_t *blob, 166 unsigned int index) 167 { 168 hb_face_t *face; 169 170 if (unlikely (!blob)) 171 blob = hb_blob_get_empty (); 172 173 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); 174 175 if (unlikely (!closure)) 176 return hb_face_get_empty (); 177 178 face = hb_face_create_for_tables (_hb_face_for_data_reference_table, 179 closure, 180 _hb_face_for_data_closure_destroy); 181 182 face->index = index; 183 184 return face; 185 } 186 187 /** 188 * hb_face_get_empty: 189 * 190 * 191 * 192 * Return value: (transfer full) 193 * 194 * Since: 0.9.2 195 **/ 196 hb_face_t * 197 hb_face_get_empty (void) 198 { 199 return const_cast<hb_face_t *> (&_hb_face_nil); 200 } 201 202 203 /** 204 * hb_face_reference: (skip) 205 * @face: a face. 206 * 207 * 208 * 209 * Return value: 210 * 211 * Since: 0.9.2 212 **/ 213 hb_face_t * 214 hb_face_reference (hb_face_t *face) 215 { 216 return hb_object_reference (face); 217 } 218 219 /** 220 * hb_face_destroy: (skip) 221 * @face: a face. 222 * 223 * 224 * 225 * Since: 0.9.2 226 **/ 227 void 228 hb_face_destroy (hb_face_t *face) 229 { 230 if (!hb_object_destroy (face)) return; 231 232 for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) 233 { 234 hb_face_t::plan_node_t *next = node->next; 235 hb_shape_plan_destroy (node->shape_plan); 236 free (node); 237 node = next; 238 } 239 240 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); 241 #include "hb-shaper-list.hh" 242 #undef HB_SHAPER_IMPLEMENT 243 244 if (face->destroy) 245 face->destroy (face->user_data); 246 247 free (face); 248 } 249 250 /** 251 * hb_face_set_user_data: (skip) 252 * @face: a face. 253 * @key: 254 * @data: 255 * @destroy: 256 * @replace: 257 * 258 * 259 * 260 * Return value: 261 * 262 * Since: 0.9.2 263 **/ 264 hb_bool_t 265 hb_face_set_user_data (hb_face_t *face, 266 hb_user_data_key_t *key, 267 void * data, 268 hb_destroy_func_t destroy, 269 hb_bool_t replace) 270 { 271 return hb_object_set_user_data (face, key, data, destroy, replace); 272 } 273 274 /** 275 * hb_face_get_user_data: (skip) 276 * @face: a face. 277 * @key: 278 * 279 * 280 * 281 * Return value: (transfer none): 282 * 283 * Since: 0.9.2 284 **/ 285 void * 286 hb_face_get_user_data (hb_face_t *face, 287 hb_user_data_key_t *key) 288 { 289 return hb_object_get_user_data (face, key); 290 } 291 292 /** 293 * hb_face_make_immutable: 294 * @face: a face. 295 * 296 * 297 * 298 * Since: 0.9.2 299 **/ 300 void 301 hb_face_make_immutable (hb_face_t *face) 302 { 303 if (unlikely (hb_object_is_inert (face))) 304 return; 305 306 face->immutable = true; 307 } 308 309 /** 310 * hb_face_is_immutable: 311 * @face: a face. 312 * 313 * 314 * 315 * Return value: 316 * 317 * Since: 0.9.2 318 **/ 319 hb_bool_t 320 hb_face_is_immutable (hb_face_t *face) 321 { 322 return face->immutable; 323 } 324 325 326 /** 327 * hb_face_reference_table: 328 * @face: a face. 329 * @tag: 330 * 331 * 332 * 333 * Return value: (transfer full): 334 * 335 * Since: 0.9.2 336 **/ 337 hb_blob_t * 338 hb_face_reference_table (hb_face_t *face, 339 hb_tag_t tag) 340 { 341 return face->reference_table (tag); 342 } 343 344 /** 345 * hb_face_reference_blob: 346 * @face: a face. 347 * 348 * 349 * 350 * Return value: (transfer full): 351 * 352 * Since: 0.9.2 353 **/ 354 hb_blob_t * 355 hb_face_reference_blob (hb_face_t *face) 356 { 357 return face->reference_table (HB_TAG_NONE); 358 } 359 360 /** 361 * hb_face_set_index: 362 * @face: a face. 363 * @index: 364 * 365 * 366 * 367 * Since: 0.9.2 368 **/ 369 void 370 hb_face_set_index (hb_face_t *face, 371 unsigned int index) 372 { 373 if (face->immutable) 374 return; 375 376 face->index = index; 377 } 378 379 /** 380 * hb_face_get_index: 381 * @face: a face. 382 * 383 * 384 * 385 * Return value: 386 * 387 * Since: 0.9.2 388 **/ 389 unsigned int 390 hb_face_get_index (hb_face_t *face) 391 { 392 return face->index; 393 } 394 395 /** 396 * hb_face_set_upem: 397 * @face: a face. 398 * @upem: 399 * 400 * 401 * 402 * Since: 0.9.2 403 **/ 404 void 405 hb_face_set_upem (hb_face_t *face, 406 unsigned int upem) 407 { 408 if (face->immutable) 409 return; 410 411 face->upem = upem; 412 } 413 414 /** 415 * hb_face_get_upem: 416 * @face: a face. 417 * 418 * 419 * 420 * Return value: 421 * 422 * Since: 0.9.2 423 **/ 424 unsigned int 425 hb_face_get_upem (hb_face_t *face) 426 { 427 return face->get_upem (); 428 } 429 430 void 431 hb_face_t::load_upem (void) const 432 { 433 hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head)); 434 const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob); 435 upem = head_table->get_upem (); 436 hb_blob_destroy (head_blob); 437 } 438 439 /** 440 * hb_face_set_glyph_count: 441 * @face: a face. 442 * @glyph_count: 443 * 444 * 445 * 446 * Since: 0.9.7 447 **/ 448 void 449 hb_face_set_glyph_count (hb_face_t *face, 450 unsigned int glyph_count) 451 { 452 if (face->immutable) 453 return; 454 455 face->num_glyphs = glyph_count; 456 } 457 458 /** 459 * hb_face_get_glyph_count: 460 * @face: a face. 461 * 462 * 463 * 464 * Return value: 465 * 466 * Since: 0.9.7 467 **/ 468 unsigned int 469 hb_face_get_glyph_count (hb_face_t *face) 470 { 471 return face->get_num_glyphs (); 472 } 473 474 void 475 hb_face_t::load_num_glyphs (void) const 476 { 477 hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp)); 478 const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob); 479 num_glyphs = maxp_table->get_num_glyphs (); 480 hb_blob_destroy (maxp_blob); 481 } 482 483 /** 484 * hb_face_get_table_tags: 485 * @face: a face. 486 * 487 * Retrieves table tags for a face, if possible. 488 * 489 * Return value: total number of tables, or 0 if not possible to list. 490 * 491 * Since: 1.6.0 492 **/ 493 unsigned int 494 hb_face_get_table_tags (hb_face_t *face, 495 unsigned int start_offset, 496 unsigned int *table_count, /* IN/OUT */ 497 hb_tag_t *table_tags /* OUT */) 498 { 499 if (face->destroy != _hb_face_for_data_closure_destroy) 500 { 501 if (table_count) 502 *table_count = 0; 503 return 0; 504 } 505 506 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data; 507 508 const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); 509 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); 510 511 return ot_face.get_table_tags (start_offset, table_count, table_tags); 512 }