1 /* 2 * Copyright © 2009 Red Hat, Inc. 3 * Copyright © 2011 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 #ifndef HB_FONT_HH 30 #define HB_FONT_HH 31 32 #include "hb.hh" 33 34 #include "hb-face.hh" 35 #include "hb-shaper.hh" 36 37 38 /* 39 * hb_font_funcs_t 40 */ 41 42 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 43 HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ 44 HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ 45 HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ 46 HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \ 47 HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ 48 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ 49 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ 50 HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \ 51 HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \ 52 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ 53 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ 54 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ 55 HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \ 56 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ 57 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ 58 HB_FONT_FUNC_IMPLEMENT (glyph_name) \ 59 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ 60 /* ^--- Add new callbacks here */ 61 62 struct hb_font_funcs_t 63 { 64 hb_object_header_t header; 65 66 struct { 67 #define HB_FONT_FUNC_IMPLEMENT(name) void *name; 68 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 69 #undef HB_FONT_FUNC_IMPLEMENT 70 } user_data; 71 72 struct { 73 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 74 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 75 #undef HB_FONT_FUNC_IMPLEMENT 76 } destroy; 77 78 /* Don't access these directly. Call font->get_*() instead. */ 79 union get_t { 80 struct get_funcs_t { 81 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; 82 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 83 #undef HB_FONT_FUNC_IMPLEMENT 84 } f; 85 void (*array[0 86 #define HB_FONT_FUNC_IMPLEMENT(name) +1 87 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 88 #undef HB_FONT_FUNC_IMPLEMENT 89 ]) (); 90 } get; 91 }; 92 DECLARE_NULL_INSTANCE (hb_font_funcs_t); 93 94 95 /* 96 * hb_font_t 97 */ 98 99 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font); 100 #include "hb-shaper-list.hh" 101 #undef HB_SHAPER_IMPLEMENT 102 103 struct hb_font_t 104 { 105 hb_object_header_t header; 106 107 hb_font_t *parent; 108 hb_face_t *face; 109 110 int32_t x_scale; 111 int32_t y_scale; 112 int64_t x_mult; 113 int64_t y_mult; 114 115 unsigned int x_ppem; 116 unsigned int y_ppem; 117 118 float ptem; 119 120 /* Font variation coordinates. */ 121 unsigned int num_coords; 122 int *coords; 123 float *design_coords; 124 125 hb_font_funcs_t *klass; 126 void *user_data; 127 hb_destroy_func_t destroy; 128 129 hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */ 130 131 132 /* Convert from font-space to user-space */ dir_multhb_font_t133 int64_t dir_mult (hb_direction_t direction) 134 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } em_scale_xhb_font_t135 hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } em_scale_yhb_font_t136 hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } em_scalef_xhb_font_t137 hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); } em_scalef_yhb_font_t138 hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); } em_fscale_xhb_font_t139 float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); } em_fscale_yhb_font_t140 float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); } em_scale_dirhb_font_t141 hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) 142 { return em_mult (v, dir_mult (direction)); } 143 144 /* Convert from parent-font user-space to our user-space */ parent_scale_x_distancehb_font_t145 hb_position_t parent_scale_x_distance (hb_position_t v) 146 { 147 if (unlikely (parent && parent->x_scale != x_scale)) 148 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 149 return v; 150 } parent_scale_y_distancehb_font_t151 hb_position_t parent_scale_y_distance (hb_position_t v) 152 { 153 if (unlikely (parent && parent->y_scale != y_scale)) 154 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 155 return v; 156 } parent_scale_x_positionhb_font_t157 hb_position_t parent_scale_x_position (hb_position_t v) 158 { return parent_scale_x_distance (v); } parent_scale_y_positionhb_font_t159 hb_position_t parent_scale_y_position (hb_position_t v) 160 { return parent_scale_y_distance (v); } 161 parent_scale_distancehb_font_t162 void parent_scale_distance (hb_position_t *x, hb_position_t *y) 163 { 164 *x = parent_scale_x_distance (*x); 165 *y = parent_scale_y_distance (*y); 166 } parent_scale_positionhb_font_t167 void parent_scale_position (hb_position_t *x, hb_position_t *y) 168 { 169 *x = parent_scale_x_position (*x); 170 *y = parent_scale_y_position (*y); 171 } 172 173 174 /* Public getters */ 175 176 HB_INTERNAL bool has_func (unsigned int i); 177 HB_INTERNAL bool has_func_set (unsigned int i); 178 179 /* has_* ... */ 180 #define HB_FONT_FUNC_IMPLEMENT(name) \ 181 bool \ 182 has_##name##_func () \ 183 { \ 184 hb_font_funcs_t *funcs = this->klass; \ 185 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 186 return has_func (i); \ 187 } \ 188 bool \ 189 has_##name##_func_set () \ 190 { \ 191 hb_font_funcs_t *funcs = this->klass; \ 192 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 193 return has_func_set (i); \ 194 } 195 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 196 #undef HB_FONT_FUNC_IMPLEMENT 197 get_font_h_extentshb_font_t198 hb_bool_t get_font_h_extents (hb_font_extents_t *extents) 199 { 200 memset (extents, 0, sizeof (*extents)); 201 return klass->get.f.font_h_extents (this, user_data, 202 extents, 203 klass->user_data.font_h_extents); 204 } get_font_v_extentshb_font_t205 hb_bool_t get_font_v_extents (hb_font_extents_t *extents) 206 { 207 memset (extents, 0, sizeof (*extents)); 208 return klass->get.f.font_v_extents (this, user_data, 209 extents, 210 klass->user_data.font_v_extents); 211 } 212 has_glyphhb_font_t213 bool has_glyph (hb_codepoint_t unicode) 214 { 215 hb_codepoint_t glyph; 216 return get_nominal_glyph (unicode, &glyph); 217 } 218 get_nominal_glyphhb_font_t219 hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, 220 hb_codepoint_t *glyph) 221 { 222 *glyph = 0; 223 return klass->get.f.nominal_glyph (this, user_data, 224 unicode, glyph, 225 klass->user_data.nominal_glyph); 226 } get_nominal_glyphshb_font_t227 unsigned int get_nominal_glyphs (unsigned int count, 228 const hb_codepoint_t *first_unicode, 229 unsigned int unicode_stride, 230 hb_codepoint_t *first_glyph, 231 unsigned int glyph_stride) 232 { 233 return klass->get.f.nominal_glyphs (this, user_data, 234 count, 235 first_unicode, unicode_stride, 236 first_glyph, glyph_stride, 237 klass->user_data.nominal_glyphs); 238 } 239 get_variation_glyphhb_font_t240 hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 241 hb_codepoint_t *glyph) 242 { 243 *glyph = 0; 244 return klass->get.f.variation_glyph (this, user_data, 245 unicode, variation_selector, glyph, 246 klass->user_data.variation_glyph); 247 } 248 get_glyph_h_advancehb_font_t249 hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 250 { 251 return klass->get.f.glyph_h_advance (this, user_data, 252 glyph, 253 klass->user_data.glyph_h_advance); 254 } 255 get_glyph_v_advancehb_font_t256 hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 257 { 258 return klass->get.f.glyph_v_advance (this, user_data, 259 glyph, 260 klass->user_data.glyph_v_advance); 261 } 262 get_glyph_h_advanceshb_font_t263 void get_glyph_h_advances (unsigned int count, 264 const hb_codepoint_t *first_glyph, 265 unsigned int glyph_stride, 266 hb_position_t *first_advance, 267 unsigned int advance_stride) 268 { 269 return klass->get.f.glyph_h_advances (this, user_data, 270 count, 271 first_glyph, glyph_stride, 272 first_advance, advance_stride, 273 klass->user_data.glyph_h_advances); 274 } 275 get_glyph_v_advanceshb_font_t276 void get_glyph_v_advances (unsigned int count, 277 const hb_codepoint_t *first_glyph, 278 unsigned int glyph_stride, 279 hb_position_t *first_advance, 280 unsigned int advance_stride) 281 { 282 return klass->get.f.glyph_v_advances (this, user_data, 283 count, 284 first_glyph, glyph_stride, 285 first_advance, advance_stride, 286 klass->user_data.glyph_v_advances); 287 } 288 get_glyph_h_originhb_font_t289 hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 290 hb_position_t *x, hb_position_t *y) 291 { 292 *x = *y = 0; 293 return klass->get.f.glyph_h_origin (this, user_data, 294 glyph, x, y, 295 klass->user_data.glyph_h_origin); 296 } 297 get_glyph_v_originhb_font_t298 hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 299 hb_position_t *x, hb_position_t *y) 300 { 301 *x = *y = 0; 302 return klass->get.f.glyph_v_origin (this, user_data, 303 glyph, x, y, 304 klass->user_data.glyph_v_origin); 305 } 306 get_glyph_h_kerninghb_font_t307 hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, 308 hb_codepoint_t right_glyph) 309 { 310 #ifdef HB_DISABLE_DEPRECATED 311 return 0; 312 #else 313 return klass->get.f.glyph_h_kerning (this, user_data, 314 left_glyph, right_glyph, 315 klass->user_data.glyph_h_kerning); 316 #endif 317 } 318 get_glyph_v_kerninghb_font_t319 hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, 320 hb_codepoint_t bottom_glyph) 321 { 322 #ifdef HB_DISABLE_DEPRECATED 323 return 0; 324 #else 325 return klass->get.f.glyph_v_kerning (this, user_data, 326 top_glyph, bottom_glyph, 327 klass->user_data.glyph_v_kerning); 328 #endif 329 } 330 get_glyph_extentshb_font_t331 hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 332 hb_glyph_extents_t *extents) 333 { 334 memset (extents, 0, sizeof (*extents)); 335 return klass->get.f.glyph_extents (this, user_data, 336 glyph, 337 extents, 338 klass->user_data.glyph_extents); 339 } 340 get_glyph_contour_pointhb_font_t341 hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 342 hb_position_t *x, hb_position_t *y) 343 { 344 *x = *y = 0; 345 return klass->get.f.glyph_contour_point (this, user_data, 346 glyph, point_index, 347 x, y, 348 klass->user_data.glyph_contour_point); 349 } 350 get_glyph_namehb_font_t351 hb_bool_t get_glyph_name (hb_codepoint_t glyph, 352 char *name, unsigned int size) 353 { 354 if (size) *name = '\0'; 355 return klass->get.f.glyph_name (this, user_data, 356 glyph, 357 name, size, 358 klass->user_data.glyph_name); 359 } 360 get_glyph_from_namehb_font_t361 hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 362 hb_codepoint_t *glyph) 363 { 364 *glyph = 0; 365 if (len == -1) len = strlen (name); 366 return klass->get.f.glyph_from_name (this, user_data, 367 name, len, 368 glyph, 369 klass->user_data.glyph_from_name); 370 } 371 372 373 /* A bit higher-level, and with fallback */ 374 get_h_extents_with_fallbackhb_font_t375 void get_h_extents_with_fallback (hb_font_extents_t *extents) 376 { 377 if (!get_font_h_extents (extents)) 378 { 379 extents->ascender = y_scale * .8; 380 extents->descender = extents->ascender - y_scale; 381 extents->line_gap = 0; 382 } 383 } get_v_extents_with_fallbackhb_font_t384 void get_v_extents_with_fallback (hb_font_extents_t *extents) 385 { 386 if (!get_font_v_extents (extents)) 387 { 388 extents->ascender = x_scale / 2; 389 extents->descender = extents->ascender - x_scale; 390 extents->line_gap = 0; 391 } 392 } 393 get_extents_for_directionhb_font_t394 void get_extents_for_direction (hb_direction_t direction, 395 hb_font_extents_t *extents) 396 { 397 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 398 get_h_extents_with_fallback (extents); 399 else 400 get_v_extents_with_fallback (extents); 401 } 402 get_glyph_advance_for_directionhb_font_t403 void get_glyph_advance_for_direction (hb_codepoint_t glyph, 404 hb_direction_t direction, 405 hb_position_t *x, hb_position_t *y) 406 { 407 *x = *y = 0; 408 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 409 *x = get_glyph_h_advance (glyph); 410 else 411 *y = get_glyph_v_advance (glyph); 412 } get_glyph_advances_for_directionhb_font_t413 void get_glyph_advances_for_direction (hb_direction_t direction, 414 unsigned int count, 415 const hb_codepoint_t *first_glyph, 416 unsigned glyph_stride, 417 hb_position_t *first_advance, 418 unsigned advance_stride) 419 { 420 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 421 get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 422 else 423 get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 424 } 425 guess_v_origin_minus_h_originhb_font_t426 void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 427 hb_position_t *x, hb_position_t *y) 428 { 429 *x = get_glyph_h_advance (glyph) / 2; 430 431 /* TODO cache this somehow?! */ 432 hb_font_extents_t extents; 433 get_h_extents_with_fallback (&extents); 434 *y = extents.ascender; 435 } 436 get_glyph_h_origin_with_fallbackhb_font_t437 void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, 438 hb_position_t *x, hb_position_t *y) 439 { 440 if (!get_glyph_h_origin (glyph, x, y) && 441 get_glyph_v_origin (glyph, x, y)) 442 { 443 hb_position_t dx, dy; 444 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 445 *x -= dx; *y -= dy; 446 } 447 } get_glyph_v_origin_with_fallbackhb_font_t448 void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, 449 hb_position_t *x, hb_position_t *y) 450 { 451 if (!get_glyph_v_origin (glyph, x, y) && 452 get_glyph_h_origin (glyph, x, y)) 453 { 454 hb_position_t dx, dy; 455 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 456 *x += dx; *y += dy; 457 } 458 } 459 get_glyph_origin_for_directionhb_font_t460 void get_glyph_origin_for_direction (hb_codepoint_t glyph, 461 hb_direction_t direction, 462 hb_position_t *x, hb_position_t *y) 463 { 464 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 465 get_glyph_h_origin_with_fallback (glyph, x, y); 466 else 467 get_glyph_v_origin_with_fallback (glyph, x, y); 468 } 469 add_glyph_h_originhb_font_t470 void add_glyph_h_origin (hb_codepoint_t glyph, 471 hb_position_t *x, hb_position_t *y) 472 { 473 hb_position_t origin_x, origin_y; 474 475 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 476 477 *x += origin_x; 478 *y += origin_y; 479 } add_glyph_v_originhb_font_t480 void add_glyph_v_origin (hb_codepoint_t glyph, 481 hb_position_t *x, hb_position_t *y) 482 { 483 hb_position_t origin_x, origin_y; 484 485 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 486 487 *x += origin_x; 488 *y += origin_y; 489 } add_glyph_origin_for_directionhb_font_t490 void add_glyph_origin_for_direction (hb_codepoint_t glyph, 491 hb_direction_t direction, 492 hb_position_t *x, hb_position_t *y) 493 { 494 hb_position_t origin_x, origin_y; 495 496 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 497 498 *x += origin_x; 499 *y += origin_y; 500 } 501 subtract_glyph_h_originhb_font_t502 void subtract_glyph_h_origin (hb_codepoint_t glyph, 503 hb_position_t *x, hb_position_t *y) 504 { 505 hb_position_t origin_x, origin_y; 506 507 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 508 509 *x -= origin_x; 510 *y -= origin_y; 511 } subtract_glyph_v_originhb_font_t512 void subtract_glyph_v_origin (hb_codepoint_t glyph, 513 hb_position_t *x, hb_position_t *y) 514 { 515 hb_position_t origin_x, origin_y; 516 517 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 518 519 *x -= origin_x; 520 *y -= origin_y; 521 } subtract_glyph_origin_for_directionhb_font_t522 void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 523 hb_direction_t direction, 524 hb_position_t *x, hb_position_t *y) 525 { 526 hb_position_t origin_x, origin_y; 527 528 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 529 530 *x -= origin_x; 531 *y -= origin_y; 532 } 533 get_glyph_kerning_for_directionhb_font_t534 void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 535 hb_direction_t direction, 536 hb_position_t *x, hb_position_t *y) 537 { 538 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 539 *y = 0; 540 *x = get_glyph_h_kerning (first_glyph, second_glyph); 541 } else { 542 *x = 0; 543 *y = get_glyph_v_kerning (first_glyph, second_glyph); 544 } 545 } 546 get_glyph_extents_for_originhb_font_t547 hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 548 hb_direction_t direction, 549 hb_glyph_extents_t *extents) 550 { 551 hb_bool_t ret = get_glyph_extents (glyph, extents); 552 553 if (ret) 554 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 555 556 return ret; 557 } 558 get_glyph_contour_point_for_originhb_font_t559 hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 560 hb_direction_t direction, 561 hb_position_t *x, hb_position_t *y) 562 { 563 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 564 565 if (ret) 566 subtract_glyph_origin_for_direction (glyph, direction, x, y); 567 568 return ret; 569 } 570 571 /* Generates gidDDD if glyph has no name. */ 572 void glyph_to_stringhb_font_t573 glyph_to_string (hb_codepoint_t glyph, 574 char *s, unsigned int size) 575 { 576 if (get_glyph_name (glyph, s, size)) return; 577 578 if (size && snprintf (s, size, "gid%u", glyph) < 0) 579 *s = '\0'; 580 } 581 582 /* Parses gidDDD and uniUUUU strings automatically. */ 583 hb_bool_t glyph_from_stringhb_font_t584 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 585 hb_codepoint_t *glyph) 586 { 587 if (get_glyph_from_name (s, len, glyph)) return true; 588 589 if (len == -1) len = strlen (s); 590 591 /* Straight glyph index. */ 592 if (hb_codepoint_parse (s, len, 10, glyph)) 593 return true; 594 595 if (len > 3) 596 { 597 /* gidDDD syntax for glyph indices. */ 598 if (0 == strncmp (s, "gid", 3) && 599 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 600 return true; 601 602 /* uniUUUU and other Unicode character indices. */ 603 hb_codepoint_t unichar; 604 if (0 == strncmp (s, "uni", 3) && 605 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 606 get_nominal_glyph (unichar, glyph)) 607 return true; 608 } 609 610 return false; 611 } 612 mults_changedhb_font_t613 void mults_changed () 614 { 615 signed upem = face->get_upem (); 616 x_mult = ((int64_t) x_scale << 16) / upem; 617 y_mult = ((int64_t) y_scale << 16) / upem; 618 } 619 em_multhb_font_t620 hb_position_t em_mult (int16_t v, int64_t mult) 621 { 622 return (hb_position_t) ((v * mult) >> 16); 623 } em_scalefhb_font_t624 hb_position_t em_scalef (float v, int scale) 625 { return (hb_position_t) roundf (v * scale / face->get_upem ()); } em_fscalehb_font_t626 float em_fscale (int16_t v, int scale) 627 { return (float) v * scale / face->get_upem (); } 628 }; 629 DECLARE_NULL_INSTANCE (hb_font_t); 630 631 632 #endif /* HB_FONT_HH */ 633