hb-font-private.hh 15.6 KB
Newer Older
1
/*
B
Behdad Esfahbod 已提交
2 3
 * Copyright © 2009  Red Hat, Inc.
 * Copyright © 2011  Google, Inc.
4
 *
B
Behdad Esfahbod 已提交
5
 *  This is part of HarfBuzz, a text shaping library.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Red Hat Author(s): Behdad Esfahbod
B
Behdad Esfahbod 已提交
26
 * Google Author(s): Behdad Esfahbod
27 28
 */

29 30
#ifndef HB_FONT_PRIVATE_HH
#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


B
Behdad Esfahbod 已提交
39

40
/*
B
Behdad Esfahbod 已提交
41
 * hb_font_funcs_t
42 43
 */

44
#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
45 46
  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
47 48
  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
49 50
  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
B
Behdad Esfahbod 已提交
51
  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
52
  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
B
Behdad Esfahbod 已提交
53 54
  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
55
  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
B
Behdad Esfahbod 已提交
56
  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
57 58
  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
B
Behdad Esfahbod 已提交
59
  /* ^--- Add new callbacks here */
60

61
struct hb_font_funcs_t {
B
Behdad Esfahbod 已提交
62
  hb_object_header_t header;
63
  ASSERT_POD ();
B
Behdad Esfahbod 已提交
64 65 66

  hb_bool_t immutable;

67
  struct {
68 69 70
#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
71 72
  } user_data;

73
  struct {
74 75 76
#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
77
  } destroy;
78 79 80 81 82 83 84 85

  /* Don't access these directly.  Call font->get_*() instead. */
  union get_t {
    struct get_funcs_t {
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
    } f;
S
Steven R. Loomis 已提交
86
    void (*array[VAR]) (void);
87
  } get;
88 89 90 91 92 93 94 95
};



/*
 * hb_font_t
 */

96
struct hb_font_t {
97
  hb_object_header_t header;
98
  ASSERT_POD ();
99

100 101
  hb_bool_t immutable;

102
  hb_font_t *parent;
103 104
  hb_face_t *face;

105 106
  int x_scale;
  int y_scale;
107 108 109

  unsigned int x_ppem;
  unsigned int y_ppem;
B
Behdad Esfahbod 已提交
110

111 112
  float ptem;

113
  /* Font variation coordinates. */
114
  unsigned int num_coords;
115
  int *coords;
116

B
Behdad Esfahbod 已提交
117 118
  hb_font_funcs_t   *klass;
  void              *user_data;
119
  hb_destroy_func_t  destroy;
120

121 122
  struct hb_shaper_data_t shaper_data;

123 124

  /* Convert from font-space to user-space */
125 126 127 128
  inline int dir_scale (hb_direction_t direction)
  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
129 130
  inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
131
  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
132
  { return em_scale (v, dir_scale (direction)); }
133

134 135 136
  /* Convert from parent-font user-space to our user-space */
  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
    if (unlikely (parent && parent->x_scale != x_scale))
B
Behdad Esfahbod 已提交
137
      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
138 139 140 141
    return v;
  }
  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
    if (unlikely (parent && parent->y_scale != y_scale))
B
Behdad Esfahbod 已提交
142
      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
143 144 145
    return v;
  }
  inline hb_position_t parent_scale_x_position (hb_position_t v) {
146
    return parent_scale_x_distance (v);
147 148
  }
  inline hb_position_t parent_scale_y_position (hb_position_t v) {
149
    return parent_scale_y_distance (v);
150 151 152 153 154 155 156 157 158 159 160 161
  }

  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
    *x = parent_scale_x_distance (*x);
    *y = parent_scale_y_distance (*y);
  }
  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
    *x = parent_scale_x_position (*x);
    *y = parent_scale_y_position (*y);
  }


B
Behdad Esfahbod 已提交
162 163
  /* Public getters */

164 165 166 167 168 169 170 171 172 173 174 175 176 177
  HB_INTERNAL bool has_func (unsigned int i);

  /* has_* ... */
#define HB_FONT_FUNC_IMPLEMENT(name) \
  bool \
  has_##name##_func (void) \
  { \
    hb_font_funcs_t *funcs = this->klass; \
    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
    return has_func (i); \
  }
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
  {
    memset (extents, 0, sizeof (*extents));
    return klass->get.f.font_h_extents (this, user_data,
					extents,
					klass->user_data.font_h_extents);
  }
  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
  {
    memset (extents, 0, sizeof (*extents));
    return klass->get.f.font_v_extents (this, user_data,
					extents,
					klass->user_data.font_v_extents);
  }

193
  inline bool has_glyph (hb_codepoint_t unicode)
B
Behdad Esfahbod 已提交
194 195
  {
    hb_codepoint_t glyph;
196
    return get_nominal_glyph (unicode, &glyph);
B
Behdad Esfahbod 已提交
197 198
  }

199 200
  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
				      hb_codepoint_t *glyph)
B
Behdad Esfahbod 已提交
201 202
  {
    *glyph = 0;
203 204 205 206 207 208 209 210 211 212 213 214
    return klass->get.f.nominal_glyph (this, user_data,
				       unicode, glyph,
				       klass->user_data.nominal_glyph);
  }

  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
					hb_codepoint_t *glyph)
  {
    *glyph = 0;
    return klass->get.f.variation_glyph (this, user_data,
					 unicode, variation_selector, glyph,
					 klass->user_data.variation_glyph);
B
Behdad Esfahbod 已提交
215 216 217 218
  }

  inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
  {
219 220 221
    return klass->get.f.glyph_h_advance (this, user_data,
					 glyph,
					 klass->user_data.glyph_h_advance);
B
Behdad Esfahbod 已提交
222 223 224 225
  }

  inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
  {
226 227 228
    return klass->get.f.glyph_v_advance (this, user_data,
					 glyph,
					 klass->user_data.glyph_v_advance);
B
Behdad Esfahbod 已提交
229 230 231 232 233 234
  }

  inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
				       hb_position_t *x, hb_position_t *y)
  {
    *x = *y = 0;
235 236 237
    return klass->get.f.glyph_h_origin (this, user_data,
					glyph, x, y,
					klass->user_data.glyph_h_origin);
B
Behdad Esfahbod 已提交
238 239 240 241 242 243
  }

  inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
				       hb_position_t *x, hb_position_t *y)
  {
    *x = *y = 0;
244 245 246
    return klass->get.f.glyph_v_origin (this, user_data,
					glyph, x, y,
					klass->user_data.glyph_v_origin);
B
Behdad Esfahbod 已提交
247 248 249 250
  }

  inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
  {
251 252 253
    return klass->get.f.glyph_h_kerning (this, user_data,
					 left_glyph, right_glyph,
					 klass->user_data.glyph_h_kerning);
B
Behdad Esfahbod 已提交
254 255
  }

256
  inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
B
Behdad Esfahbod 已提交
257
  {
258 259 260
    return klass->get.f.glyph_v_kerning (this, user_data,
					 top_glyph, bottom_glyph,
					 klass->user_data.glyph_v_kerning);
B
Behdad Esfahbod 已提交
261 262 263 264 265 266
  }

  inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
				      hb_glyph_extents_t *extents)
  {
    memset (extents, 0, sizeof (*extents));
267 268 269 270
    return klass->get.f.glyph_extents (this, user_data,
				       glyph,
				       extents,
				       klass->user_data.glyph_extents);
B
Behdad Esfahbod 已提交
271 272 273 274 275 276
  }

  inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
					    hb_position_t *x, hb_position_t *y)
  {
    *x = *y = 0;
277 278 279 280
    return klass->get.f.glyph_contour_point (this, user_data,
					     glyph, point_index,
					     x, y,
					     klass->user_data.glyph_contour_point);
B
Behdad Esfahbod 已提交
281 282 283 284 285
  }

  inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
				   char *name, unsigned int size)
  {
286
    if (size) *name = '\0';
287 288 289 290
    return klass->get.f.glyph_name (this, user_data,
				    glyph,
				    name, size,
				    klass->user_data.glyph_name);
B
Behdad Esfahbod 已提交
291 292 293 294 295
  }

  inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
					hb_codepoint_t *glyph)
  {
296 297
    *glyph = 0;
    if (len == -1) len = strlen (name);
298 299 300 301
    return klass->get.f.glyph_from_name (this, user_data,
					 name, len,
					 glyph,
					 klass->user_data.glyph_from_name);
B
Behdad Esfahbod 已提交
302 303 304 305 306
  }


  /* A bit higher-level, and with fallback */

B
Behdad Esfahbod 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
  {
    if (!get_font_h_extents (extents))
    {
      extents->ascender = y_scale * .8;
      extents->descender = extents->ascender - y_scale;
      extents->line_gap = 0;
    }
  }
  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
  {
    if (!get_font_v_extents (extents))
    {
      extents->ascender = x_scale / 2;
      extents->descender = extents->ascender - x_scale;
      extents->line_gap = 0;
    }
  }

326 327 328
  inline void get_extents_for_direction (hb_direction_t direction,
					 hb_font_extents_t *extents)
  {
B
Behdad Esfahbod 已提交
329 330 331 332
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
      get_h_extents_with_fallback (extents);
    else
      get_v_extents_with_fallback (extents);
333 334
  }

B
Behdad Esfahbod 已提交
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
  inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
					       hb_direction_t direction,
					       hb_position_t *x, hb_position_t *y)
  {
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
      *x = get_glyph_h_advance (glyph);
      *y = 0;
    } else {
      *x = 0;
      *y = get_glyph_v_advance (glyph);
    }
  }

  inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
					     hb_position_t *x, hb_position_t *y)
  {
    *x = get_glyph_h_advance (glyph) / 2;

353 354 355 356
    /* TODO cache this somehow?! */
    hb_font_extents_t extents;
    get_h_extents_with_fallback (&extents);
    *y = extents.ascender;
B
Behdad Esfahbod 已提交
357 358
  }

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
						hb_position_t *x, hb_position_t *y)
  {
    if (!get_glyph_h_origin (glyph, x, y) &&
	 get_glyph_v_origin (glyph, x, y))
    {
      hb_position_t dx, dy;
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
      *x -= dx; *y -= dy;
    }
  }
  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
						hb_position_t *x, hb_position_t *y)
  {
    if (!get_glyph_v_origin (glyph, x, y) &&
	 get_glyph_h_origin (glyph, x, y))
    {
      hb_position_t dx, dy;
      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
      *x += dx; *y += dy;
    }
  }

B
Behdad Esfahbod 已提交
382 383 384 385
  inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
					      hb_direction_t direction,
					      hb_position_t *x, hb_position_t *y)
  {
386
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
387
      get_glyph_h_origin_with_fallback (glyph, x, y);
388
    else
389
      get_glyph_v_origin_with_fallback (glyph, x, y);
B
Behdad Esfahbod 已提交
390 391
  }

392 393 394 395 396
  inline void add_glyph_h_origin (hb_codepoint_t glyph,
				  hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

397
    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
398 399 400 401 402 403 404 405 406

    *x += origin_x;
    *y += origin_y;
  }
  inline void add_glyph_v_origin (hb_codepoint_t glyph,
				  hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

407
    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
408 409 410 411

    *x += origin_x;
    *y += origin_y;
  }
B
Behdad Esfahbod 已提交
412 413 414 415 416 417 418 419 420 421 422 423
  inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
					      hb_direction_t direction,
					      hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);

    *x += origin_x;
    *y += origin_y;
  }

424 425 426 427 428
  inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
				       hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

429
    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
430 431 432 433 434 435 436 437 438

    *x -= origin_x;
    *y -= origin_y;
  }
  inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
				       hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

439
    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
440 441 442 443

    *x -= origin_x;
    *y -= origin_y;
  }
B
Behdad Esfahbod 已提交
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
  inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
						   hb_direction_t direction,
						   hb_position_t *x, hb_position_t *y)
  {
    hb_position_t origin_x, origin_y;

    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);

    *x -= origin_x;
    *y -= origin_y;
  }

  inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
					       hb_direction_t direction,
					       hb_position_t *x, hb_position_t *y)
  {
    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
      *x = get_glyph_h_kerning (first_glyph, second_glyph);
      *y = 0;
    } else {
      *x = 0;
      *y = get_glyph_v_kerning (first_glyph, second_glyph);
    }
  }

  inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
						 hb_direction_t direction,
						 hb_glyph_extents_t *extents)
  {
    hb_bool_t ret = get_glyph_extents (glyph, extents);

    if (ret)
      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);

    return ret;
  }

  inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
						       hb_direction_t direction,
						       hb_position_t *x, hb_position_t *y)
  {
    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);

    if (ret)
      subtract_glyph_origin_for_direction (glyph, direction, x, y);

    return ret;
  }

493 494 495 496 497 498 499
  /* Generates gidDDD if glyph has no name. */
  inline void
  glyph_to_string (hb_codepoint_t glyph,
		   char *s, unsigned int size)
  {
    if (get_glyph_name (glyph, s, size)) return;

B
Behdad Esfahbod 已提交
500 501
    if (size && snprintf (s, size, "gid%u", glyph) < 0)
      *s = '\0';
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
  }

  /* Parses gidDDD and uniUUUU strings automatically. */
  inline hb_bool_t
  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
		     hb_codepoint_t *glyph)
  {
    if (get_glyph_from_name (s, len, glyph)) return true;

    if (len == -1) len = strlen (s);

    /* Straight glyph index. */
    if (hb_codepoint_parse (s, len, 10, glyph))
      return true;

    if (len > 3)
    {
      /* gidDDD syntax for glyph indices. */
      if (0 == strncmp (s, "gid", 3) &&
	  hb_codepoint_parse (s + 3, len - 3, 10, glyph))
	return true;

      /* uniUUUU and other Unicode character indices. */
      hb_codepoint_t unichar;
      if (0 == strncmp (s, "uni", 3) &&
	  hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
528
	  get_nominal_glyph (unichar, glyph))
529 530 531 532 533
	return true;
    }

    return false;
  }
B
Behdad Esfahbod 已提交
534

535 536 537 538 539 540 541
  inline hb_position_t em_scale (int16_t v, int scale)
  {
    int upem = face->get_upem ();
    int64_t scaled = v * (int64_t) scale;
    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
    return (hb_position_t) (scaled / upem);
  }
542 543 544 545
  inline hb_position_t em_scalef (float v, int scale)
  {
    return (hb_position_t) (v * scale / face->get_upem ());
  }
546 547
};

B
Behdad Esfahbod 已提交
548
#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
549 550 551
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
B
Behdad Esfahbod 已提交
552
#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
553 554


555
#endif /* HB_FONT_PRIVATE_HH */