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