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 (get_,font_h_extents) \ 44 HB_FONT_FUNC_IMPLEMENT (get_,font_v_extents) \ 45 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyph) \ 46 HB_FONT_FUNC_IMPLEMENT (get_,nominal_glyphs) \ 47 HB_FONT_FUNC_IMPLEMENT (get_,variation_glyph) \ 48 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advance) \ 49 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advance) \ 50 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_advances) \ 51 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \ 52 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \ 53 HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \ 54 HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \ 55 HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \ 56 HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \ 57 HB_FONT_FUNC_IMPLEMENT (get_,glyph_contour_point) \ 58 HB_FONT_FUNC_IMPLEMENT (get_,glyph_name) \ 59 HB_FONT_FUNC_IMPLEMENT (get_,glyph_from_name) \ 60 HB_FONT_FUNC_IMPLEMENT (,draw_glyph) \ 61 HB_FONT_FUNC_IMPLEMENT (,paint_glyph) \ 62 /* ^--- Add new callbacks here */ 63 64 struct hb_font_funcs_t 65 { 66 hb_object_header_t header; 67 68 struct { 69 #define HB_FONT_FUNC_IMPLEMENT(get_,name) void *name; 70 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 71 #undef HB_FONT_FUNC_IMPLEMENT 72 } *user_data; 73 74 struct { 75 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_destroy_func_t name; 76 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 77 #undef HB_FONT_FUNC_IMPLEMENT 78 } *destroy; 79 80 /* Don't access these directly. Call font->get_*() instead. */ 81 union get_t { 82 struct get_funcs_t { 83 #define HB_FONT_FUNC_IMPLEMENT(get_,name) hb_font_##get_##name##_func_t name; 84 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 85 #undef HB_FONT_FUNC_IMPLEMENT 86 } f; 87 void (*array[0 88 #define HB_FONT_FUNC_IMPLEMENT(get_,name) +1 89 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 90 #undef HB_FONT_FUNC_IMPLEMENT 91 ]) (); 92 } get; 93 }; 94 DECLARE_NULL_INSTANCE (hb_font_funcs_t); 95 96 97 /* 98 * hb_font_t 99 */ 100 101 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font); 102 #include "hb-shaper-list.hh" 103 #undef HB_SHAPER_IMPLEMENT 104 105 struct hb_font_t 106 { 107 hb_object_header_t header; 108 unsigned int serial; 109 unsigned int serial_coords; 110 111 hb_font_t *parent; 112 hb_face_t *face; 113 114 int32_t x_scale; 115 int32_t y_scale; 116 117 float x_embolden; 118 float y_embolden; 119 bool embolden_in_place; 120 int32_t x_strength; /* x_embolden, in scaled units. */ 121 int32_t y_strength; /* y_embolden, in scaled units. */ 122 123 float slant; 124 float slant_xy; 125 126 float x_multf; 127 float y_multf; 128 int64_t x_mult; 129 int64_t y_mult; 130 131 unsigned int x_ppem; 132 unsigned int y_ppem; 133 134 float ptem; 135 136 /* Font variation coordinates. */ 137 unsigned int instance_index; 138 unsigned int num_coords; 139 int *coords; 140 float *design_coords; 141 142 hb_font_funcs_t *klass; 143 void *user_data; 144 hb_destroy_func_t destroy; 145 146 hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */ 147 148 149 /* Convert from font-space to user-space */ dir_multhb_font_t150 int64_t dir_mult (hb_direction_t direction) 151 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; } em_scale_xhb_font_t152 hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); } em_scale_yhb_font_t153 hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); } em_scalef_xhb_font_t154 hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); } em_scalef_yhb_font_t155 hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); } em_fscale_xhb_font_t156 float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); } em_fscale_yhb_font_t157 float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); } em_fscalef_xhb_font_t158 float em_fscalef_x (float v) { return em_fmultf (v, x_multf); } em_fscalef_yhb_font_t159 float em_fscalef_y (float v) { return em_fmultf (v, y_multf); } em_scale_dirhb_font_t160 hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) 161 { return em_mult (v, dir_mult (direction)); } 162 163 /* Convert from parent-font user-space to our user-space */ parent_scale_x_distancehb_font_t164 hb_position_t parent_scale_x_distance (hb_position_t v) 165 { 166 if (unlikely (parent && parent->x_scale != x_scale)) 167 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 168 return v; 169 } parent_scale_y_distancehb_font_t170 hb_position_t parent_scale_y_distance (hb_position_t v) 171 { 172 if (unlikely (parent && parent->y_scale != y_scale)) 173 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 174 return v; 175 } parent_scale_x_positionhb_font_t176 hb_position_t parent_scale_x_position (hb_position_t v) 177 { return parent_scale_x_distance (v); } parent_scale_y_positionhb_font_t178 hb_position_t parent_scale_y_position (hb_position_t v) 179 { return parent_scale_y_distance (v); } 180 parent_scale_distancehb_font_t181 void parent_scale_distance (hb_position_t *x, hb_position_t *y) 182 { 183 *x = parent_scale_x_distance (*x); 184 *y = parent_scale_y_distance (*y); 185 } parent_scale_positionhb_font_t186 void parent_scale_position (hb_position_t *x, hb_position_t *y) 187 { 188 *x = parent_scale_x_position (*x); 189 *y = parent_scale_y_position (*y); 190 } 191 scale_glyph_extentshb_font_t192 void scale_glyph_extents (hb_glyph_extents_t *extents) 193 { 194 float x1 = em_fscale_x (extents->x_bearing); 195 float y1 = em_fscale_y (extents->y_bearing); 196 float x2 = em_fscale_x (extents->x_bearing + extents->width); 197 float y2 = em_fscale_y (extents->y_bearing + extents->height); 198 199 /* Apply slant. */ 200 if (slant_xy) 201 { 202 x1 += hb_min (y1 * slant_xy, y2 * slant_xy); 203 x2 += hb_max (y1 * slant_xy, y2 * slant_xy); 204 } 205 206 extents->x_bearing = floorf (x1); 207 extents->y_bearing = floorf (y1); 208 extents->width = ceilf (x2) - extents->x_bearing; 209 extents->height = ceilf (y2) - extents->y_bearing; 210 211 if (x_strength || y_strength) 212 { 213 /* Y */ 214 int y_shift = y_strength; 215 if (y_scale < 0) y_shift = -y_shift; 216 extents->y_bearing += y_shift; 217 extents->height -= y_shift; 218 219 /* X */ 220 int x_shift = x_strength; 221 if (x_scale < 0) x_shift = -x_shift; 222 if (embolden_in_place) 223 extents->x_bearing -= x_shift / 2; 224 extents->width += x_shift; 225 } 226 } 227 228 229 /* Public getters */ 230 231 HB_INTERNAL bool has_func (unsigned int i); 232 HB_INTERNAL bool has_func_set (unsigned int i); 233 234 /* has_* ... */ 235 #define HB_FONT_FUNC_IMPLEMENT(get_,name) \ 236 bool \ 237 has_##name##_func () \ 238 { \ 239 hb_font_funcs_t *funcs = this->klass; \ 240 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 241 return has_func (i); \ 242 } \ 243 bool \ 244 has_##name##_func_set () \ 245 { \ 246 hb_font_funcs_t *funcs = this->klass; \ 247 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 248 return has_func_set (i); \ 249 } 250 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 251 #undef HB_FONT_FUNC_IMPLEMENT 252 get_font_h_extentshb_font_t253 hb_bool_t get_font_h_extents (hb_font_extents_t *extents) 254 { 255 hb_memset (extents, 0, sizeof (*extents)); 256 return klass->get.f.font_h_extents (this, user_data, 257 extents, 258 !klass->user_data ? nullptr : klass->user_data->font_h_extents); 259 } get_font_v_extentshb_font_t260 hb_bool_t get_font_v_extents (hb_font_extents_t *extents) 261 { 262 hb_memset (extents, 0, sizeof (*extents)); 263 return klass->get.f.font_v_extents (this, user_data, 264 extents, 265 !klass->user_data ? nullptr : klass->user_data->font_v_extents); 266 } 267 has_glyphhb_font_t268 bool has_glyph (hb_codepoint_t unicode) 269 { 270 hb_codepoint_t glyph; 271 return get_nominal_glyph (unicode, &glyph); 272 } 273 get_nominal_glyphhb_font_t274 hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, 275 hb_codepoint_t *glyph, 276 hb_codepoint_t not_found = 0) 277 { 278 *glyph = not_found; 279 return klass->get.f.nominal_glyph (this, user_data, 280 unicode, glyph, 281 !klass->user_data ? nullptr : klass->user_data->nominal_glyph); 282 } get_nominal_glyphshb_font_t283 unsigned int get_nominal_glyphs (unsigned int count, 284 const hb_codepoint_t *first_unicode, 285 unsigned int unicode_stride, 286 hb_codepoint_t *first_glyph, 287 unsigned int glyph_stride) 288 { 289 return klass->get.f.nominal_glyphs (this, user_data, 290 count, 291 first_unicode, unicode_stride, 292 first_glyph, glyph_stride, 293 !klass->user_data ? nullptr : klass->user_data->nominal_glyphs); 294 } 295 get_variation_glyphhb_font_t296 hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 297 hb_codepoint_t *glyph, 298 hb_codepoint_t not_found = 0) 299 { 300 *glyph = not_found; 301 return klass->get.f.variation_glyph (this, user_data, 302 unicode, variation_selector, glyph, 303 !klass->user_data ? nullptr : klass->user_data->variation_glyph); 304 } 305 get_glyph_h_advancehb_font_t306 hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 307 { 308 return klass->get.f.glyph_h_advance (this, user_data, 309 glyph, 310 !klass->user_data ? nullptr : klass->user_data->glyph_h_advance); 311 } 312 get_glyph_v_advancehb_font_t313 hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 314 { 315 return klass->get.f.glyph_v_advance (this, user_data, 316 glyph, 317 !klass->user_data ? nullptr : klass->user_data->glyph_v_advance); 318 } 319 get_glyph_h_advanceshb_font_t320 void get_glyph_h_advances (unsigned int count, 321 const hb_codepoint_t *first_glyph, 322 unsigned int glyph_stride, 323 hb_position_t *first_advance, 324 unsigned int advance_stride) 325 { 326 return klass->get.f.glyph_h_advances (this, user_data, 327 count, 328 first_glyph, glyph_stride, 329 first_advance, advance_stride, 330 !klass->user_data ? nullptr : klass->user_data->glyph_h_advances); 331 } 332 get_glyph_v_advanceshb_font_t333 void get_glyph_v_advances (unsigned int count, 334 const hb_codepoint_t *first_glyph, 335 unsigned int glyph_stride, 336 hb_position_t *first_advance, 337 unsigned int advance_stride) 338 { 339 return klass->get.f.glyph_v_advances (this, user_data, 340 count, 341 first_glyph, glyph_stride, 342 first_advance, advance_stride, 343 !klass->user_data ? nullptr : klass->user_data->glyph_v_advances); 344 } 345 get_glyph_h_originhb_font_t346 hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 347 hb_position_t *x, hb_position_t *y) 348 { 349 *x = *y = 0; 350 return klass->get.f.glyph_h_origin (this, user_data, 351 glyph, x, y, 352 !klass->user_data ? nullptr : klass->user_data->glyph_h_origin); 353 } 354 get_glyph_v_originhb_font_t355 hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 356 hb_position_t *x, hb_position_t *y) 357 { 358 *x = *y = 0; 359 return klass->get.f.glyph_v_origin (this, user_data, 360 glyph, x, y, 361 !klass->user_data ? nullptr : klass->user_data->glyph_v_origin); 362 } 363 get_glyph_h_kerninghb_font_t364 hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, 365 hb_codepoint_t right_glyph) 366 { 367 #ifdef HB_DISABLE_DEPRECATED 368 return 0; 369 #else 370 return klass->get.f.glyph_h_kerning (this, user_data, 371 left_glyph, right_glyph, 372 !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning); 373 #endif 374 } 375 get_glyph_v_kerninghb_font_t376 hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, 377 hb_codepoint_t bottom_glyph) 378 { 379 #ifdef HB_DISABLE_DEPRECATED 380 return 0; 381 #else 382 return klass->get.f.glyph_v_kerning (this, user_data, 383 top_glyph, bottom_glyph, 384 !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning); 385 #endif 386 } 387 get_glyph_extentshb_font_t388 hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 389 hb_glyph_extents_t *extents) 390 { 391 hb_memset (extents, 0, sizeof (*extents)); 392 return klass->get.f.glyph_extents (this, user_data, 393 glyph, 394 extents, 395 !klass->user_data ? nullptr : klass->user_data->glyph_extents); 396 } 397 get_glyph_contour_pointhb_font_t398 hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 399 hb_position_t *x, hb_position_t *y) 400 { 401 *x = *y = 0; 402 return klass->get.f.glyph_contour_point (this, user_data, 403 glyph, point_index, 404 x, y, 405 !klass->user_data ? nullptr : klass->user_data->glyph_contour_point); 406 } 407 get_glyph_namehb_font_t408 hb_bool_t get_glyph_name (hb_codepoint_t glyph, 409 char *name, unsigned int size) 410 { 411 if (size) *name = '\0'; 412 return klass->get.f.glyph_name (this, user_data, 413 glyph, 414 name, size, 415 !klass->user_data ? nullptr : klass->user_data->glyph_name); 416 } 417 get_glyph_from_namehb_font_t418 hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 419 hb_codepoint_t *glyph) 420 { 421 *glyph = 0; 422 if (len == -1) len = strlen (name); 423 return klass->get.f.glyph_from_name (this, user_data, 424 name, len, 425 glyph, 426 !klass->user_data ? nullptr : klass->user_data->glyph_from_name); 427 } 428 draw_glyphhb_font_t429 void draw_glyph (hb_codepoint_t glyph, 430 hb_draw_funcs_t *draw_funcs, void *draw_data) 431 { 432 klass->get.f.draw_glyph (this, user_data, 433 glyph, 434 draw_funcs, draw_data, 435 !klass->user_data ? nullptr : klass->user_data->draw_glyph); 436 } 437 paint_glyphhb_font_t438 void paint_glyph (hb_codepoint_t glyph, 439 hb_paint_funcs_t *paint_funcs, void *paint_data, 440 unsigned int palette, 441 hb_color_t foreground) 442 { 443 klass->get.f.paint_glyph (this, user_data, 444 glyph, 445 paint_funcs, paint_data, 446 palette, foreground, 447 !klass->user_data ? nullptr : klass->user_data->paint_glyph); 448 } 449 450 /* A bit higher-level, and with fallback */ 451 get_h_extents_with_fallbackhb_font_t452 void get_h_extents_with_fallback (hb_font_extents_t *extents) 453 { 454 if (!get_font_h_extents (extents)) 455 { 456 extents->ascender = y_scale * .8; 457 extents->descender = extents->ascender - y_scale; 458 extents->line_gap = 0; 459 } 460 } get_v_extents_with_fallbackhb_font_t461 void get_v_extents_with_fallback (hb_font_extents_t *extents) 462 { 463 if (!get_font_v_extents (extents)) 464 { 465 extents->ascender = x_scale / 2; 466 extents->descender = extents->ascender - x_scale; 467 extents->line_gap = 0; 468 } 469 } 470 get_extents_for_directionhb_font_t471 void get_extents_for_direction (hb_direction_t direction, 472 hb_font_extents_t *extents) 473 { 474 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 475 get_h_extents_with_fallback (extents); 476 else 477 get_v_extents_with_fallback (extents); 478 } 479 get_glyph_advance_for_directionhb_font_t480 void get_glyph_advance_for_direction (hb_codepoint_t glyph, 481 hb_direction_t direction, 482 hb_position_t *x, hb_position_t *y) 483 { 484 *x = *y = 0; 485 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 486 *x = get_glyph_h_advance (glyph); 487 else 488 *y = get_glyph_v_advance (glyph); 489 } get_glyph_advances_for_directionhb_font_t490 void get_glyph_advances_for_direction (hb_direction_t direction, 491 unsigned int count, 492 const hb_codepoint_t *first_glyph, 493 unsigned glyph_stride, 494 hb_position_t *first_advance, 495 unsigned advance_stride) 496 { 497 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 498 get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 499 else 500 get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride); 501 } 502 guess_v_origin_minus_h_originhb_font_t503 void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 504 hb_position_t *x, hb_position_t *y) 505 { 506 *x = get_glyph_h_advance (glyph) / 2; 507 508 hb_font_extents_t extents; 509 get_h_extents_with_fallback (&extents); 510 *y = extents.ascender; 511 } 512 get_glyph_h_origin_with_fallbackhb_font_t513 void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, 514 hb_position_t *x, hb_position_t *y) 515 { 516 if (!get_glyph_h_origin (glyph, x, y) && 517 get_glyph_v_origin (glyph, x, y)) 518 { 519 hb_position_t dx, dy; 520 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 521 *x -= dx; *y -= dy; 522 } 523 } get_glyph_v_origin_with_fallbackhb_font_t524 void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, 525 hb_position_t *x, hb_position_t *y) 526 { 527 if (!get_glyph_v_origin (glyph, x, y) && 528 get_glyph_h_origin (glyph, x, y)) 529 { 530 hb_position_t dx, dy; 531 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 532 *x += dx; *y += dy; 533 } 534 } 535 get_glyph_origin_for_directionhb_font_t536 void get_glyph_origin_for_direction (hb_codepoint_t glyph, 537 hb_direction_t direction, 538 hb_position_t *x, hb_position_t *y) 539 { 540 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 541 get_glyph_h_origin_with_fallback (glyph, x, y); 542 else 543 get_glyph_v_origin_with_fallback (glyph, x, y); 544 } 545 add_glyph_h_originhb_font_t546 void add_glyph_h_origin (hb_codepoint_t glyph, 547 hb_position_t *x, hb_position_t *y) 548 { 549 hb_position_t origin_x, origin_y; 550 551 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 552 553 *x += origin_x; 554 *y += origin_y; 555 } add_glyph_v_originhb_font_t556 void add_glyph_v_origin (hb_codepoint_t glyph, 557 hb_position_t *x, hb_position_t *y) 558 { 559 hb_position_t origin_x, origin_y; 560 561 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 562 563 *x += origin_x; 564 *y += origin_y; 565 } add_glyph_origin_for_directionhb_font_t566 void add_glyph_origin_for_direction (hb_codepoint_t glyph, 567 hb_direction_t direction, 568 hb_position_t *x, hb_position_t *y) 569 { 570 hb_position_t origin_x, origin_y; 571 572 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 573 574 *x += origin_x; 575 *y += origin_y; 576 } 577 subtract_glyph_h_originhb_font_t578 void subtract_glyph_h_origin (hb_codepoint_t glyph, 579 hb_position_t *x, hb_position_t *y) 580 { 581 hb_position_t origin_x, origin_y; 582 583 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 584 585 *x -= origin_x; 586 *y -= origin_y; 587 } subtract_glyph_v_originhb_font_t588 void subtract_glyph_v_origin (hb_codepoint_t glyph, 589 hb_position_t *x, hb_position_t *y) 590 { 591 hb_position_t origin_x, origin_y; 592 593 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 594 595 *x -= origin_x; 596 *y -= origin_y; 597 } subtract_glyph_origin_for_directionhb_font_t598 void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 599 hb_direction_t direction, 600 hb_position_t *x, hb_position_t *y) 601 { 602 hb_position_t origin_x, origin_y; 603 604 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 605 606 *x -= origin_x; 607 *y -= origin_y; 608 } 609 get_glyph_kerning_for_directionhb_font_t610 void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 611 hb_direction_t direction, 612 hb_position_t *x, hb_position_t *y) 613 { 614 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 615 *y = 0; 616 *x = get_glyph_h_kerning (first_glyph, second_glyph); 617 } else { 618 *x = 0; 619 *y = get_glyph_v_kerning (first_glyph, second_glyph); 620 } 621 } 622 get_glyph_extents_for_originhb_font_t623 hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 624 hb_direction_t direction, 625 hb_glyph_extents_t *extents) 626 { 627 hb_bool_t ret = get_glyph_extents (glyph, extents); 628 629 if (ret) 630 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 631 632 return ret; 633 } 634 get_glyph_contour_point_for_originhb_font_t635 hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 636 hb_direction_t direction, 637 hb_position_t *x, hb_position_t *y) 638 { 639 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 640 641 if (ret) 642 subtract_glyph_origin_for_direction (glyph, direction, x, y); 643 644 return ret; 645 } 646 647 /* Generates gidDDD if glyph has no name. */ 648 void glyph_to_stringhb_font_t649 glyph_to_string (hb_codepoint_t glyph, 650 char *s, unsigned int size) 651 { 652 if (get_glyph_name (glyph, s, size)) return; 653 654 if (size && snprintf (s, size, "gid%" PRIu32, glyph) < 0) 655 *s = '\0'; 656 } 657 658 /* Parses gidDDD and uniUUUU strings automatically. */ 659 hb_bool_t glyph_from_stringhb_font_t660 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 661 hb_codepoint_t *glyph) 662 { 663 if (get_glyph_from_name (s, len, glyph)) return true; 664 665 if (len == -1) len = strlen (s); 666 667 /* Straight glyph index. */ 668 if (hb_codepoint_parse (s, len, 10, glyph)) 669 return true; 670 671 if (len > 3) 672 { 673 /* gidDDD syntax for glyph indices. */ 674 if (0 == strncmp (s, "gid", 3) && 675 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 676 return true; 677 678 /* uniUUUU and other Unicode character indices. */ 679 hb_codepoint_t unichar; 680 if (0 == strncmp (s, "uni", 3) && 681 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 682 get_nominal_glyph (unichar, glyph)) 683 return true; 684 } 685 686 return false; 687 } 688 mults_changedhb_font_t689 void mults_changed () 690 { 691 float upem = face->get_upem (); 692 693 x_multf = x_scale / upem; 694 y_multf = y_scale / upem; 695 bool x_neg = x_scale < 0; 696 x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem; 697 bool y_neg = y_scale < 0; 698 y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem; 699 700 x_strength = fabsf (roundf (x_scale * x_embolden)); 701 y_strength = fabsf (roundf (y_scale * y_embolden)); 702 703 slant_xy = y_scale ? slant * x_scale / y_scale : 0.f; 704 705 data.fini (); 706 } 707 em_multhb_font_t708 hb_position_t em_mult (int16_t v, int64_t mult) 709 { return (hb_position_t) ((v * mult + 32768) >> 16); } em_multfhb_font_t710 hb_position_t em_multf (float v, float mult) 711 { return (hb_position_t) roundf (em_fmultf (v, mult)); } em_fmultfhb_font_t712 float em_fmultf (float v, float mult) 713 { return v * mult; } em_fmulthb_font_t714 float em_fmult (int16_t v, float mult) 715 { return (float) v * mult; } 716 }; 717 DECLARE_NULL_INSTANCE (hb_font_t); 718 719 720 #endif /* HB_FONT_HH */ 721