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-font.h" 35 #include "hb-object-private.hh" 36 #include "hb-shaper-private.hh" 37 #include "hb-shape-plan-private.hh" 38 39 40 41 /* 42 * hb_font_funcs_t 43 */ 44 45 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 46 HB_FONT_FUNC_IMPLEMENT (glyph) \ 47 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ 48 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ 49 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ 50 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ 51 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ 52 HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ 53 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ 54 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ 55 HB_FONT_FUNC_IMPLEMENT (glyph_name) \ 56 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ 57 /* ^--- Add new callbacks here */ 58 59 struct hb_font_funcs_t { 60 hb_object_header_t header; 61 ASSERT_POD (); 62 63 hb_bool_t immutable; 64 65 /* Don't access these directly. Call hb_font_get_*() instead. */ 66 67 struct { 68 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; 69 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 70 #undef HB_FONT_FUNC_IMPLEMENT 71 } get; 72 73 struct { 74 #define HB_FONT_FUNC_IMPLEMENT(name) void *name; 75 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 76 #undef HB_FONT_FUNC_IMPLEMENT 77 } user_data; 78 79 struct { 80 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 81 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 82 #undef HB_FONT_FUNC_IMPLEMENT 83 } destroy; 84 }; 85 86 87 /* 88 * hb_face_t 89 */ 90 91 struct hb_face_t { 92 hb_object_header_t header; 93 ASSERT_POD (); 94 95 hb_bool_t immutable; 96 97 hb_reference_table_func_t reference_table_func; 98 void *user_data; 99 hb_destroy_func_t destroy; 100 101 unsigned int index; 102 mutable unsigned int upem; 103 mutable unsigned int num_glyphs; 104 105 struct hb_shaper_data_t shaper_data; 106 107 struct plan_node_t { 108 hb_shape_plan_t *shape_plan; 109 plan_node_t *next; 110 } *shape_plans; 111 112 113 inline hb_blob_t *reference_table (hb_tag_t tag) const 114 { 115 hb_blob_t *blob; 116 117 if (unlikely (!this || !reference_table_func)) 118 return hb_blob_get_empty (); 119 120 blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data); 121 if (unlikely (!blob)) 122 return hb_blob_get_empty (); 123 124 return blob; 125 } 126 127 inline unsigned int get_upem (void) const 128 { 129 if (unlikely (!upem)) 130 load_upem (); 131 return upem; 132 } 133 134 inline unsigned int get_num_glyphs (void) const 135 { 136 if (unlikely (num_glyphs == (unsigned int) -1)) 137 load_num_glyphs (); 138 return num_glyphs; 139 } 140 141 private: 142 HB_INTERNAL void load_upem (void) const; 143 HB_INTERNAL void load_num_glyphs (void) const; 144 }; 145 146 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 147 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face); 148 #include "hb-shaper-list.hh" 149 #undef HB_SHAPER_IMPLEMENT 150 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 151 152 153 /* 154 * hb_font_t 155 */ 156 157 struct hb_font_t { 158 hb_object_header_t header; 159 ASSERT_POD (); 160 161 hb_bool_t immutable; 162 163 hb_font_t *parent; 164 hb_face_t *face; 165 166 int x_scale; 167 int y_scale; 168 169 unsigned int x_ppem; 170 unsigned int y_ppem; 171 172 hb_font_funcs_t *klass; 173 void *user_data; 174 hb_destroy_func_t destroy; 175 176 struct hb_shaper_data_t shaper_data; 177 178 179 /* Convert from font-space to user-space */ 180 inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } 181 inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } 182 183 /* Convert from parent-font user-space to our user-space */ 184 inline hb_position_t parent_scale_x_distance (hb_position_t v) { 185 if (unlikely (parent && parent->x_scale != x_scale)) 186 return v * (int64_t) this->x_scale / this->parent->x_scale; 187 return v; 188 } 189 inline hb_position_t parent_scale_y_distance (hb_position_t v) { 190 if (unlikely (parent && parent->y_scale != y_scale)) 191 return v * (int64_t) this->y_scale / this->parent->y_scale; 192 return v; 193 } 194 inline hb_position_t parent_scale_x_position (hb_position_t v) { 195 return parent_scale_x_distance (v); 196 } 197 inline hb_position_t parent_scale_y_position (hb_position_t v) { 198 return parent_scale_y_distance (v); 199 } 200 201 inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) { 202 *x = parent_scale_x_distance (*x); 203 *y = parent_scale_y_distance (*y); 204 } 205 inline void parent_scale_position (hb_position_t *x, hb_position_t *y) { 206 *x = parent_scale_x_position (*x); 207 *y = parent_scale_y_position (*y); 208 } 209 210 211 /* Public getters */ 212 213 inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 214 hb_codepoint_t *glyph) 215 { 216 *glyph = 0; 217 return klass->get.glyph (this, user_data, 218 unicode, variation_selector, glyph, 219 klass->user_data.glyph); 220 } 221 222 inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 223 { 224 return klass->get.glyph_h_advance (this, user_data, 225 glyph, 226 klass->user_data.glyph_h_advance); 227 } 228 229 inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 230 { 231 return klass->get.glyph_v_advance (this, user_data, 232 glyph, 233 klass->user_data.glyph_v_advance); 234 } 235 236 inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 237 hb_position_t *x, hb_position_t *y) 238 { 239 *x = *y = 0; 240 return klass->get.glyph_h_origin (this, user_data, 241 glyph, x, y, 242 klass->user_data.glyph_h_origin); 243 } 244 245 inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 246 hb_position_t *x, hb_position_t *y) 247 { 248 *x = *y = 0; 249 return klass->get.glyph_v_origin (this, user_data, 250 glyph, x, y, 251 klass->user_data.glyph_v_origin); 252 } 253 254 inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 255 { 256 return klass->get.glyph_h_kerning (this, user_data, 257 left_glyph, right_glyph, 258 klass->user_data.glyph_h_kerning); 259 } 260 261 inline hb_position_t get_glyph_v_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 262 { 263 return klass->get.glyph_v_kerning (this, user_data, 264 left_glyph, right_glyph, 265 klass->user_data.glyph_v_kerning); 266 } 267 268 inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 269 hb_glyph_extents_t *extents) 270 { 271 memset (extents, 0, sizeof (*extents)); 272 return klass->get.glyph_extents (this, user_data, 273 glyph, 274 extents, 275 klass->user_data.glyph_extents); 276 } 277 278 inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 279 hb_position_t *x, hb_position_t *y) 280 { 281 *x = *y = 0; 282 return klass->get.glyph_contour_point (this, user_data, 283 glyph, point_index, 284 x, y, 285 klass->user_data.glyph_contour_point); 286 } 287 288 inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, 289 char *name, unsigned int size) 290 { 291 if (size) *name = '\0'; 292 return klass->get.glyph_name (this, user_data, 293 glyph, 294 name, size, 295 klass->user_data.glyph_name); 296 } 297 298 inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 299 hb_codepoint_t *glyph) 300 { 301 *glyph = 0; 302 if (len == -1) len = strlen (name); 303 return klass->get.glyph_from_name (this, user_data, 304 name, len, 305 glyph, 306 klass->user_data.glyph_from_name); 307 } 308 309 310 /* A bit higher-level, and with fallback */ 311 312 inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, 313 hb_direction_t direction, 314 hb_position_t *x, hb_position_t *y) 315 { 316 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 317 *x = get_glyph_h_advance (glyph); 318 *y = 0; 319 } else { 320 *x = 0; 321 *y = get_glyph_v_advance (glyph); 322 } 323 } 324 325 /* Internal only */ 326 inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 327 hb_position_t *x, hb_position_t *y) 328 { 329 *x = get_glyph_h_advance (glyph) / 2; 330 331 /* TODO use font_metics.ascent */ 332 *y = y_scale; 333 } 334 335 inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, 336 hb_direction_t direction, 337 hb_position_t *x, hb_position_t *y) 338 { 339 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 340 hb_bool_t ret = get_glyph_h_origin (glyph, x, y); 341 if (!ret && (ret = get_glyph_v_origin (glyph, x, y))) { 342 hb_position_t dx, dy; 343 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 344 *x -= dx; *y -= dy; 345 } 346 } else { 347 hb_bool_t ret = get_glyph_v_origin (glyph, x, y); 348 if (!ret && (ret = get_glyph_h_origin (glyph, x, y))) { 349 hb_position_t dx, dy; 350 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 351 *x += dx; *y += dy; 352 } 353 } 354 } 355 356 inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, 357 hb_direction_t direction, 358 hb_position_t *x, hb_position_t *y) 359 { 360 hb_position_t origin_x, origin_y; 361 362 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 363 364 *x += origin_x; 365 *y += origin_y; 366 } 367 368 inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 369 hb_direction_t direction, 370 hb_position_t *x, hb_position_t *y) 371 { 372 hb_position_t origin_x, origin_y; 373 374 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 375 376 *x -= origin_x; 377 *y -= origin_y; 378 } 379 380 inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_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 *x = get_glyph_h_kerning (first_glyph, second_glyph); 386 *y = 0; 387 } else { 388 *x = 0; 389 *y = get_glyph_v_kerning (first_glyph, second_glyph); 390 } 391 } 392 393 inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 394 hb_direction_t direction, 395 hb_glyph_extents_t *extents) 396 { 397 hb_bool_t ret = get_glyph_extents (glyph, extents); 398 399 if (ret) 400 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 401 402 return ret; 403 } 404 405 inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 406 hb_direction_t direction, 407 hb_position_t *x, hb_position_t *y) 408 { 409 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 410 411 if (ret) 412 subtract_glyph_origin_for_direction (glyph, direction, x, y); 413 414 return ret; 415 } 416 417 /* Generates gidDDD if glyph has no name. */ 418 inline void 419 glyph_to_string (hb_codepoint_t glyph, 420 char *s, unsigned int size) 421 { 422 if (get_glyph_name (glyph, s, size)) return; 423 424 snprintf (s, size, "gid%u", glyph); 425 } 426 427 /* Parses gidDDD and uniUUUU strings automatically. */ 428 inline hb_bool_t 429 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 430 hb_codepoint_t *glyph) 431 { 432 if (get_glyph_from_name (s, len, glyph)) return true; 433 434 if (len == -1) len = strlen (s); 435 436 /* Straight glyph index. */ 437 if (hb_codepoint_parse (s, len, 10, glyph)) 438 return true; 439 440 if (len > 3) 441 { 442 /* gidDDD syntax for glyph indices. */ 443 if (0 == strncmp (s, "gid", 3) && 444 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 445 return true; 446 447 /* uniUUUU and other Unicode character indices. */ 448 hb_codepoint_t unichar; 449 if (0 == strncmp (s, "uni", 3) && 450 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 451 get_glyph (unichar, 0, glyph)) 452 return true; 453 } 454 455 return false; 456 } 457 458 private: 459 inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); } 460 }; 461 462 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 463 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); 464 #include "hb-shaper-list.hh" 465 #undef HB_SHAPER_IMPLEMENT 466 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 467 468 469 #endif /* HB_FONT_PRIVATE_HH */ 470