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