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