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_PRIVATE_HH 30 #define HB_FONT_PRIVATE_HH 31 32 #include "hb-private.hh" 33 34 #include "hb-object-private.hh" 35 #include "hb-face-private.hh" 36 #include "hb-shaper-private.hh" 37 38 39 40 /* 41 * hb_font_funcs_t 42 */ 43 44 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 45 HB_FONT_FUNC_IMPLEMENT (font_h_extents) \ 46 HB_FONT_FUNC_IMPLEMENT (font_v_extents) \ 47 HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \ 48 HB_FONT_FUNC_IMPLEMENT (variation_glyph) \ 49 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ 50 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ 51 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ 52 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ 53 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ 54 HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ 55 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ 56 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ 57 HB_FONT_FUNC_IMPLEMENT (glyph_name) \ 58 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ 59 /* ^--- Add new callbacks here */ 60 61 struct hb_font_funcs_t { 62 hb_object_header_t header; 63 ASSERT_POD (); 64 65 hb_bool_t immutable; 66 67 struct { 68 #define HB_FONT_FUNC_IMPLEMENT(name) void *name; 69 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 70 #undef HB_FONT_FUNC_IMPLEMENT 71 } user_data; 72 73 struct { 74 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 75 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 76 #undef HB_FONT_FUNC_IMPLEMENT 77 } destroy; 78 79 /* Don't access these directly. Call font->get_*() instead. */ 80 union get_t { 81 struct get_funcs_t { 82 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; 83 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 84 #undef HB_FONT_FUNC_IMPLEMENT 85 } f; 86 void (*array[VAR]) (void); 87 } get; 88 }; 89 90 91 92 /* 93 * hb_font_t 94 */ 95 96 struct hb_font_t { 97 hb_object_header_t header; 98 ASSERT_POD (); 99 100 hb_bool_t immutable; 101 102 hb_font_t *parent; 103 hb_face_t *face; 104 105 int x_scale; 106 int y_scale; 107 108 unsigned int x_ppem; 109 unsigned int y_ppem; 110 111 /* Font variation coordinates. */ 112 unsigned int num_coords; 113 int *coords; 114 115 hb_font_funcs_t *klass; 116 void *user_data; 117 hb_destroy_func_t destroy; 118 119 struct hb_shaper_data_t shaper_data; 120 121 122 /* Convert from font-space to user-space */ 123 inline int dir_scale (hb_direction_t direction) 124 { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; } 125 inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); } 126 inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); } 127 inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); } 128 inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); } 129 inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction) 130 { return em_scale (v, dir_scale (direction)); } 131 132 /* Convert from parent-font user-space to our user-space */ 133 inline hb_position_t parent_scale_x_distance (hb_position_t v) { 134 if (unlikely (parent && parent->x_scale != x_scale)) 135 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 136 return v; 137 } 138 inline hb_position_t parent_scale_y_distance (hb_position_t v) { 139 if (unlikely (parent && parent->y_scale != y_scale)) 140 return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 141 return v; 142 } 143 inline hb_position_t parent_scale_x_position (hb_position_t v) { 144 return parent_scale_x_distance (v); 145 } 146 inline hb_position_t parent_scale_y_position (hb_position_t v) { 147 return parent_scale_y_distance (v); 148 } 149 150 inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) { 151 *x = parent_scale_x_distance (*x); 152 *y = parent_scale_y_distance (*y); 153 } 154 inline void parent_scale_position (hb_position_t *x, hb_position_t *y) { 155 *x = parent_scale_x_position (*x); 156 *y = parent_scale_y_position (*y); 157 } 158 159 160 /* Public getters */ 161 162 HB_INTERNAL bool has_func (unsigned int i); 163 164 /* has_* ... */ 165 #define HB_FONT_FUNC_IMPLEMENT(name) \ 166 bool \ 167 has_##name##_func (void) \ 168 { \ 169 hb_font_funcs_t *funcs = this->klass; \ 170 unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ 171 return has_func (i); \ 172 } 173 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 174 #undef HB_FONT_FUNC_IMPLEMENT 175 176 inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents) 177 { 178 memset (extents, 0, sizeof (*extents)); 179 return klass->get.f.font_h_extents (this, user_data, 180 extents, 181 klass->user_data.font_h_extents); 182 } 183 inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents) 184 { 185 memset (extents, 0, sizeof (*extents)); 186 return klass->get.f.font_v_extents (this, user_data, 187 extents, 188 klass->user_data.font_v_extents); 189 } 190 191 inline bool has_glyph (hb_codepoint_t unicode) 192 { 193 hb_codepoint_t glyph; 194 return get_nominal_glyph (unicode, &glyph); 195 } 196 197 inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode, 198 hb_codepoint_t *glyph) 199 { 200 *glyph = 0; 201 return klass->get.f.nominal_glyph (this, user_data, 202 unicode, glyph, 203 klass->user_data.nominal_glyph); 204 } 205 206 inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 207 hb_codepoint_t *glyph) 208 { 209 *glyph = 0; 210 return klass->get.f.variation_glyph (this, user_data, 211 unicode, variation_selector, glyph, 212 klass->user_data.variation_glyph); 213 } 214 215 inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 216 { 217 return klass->get.f.glyph_h_advance (this, user_data, 218 glyph, 219 klass->user_data.glyph_h_advance); 220 } 221 222 inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 223 { 224 return klass->get.f.glyph_v_advance (this, user_data, 225 glyph, 226 klass->user_data.glyph_v_advance); 227 } 228 229 inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 230 hb_position_t *x, hb_position_t *y) 231 { 232 *x = *y = 0; 233 return klass->get.f.glyph_h_origin (this, user_data, 234 glyph, x, y, 235 klass->user_data.glyph_h_origin); 236 } 237 238 inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 239 hb_position_t *x, hb_position_t *y) 240 { 241 *x = *y = 0; 242 return klass->get.f.glyph_v_origin (this, user_data, 243 glyph, x, y, 244 klass->user_data.glyph_v_origin); 245 } 246 247 inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 248 { 249 return klass->get.f.glyph_h_kerning (this, user_data, 250 left_glyph, right_glyph, 251 klass->user_data.glyph_h_kerning); 252 } 253 254 inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) 255 { 256 return klass->get.f.glyph_v_kerning (this, user_data, 257 top_glyph, bottom_glyph, 258 klass->user_data.glyph_v_kerning); 259 } 260 261 inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 262 hb_glyph_extents_t *extents) 263 { 264 memset (extents, 0, sizeof (*extents)); 265 return klass->get.f.glyph_extents (this, user_data, 266 glyph, 267 extents, 268 klass->user_data.glyph_extents); 269 } 270 271 inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 272 hb_position_t *x, hb_position_t *y) 273 { 274 *x = *y = 0; 275 return klass->get.f.glyph_contour_point (this, user_data, 276 glyph, point_index, 277 x, y, 278 klass->user_data.glyph_contour_point); 279 } 280 281 inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, 282 char *name, unsigned int size) 283 { 284 if (size) *name = '\0'; 285 return klass->get.f.glyph_name (this, user_data, 286 glyph, 287 name, size, 288 klass->user_data.glyph_name); 289 } 290 291 inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 292 hb_codepoint_t *glyph) 293 { 294 *glyph = 0; 295 if (len == -1) len = strlen (name); 296 return klass->get.f.glyph_from_name (this, user_data, 297 name, len, 298 glyph, 299 klass->user_data.glyph_from_name); 300 } 301 302 303 /* A bit higher-level, and with fallback */ 304 305 inline void get_h_extents_with_fallback (hb_font_extents_t *extents) 306 { 307 if (!get_font_h_extents (extents)) 308 { 309 extents->ascender = y_scale * .8; 310 extents->descender = extents->ascender - y_scale; 311 extents->line_gap = 0; 312 } 313 } 314 inline void get_v_extents_with_fallback (hb_font_extents_t *extents) 315 { 316 if (!get_font_v_extents (extents)) 317 { 318 extents->ascender = x_scale / 2; 319 extents->descender = extents->ascender - x_scale; 320 extents->line_gap = 0; 321 } 322 } 323 324 inline void get_extents_for_direction (hb_direction_t direction, 325 hb_font_extents_t *extents) 326 { 327 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 328 get_h_extents_with_fallback (extents); 329 else 330 get_v_extents_with_fallback (extents); 331 } 332 333 inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, 334 hb_direction_t direction, 335 hb_position_t *x, hb_position_t *y) 336 { 337 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 338 *x = get_glyph_h_advance (glyph); 339 *y = 0; 340 } else { 341 *x = 0; 342 *y = get_glyph_v_advance (glyph); 343 } 344 } 345 346 inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 347 hb_position_t *x, hb_position_t *y) 348 { 349 *x = get_glyph_h_advance (glyph) / 2; 350 351 /* TODO cache this somehow?! */ 352 hb_font_extents_t extents; 353 get_h_extents_with_fallback (&extents); 354 *y = extents.ascender; 355 } 356 357 inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph, 358 hb_position_t *x, hb_position_t *y) 359 { 360 if (!get_glyph_h_origin (glyph, x, y) && 361 get_glyph_v_origin (glyph, x, y)) 362 { 363 hb_position_t dx, dy; 364 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 365 *x -= dx; *y -= dy; 366 } 367 } 368 inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph, 369 hb_position_t *x, hb_position_t *y) 370 { 371 if (!get_glyph_v_origin (glyph, x, y) && 372 get_glyph_h_origin (glyph, x, y)) 373 { 374 hb_position_t dx, dy; 375 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 376 *x += dx; *y += dy; 377 } 378 } 379 380 inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, 381 hb_direction_t direction, 382 hb_position_t *x, hb_position_t *y) 383 { 384 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 385 get_glyph_h_origin_with_fallback (glyph, x, y); 386 else 387 get_glyph_v_origin_with_fallback (glyph, x, y); 388 } 389 390 inline void add_glyph_h_origin (hb_codepoint_t glyph, 391 hb_position_t *x, hb_position_t *y) 392 { 393 hb_position_t origin_x, origin_y; 394 395 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 396 397 *x += origin_x; 398 *y += origin_y; 399 } 400 inline void add_glyph_v_origin (hb_codepoint_t glyph, 401 hb_position_t *x, hb_position_t *y) 402 { 403 hb_position_t origin_x, origin_y; 404 405 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 406 407 *x += origin_x; 408 *y += origin_y; 409 } 410 inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, 411 hb_direction_t direction, 412 hb_position_t *x, hb_position_t *y) 413 { 414 hb_position_t origin_x, origin_y; 415 416 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 417 418 *x += origin_x; 419 *y += origin_y; 420 } 421 422 inline void subtract_glyph_h_origin (hb_codepoint_t glyph, 423 hb_position_t *x, hb_position_t *y) 424 { 425 hb_position_t origin_x, origin_y; 426 427 get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y); 428 429 *x -= origin_x; 430 *y -= origin_y; 431 } 432 inline void subtract_glyph_v_origin (hb_codepoint_t glyph, 433 hb_position_t *x, hb_position_t *y) 434 { 435 hb_position_t origin_x, origin_y; 436 437 get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y); 438 439 *x -= origin_x; 440 *y -= origin_y; 441 } 442 inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 443 hb_direction_t direction, 444 hb_position_t *x, hb_position_t *y) 445 { 446 hb_position_t origin_x, origin_y; 447 448 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 449 450 *x -= origin_x; 451 *y -= origin_y; 452 } 453 454 inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 455 hb_direction_t direction, 456 hb_position_t *x, hb_position_t *y) 457 { 458 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 459 *x = get_glyph_h_kerning (first_glyph, second_glyph); 460 *y = 0; 461 } else { 462 *x = 0; 463 *y = get_glyph_v_kerning (first_glyph, second_glyph); 464 } 465 } 466 467 inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 468 hb_direction_t direction, 469 hb_glyph_extents_t *extents) 470 { 471 hb_bool_t ret = get_glyph_extents (glyph, extents); 472 473 if (ret) 474 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 475 476 return ret; 477 } 478 479 inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 480 hb_direction_t direction, 481 hb_position_t *x, hb_position_t *y) 482 { 483 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 484 485 if (ret) 486 subtract_glyph_origin_for_direction (glyph, direction, x, y); 487 488 return ret; 489 } 490 491 /* Generates gidDDD if glyph has no name. */ 492 inline void 493 glyph_to_string (hb_codepoint_t glyph, 494 char *s, unsigned int size) 495 { 496 if (get_glyph_name (glyph, s, size)) return; 497 498 if (size && snprintf (s, size, "gid%u", glyph) < 0) 499 *s = '\0'; 500 } 501 502 /* Parses gidDDD and uniUUUU strings automatically. */ 503 inline hb_bool_t 504 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 505 hb_codepoint_t *glyph) 506 { 507 if (get_glyph_from_name (s, len, glyph)) return true; 508 509 if (len == -1) len = strlen (s); 510 511 /* Straight glyph index. */ 512 if (hb_codepoint_parse (s, len, 10, glyph)) 513 return true; 514 515 if (len > 3) 516 { 517 /* gidDDD syntax for glyph indices. */ 518 if (0 == strncmp (s, "gid", 3) && 519 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 520 return true; 521 522 /* uniUUUU and other Unicode character indices. */ 523 hb_codepoint_t unichar; 524 if (0 == strncmp (s, "uni", 3) && 525 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 526 get_nominal_glyph (unichar, glyph)) 527 return true; 528 } 529 530 return false; 531 } 532 533 inline hb_position_t em_scale (int16_t v, int scale) 534 { 535 int upem = face->get_upem (); 536 int64_t scaled = v * (int64_t) scale; 537 scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */ 538 return (hb_position_t) (scaled / upem); 539 } 540 inline hb_position_t em_scalef (float v, int scale) 541 { 542 return (hb_position_t) (v * scale / face->get_upem ()); 543 } 544 }; 545 546 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 547 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); 548 #include "hb-shaper-list.hh" 549 #undef HB_SHAPER_IMPLEMENT 550 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 551 552 553 #endif /* HB_FONT_PRIVATE_HH */ 554