1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 /* 31 * Copyright © 2009 Red Hat, Inc. 32 * Copyright © 2012 Google, Inc. 33 * 34 * This is part of HarfBuzz, a text shaping library. 35 * 36 * Permission is hereby granted, without written agreement and without 37 * license or royalty fees, to use, copy, modify, and distribute this 38 * software and its documentation for any purpose, provided that the 39 * above copyright notice and the following two paragraphs appear in 40 * all copies of this software. 41 * 42 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 43 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 44 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 45 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 46 * DAMAGE. 47 * 48 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 49 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 50 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 51 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 52 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 53 * 54 * Red Hat Author(s): Behdad Esfahbod 55 * Google Author(s): Behdad Esfahbod 56 */ 57 58 #include "hb-private.hh" 59 60 #include "hb-ot-layout-private.hh" 61 62 #include "hb-font-private.hh" 63 #include "hb-open-file-private.hh" 64 #include "hb-ot-head-table.hh" 65 #include "hb-ot-maxp-table.hh" 66 67 #include "hb-cache-private.hh" 68 69 #include <string.h> 70 71 72 /* 73 * hb_face_t 74 */ 75 76 const hb_face_t _hb_face_nil = { 77 HB_OBJECT_HEADER_STATIC, 78 79 true, /* immutable */ 80 81 NULL, /* reference_table_func */ 82 NULL, /* user_data */ 83 NULL, /* destroy */ 84 85 0, /* index */ 86 1000, /* upem */ 87 0, /* num_glyphs */ 88 89 { 90 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, 91 #include "hb-shaper-list.hh" 92 #undef HB_SHAPER_IMPLEMENT 93 }, 94 95 NULL, /* shape_plans */ 96 }; 97 98 99 /** 100 * hb_face_create_for_tables: 101 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): 102 * @user_data: 103 * @destroy: 104 * 105 * 106 * 107 * Return value: (transfer full) 108 * 109 * Since: 0.9.2 110 **/ 111 hb_face_t * 112 hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, 113 void *user_data, 114 hb_destroy_func_t destroy) 115 { 116 hb_face_t *face; 117 118 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) { 119 if (destroy) 120 destroy (user_data); 121 return hb_face_get_empty (); 122 } 123 124 face->reference_table_func = reference_table_func; 125 face->user_data = user_data; 126 face->destroy = destroy; 127 128 face->upem = 0; 129 face->num_glyphs = (unsigned int) -1; 130 131 return face; 132 } 133 134 135 typedef struct hb_face_for_data_closure_t { 136 hb_blob_t *blob; 137 unsigned int index; 138 } hb_face_for_data_closure_t; 139 140 static hb_face_for_data_closure_t * 141 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index) 142 { 143 hb_face_for_data_closure_t *closure; 144 145 closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t)); 146 if (unlikely (!closure)) 147 return NULL; 148 149 closure->blob = blob; 150 closure->index = index; 151 152 return closure; 153 } 154 155 static void 156 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure) 157 { 158 hb_blob_destroy (closure->blob); 159 free (closure); 160 } 161 162 static hb_blob_t * 163 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) 164 { 165 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data; 166 167 if (tag == HB_TAG_NONE) 168 return hb_blob_reference (data->blob); 169 170 const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob); 171 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index); 172 173 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag); 174 175 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length); 176 177 return blob; 178 } 179 180 /** 181 * hb_face_create: (Xconstructor) 182 * @blob: 183 * @index: 184 * 185 * 186 * 187 * Return value: (transfer full): 188 * 189 * Since: 0.9.2 190 **/ 191 hb_face_t * 192 hb_face_create (hb_blob_t *blob, 193 unsigned int index) 194 { 195 hb_face_t *face; 196 197 if (unlikely (!blob)) 198 blob = hb_blob_get_empty (); 199 200 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index); 201 202 if (unlikely (!closure)) 203 return hb_face_get_empty (); 204 205 face = hb_face_create_for_tables (_hb_face_for_data_reference_table, 206 closure, 207 (hb_destroy_func_t) _hb_face_for_data_closure_destroy); 208 209 hb_face_set_index (face, index); 210 211 return face; 212 } 213 214 /** 215 * hb_face_get_empty: 216 * 217 * 218 * 219 * Return value: (transfer full) 220 * 221 * Since: 0.9.2 222 **/ 223 hb_face_t * 224 hb_face_get_empty (void) 225 { 226 return const_cast<hb_face_t *> (&_hb_face_nil); 227 } 228 229 230 /** 231 * hb_face_reference: (skip) 232 * @face: a face. 233 * 234 * 235 * 236 * Return value: 237 * 238 * Since: 0.9.2 239 **/ 240 hb_face_t * 241 hb_face_reference (hb_face_t *face) 242 { 243 return hb_object_reference (face); 244 } 245 246 /** 247 * hb_face_destroy: (skip) 248 * @face: a face. 249 * 250 * 251 * 252 * Since: 0.9.2 253 **/ 254 void 255 hb_face_destroy (hb_face_t *face) 256 { 257 if (!hb_object_destroy (face)) return; 258 259 for (hb_face_t::plan_node_t *node = face->shape_plans; node; ) 260 { 261 hb_face_t::plan_node_t *next = node->next; 262 hb_shape_plan_destroy (node->shape_plan); 263 free (node); 264 node = next; 265 } 266 267 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face); 268 #include "hb-shaper-list.hh" 269 #undef HB_SHAPER_IMPLEMENT 270 271 if (face->destroy) 272 face->destroy (face->user_data); 273 274 free (face); 275 } 276 277 /** 278 * hb_face_set_user_data: (skip) 279 * @face: a face. 280 * @key: 281 * @data: 282 * @destroy: 283 * @replace: 284 * 285 * 286 * 287 * Return value: 288 * 289 * Since: 0.9.2 290 **/ 291 hb_bool_t 292 hb_face_set_user_data (hb_face_t *face, 293 hb_user_data_key_t *key, 294 void * data, 295 hb_destroy_func_t destroy, 296 hb_bool_t replace) 297 { 298 return hb_object_set_user_data (face, key, data, destroy, replace); 299 } 300 301 /** 302 * hb_face_get_user_data: (skip) 303 * @face: a face. 304 * @key: 305 * 306 * 307 * 308 * Return value: (transfer none): 309 * 310 * Since: 0.9.2 311 **/ 312 void * 313 hb_face_get_user_data (hb_face_t *face, 314 hb_user_data_key_t *key) 315 { 316 return hb_object_get_user_data (face, key); 317 } 318 319 /** 320 * hb_face_make_immutable: 321 * @face: a face. 322 * 323 * 324 * 325 * Since: 0.9.2 326 **/ 327 void 328 hb_face_make_immutable (hb_face_t *face) 329 { 330 if (unlikely (hb_object_is_inert (face))) 331 return; 332 333 face->immutable = true; 334 } 335 336 /** 337 * hb_face_is_immutable: 338 * @face: a face. 339 * 340 * 341 * 342 * Return value: 343 * 344 * Since: 0.9.2 345 **/ 346 hb_bool_t 347 hb_face_is_immutable (hb_face_t *face) 348 { 349 return face->immutable; 350 } 351 352 353 /** 354 * hb_face_reference_table: 355 * @face: a face. 356 * @tag: 357 * 358 * 359 * 360 * Return value: (transfer full): 361 * 362 * Since: 0.9.2 363 **/ 364 hb_blob_t * 365 hb_face_reference_table (hb_face_t *face, 366 hb_tag_t tag) 367 { 368 return face->reference_table (tag); 369 } 370 371 /** 372 * hb_face_reference_blob: 373 * @face: a face. 374 * 375 * 376 * 377 * Return value: (transfer full): 378 * 379 * Since: 0.9.2 380 **/ 381 hb_blob_t * 382 hb_face_reference_blob (hb_face_t *face) 383 { 384 return face->reference_table (HB_TAG_NONE); 385 } 386 387 /** 388 * hb_face_set_index: 389 * @face: a face. 390 * @index: 391 * 392 * 393 * 394 * Since: 0.9.2 395 **/ 396 void 397 hb_face_set_index (hb_face_t *face, 398 unsigned int index) 399 { 400 if (face->immutable) 401 return; 402 403 face->index = index; 404 } 405 406 /** 407 * hb_face_get_index: 408 * @face: a face. 409 * 410 * 411 * 412 * Return value: 413 * 414 * Since: 0.9.2 415 **/ 416 unsigned int 417 hb_face_get_index (hb_face_t *face) 418 { 419 return face->index; 420 } 421 422 /** 423 * hb_face_set_upem: 424 * @face: a face. 425 * @upem: 426 * 427 * 428 * 429 * Since: 0.9.2 430 **/ 431 void 432 hb_face_set_upem (hb_face_t *face, 433 unsigned int upem) 434 { 435 if (face->immutable) 436 return; 437 438 face->upem = upem; 439 } 440 441 /** 442 * hb_face_get_upem: 443 * @face: a face. 444 * 445 * 446 * 447 * Return value: 448 * 449 * Since: 0.9.2 450 **/ 451 unsigned int 452 hb_face_get_upem (hb_face_t *face) 453 { 454 return face->get_upem (); 455 } 456 457 void 458 hb_face_t::load_upem (void) const 459 { 460 hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head)); 461 const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob); 462 upem = head_table->get_upem (); 463 hb_blob_destroy (head_blob); 464 } 465 466 /** 467 * hb_face_set_glyph_count: 468 * @face: a face. 469 * @glyph_count: 470 * 471 * 472 * 473 * Since: 0.9.7 474 **/ 475 void 476 hb_face_set_glyph_count (hb_face_t *face, 477 unsigned int glyph_count) 478 { 479 if (face->immutable) 480 return; 481 482 face->num_glyphs = glyph_count; 483 } 484 485 /** 486 * hb_face_get_glyph_count: 487 * @face: a face. 488 * 489 * 490 * 491 * Return value: 492 * 493 * Since: 0.9.7 494 **/ 495 unsigned int 496 hb_face_get_glyph_count (hb_face_t *face) 497 { 498 return face->get_num_glyphs (); 499 } 500 501 void 502 hb_face_t::load_num_glyphs (void) const 503 { 504 hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp)); 505 const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob); 506 num_glyphs = maxp_table->get_num_glyphs (); 507 hb_blob_destroy (maxp_blob); 508 } 509 510