1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 /* 31 * Copyright © 2009 Red Hat, Inc. 32 * Copyright © 2011 Google, Inc. 33 * 34 * This is part of HarfBuzz, a text shaping library. 35 * 36 * Permission is hereby granted, without written agreement and without 37 * license or royalty fees, to use, copy, modify, and distribute this 38 * software and its documentation for any purpose, provided that the 39 * above copyright notice and the following two paragraphs appear in 40 * all copies of this software. 41 * 42 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 43 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 44 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 45 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 46 * DAMAGE. 47 * 48 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 49 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 50 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 51 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 52 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 53 * 54 * Red Hat Author(s): Behdad Esfahbod 55 * Google Author(s): Behdad Esfahbod 56 */ 57 58 #ifndef HB_FONT_PRIVATE_HH 59 #define HB_FONT_PRIVATE_HH 60 61 #include "hb-private.hh" 62 63 #include "hb-object-private.hh" 64 #include "hb-face-private.hh" 65 #include "hb-shaper-private.hh" 66 67 68 69 /* 70 * hb_font_funcs_t 71 */ 72 73 #define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 74 HB_FONT_FUNC_IMPLEMENT (glyph) \ 75 HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ 76 HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ 77 HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ 78 HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ 79 HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ 80 HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ 81 HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ 82 HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ 83 HB_FONT_FUNC_IMPLEMENT (glyph_name) \ 84 HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ 85 /* ^--- Add new callbacks here */ 86 87 struct hb_font_funcs_t { 88 hb_object_header_t header; 89 ASSERT_POD (); 90 91 hb_bool_t immutable; 92 93 /* Don't access these directly. Call hb_font_get_*() instead. */ 94 95 struct { 96 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; 97 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 98 #undef HB_FONT_FUNC_IMPLEMENT 99 } get; 100 101 struct { 102 #define HB_FONT_FUNC_IMPLEMENT(name) void *name; 103 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 104 #undef HB_FONT_FUNC_IMPLEMENT 105 } user_data; 106 107 struct { 108 #define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 109 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 110 #undef HB_FONT_FUNC_IMPLEMENT 111 } destroy; 112 }; 113 114 115 116 /* 117 * hb_font_t 118 */ 119 120 struct hb_font_t { 121 hb_object_header_t header; 122 ASSERT_POD (); 123 124 hb_bool_t immutable; 125 126 hb_font_t *parent; 127 hb_face_t *face; 128 129 int x_scale; 130 int y_scale; 131 132 unsigned int x_ppem; 133 unsigned int y_ppem; 134 135 hb_font_funcs_t *klass; 136 void *user_data; 137 hb_destroy_func_t destroy; 138 139 struct hb_shaper_data_t shaper_data; 140 141 142 /* Convert from font-space to user-space */ 143 inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } 144 inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } 145 146 /* Convert from parent-font user-space to our user-space */ 147 inline hb_position_t parent_scale_x_distance (hb_position_t v) { 148 if (unlikely (parent && parent->x_scale != x_scale)) 149 return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 150 return v; 151 } 152 inline hb_position_t parent_scale_y_distance (hb_position_t v) { 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 } 157 inline hb_position_t parent_scale_x_position (hb_position_t v) { 158 return parent_scale_x_distance (v); 159 } 160 inline hb_position_t parent_scale_y_position (hb_position_t v) { 161 return parent_scale_y_distance (v); 162 } 163 164 inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) { 165 *x = parent_scale_x_distance (*x); 166 *y = parent_scale_y_distance (*y); 167 } 168 inline void parent_scale_position (hb_position_t *x, hb_position_t *y) { 169 *x = parent_scale_x_position (*x); 170 *y = parent_scale_y_position (*y); 171 } 172 173 174 /* Public getters */ 175 176 inline hb_bool_t has_glyph (hb_codepoint_t unicode) 177 { 178 hb_codepoint_t glyph; 179 return get_glyph (unicode, 0, &glyph); 180 } 181 182 inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 183 hb_codepoint_t *glyph) 184 { 185 *glyph = 0; 186 return klass->get.glyph (this, user_data, 187 unicode, variation_selector, glyph, 188 klass->user_data.glyph); 189 } 190 191 inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 192 { 193 return klass->get.glyph_h_advance (this, user_data, 194 glyph, 195 klass->user_data.glyph_h_advance); 196 } 197 198 inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 199 { 200 return klass->get.glyph_v_advance (this, user_data, 201 glyph, 202 klass->user_data.glyph_v_advance); 203 } 204 205 inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 206 hb_position_t *x, hb_position_t *y) 207 { 208 *x = *y = 0; 209 return klass->get.glyph_h_origin (this, user_data, 210 glyph, x, y, 211 klass->user_data.glyph_h_origin); 212 } 213 214 inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 215 hb_position_t *x, hb_position_t *y) 216 { 217 *x = *y = 0; 218 return klass->get.glyph_v_origin (this, user_data, 219 glyph, x, y, 220 klass->user_data.glyph_v_origin); 221 } 222 223 inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 224 { 225 return klass->get.glyph_h_kerning (this, user_data, 226 left_glyph, right_glyph, 227 klass->user_data.glyph_h_kerning); 228 } 229 230 inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) 231 { 232 return klass->get.glyph_v_kerning (this, user_data, 233 top_glyph, bottom_glyph, 234 klass->user_data.glyph_v_kerning); 235 } 236 237 inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 238 hb_glyph_extents_t *extents) 239 { 240 memset (extents, 0, sizeof (*extents)); 241 return klass->get.glyph_extents (this, user_data, 242 glyph, 243 extents, 244 klass->user_data.glyph_extents); 245 } 246 247 inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 248 hb_position_t *x, hb_position_t *y) 249 { 250 *x = *y = 0; 251 return klass->get.glyph_contour_point (this, user_data, 252 glyph, point_index, 253 x, y, 254 klass->user_data.glyph_contour_point); 255 } 256 257 inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, 258 char *name, unsigned int size) 259 { 260 if (size) *name = '\0'; 261 return klass->get.glyph_name (this, user_data, 262 glyph, 263 name, size, 264 klass->user_data.glyph_name); 265 } 266 267 inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 268 hb_codepoint_t *glyph) 269 { 270 *glyph = 0; 271 if (len == -1) len = strlen (name); 272 return klass->get.glyph_from_name (this, user_data, 273 name, len, 274 glyph, 275 klass->user_data.glyph_from_name); 276 } 277 278 279 /* A bit higher-level, and with fallback */ 280 281 inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, 282 hb_direction_t direction, 283 hb_position_t *x, hb_position_t *y) 284 { 285 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 286 *x = get_glyph_h_advance (glyph); 287 *y = 0; 288 } else { 289 *x = 0; 290 *y = get_glyph_v_advance (glyph); 291 } 292 } 293 294 /* Internal only */ 295 inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 296 hb_position_t *x, hb_position_t *y) 297 { 298 *x = get_glyph_h_advance (glyph) / 2; 299 300 /* TODO use font_metrics.ascent */ 301 *y = y_scale; 302 } 303 304 inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, 305 hb_direction_t direction, 306 hb_position_t *x, hb_position_t *y) 307 { 308 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 309 { 310 if (!get_glyph_h_origin (glyph, x, y) && 311 get_glyph_v_origin (glyph, x, y)) 312 { 313 hb_position_t dx, dy; 314 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 315 *x -= dx; *y -= dy; 316 } 317 } 318 else 319 { 320 if (!get_glyph_v_origin (glyph, x, y) && 321 get_glyph_h_origin (glyph, x, y)) 322 { 323 hb_position_t dx, dy; 324 guess_v_origin_minus_h_origin (glyph, &dx, &dy); 325 *x += dx; *y += dy; 326 } 327 } 328 } 329 330 inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, 331 hb_direction_t direction, 332 hb_position_t *x, hb_position_t *y) 333 { 334 hb_position_t origin_x, origin_y; 335 336 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 337 338 *x += origin_x; 339 *y += origin_y; 340 } 341 342 inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 343 hb_direction_t direction, 344 hb_position_t *x, hb_position_t *y) 345 { 346 hb_position_t origin_x, origin_y; 347 348 get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 349 350 *x -= origin_x; 351 *y -= origin_y; 352 } 353 354 inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 355 hb_direction_t direction, 356 hb_position_t *x, hb_position_t *y) 357 { 358 if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 359 *x = get_glyph_h_kerning (first_glyph, second_glyph); 360 *y = 0; 361 } else { 362 *x = 0; 363 *y = get_glyph_v_kerning (first_glyph, second_glyph); 364 } 365 } 366 367 inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 368 hb_direction_t direction, 369 hb_glyph_extents_t *extents) 370 { 371 hb_bool_t ret = get_glyph_extents (glyph, extents); 372 373 if (ret) 374 subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 375 376 return ret; 377 } 378 379 inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 380 hb_direction_t direction, 381 hb_position_t *x, hb_position_t *y) 382 { 383 hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 384 385 if (ret) 386 subtract_glyph_origin_for_direction (glyph, direction, x, y); 387 388 return ret; 389 } 390 391 /* Generates gidDDD if glyph has no name. */ 392 inline void 393 glyph_to_string (hb_codepoint_t glyph, 394 char *s, unsigned int size) 395 { 396 if (get_glyph_name (glyph, s, size)) return; 397 398 if (size && snprintf (s, size, "gid%u", glyph) < 0) 399 *s = '\0'; 400 } 401 402 /* Parses gidDDD and uniUUUU strings automatically. */ 403 inline hb_bool_t 404 glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 405 hb_codepoint_t *glyph) 406 { 407 if (get_glyph_from_name (s, len, glyph)) return true; 408 409 if (len == -1) len = strlen (s); 410 411 /* Straight glyph index. */ 412 if (hb_codepoint_parse (s, len, 10, glyph)) 413 return true; 414 415 if (len > 3) 416 { 417 /* gidDDD syntax for glyph indices. */ 418 if (0 == strncmp (s, "gid", 3) && 419 hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 420 return true; 421 422 /* uniUUUU and other Unicode character indices. */ 423 hb_codepoint_t unichar; 424 if (0 == strncmp (s, "uni", 3) && 425 hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 426 get_glyph (unichar, 0, glyph)) 427 return true; 428 } 429 430 return false; 431 } 432 433 private: 434 inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); } 435 }; 436 437 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 438 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); 439 #include "hb-shaper-list.hh" 440 #undef HB_SHAPER_IMPLEMENT 441 #undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 442 443 444 #endif /* HB_FONT_PRIVATE_HH */