1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/harfbuzz/src/hb-font-private.hh Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,415 @@ 1.4 +/* 1.5 + * Copyright © 2009 Red Hat, Inc. 1.6 + * Copyright © 2011 Google, Inc. 1.7 + * 1.8 + * This is part of HarfBuzz, a text shaping library. 1.9 + * 1.10 + * Permission is hereby granted, without written agreement and without 1.11 + * license or royalty fees, to use, copy, modify, and distribute this 1.12 + * software and its documentation for any purpose, provided that the 1.13 + * above copyright notice and the following two paragraphs appear in 1.14 + * all copies of this software. 1.15 + * 1.16 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 1.17 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 1.18 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 1.19 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 1.20 + * DAMAGE. 1.21 + * 1.22 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 1.23 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 1.24 + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 1.25 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 1.26 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 1.27 + * 1.28 + * Red Hat Author(s): Behdad Esfahbod 1.29 + * Google Author(s): Behdad Esfahbod 1.30 + */ 1.31 + 1.32 +#ifndef HB_FONT_PRIVATE_HH 1.33 +#define HB_FONT_PRIVATE_HH 1.34 + 1.35 +#include "hb-private.hh" 1.36 + 1.37 +#include "hb-object-private.hh" 1.38 +#include "hb-face-private.hh" 1.39 +#include "hb-shaper-private.hh" 1.40 + 1.41 + 1.42 + 1.43 +/* 1.44 + * hb_font_funcs_t 1.45 + */ 1.46 + 1.47 +#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \ 1.48 + HB_FONT_FUNC_IMPLEMENT (glyph) \ 1.49 + HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \ 1.50 + HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \ 1.51 + HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \ 1.52 + HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \ 1.53 + HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \ 1.54 + HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \ 1.55 + HB_FONT_FUNC_IMPLEMENT (glyph_extents) \ 1.56 + HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \ 1.57 + HB_FONT_FUNC_IMPLEMENT (glyph_name) \ 1.58 + HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \ 1.59 + /* ^--- Add new callbacks here */ 1.60 + 1.61 +struct hb_font_funcs_t { 1.62 + hb_object_header_t header; 1.63 + ASSERT_POD (); 1.64 + 1.65 + hb_bool_t immutable; 1.66 + 1.67 + /* Don't access these directly. Call hb_font_get_*() instead. */ 1.68 + 1.69 + struct { 1.70 +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; 1.71 + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 1.72 +#undef HB_FONT_FUNC_IMPLEMENT 1.73 + } get; 1.74 + 1.75 + struct { 1.76 +#define HB_FONT_FUNC_IMPLEMENT(name) void *name; 1.77 + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 1.78 +#undef HB_FONT_FUNC_IMPLEMENT 1.79 + } user_data; 1.80 + 1.81 + struct { 1.82 +#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name; 1.83 + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS 1.84 +#undef HB_FONT_FUNC_IMPLEMENT 1.85 + } destroy; 1.86 +}; 1.87 + 1.88 + 1.89 + 1.90 +/* 1.91 + * hb_font_t 1.92 + */ 1.93 + 1.94 +struct hb_font_t { 1.95 + hb_object_header_t header; 1.96 + ASSERT_POD (); 1.97 + 1.98 + hb_bool_t immutable; 1.99 + 1.100 + hb_font_t *parent; 1.101 + hb_face_t *face; 1.102 + 1.103 + int x_scale; 1.104 + int y_scale; 1.105 + 1.106 + unsigned int x_ppem; 1.107 + unsigned int y_ppem; 1.108 + 1.109 + hb_font_funcs_t *klass; 1.110 + void *user_data; 1.111 + hb_destroy_func_t destroy; 1.112 + 1.113 + struct hb_shaper_data_t shaper_data; 1.114 + 1.115 + 1.116 + /* Convert from font-space to user-space */ 1.117 + inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); } 1.118 + inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); } 1.119 + 1.120 + /* Convert from parent-font user-space to our user-space */ 1.121 + inline hb_position_t parent_scale_x_distance (hb_position_t v) { 1.122 + if (unlikely (parent && parent->x_scale != x_scale)) 1.123 + return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale); 1.124 + return v; 1.125 + } 1.126 + inline hb_position_t parent_scale_y_distance (hb_position_t v) { 1.127 + if (unlikely (parent && parent->y_scale != y_scale)) 1.128 + return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale); 1.129 + return v; 1.130 + } 1.131 + inline hb_position_t parent_scale_x_position (hb_position_t v) { 1.132 + return parent_scale_x_distance (v); 1.133 + } 1.134 + inline hb_position_t parent_scale_y_position (hb_position_t v) { 1.135 + return parent_scale_y_distance (v); 1.136 + } 1.137 + 1.138 + inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) { 1.139 + *x = parent_scale_x_distance (*x); 1.140 + *y = parent_scale_y_distance (*y); 1.141 + } 1.142 + inline void parent_scale_position (hb_position_t *x, hb_position_t *y) { 1.143 + *x = parent_scale_x_position (*x); 1.144 + *y = parent_scale_y_position (*y); 1.145 + } 1.146 + 1.147 + 1.148 + /* Public getters */ 1.149 + 1.150 + inline hb_bool_t has_glyph (hb_codepoint_t unicode) 1.151 + { 1.152 + hb_codepoint_t glyph; 1.153 + return get_glyph (unicode, 0, &glyph); 1.154 + } 1.155 + 1.156 + inline hb_bool_t get_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector, 1.157 + hb_codepoint_t *glyph) 1.158 + { 1.159 + *glyph = 0; 1.160 + return klass->get.glyph (this, user_data, 1.161 + unicode, variation_selector, glyph, 1.162 + klass->user_data.glyph); 1.163 + } 1.164 + 1.165 + inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) 1.166 + { 1.167 + return klass->get.glyph_h_advance (this, user_data, 1.168 + glyph, 1.169 + klass->user_data.glyph_h_advance); 1.170 + } 1.171 + 1.172 + inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) 1.173 + { 1.174 + return klass->get.glyph_v_advance (this, user_data, 1.175 + glyph, 1.176 + klass->user_data.glyph_v_advance); 1.177 + } 1.178 + 1.179 + inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, 1.180 + hb_position_t *x, hb_position_t *y) 1.181 + { 1.182 + *x = *y = 0; 1.183 + return klass->get.glyph_h_origin (this, user_data, 1.184 + glyph, x, y, 1.185 + klass->user_data.glyph_h_origin); 1.186 + } 1.187 + 1.188 + inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, 1.189 + hb_position_t *x, hb_position_t *y) 1.190 + { 1.191 + *x = *y = 0; 1.192 + return klass->get.glyph_v_origin (this, user_data, 1.193 + glyph, x, y, 1.194 + klass->user_data.glyph_v_origin); 1.195 + } 1.196 + 1.197 + inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) 1.198 + { 1.199 + return klass->get.glyph_h_kerning (this, user_data, 1.200 + left_glyph, right_glyph, 1.201 + klass->user_data.glyph_h_kerning); 1.202 + } 1.203 + 1.204 + inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) 1.205 + { 1.206 + return klass->get.glyph_v_kerning (this, user_data, 1.207 + top_glyph, bottom_glyph, 1.208 + klass->user_data.glyph_v_kerning); 1.209 + } 1.210 + 1.211 + inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, 1.212 + hb_glyph_extents_t *extents) 1.213 + { 1.214 + memset (extents, 0, sizeof (*extents)); 1.215 + return klass->get.glyph_extents (this, user_data, 1.216 + glyph, 1.217 + extents, 1.218 + klass->user_data.glyph_extents); 1.219 + } 1.220 + 1.221 + inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, 1.222 + hb_position_t *x, hb_position_t *y) 1.223 + { 1.224 + *x = *y = 0; 1.225 + return klass->get.glyph_contour_point (this, user_data, 1.226 + glyph, point_index, 1.227 + x, y, 1.228 + klass->user_data.glyph_contour_point); 1.229 + } 1.230 + 1.231 + inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, 1.232 + char *name, unsigned int size) 1.233 + { 1.234 + if (size) *name = '\0'; 1.235 + return klass->get.glyph_name (this, user_data, 1.236 + glyph, 1.237 + name, size, 1.238 + klass->user_data.glyph_name); 1.239 + } 1.240 + 1.241 + inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ 1.242 + hb_codepoint_t *glyph) 1.243 + { 1.244 + *glyph = 0; 1.245 + if (len == -1) len = strlen (name); 1.246 + return klass->get.glyph_from_name (this, user_data, 1.247 + name, len, 1.248 + glyph, 1.249 + klass->user_data.glyph_from_name); 1.250 + } 1.251 + 1.252 + 1.253 + /* A bit higher-level, and with fallback */ 1.254 + 1.255 + inline void get_glyph_advance_for_direction (hb_codepoint_t glyph, 1.256 + hb_direction_t direction, 1.257 + hb_position_t *x, hb_position_t *y) 1.258 + { 1.259 + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 1.260 + *x = get_glyph_h_advance (glyph); 1.261 + *y = 0; 1.262 + } else { 1.263 + *x = 0; 1.264 + *y = get_glyph_v_advance (glyph); 1.265 + } 1.266 + } 1.267 + 1.268 + /* Internal only */ 1.269 + inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph, 1.270 + hb_position_t *x, hb_position_t *y) 1.271 + { 1.272 + *x = get_glyph_h_advance (glyph) / 2; 1.273 + 1.274 + /* TODO use font_metics.ascent */ 1.275 + *y = y_scale; 1.276 + } 1.277 + 1.278 + inline void get_glyph_origin_for_direction (hb_codepoint_t glyph, 1.279 + hb_direction_t direction, 1.280 + hb_position_t *x, hb_position_t *y) 1.281 + { 1.282 + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) 1.283 + { 1.284 + if (!get_glyph_h_origin (glyph, x, y) && 1.285 + get_glyph_v_origin (glyph, x, y)) 1.286 + { 1.287 + hb_position_t dx, dy; 1.288 + guess_v_origin_minus_h_origin (glyph, &dx, &dy); 1.289 + *x -= dx; *y -= dy; 1.290 + } 1.291 + } 1.292 + else 1.293 + { 1.294 + if (!get_glyph_v_origin (glyph, x, y) && 1.295 + get_glyph_h_origin (glyph, x, y)) 1.296 + { 1.297 + hb_position_t dx, dy; 1.298 + guess_v_origin_minus_h_origin (glyph, &dx, &dy); 1.299 + *x += dx; *y += dy; 1.300 + } 1.301 + } 1.302 + } 1.303 + 1.304 + inline void add_glyph_origin_for_direction (hb_codepoint_t glyph, 1.305 + hb_direction_t direction, 1.306 + hb_position_t *x, hb_position_t *y) 1.307 + { 1.308 + hb_position_t origin_x, origin_y; 1.309 + 1.310 + get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 1.311 + 1.312 + *x += origin_x; 1.313 + *y += origin_y; 1.314 + } 1.315 + 1.316 + inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph, 1.317 + hb_direction_t direction, 1.318 + hb_position_t *x, hb_position_t *y) 1.319 + { 1.320 + hb_position_t origin_x, origin_y; 1.321 + 1.322 + get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y); 1.323 + 1.324 + *x -= origin_x; 1.325 + *y -= origin_y; 1.326 + } 1.327 + 1.328 + inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, 1.329 + hb_direction_t direction, 1.330 + hb_position_t *x, hb_position_t *y) 1.331 + { 1.332 + if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { 1.333 + *x = get_glyph_h_kerning (first_glyph, second_glyph); 1.334 + *y = 0; 1.335 + } else { 1.336 + *x = 0; 1.337 + *y = get_glyph_v_kerning (first_glyph, second_glyph); 1.338 + } 1.339 + } 1.340 + 1.341 + inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph, 1.342 + hb_direction_t direction, 1.343 + hb_glyph_extents_t *extents) 1.344 + { 1.345 + hb_bool_t ret = get_glyph_extents (glyph, extents); 1.346 + 1.347 + if (ret) 1.348 + subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing); 1.349 + 1.350 + return ret; 1.351 + } 1.352 + 1.353 + inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index, 1.354 + hb_direction_t direction, 1.355 + hb_position_t *x, hb_position_t *y) 1.356 + { 1.357 + hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y); 1.358 + 1.359 + if (ret) 1.360 + subtract_glyph_origin_for_direction (glyph, direction, x, y); 1.361 + 1.362 + return ret; 1.363 + } 1.364 + 1.365 + /* Generates gidDDD if glyph has no name. */ 1.366 + inline void 1.367 + glyph_to_string (hb_codepoint_t glyph, 1.368 + char *s, unsigned int size) 1.369 + { 1.370 + if (get_glyph_name (glyph, s, size)) return; 1.371 + 1.372 + if (size && snprintf (s, size, "gid%u", glyph) < 0) 1.373 + *s = '\0'; 1.374 + } 1.375 + 1.376 + /* Parses gidDDD and uniUUUU strings automatically. */ 1.377 + inline hb_bool_t 1.378 + glyph_from_string (const char *s, int len, /* -1 means nul-terminated */ 1.379 + hb_codepoint_t *glyph) 1.380 + { 1.381 + if (get_glyph_from_name (s, len, glyph)) return true; 1.382 + 1.383 + if (len == -1) len = strlen (s); 1.384 + 1.385 + /* Straight glyph index. */ 1.386 + if (hb_codepoint_parse (s, len, 10, glyph)) 1.387 + return true; 1.388 + 1.389 + if (len > 3) 1.390 + { 1.391 + /* gidDDD syntax for glyph indices. */ 1.392 + if (0 == strncmp (s, "gid", 3) && 1.393 + hb_codepoint_parse (s + 3, len - 3, 10, glyph)) 1.394 + return true; 1.395 + 1.396 + /* uniUUUU and other Unicode character indices. */ 1.397 + hb_codepoint_t unichar; 1.398 + if (0 == strncmp (s, "uni", 3) && 1.399 + hb_codepoint_parse (s + 3, len - 3, 16, &unichar) && 1.400 + get_glyph (unichar, 0, glyph)) 1.401 + return true; 1.402 + } 1.403 + 1.404 + return false; 1.405 + } 1.406 + 1.407 + private: 1.408 + inline hb_position_t em_scale (int16_t v, int scale) { return (hb_position_t) (v * (int64_t) scale / face->get_upem ()); } 1.409 +}; 1.410 + 1.411 +#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 1.412 +#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font); 1.413 +#include "hb-shaper-list.hh" 1.414 +#undef HB_SHAPER_IMPLEMENT 1.415 +#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS 1.416 + 1.417 + 1.418 +#endif /* HB_FONT_PRIVATE_HH */