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