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 #include "inttypes.h" 37 38 39 /* 40 * hb_font_funcs_t 41 */ 42 43 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 44 HB_FONT_FUNC_IMPLEMENT (get_,font_h_extents) \ 45 HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \ 46 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \ 47 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \ 48 HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \ 49 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \ 50 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \ 51 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \ 52 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \ 53 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \ 54 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \ 55 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \ 56 HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \ 57 HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \ 58 HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ 59 HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ 60 HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ 61 HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \ 62 HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \ 63 /* ^--- Add new callbacks here */ 64 65 struct hb_font_funcs_t 66 { 67 hb_object_header_t header; 68 69 struct { 70 #define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name; 71 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 72 #undef HB_FONT_FUNC_IMPLEMENT 73 } *user_data; 74 75 struct { 76 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name; 77 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 78 #undef HB_FONT_FUNC_IMPLEMENT 79 } *destroy; 80 81 /* Don't access these directly. Call font->get_*() instead. */ 82 union get_t { 83 struct get_funcs_t { 84 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name; 85 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 86 #undef HB_FONT_FUNC_IMPLEMENT 87 } f; 88 void (*array[0 89 #define HB_FONT_FUNC_IMPLEMENT(get_,name) +1 90 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 91 #undef HB_FONT_FUNC_IMPLEMENT 92 ]) (); 93 } get; 94 }; 95 DECLARE_NULL_INSTANCE (hb_font_funcs_t); 96 97 98 /* 99 * hb_font_t 100 */ 101 102 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font); 103 #include "hb-shaper-list.hh" 104 #undef HB_SHAPER_IMPLEMENT 105 106 struct hb_font_t 107 { 108 hb_object_header_t header; 109 unsigned int serial; 110 unsigned int serial_coords; 111 112 hb_font_t *parent; 113 hb_face_t *face; 114 115 int32_t x_scale; 116 int32_t y_scale; 117 118 float x_embolden; 119 float y_embolden; 120 bool embolden_in_place; 121 int32_t x_strength; /* x_embolden, in scaled units. */ 122 int32_t y_strength; /* y_embolden, in scaled units. */ 123 124 float slant; 125 float slant_xy; 126 127 float x_multf; 128 float y_multf; 129 int64_t x_mult; 130 int64_t y_mult; 131 132 unsigned int x_ppem; 133 unsigned int y_ppem; 134 135 float ptem; 136 137 /* Font variation coordinates. */ 138 unsigned int instance_index; 139 unsigned int num_coords; 140 int *coords; 141 float *design_coords; 142 143 hb_font_funcs_t *klass; 144 void *user_data; 145 hb_destroy_func_t destroy; 146 147 hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */ 148 149 150 /* Convert from font-space to user-space */ dir_multhb_font_t151 int64_t dir_mult (hb_direction_t direction) 152 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } em_scale_xhb_font_t153 hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } em_scale_yhb_font_t154 hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } em_scalef_xhb_font_t155 hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); } em_scalef_yhb_font_t156 hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); } em_fscale_xhb_font_t157 float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); } em_fscale_yhb_font_t158 float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); } em_fscalef_xhb_font_t159 float em_fscalef_x (float v) { return em_fmultf (v, x_multf); } em_fscalef_yhb_font_t160 float em_fscalef_y (float v) { return em_fmultf (v, y_multf); } em_scale_dirhb_font_t161 hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) 162 { return em_mult (v, dir_mult (direction)); } 163 164 /* Convert from parent-font user-space to our user-space */ parent_scale_x_distancehb_font_t165 hb_position_t parent_scale_x_distance (hb_position_t v) 166 { 167 if (unlikely (parent && parent->x_scale != x_scale)) 168 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 169 return v; 170 } parent_scale_y_distancehb_font_t171 hb_position_t parent_scale_y_distance (hb_position_t v) 172 { 173 if (unlikely (parent && parent->y_scale != y_scale)) 174 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 175 return v; 176 } parent_scale_x_positionhb_font_t177 hb_position_t parent_scale_x_position (hb_position_t v) 178 { return parent_scale_x_distance (v); } parent_scale_y_positionhb_font_t179 hb_position_t parent_scale_y_position (hb_position_t v) 180 { return parent_scale_y_distance (v); } 181 parent_scale_distancehb_font_t182 void parent_scale_distance (hb_position_t *x, hb_position_t *y) 183 { 184 *x = parent_scale_x_distance (*x); 185 *y = parent_scale_y_distance (*y); 186 } parent_scale_positionhb_font_t187 void parent_scale_position (hb_position_t *x, hb_position_t *y) 188 { 189 *x = parent_scale_x_position (*x); 190 *y = parent_scale_y_position (*y); 191 } 192 scale_glyph_extentshb_font_t193 void scale_glyph_extents (hb_glyph_extents_t *extents) 194 { 195 float x1 = em_fscale_x (extents->x_bearing); 196 float y1 = em_fscale_y (extents->y_bearing); 197 float x2 = em_fscale_x (extents->x_bearing + extents->width); 198 float y2 = em_fscale_y (extents->y_bearing + extents->height); 199 200 /* Apply slant. */ 201 if (slant_xy) 202 { 203 x1 += hb_min (y1 * slant_xy, y2 * slant_xy); 204 x2 += hb_max (y1 * slant_xy, y2 * slant_xy); 205 } 206 207 extents->x_bearing = floorf (x1); 208 extents->y_bearing = floorf (y1); 209 extents->width = ceilf (x2) - extents->x_bearing; 210 extents->height = ceilf (y2) - extents->y_bearing; 211 212 if (x_strength || y_strength) 213 { 214 /* Y */ 215 int y_shift = y_strength; 216 if (y_scale < 0) y_shift = -y_shift; 217 extents->y_bearing += y_shift; 218 extents->height -= y_shift; 219 220 /* X */ 221 int x_shift = x_strength; 222 if (x_scale < 0) x_shift = -x_shift; 223 if (embolden_in_place) 224 extents->x_bearing -= x_shift / 2; 225 extents->width += x_shift; 226 } 227 } 228 229 230 /* Public getters */ 231 232 HB_INTERNAL bool has_func (unsigned int i); 233 HB_INTERNAL bool has_func_set (unsigned int i); 234 235 /* has_* ... */ 236 #define HB_FONT_FUNC_IMPLEMENT(get_,name) \ 237 bool \ 238 has_##name##_func () \ 239 { \ 240 hb_font_funcs_t *funcs = this->klass; \ 241 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 242 return has_func (i); \ 243 } \ 244 bool \ 245 has_##name##_func_set () \ 246 { \ 247 hb_font_funcs_t *funcs = this->klass; \ 248 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 249 return has_func_set (i); \ 250 } 251 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 252 #undef HB_FONT_FUNC_IMPLEMENT 253 get_font_h_extentshb_font_t254 hb_bool_t get_font_h_extents (hb_font_extents_t *extents) 255 { 256 hb_memset (extents, 0, sizeof (*extents)); 257 return klass->get.f.font_h_extents (this, user_data, 258 extents, 259 !klass->user_data ? nullptr : klass->user_data->font_h_extents); 260 } get_font_v_extentshb_font_t261 hb_bool_t get_font_v_extents (hb_font_extents_t *extents) 262 { 263 hb_memset (extents, 0, sizeof (*extents)); 264 return klass->get.f.font_v_extents (this, user_data, 265 extents, 266 !klass->user_data ? nullptr : klass->user_data->font_v_extents); 267 } 268 has_glyphhb_font_t269 bool has_glyph (hb_codepoint_t unicode) 270 { 271 hb_codepoint_t glyph; 272 return get_nominal_glyph (unicode, &glyph); 273 } 274 get_nominal_glyphhb_font_t275 hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, 276 hb_codepoint_t *glyph, 277 hb_codepoint_t not_found = 0) 278 { 279 *glyph = not_found; 280 return klass->get.f.nominal_glyph (this, user_data, 281 unicode, glyph, 282 !klass->user_data ? nullptr : klass->user_data->nominal_glyph); 283 } get_nominal_glyphshb_font_t284 unsigned int get_nominal_glyphs (unsigned int count, 285 const hb_codepoint_t *first_unicode, 286 unsigned int unicode_stride, 287 hb_codepoint_t *first_glyph, 288 unsigned int glyph_stride) 289 { 290 return klass->get.f.nominal_glyphs (this, user_data, 291 count, 292 first_unicode, unicode_stride, 293 first_glyph, glyph_stride, 294 !klass->user_data ? nullptr : klass->user_data->nominal_glyphs); 295 } 296 get_variation_glyphhb_font_t297 hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 298 hb_codepoint_t *glyph, 299 hb_codepoint_t not_found = 0) 300 { 301 *glyph = not_found; 302 return klass->get.f.variation_glyph (this, user_data, 303 unicode, variation_selector, glyph, 304 !klass->user_data ? nullptr : klass->user_data->variation_glyph); 305 } 306 get_glyph_h_advancehb_font_t307 hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 308 { 309 return klass->get.f.glyph_h_advance (this, user_data, 310 glyph, 311 !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); 312 } 313 get_glyph_v_advancehb_font_t314 hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 315 { 316 return klass->get.f.glyph_v_advance (this, user_data, 317 glyph, 318 !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); 319 } 320 get_glyph_h_advanceshb_font_t321 void get_glyph_h_advances (unsigned int count, 322 const hb_codepoint_t *first_glyph, 323 unsigned int glyph_stride, 324 hb_position_t *first_advance, 325 unsigned int advance_stride) 326 { 327 return klass->get.f.glyph_h_advances (this, user_data, 328 count, 329 first_glyph, glyph_stride, 330 first_advance, advance_stride, 331 !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); 332 } 333 get_glyph_v_advanceshb_font_t334 void get_glyph_v_advances (unsigned int count, 335 const hb_codepoint_t *first_glyph, 336 unsigned int glyph_stride, 337 hb_position_t *first_advance, 338 unsigned int advance_stride) 339 { 340 return klass->get.f.glyph_v_advances (this, user_data, 341 count, 342 first_glyph, glyph_stride, 343 first_advance, advance_stride, 344 !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); 345 } 346 get_glyph_h_originhb_font_t347 hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 348 hb_position_t *x, hb_position_t *y) 349 { 350 *x = *y = 0; 351 return klass->get.f.glyph_h_origin (this, user_data, 352 glyph, x, y, 353 !klass->user_data ? nullptr : klass->user_data->glyph_h_origin); 354 } 355 get_glyph_v_originhb_font_t356 hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 357 hb_position_t *x, hb_position_t *y) 358 { 359 *x = *y = 0; 360 return klass->get.f.glyph_v_origin (this, user_data, 361 glyph, x, y, 362 !klass->user_data ? nullptr : klass->user_data->glyph_v_origin); 363 } 364 get_glyph_h_kerninghb_font_t365 hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, 366 hb_codepoint_t right_glyph) 367 { 368 #ifdef HB_DISABLE_DEPRECATED 369 return 0; 370 #else 371 return klass->get.f.glyph_h_kerning (this, user_data, 372 left_glyph, right_glyph, 373 !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning); 374 #endif 375 } 376 get_glyph_v_kerninghb_font_t377 hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, 378 hb_codepoint_t bottom_glyph) 379 { 380 #ifdef HB_DISABLE_DEPRECATED 381 return 0; 382 #else 383 return klass->get.f.glyph_v_kerning (this, user_data, 384 top_glyph, bottom_glyph, 385 !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning); 386 #endif 387 } 388 get_glyph_extentshb_font_t389 hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 390 hb_glyph_extents_t *extents) 391 { 392 hb_memset (extents, 0, sizeof (*extents)); 393 return klass->get.f.glyph_extents (this, user_data, 394 glyph, 395 extents, 396 !klass->user_data ? nullptr : klass->user_data->glyph_extents); 397 } 398 get_glyph_contour_pointhb_font_t399 hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 400 hb_position_t *x, hb_position_t *y) 401 { 402 *x = *y = 0; 403 return klass->get.f.glyph_contour_point (this, user_data, 404 glyph, point_index, 405 x, y, 406 !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); 407 } 408 get_glyph_namehb_font_t409 hb_bool_t get_glyph_name (hb_codepoint_t glyph, 410 char *name, unsigned int size) 411 { 412 if (size) *name = '\0'; 413 return klass->get.f.glyph_name (this, user_data, 414 glyph, 415 name, size, 416 !klass->user_data ? nullptr : klass->user_data->glyph_name); 417 } 418 get_glyph_from_namehb_font_t419 hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 420 hb_codepoint_t *glyph) 421 { 422 *glyph = 0; 423 if (len == -1) len = strlen (name); 424 return klass->get.f.glyph_from_name (this, user_data, 425 name, len, 426 glyph, 427 !klass->user_data ? nullptr : klass->user_data->glyph_from_name); 428 } 429 draw_glyphhb_font_t430 void draw_glyph (hb_codepoint_t glyph, 431 hb_draw_funcs_t *draw_funcs, void *draw_data) 432 { 433 klass->get.f.draw_glyph (this, user_data, 434 glyph, 435 draw_funcs, draw_data, 436 !klass->user_data ? nullptr : klass->user_data->draw_glyph); 437 } 438 paint_glyphhb_font_t439 void paint_glyph (hb_codepoint_t glyph, 440 hb_paint_funcs_t *paint_funcs, void *paint_data, 441 unsigned int palette, 442 hb_color_t foreground) 443 { 444 klass->get.f.paint_glyph (this, user_data, 445 glyph, 446 paint_funcs, paint_data, 447 palette, foreground, 448 !klass->user_data ? nullptr : klass->user_data->paint_glyph); 449 } 450 451 /* A bit higher-level, and with fallback */ 452 get_h_extents_with_fallbackhb_font_t453 void get_h_extents_with_fallback (hb_font_extents_t *extents) 454 { 455 if (!get_font_h_extents (extents)) 456 { 457 extents->ascender = y_scale * .8; 458 extents->descender = extents->ascender - y_scale; 459 extents->line_gap = 0; 460 } 461 } get_v_extents_with_fallbackhb_font_t462 void get_v_extents_with_fallback (hb_font_extents_t *extents) 463 { 464 if (!get_font_v_extents (extents)) 465 { 466 extents->ascender = x_scale / 2; 467 extents->descender = extents->ascender - x_scale; 468 extents->line_gap = 0; 469 } 470 } 471 get_extents_for_directionhb_font_t472 void get_extents_for_direction (hb_direction_t direction, 473 hb_font_extents_t *extents) 474 { 475 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 476 get_h_extents_with_fallback (extents); 477 else 478 get_v_extents_with_fallback (extents); 479 } 480 get_glyph_advance_for_directionhb_font_t481 void get_glyph_advance_for_direction (hb_codepoint_t glyph, 482 hb_direction_t direction, 483 hb_position_t *x, hb_position_t *y) 484 { 485 *x = *y = 0; 486 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 487 *x = get_glyph_h_advance (glyph); 488 else 489 *y = get_glyph_v_advance (glyph); 490 } get_glyph_advances_for_directionhb_font_t491 void get_glyph_advances_for_direction (hb_direction_t direction, 492 unsigned int count, 493 const hb_codepoint_t *first_glyph, 494 unsigned glyph_stride, 495 hb_position_t *first_advance, 496 unsigned advance_stride) 497 { 498 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 499 get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 500 else 501 get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 502 } 503 guess_v_origin_minus_h_originhb_font_t504 void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 505 hb_position_t *x, hb_position_t *y) 506 { 507 *x = get_glyph_h_advance (glyph) / 2; 508 509 hb_font_extents_t extents; 510 get_h_extents_with_fallback (&extents); 511 *y = extents.ascender; 512 } 513 get_glyph_h_origin_with_fallbackhb_font_t514 void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, 515 hb_position_t *x, hb_position_t *y) 516 { 517 if (!get_glyph_h_origin (glyph, x, y) && 518 get_glyph_v_origin (glyph, x, y)) 519 { 520 hb_position_t dx, dy; 521 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 522 *x -= dx; *y -= dy; 523 } 524 } get_glyph_v_origin_with_fallbackhb_font_t525 void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, 526 hb_position_t *x, hb_position_t *y) 527 { 528 if (!get_glyph_v_origin (glyph, x, y) && 529 get_glyph_h_origin (glyph, x, y)) 530 { 531 hb_position_t dx, dy; 532 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 533 *x += dx; *y += dy; 534 } 535 } 536 get_glyph_origin_for_directionhb_font_t537 void get_glyph_origin_for_direction (hb_codepoint_t glyph, 538 hb_direction_t direction, 539 hb_position_t *x, hb_position_t *y) 540 { 541 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 542 get_glyph_h_origin_with_fallback (glyph, x, y); 543 else 544 get_glyph_v_origin_with_fallback (glyph, x, y); 545 } 546 add_glyph_h_originhb_font_t547 void add_glyph_h_origin (hb_codepoint_t glyph, 548 hb_position_t *x, hb_position_t *y) 549 { 550 hb_position_t origin_x, origin_y; 551 552 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 553 554 *x += origin_x; 555 *y += origin_y; 556 } add_glyph_v_originhb_font_t557 void add_glyph_v_origin (hb_codepoint_t glyph, 558 hb_position_t *x, hb_position_t *y) 559 { 560 hb_position_t origin_x, origin_y; 561 562 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 563 564 *x += origin_x; 565 *y += origin_y; 566 } add_glyph_origin_for_directionhb_font_t567 void add_glyph_origin_for_direction (hb_codepoint_t glyph, 568 hb_direction_t direction, 569 hb_position_t *x, hb_position_t *y) 570 { 571 hb_position_t origin_x, origin_y; 572 573 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 574 575 *x += origin_x; 576 *y += origin_y; 577 } 578 subtract_glyph_h_originhb_font_t579 void subtract_glyph_h_origin (hb_codepoint_t glyph, 580 hb_position_t *x, hb_position_t *y) 581 { 582 hb_position_t origin_x, origin_y; 583 584 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 585 586 *x -= origin_x; 587 *y -= origin_y; 588 } subtract_glyph_v_originhb_font_t589 void subtract_glyph_v_origin (hb_codepoint_t glyph, 590 hb_position_t *x, hb_position_t *y) 591 { 592 hb_position_t origin_x, origin_y; 593 594 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 595 596 *x -= origin_x; 597 *y -= origin_y; 598 } subtract_glyph_origin_for_directionhb_font_t599 void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 600 hb_direction_t direction, 601 hb_position_t *x, hb_position_t *y) 602 { 603 hb_position_t origin_x, origin_y; 604 605 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 606 607 *x -= origin_x; 608 *y -= origin_y; 609 } 610 get_glyph_kerning_for_directionhb_font_t611 void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 612 hb_direction_t direction, 613 hb_position_t *x, hb_position_t *y) 614 { 615 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 616 *y = 0; 617 *x = get_glyph_h_kerning (first_glyph, second_glyph); 618 } else { 619 *x = 0; 620 *y = get_glyph_v_kerning (first_glyph, second_glyph); 621 } 622 } 623 get_glyph_extents_for_originhb_font_t624 hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 625 hb_direction_t direction, 626 hb_glyph_extents_t *extents) 627 { 628 hb_bool_t ret = get_glyph_extents (glyph, extents); 629 630 if (ret) 631 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 632 633 return ret; 634 } 635 get_glyph_contour_point_for_originhb_font_t636 hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 637 hb_direction_t direction, 638 hb_position_t *x, hb_position_t *y) 639 { 640 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 641 642 if (ret) 643 subtract_glyph_origin_for_direction (glyph, direction, x, y); 644 645 return ret; 646 } 647 648 /* Generates gidDDD if glyph has no name. */ 649 void glyph_to_stringhb_font_t650 glyph_to_string (hb_codepoint_t glyph, 651 char *s, unsigned int size) 652 { 653 if (get_glyph_name (glyph, s, size)) return; 654 655 if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0) 656 *s = '\0'; 657 } 658 659 /* Parses gidDDD and uniUUUU strings automatically. */ 660 hb_bool_t glyph_from_stringhb_font_t661 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 662 hb_codepoint_t *glyph) 663 { 664 if (get_glyph_from_name (s, len, glyph)) return true; 665 666 if (len == -1) len = strlen (s); 667 668 /* Straight glyph index. */ 669 if (hb_codepoint_parse (s, len, 10, glyph)) 670 return true; 671 672 if (len > 3) 673 { 674 /* gidDDD syntax for glyph indices. */ 675 if (0 == strncmp (s, "gid", 3) && 676 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 677 return true; 678 679 /* uniUUUU and other Unicode character indices. */ 680 hb_codepoint_t unichar; 681 if (0 == strncmp (s, "uni", 3) && 682 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 683 get_nominal_glyph (unichar, glyph)) 684 return true; 685 } 686 687 return false; 688 } 689 mults_changedhb_font_t690 void mults_changed () 691 { 692 float upem = face->get_upem (); 693 694 x_multf = x_scale / upem; 695 y_multf = y_scale / upem; 696 bool x_neg = x_scale < 0; 697 x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem; 698 bool y_neg = y_scale < 0; 699 y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; 700 701 x_strength = fabsf (roundf (x_scale * x_embolden)); 702 y_strength = fabsf (roundf (y_scale * y_embolden)); 703 704 slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; 705 706 data.fini (); 707 } 708 em_multhb_font_t709 hb_position_t em_mult (int16_t v, int64_t mult) 710 { return (hb_position_t) ((v * mult + 32768) >> 16); } em_multfhb_font_t711 hb_position_t em_multf (float v, float mult) 712 { return (hb_position_t) roundf (em_fmultf (v, mult)); } em_fmultfhb_font_t713 float em_fmultf (float v, float mult) 714 { return v * mult; } em_fmulthb_font_t715 float em_fmult (int16_t v, float mult) 716 { return (float) v * mult; } 717 }; 718 DECLARE_NULL_INSTANCE (hb_font_t); 719 720 721 #endif /* HB_FONT_HH */ 722