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 47const 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: 1.0 81 **/ 82hb_face_t * 83hb_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 106typedef struct hb_face_for_data_closure_t { 107 hb_blob_t *blob; 108 unsigned int index; 109} hb_face_for_data_closure_t; 110 111static 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 *) malloc (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 126static 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 133static 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: 1.0 161 **/ 162hb_face_t * 163hb_face_create (hb_blob_t *blob, 164 unsigned int index) 165{ 166 hb_face_t *face; 167 168 if (unlikely (!blob || !hb_blob_get_length (blob))) 169 return hb_face_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: 1.0 193 **/ 194hb_face_t * 195hb_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: 1.0 210 **/ 211hb_face_t * 212hb_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: 1.0 224 **/ 225void 226hb_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: 1.0 261 **/ 262hb_bool_t 263hb_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: 1.0 282 **/ 283void * 284hb_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: 1.0 297 **/ 298void 299hb_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: 1.0 316 **/ 317hb_bool_t 318hb_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: 1.0 334 **/ 335hb_blob_t * 336hb_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: 1.0 351 **/ 352hb_blob_t * 353hb_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: 1.0 366 **/ 367void 368hb_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: 1.0 386 **/ 387unsigned int 388hb_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: 1.0 401 **/ 402void 403hb_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: 1.0 421 **/ 422unsigned int 423hb_face_get_upem (hb_face_t *face) 424{ 425 return face->get_upem (); 426} 427 428void 429hb_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: 1.0 445 **/ 446void 447hb_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: 1.0 465 **/ 466unsigned int 467hb_face_get_glyph_count (hb_face_t *face) 468{ 469 return face->get_num_glyphs (); 470} 471 472void 473hb_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