hb-font.cc 21.2 KB
Newer Older
1
/*
B
Behdad Esfahbod 已提交
2
 * Copyright © 2009  Red Hat, Inc.
3
 *
B
Behdad Esfahbod 已提交
4
 *  This is part of HarfBuzz, a text shaping library.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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
 */

27
#include "hb-private.hh"
28

29 30
#include "hb-ot-layout-private.hh"

31
#include "hb-font-private.hh"
B
Behdad Esfahbod 已提交
32
#include "hb-blob.h"
33
#include "hb-open-file-private.hh"
34

B
Behdad Esfahbod 已提交
35 36
#include <string.h>

B
Behdad Esfahbod 已提交
37

B
Behdad Esfahbod 已提交
38

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

43
static hb_bool_t
44 45 46 47 48 49 50 51 52 53 54 55 56 57
hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
		       void *font_data HB_UNUSED,
		       hb_codepoint_t unicode,
		       hb_codepoint_t variation_selector,
		       hb_codepoint_t *glyph,
		       void *user_data HB_UNUSED)
{
  if (font->parent)
    return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);

  *glyph = 0;
  return FALSE;
}

58
static hb_position_t
59 60 61 62
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
				 void *user_data HB_UNUSED)
63
{
64 65
  if (font->parent)
    return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
66

67
  return font->x_scale;
68
}
B
Behdad Esfahbod 已提交
69

70
static hb_position_t
71 72 73 74
hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
				 void *user_data HB_UNUSED)
75
{
76 77
  if (font->parent)
    return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
78

79
  return font->y_scale;
80 81
}

B
Behdad Esfahbod 已提交
82 83 84 85
static hb_bool_t
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
				void *font_data HB_UNUSED,
				hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
86 87
				hb_position_t *x,
				hb_position_t *y,
B
Behdad Esfahbod 已提交
88 89 90 91 92
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
93
						x, y);
94 95
    if (ret)
      font->parent_scale_position (x, y);
B
Behdad Esfahbod 已提交
96 97 98
    return ret;
  }

B
Behdad Esfahbod 已提交
99
  *x = *y = 0;
B
Behdad Esfahbod 已提交
100 101 102
  return FALSE;
}

103 104 105 106
static hb_bool_t
hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
				void *font_data HB_UNUSED,
				hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
107 108
				hb_position_t *x,
				hb_position_t *y,
109 110 111 112 113
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
114
						x, y);
115 116
    if (ret)
      font->parent_scale_position (x, y);
117 118 119
    return ret;
  }

B
Behdad Esfahbod 已提交
120
  *x = *y = 0;
121 122 123
  return FALSE;
}

124
static hb_position_t
B
Behdad Esfahbod 已提交
125 126 127 128 129
hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t left_glyph,
				 hb_codepoint_t right_glyph,
				 void *user_data HB_UNUSED)
130
{
131 132
  if (font->parent)
    return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
133

134
  return 0;
135 136
}

137
static hb_position_t
B
Behdad Esfahbod 已提交
138 139 140 141 142
hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t top_glyph,
				 hb_codepoint_t bottom_glyph,
				 void *user_data HB_UNUSED)
143
{
144 145
  if (font->parent)
    return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
146

147
  return 0;
148
}
B
Behdad Esfahbod 已提交
149

150
static hb_bool_t
151
hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
152
			       void *font_data HB_UNUSED,
153 154
			       hb_codepoint_t glyph,
			       hb_glyph_extents_t *extents,
155
			       void *user_data HB_UNUSED)
156 157
{
  if (font->parent) {
158 159 160
    hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
					       glyph,
					       extents);
161 162 163 164
    if (ret) {
      font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
      font->parent_scale_distance (&extents->width, &extents->height);
    }
165
    return ret;
166 167
  }

168
  memset (extents, 0, sizeof (*extents));
169
  return FALSE;
170
}
171

172
static hb_bool_t
B
Behdad Esfahbod 已提交
173 174 175 176 177 178 179
hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
				     void *font_data HB_UNUSED,
				     hb_codepoint_t glyph,
				     unsigned int point_index,
				     hb_position_t *x,
				     hb_position_t *y,
				     void *user_data HB_UNUSED)
180
{
181
  if (font->parent) {
B
Behdad Esfahbod 已提交
182 183 184
    hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
						     glyph, point_index,
						     x, y);
185 186
    if (ret)
      font->parent_scale_position (x, y);
187
    return ret;
188
  }
189

190 191
  *x = *y = 0;
  return FALSE;
192
}
B
Behdad Esfahbod 已提交
193

B
Behdad Esfahbod 已提交
194 195

static hb_font_funcs_t _hb_font_funcs_nil = {
196 197
  HB_OBJECT_HEADER_STATIC,

198
  TRUE, /* immutable */
199

200
  {
201 202 203
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
204
  }
205 206
};

B
Behdad Esfahbod 已提交
207

B
Behdad Esfahbod 已提交
208 209
hb_font_funcs_t *
hb_font_funcs_create (void)
210
{
B
Behdad Esfahbod 已提交
211
  hb_font_funcs_t *ffuncs;
212

213
  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
B
Behdad Esfahbod 已提交
214
    return &_hb_font_funcs_nil;
215

216
  ffuncs->get = _hb_font_funcs_nil.get;
217

B
Behdad Esfahbod 已提交
218
  return ffuncs;
219 220
}

221 222 223 224 225 226
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
  return &_hb_font_funcs_nil;
}

B
Behdad Esfahbod 已提交
227 228
hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
229
{
230
  return hb_object_reference (ffuncs);
231 232 233
}

void
B
Behdad Esfahbod 已提交
234
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
235
{
236
  if (!hb_object_destroy (ffuncs)) return;
237

B
Behdad Esfahbod 已提交
238 239
#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
  ffuncs->destroy.name (ffuncs->user_data.name);
240 241
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
242

B
Behdad Esfahbod 已提交
243
  free (ffuncs);
244 245
}

246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
hb_bool_t
hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
			     hb_user_data_key_t *key,
			     void *              data,
			     hb_destroy_func_t   destroy)
{
  return hb_object_set_user_data (ffuncs, key, data, destroy);
}

void *
hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
			     hb_user_data_key_t *key)
{
  return hb_object_get_user_data (ffuncs, key);
}


263 264 265
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
266
  if (hb_object_is_inert (ffuncs))
267 268 269
    return;

  ffuncs->immutable = TRUE;
B
Behdad Esfahbod 已提交
270 271 272 273 274
}

hb_bool_t
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
{
B
Behdad Esfahbod 已提交
275
  return ffuncs->immutable;
276 277
}

278

279
#define HB_FONT_FUNC_IMPLEMENT(name) \
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
                                                                         \
void                                                                     \
hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
                                 hb_font_get_##name##_func_t  func,      \
                                 void                        *user_data, \
                                 hb_destroy_func_t            destroy)   \
{                                                                        \
  if (ffuncs->immutable)                                                 \
    return;                                                              \
                                                                         \
  if (ffuncs->destroy.name)                                              \
    ffuncs->destroy.name (ffuncs->user_data.name);                       \
                                                                         \
  if (func) {                                                            \
    ffuncs->get.name = func;                                             \
    ffuncs->user_data.name = user_data;                                  \
    ffuncs->destroy.name = destroy;                                      \
  } else {                                                               \
    ffuncs->get.name = hb_font_get_##name##_nil;                         \
    ffuncs->user_data.name = NULL;                                       \
    ffuncs->destroy.name = NULL;                                         \
  }                                                                      \
B
Behdad Esfahbod 已提交
302 303
}

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT


hb_bool_t
hb_font_get_glyph (hb_font_t *font,
		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
		   hb_codepoint_t *glyph)
{
  *glyph = 0;
  return font->klass->get.glyph (font, font->user_data,
				 unicode, variation_selector, glyph,
				 font->klass->user_data.glyph);
}

319
hb_position_t
320
hb_font_get_glyph_h_advance (hb_font_t *font,
321
			     hb_codepoint_t glyph)
322
{
323 324 325
  return font->klass->get.glyph_h_advance (font, font->user_data,
					   glyph,
					   font->klass->user_data.glyph_h_advance);
326 327
}

328
hb_position_t
329
hb_font_get_glyph_v_advance (hb_font_t *font,
330
			     hb_codepoint_t glyph)
331
{
332 333 334
  return font->klass->get.glyph_v_advance (font, font->user_data,
					   glyph,
					   font->klass->user_data.glyph_v_advance);
335 336
}

B
Behdad Esfahbod 已提交
337 338 339
hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
340
			    hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
341
{
B
Behdad Esfahbod 已提交
342
  *x = *y = 0;
B
Behdad Esfahbod 已提交
343
  return font->klass->get.glyph_h_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
344
					   glyph, x, y,
B
Behdad Esfahbod 已提交
345 346 347
					   font->klass->user_data.glyph_h_origin);
}

348 349 350
hb_bool_t
hb_font_get_glyph_v_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
351
			    hb_position_t *x, hb_position_t *y)
352
{
B
Behdad Esfahbod 已提交
353
  *x = *y = 0;
354
  return font->klass->get.glyph_v_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
355
					   glyph, x, y,
356 357 358
					   font->klass->user_data.glyph_v_origin);
}

359
hb_position_t
B
Behdad Esfahbod 已提交
360
hb_font_get_glyph_h_kerning (hb_font_t *font,
361
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
362
{
B
Behdad Esfahbod 已提交
363 364 365
  return font->klass->get.glyph_h_kerning (font, font->user_data,
					   left_glyph, right_glyph,
					   font->klass->user_data.glyph_h_kerning);
366
}
B
Behdad Esfahbod 已提交
367

368
hb_position_t
B
Behdad Esfahbod 已提交
369
hb_font_get_glyph_v_kerning (hb_font_t *font,
370
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
371
{
B
Behdad Esfahbod 已提交
372
  return font->klass->get.glyph_v_kerning (font, font->user_data,
373
				     left_glyph, right_glyph,
B
Behdad Esfahbod 已提交
374
				     font->klass->user_data.glyph_v_kerning);
375
}
B
Behdad Esfahbod 已提交
376

377 378 379 380 381 382 383 384 385 386 387
hb_bool_t
hb_font_get_glyph_extents (hb_font_t *font,
			   hb_codepoint_t glyph,
			   hb_glyph_extents_t *extents)
{
  memset (extents, 0, sizeof (*extents));
  return font->klass->get.glyph_extents (font, font->user_data,
					 glyph,
					 extents,
					 font->klass->user_data.glyph_extents);
}
388

389
hb_bool_t
B
Behdad Esfahbod 已提交
390 391 392
hb_font_get_glyph_contour_point (hb_font_t *font,
				 hb_codepoint_t glyph, unsigned int point_index,
				 hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
393
{
394
  *x = *y = 0;
B
Behdad Esfahbod 已提交
395 396 397 398
  return font->klass->get.glyph_contour_point (font, font->user_data,
					       glyph, point_index,
					       x, y,
					       font->klass->user_data.glyph_contour_point);
B
Behdad Esfahbod 已提交
399 400
}

401 402 403

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

404
void
405 406 407
hb_font_get_glyph_advance_for_direction (hb_font_t *font,
					 hb_codepoint_t glyph,
					 hb_direction_t direction,
B
Behdad Esfahbod 已提交
408
					 hb_position_t *x, hb_position_t *y)
409
{
410
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
411
    *x = hb_font_get_glyph_h_advance (font, glyph);
412
    *y = 0;
413
  } else {
414
    *x = 0;
415
    *y = hb_font_get_glyph_v_advance (font, glyph);
416
  }
417 418
}

419 420 421 422 423
static void
guess_v_origin_minus_h_origin (hb_font_t *font,
			       hb_codepoint_t glyph,
			       hb_position_t *x, hb_position_t *y)
{
424
  *x = hb_font_get_glyph_h_advance (font, glyph) / 2;
425 426 427 428 429 430

  /* TODO use font_metics.ascent */
  *y = font->y_scale;
}


431
void
B
Behdad Esfahbod 已提交
432 433 434
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
					hb_codepoint_t glyph,
					hb_direction_t direction,
B
Behdad Esfahbod 已提交
435
					hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
436
{
437
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
438 439 440 441 442 443
    hb_bool_t ret = hb_font_get_glyph_h_origin (font, glyph, x, y);
    if (!ret && (ret = hb_font_get_glyph_v_origin (font, glyph, x, y))) {
      hb_position_t dx, dy;
      guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
      *x -= dx; *y -= dy;
    }
444
  } else {
B
Behdad Esfahbod 已提交
445
    hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
446 447 448 449
    if (!ret && (ret = hb_font_get_glyph_h_origin (font, glyph, x, y))) {
      hb_position_t dx, dy;
      guess_v_origin_minus_h_origin (font, glyph, &dx, &dy);
      *x += dx; *y += dy;
B
Behdad Esfahbod 已提交
450 451 452 453
    }
  }
}

B
Behdad Esfahbod 已提交
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
void
hb_font_add_glyph_origin_for_direction (hb_font_t *font,
					hb_codepoint_t glyph,
					hb_direction_t direction,
					hb_position_t *x, hb_position_t *y)
{
  hb_position_t origin_x, origin_y;

  hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);

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

void
hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
					     hb_codepoint_t glyph,
					     hb_direction_t direction,
					     hb_position_t *x, hb_position_t *y)
{
  hb_position_t origin_x, origin_y;

  hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);

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

B
Behdad Esfahbod 已提交
482 483 484 485
void
hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
					 hb_direction_t direction,
B
Behdad Esfahbod 已提交
486
					 hb_position_t *x, hb_position_t *y)
487
{
488
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
489
    *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
490 491 492
    *y = 0;
  } else {
    *x = 0;
493
    *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
494
  }
495 496
}

497 498 499 500 501
hb_bool_t
hb_font_get_glyph_extents_for_origin (hb_font_t *font,
				      hb_codepoint_t glyph,
				      hb_direction_t direction,
				      hb_glyph_extents_t *extents)
B
Behdad Esfahbod 已提交
502
{
B
Behdad Esfahbod 已提交
503
  hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
504

B
Behdad Esfahbod 已提交
505 506
  if (ret)
    hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing);
507 508

  return ret;
B
Behdad Esfahbod 已提交
509 510
}

511
hb_bool_t
512 513 514 515
hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
					    hb_codepoint_t glyph, unsigned int point_index,
					    hb_direction_t direction,
					    hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
516
{
B
Behdad Esfahbod 已提交
517
  hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
518

B
Behdad Esfahbod 已提交
519 520
  if (ret)
    hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y);
521 522

  return ret;
B
Behdad Esfahbod 已提交
523 524
}

525

526 527 528 529 530
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
531
  HB_OBJECT_HEADER_STATIC,
532

533 534
  TRUE, /* immutable */

535 536
  NULL, /* get_table */
  NULL, /* user_data */
537
  NULL, /* destroy */
538

539 540 541
  NULL, /* ot_layout */

  1000
542 543
};

544

545 546
hb_face_t *
hb_face_create_for_tables (hb_get_table_func_t  get_table,
547 548
			   void                *user_data,
			   hb_destroy_func_t    destroy)
549 550 551
{
  hb_face_t *face;

552
  if (!get_table || !(face = hb_object_create<hb_face_t> ())) {
553 554 555 556 557 558 559
    if (destroy)
      destroy (user_data);
    return &_hb_face_nil;
  }

  face->get_table = get_table;
  face->user_data = user_data;
560
  face->destroy = destroy;
561

562
  face->ot_layout = _hb_ot_layout_create (face);
563

564 565
  face->upem = _hb_ot_layout_get_upem (face);

566 567 568
  return face;
}

569 570 571 572 573 574 575 576 577 578 579 580

typedef struct _hb_face_for_data_closure_t {
  hb_blob_t *blob;
  unsigned int  index;
} hb_face_for_data_closure_t;

static hb_face_for_data_closure_t *
_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
{
  hb_face_for_data_closure_t *closure;

  closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
581
  if (unlikely (!closure))
582
    return NULL;
583

B
Behdad Esfahbod 已提交
584
  closure->blob = blob;
585 586 587 588 589 590 591 592
  closure->index = index;

  return closure;
}

static void
_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
{
593 594
  hb_blob_destroy (closure->blob);
  free (closure);
595 596 597
}

static hb_blob_t *
B
Behdad Esfahbod 已提交
598
_hb_face_for_data_get_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
599 600 601
{
  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;

602
  const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
603 604 605 606 607 608 609 610 611
  const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);

  const OpenTypeTable &table = ot_face.get_table_by_tag (tag);

  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);

  return blob;
}

612
hb_face_t *
613 614
hb_face_create (hb_blob_t    *blob,
		unsigned int  index)
615
{
B
Behdad Esfahbod 已提交
616
  if (unlikely (!blob || !hb_blob_get_length (blob)))
617 618
    return &_hb_face_nil;

619
  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
B
Behdad Esfahbod 已提交
620

621 622
  if (unlikely (!closure))
    return &_hb_face_nil;
623

624
  return hb_face_create_for_tables (_hb_face_for_data_get_table,
625 626
				    closure,
				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
627 628
}

629 630 631 632 633 634
hb_face_t *
hb_face_get_empty (void)
{
  return &_hb_face_nil;
}

635

636 637 638
hb_face_t *
hb_face_reference (hb_face_t *face)
{
639
  return hb_object_reference (face);
640 641 642 643 644
}

void
hb_face_destroy (hb_face_t *face)
{
645
  if (!hb_object_destroy (face)) return;
646

647
  _hb_ot_layout_destroy (face->ot_layout);
B
Behdad Esfahbod 已提交
648

649 650 651 652 653 654
  if (face->destroy)
    face->destroy (face->user_data);

  free (face);
}

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
hb_bool_t
hb_face_set_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key,
		       void *              data,
		       hb_destroy_func_t   destroy)
{
  return hb_object_set_user_data (face, key, data, destroy);
}

void *
hb_face_get_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key)
{
  return hb_object_get_user_data (face, key);
}

671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
void
hb_face_make_immutable (hb_face_t *face)
{
  if (hb_object_is_inert (face))
    return;

  face->immutable = true;
}

hb_bool_t
hb_face_is_immutable (hb_face_t *face)
{
  return face->immutable;
}

686

B
Behdad Esfahbod 已提交
687 688 689 690 691 692 693 694 695 696
hb_blob_t *
hb_face_get_blob (hb_face_t *face)
{
  if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
    return hb_blob_get_empty ();

  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
  return data->blob;
}

697
hb_blob_t *
698
hb_face_reference_table (hb_face_t *face,
699
			 hb_tag_t   tag)
700
{
701 702
  hb_blob_t *blob;

703
  if (unlikely (!face || !face->get_table))
B
Behdad Esfahbod 已提交
704
    return hb_blob_get_empty ();
705

B
Behdad Esfahbod 已提交
706
  blob = face->get_table (face, tag, face->user_data);
707
  if (unlikely (!blob))
B
Behdad Esfahbod 已提交
708
    return hb_blob_get_empty ();
709

710
  return blob;
711
}
712

B
Behdad Esfahbod 已提交
713 714 715
unsigned int
hb_face_get_upem (hb_face_t *face)
{
716
  return _hb_ot_layout_get_upem (face);
B
Behdad Esfahbod 已提交
717 718
}

719 720 721 722 723 724

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
725
  HB_OBJECT_HEADER_STATIC,
726

727
  TRUE, /* immutable */
728

729
  NULL, /* parent */
730 731
  &_hb_face_nil,

732 733 734 735
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
736 737
  0, /* y_ppem */

738
  &_hb_font_funcs_nil, /* klass */
739 740
  NULL, /* user_data */
  NULL  /* destroy */
741 742 743
};

hb_font_t *
744
hb_font_create (hb_face_t *face)
745 746 747
{
  hb_font_t *font;

748 749 750 751
  if (unlikely (!face))
    face = &_hb_face_nil;
  if (unlikely (hb_object_is_inert (face)))
    return &_hb_font_nil;
752
  if (!(font = hb_object_create<hb_font_t> ()))
753 754
    return &_hb_font_nil;

755
  hb_face_make_immutable (face);
756
  font->face = hb_face_reference (face);
B
Behdad Esfahbod 已提交
757 758
  font->klass = &_hb_font_funcs_nil;

759 760 761
  return font;
}

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
hb_font_t *
hb_font_create_sub_font (hb_font_t *parent)
{
  if (unlikely (!parent))
    return &_hb_font_nil;

  hb_font_t *font = hb_font_create (parent->face);

  if (unlikely (hb_object_is_inert (font)))
    return font;

  hb_font_make_immutable (parent);
  font->parent = hb_font_reference (parent);

  font->x_scale = parent->x_scale;
  font->y_scale = parent->y_scale;
  font->x_ppem = parent->x_ppem;
  font->y_ppem = parent->y_ppem;

B
Behdad Esfahbod 已提交
781
  font->klass = &_hb_font_funcs_nil;
782 783 784 785

  return font;
}

786 787 788 789 790 791
hb_font_t *
hb_font_get_empty (void)
{
  return &_hb_font_nil;
}

792 793 794
hb_font_t *
hb_font_reference (hb_font_t *font)
{
795
  return hb_object_reference (font);
796 797 798 799 800
}

void
hb_font_destroy (hb_font_t *font)
{
801
  if (!hb_object_destroy (font)) return;
802

803
  hb_font_destroy (font->parent);
804
  hb_face_destroy (font->face);
B
Behdad Esfahbod 已提交
805
  hb_font_funcs_destroy (font->klass);
B
Behdad Esfahbod 已提交
806 807
  if (font->destroy)
    font->destroy (font->user_data);
808 809 810 811

  free (font);
}

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
hb_bool_t
hb_font_set_user_data (hb_font_t          *font,
		       hb_user_data_key_t *key,
		       void *              data,
		       hb_destroy_func_t   destroy)
{
  return hb_object_set_user_data (font, key, data, destroy);
}

void *
hb_font_get_user_data (hb_font_t          *font,
		       hb_user_data_key_t *key)
{
  return hb_object_get_user_data (font, key);
}

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
void
hb_font_make_immutable (hb_font_t *font)
{
  if (hb_object_is_inert (font))
    return;

  font->immutable = true;
}

hb_bool_t
hb_font_is_immutable (hb_font_t *font)
{
  return font->immutable;
}

843 844 845 846 847
hb_font_t *
hb_font_get_parent (hb_font_t *font)
{
  return font->parent;
}
848

849 850 851 852 853 854 855
hb_face_t *
hb_font_get_face (hb_font_t *font)
{
  return font->face;
}


B
Behdad Esfahbod 已提交
856
void
B
Behdad Esfahbod 已提交
857 858
hb_font_set_funcs (hb_font_t         *font,
		   hb_font_funcs_t   *klass,
859 860
		   void              *user_data,
		   hb_destroy_func_t  destroy)
861
{
862
  if (font->immutable)
B
Behdad Esfahbod 已提交
863
    return;
864

B
Behdad Esfahbod 已提交
865 866 867
  if (font->destroy)
    font->destroy (font->user_data);

B
Behdad Esfahbod 已提交
868 869 870
  if (!klass)
    klass = &_hb_font_funcs_nil;

B
Behdad Esfahbod 已提交
871 872 873
  hb_font_funcs_reference (klass);
  hb_font_funcs_destroy (font->klass);
  font->klass = klass;
B
Behdad Esfahbod 已提交
874
  font->user_data = user_data;
875
  font->destroy = destroy;
876 877
}

B
Behdad Esfahbod 已提交
878

879 880
void
hb_font_set_scale (hb_font_t *font,
881 882
		   int x_scale,
		   int y_scale)
883
{
884
  if (font->immutable)
885 886 887 888 889 890
    return;

  font->x_scale = x_scale;
  font->y_scale = y_scale;
}

B
Behdad Esfahbod 已提交
891 892
void
hb_font_get_scale (hb_font_t *font,
893 894
		   int *x_scale,
		   int *y_scale)
B
Behdad Esfahbod 已提交
895 896 897 898 899
{
  if (x_scale) *x_scale = font->x_scale;
  if (y_scale) *y_scale = font->y_scale;
}

900 901 902 903 904
void
hb_font_set_ppem (hb_font_t *font,
		  unsigned int x_ppem,
		  unsigned int y_ppem)
{
905
  if (font->immutable)
906 907 908 909 910 911
    return;

  font->x_ppem = x_ppem;
  font->y_ppem = y_ppem;
}

B
Behdad Esfahbod 已提交
912 913 914 915 916 917 918 919 920
void
hb_font_get_ppem (hb_font_t *font,
		  unsigned int *x_ppem,
		  unsigned int *y_ppem)
{
  if (x_ppem) *x_ppem = font->x_ppem;
  if (y_ppem) *y_ppem = font->y_ppem;
}

B
Behdad Esfahbod 已提交
921