hb-font.cc 22.4 KB
Newer Older
1
/*
B
Behdad Esfahbod 已提交
2
 * Copyright © 2009  Red Hat, Inc.
3
 * Copyright © 2012  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
26
 * Google Author(s): Behdad Esfahbod
27 28
 */

29
#include "hb-private.hh"
30

31 32
#include "hb-ot-layout-private.hh"

33
#include "hb-font-private.hh"
B
Behdad Esfahbod 已提交
34
#include "hb-blob.h"
35
#include "hb-open-file-private.hh"
36
#include "hb-ot-head-table.hh"
37

38 39
#include "hb-cache-private.hh"

B
Behdad Esfahbod 已提交
40 41
#include <string.h>

B
Behdad Esfahbod 已提交
42

B
Behdad Esfahbod 已提交
43

44
/*
B
Behdad Esfahbod 已提交
45
 * hb_font_funcs_t
46 47
 */

48
static hb_bool_t
49
hb_font_get_glyph_nil (hb_font_t *font,
50 51 52 53 54 55 56
		       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)
B
Behdad Esfahbod 已提交
57
    return font->parent->get_glyph (unicode, variation_selector, glyph);
58 59

  *glyph = 0;
60
  return false;
61 62
}

63
static hb_position_t
64
hb_font_get_glyph_h_advance_nil (hb_font_t *font,
65 66 67
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
				 void *user_data HB_UNUSED)
68
{
69
  if (font->parent)
B
Behdad Esfahbod 已提交
70
    return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
71

72
  return font->x_scale;
73
}
B
Behdad Esfahbod 已提交
74

75
static hb_position_t
76
hb_font_get_glyph_v_advance_nil (hb_font_t *font,
77 78 79
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
				 void *user_data HB_UNUSED)
80
{
81
  if (font->parent)
B
Behdad Esfahbod 已提交
82
    return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
83

84
  return font->y_scale;
85 86
}

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

B
Behdad Esfahbod 已提交
102
  *x = *y = 0;
103
  return false;
B
Behdad Esfahbod 已提交
104 105
}

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

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

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

135
  return 0;
136 137
}

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

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

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

167
  memset (extents, 0, sizeof (*extents));
168
  return false;
169
}
170

171
static hb_bool_t
172
hb_font_get_glyph_contour_point_nil (hb_font_t *font,
B
Behdad Esfahbod 已提交
173 174 175 176 177 178
				     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)
179
{
180
  if (font->parent) {
B
Behdad Esfahbod 已提交
181
    hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
182 183
    if (ret)
      font->parent_scale_position (x, y);
184
    return ret;
185
  }
186

187
  *x = *y = 0;
188
  return false;
189
}
B
Behdad Esfahbod 已提交
190

191 192 193 194 195 196 197 198
static hb_bool_t
hb_font_get_glyph_name_nil (hb_font_t *font,
			    void *font_data HB_UNUSED,
			    hb_codepoint_t glyph,
			    char *name, unsigned int size,
			    void *user_data HB_UNUSED)
{
  if (font->parent)
B
Behdad Esfahbod 已提交
199
    return font->parent->get_glyph_name (glyph, name, size);
200

201
  if (size) *name = '\0';
202
  return false;
203 204 205 206 207 208 209 210 211 212
}

static hb_bool_t
hb_font_get_glyph_from_name_nil (hb_font_t *font,
				 void *font_data HB_UNUSED,
				 const char *name, int len, /* -1 means nul-terminated */
				 hb_codepoint_t *glyph,
				 void *user_data HB_UNUSED)
{
  if (font->parent)
B
Behdad Esfahbod 已提交
213
    return font->parent->get_glyph_from_name (name, len, glyph);
214 215

  *glyph = 0;
216
  return false;
217 218
}

B
Behdad Esfahbod 已提交
219

220
static const hb_font_funcs_t _hb_font_funcs_nil = {
221 222
  HB_OBJECT_HEADER_STATIC,

223
  true, /* immutable */
224

225
  {
226 227 228
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
229
  }
230 231
};

B
Behdad Esfahbod 已提交
232

B
Behdad Esfahbod 已提交
233 234
hb_font_funcs_t *
hb_font_funcs_create (void)
235
{
B
Behdad Esfahbod 已提交
236
  hb_font_funcs_t *ffuncs;
237

238
  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
239
    return hb_font_funcs_get_empty ();
240

241
  ffuncs->get = _hb_font_funcs_nil.get;
242

B
Behdad Esfahbod 已提交
243
  return ffuncs;
244 245
}

246 247 248
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
249
  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
250 251
}

B
Behdad Esfahbod 已提交
252 253
hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
254
{
255
  return hb_object_reference (ffuncs);
256 257 258
}

void
B
Behdad Esfahbod 已提交
259
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
260
{
261
  if (!hb_object_destroy (ffuncs)) return;
262

B
Behdad Esfahbod 已提交
263 264
#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
  ffuncs->destroy.name (ffuncs->user_data.name);
265 266
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
267

B
Behdad Esfahbod 已提交
268
  free (ffuncs);
269 270
}

271 272 273 274
hb_bool_t
hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
			     hb_user_data_key_t *key,
			     void *              data,
275 276
			     hb_destroy_func_t   destroy,
			     hb_bool_t           replace)
277
{
278
  return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
279 280 281 282 283 284 285 286 287 288
}

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);
}


289 290 291
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
292
  if (hb_object_is_inert (ffuncs))
293 294
    return;

295
  ffuncs->immutable = true;
B
Behdad Esfahbod 已提交
296 297 298 299 300
}

hb_bool_t
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
{
B
Behdad Esfahbod 已提交
301
  return ffuncs->immutable;
302 303
}

304

305
#define HB_FONT_FUNC_IMPLEMENT(name) \
306 307 308 309 310 311 312
                                                                         \
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)   \
{                                                                        \
B
Behdad Esfahbod 已提交
313 314 315
  if (ffuncs->immutable) {                                               \
    if (destroy)                                                         \
      destroy (user_data);                                               \
316
    return;                                                              \
B
Behdad Esfahbod 已提交
317
  }                                                                      \
318 319 320 321 322 323 324 325 326 327 328 329 330
                                                                         \
  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 已提交
331 332
}

333 334 335 336
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT


B
Behdad Esfahbod 已提交
337 338
/* Public getters */

339 340 341 342 343
hb_bool_t
hb_font_get_glyph (hb_font_t *font,
		   hb_codepoint_t unicode, hb_codepoint_t variation_selector,
		   hb_codepoint_t *glyph)
{
B
Behdad Esfahbod 已提交
344
  return font->get_glyph (unicode, variation_selector, glyph);
345 346
}

347
hb_position_t
348
hb_font_get_glyph_h_advance (hb_font_t *font,
349
			     hb_codepoint_t glyph)
350
{
B
Behdad Esfahbod 已提交
351
  return font->get_glyph_h_advance (glyph);
352 353
}

354
hb_position_t
355
hb_font_get_glyph_v_advance (hb_font_t *font,
356
			     hb_codepoint_t glyph)
357
{
B
Behdad Esfahbod 已提交
358
  return font->get_glyph_v_advance (glyph);
359 360
}

B
Behdad Esfahbod 已提交
361 362 363
hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
364
			    hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
365
{
B
Behdad Esfahbod 已提交
366
  return font->get_glyph_h_origin (glyph, x, y);
B
Behdad Esfahbod 已提交
367 368
}

369 370 371
hb_bool_t
hb_font_get_glyph_v_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
372
			    hb_position_t *x, hb_position_t *y)
373
{
B
Behdad Esfahbod 已提交
374
  return font->get_glyph_v_origin (glyph, x, y);
375 376
}

377
hb_position_t
B
Behdad Esfahbod 已提交
378
hb_font_get_glyph_h_kerning (hb_font_t *font,
379
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
380
{
B
Behdad Esfahbod 已提交
381
  return font->get_glyph_h_kerning (left_glyph, right_glyph);
382
}
B
Behdad Esfahbod 已提交
383

384
hb_position_t
B
Behdad Esfahbod 已提交
385
hb_font_get_glyph_v_kerning (hb_font_t *font,
386
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
387
{
B
Behdad Esfahbod 已提交
388
  return font->get_glyph_v_kerning (left_glyph, right_glyph);
389
}
B
Behdad Esfahbod 已提交
390

391 392 393 394 395
hb_bool_t
hb_font_get_glyph_extents (hb_font_t *font,
			   hb_codepoint_t glyph,
			   hb_glyph_extents_t *extents)
{
B
Behdad Esfahbod 已提交
396
  return font->get_glyph_extents (glyph, extents);
397
}
398

399
hb_bool_t
B
Behdad Esfahbod 已提交
400 401 402
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 已提交
403
{
B
Behdad Esfahbod 已提交
404
  return font->get_glyph_contour_point (glyph, point_index, x, y);
B
Behdad Esfahbod 已提交
405 406
}

407 408 409 410 411
hb_bool_t
hb_font_get_glyph_name (hb_font_t *font,
			hb_codepoint_t glyph,
			char *name, unsigned int size)
{
412
  return font->get_glyph_name (glyph, name, size);
413 414 415 416 417 418 419
}

hb_bool_t
hb_font_get_glyph_from_name (hb_font_t *font,
			     const char *name, int len, /* -1 means nul-terminated */
			     hb_codepoint_t *glyph)
{
B
Behdad Esfahbod 已提交
420
  return font->get_glyph_from_name (name, len, glyph);
421 422
}

423 424 425

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

426
void
427 428 429
hb_font_get_glyph_advance_for_direction (hb_font_t *font,
					 hb_codepoint_t glyph,
					 hb_direction_t direction,
B
Behdad Esfahbod 已提交
430
					 hb_position_t *x, hb_position_t *y)
431
{
B
Behdad Esfahbod 已提交
432
  return font->get_glyph_advance_for_direction (glyph, direction, x, y);
433 434
}

435
void
B
Behdad Esfahbod 已提交
436 437 438
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
					hb_codepoint_t glyph,
					hb_direction_t direction,
B
Behdad Esfahbod 已提交
439
					hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
440
{
B
Behdad Esfahbod 已提交
441
  return font->get_glyph_origin_for_direction (glyph, direction, x, y);
B
Behdad Esfahbod 已提交
442 443
}

B
Behdad Esfahbod 已提交
444 445 446 447 448 449
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)
{
B
Behdad Esfahbod 已提交
450
  return font->add_glyph_origin_for_direction (glyph, direction, x, y);
B
Behdad Esfahbod 已提交
451 452 453 454 455 456 457 458
}

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)
{
B
Behdad Esfahbod 已提交
459
  return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
B
Behdad Esfahbod 已提交
460 461
}

B
Behdad Esfahbod 已提交
462 463 464 465
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 已提交
466
					 hb_position_t *x, hb_position_t *y)
467
{
B
Behdad Esfahbod 已提交
468
  return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
469 470
}

471 472 473 474 475
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 已提交
476
{
B
Behdad Esfahbod 已提交
477
  return font->get_glyph_extents_for_origin (glyph, direction, extents);
B
Behdad Esfahbod 已提交
478 479
}

480
hb_bool_t
481 482 483 484
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 已提交
485
{
B
Behdad Esfahbod 已提交
486
  return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
B
Behdad Esfahbod 已提交
487 488
}

489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
/* Generates gidDDD if glyph has no name. */
void
hb_font_glyph_to_string (hb_font_t *font,
			 hb_codepoint_t glyph,
			 char *s, unsigned int size)
{
  font->glyph_to_string (glyph, s, size);
}

/* Parses gidDDD and uniUUUU strings automatically. */
hb_bool_t
hb_font_glyph_from_string (hb_font_t *font,
			   const char *s, int len, /* -1 means nul-terminated */
			   hb_codepoint_t *glyph)
{
  return font->glyph_from_string (s, len, glyph);
}

507

508 509 510 511
/*
 * hb_face_t
 */

512
static const hb_face_t _hb_face_nil = {
513
  HB_OBJECT_HEADER_STATIC,
514

515
  true, /* immutable */
516

B
Behdad Esfahbod 已提交
517
  NULL, /* reference_table_func */
518
  NULL, /* user_data */
519
  NULL, /* destroy */
520

B
Behdad Esfahbod 已提交
521
  0,    /* index */
522 523 524 525 526 527
  1000, /* upem */

  {
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
B
Behdad Esfahbod 已提交
528 529 530
  },

  NULL, /* shape_plans */
531 532
};

533

534
hb_face_t *
B
Behdad Esfahbod 已提交
535
hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
536 537
			   void                      *user_data,
			   hb_destroy_func_t          destroy)
538 539 540
{
  hb_face_t *face;

B
Behdad Esfahbod 已提交
541
  if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
542 543
    if (destroy)
      destroy (user_data);
544
    return hb_face_get_empty ();
545 546
  }

B
Behdad Esfahbod 已提交
547
  face->reference_table_func = reference_table_func;
548
  face->user_data = user_data;
549
  face->destroy = destroy;
550

B
Behdad Esfahbod 已提交
551
  face->upem = 0;
552

553 554 555
  return face;
}

556

557
typedef struct hb_face_for_data_closure_t {
558 559 560 561 562 563 564 565 566 567
  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));
568
  if (unlikely (!closure))
569
    return NULL;
570

B
Behdad Esfahbod 已提交
571
  closure->blob = blob;
572 573 574 575 576 577 578 579
  closure->index = index;

  return closure;
}

static void
_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
{
580 581
  hb_blob_destroy (closure->blob);
  free (closure);
582 583 584
}

static hb_blob_t *
585
_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
586 587 588
{
  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;

B
Behdad Esfahbod 已提交
589 590 591
  if (tag == HB_TAG_NONE)
    return hb_blob_reference (data->blob);

592 593
  const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
594

595
  const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
596 597 598 599 600 601

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

  return blob;
}

602
hb_face_t *
603 604
hb_face_create (hb_blob_t    *blob,
		unsigned int  index)
605
{
B
Behdad Esfahbod 已提交
606 607
  hb_face_t *face;

B
Behdad Esfahbod 已提交
608
  if (unlikely (!blob || !hb_blob_get_length (blob)))
609
    return hb_face_get_empty ();
610

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

613
  if (unlikely (!closure))
614
    return hb_face_get_empty ();
615

B
Behdad Esfahbod 已提交
616
  face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
617 618
				    closure,
				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
B
Behdad Esfahbod 已提交
619 620 621 622

  hb_face_set_index (face, index);

  return face;
623 624
}

625 626 627
hb_face_t *
hb_face_get_empty (void)
{
628
  return const_cast<hb_face_t *> (&_hb_face_nil);
629 630
}

631

632 633 634
hb_face_t *
hb_face_reference (hb_face_t *face)
{
635
  return hb_object_reference (face);
636 637 638 639 640
}

void
hb_face_destroy (hb_face_t *face)
{
641
  if (!hb_object_destroy (face)) return;
642

B
Behdad Esfahbod 已提交
643 644 645 646 647 648 649 650
  for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
  {
    hb_face_t::plan_node_t *next = node->next;
    hb_shape_plan_destroy (node->shape_plan);
    free (node);
    node = next;
  }

651 652 653 654
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT

655 656 657 658 659 660
  if (face->destroy)
    face->destroy (face->user_data);

  free (face);
}

661 662 663 664
hb_bool_t
hb_face_set_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key,
		       void *              data,
665 666
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace)
667
{
668
  return hb_object_set_user_data (face, key, data, destroy, replace);
669 670 671 672 673 674 675 676 677
}

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

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
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;
}

693

694
hb_blob_t *
695
hb_face_reference_table (hb_face_t *face,
696
			 hb_tag_t   tag)
697
{
B
Behdad Esfahbod 已提交
698
  return face->reference_table (tag);
699
}
700

B
Behdad Esfahbod 已提交
701 702 703
hb_blob_t *
hb_face_reference_blob (hb_face_t *face)
{
B
Behdad Esfahbod 已提交
704
  return face->reference_table (HB_TAG_NONE);
B
Behdad Esfahbod 已提交
705 706 707 708 709 710 711 712 713
}

void
hb_face_set_index (hb_face_t    *face,
		   unsigned int  index)
{
  if (hb_object_is_inert (face))
    return;

B
Behdad Esfahbod 已提交
714
  face->index = index;
B
Behdad Esfahbod 已提交
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
}

unsigned int
hb_face_get_index (hb_face_t    *face)
{
  return face->index;
}

void
hb_face_set_upem (hb_face_t    *face,
		  unsigned int  upem)
{
  if (hb_object_is_inert (face))
    return;

  face->upem = upem;
}

B
Behdad Esfahbod 已提交
733 734 735
unsigned int
hb_face_get_upem (hb_face_t *face)
{
B
Behdad Esfahbod 已提交
736 737 738 739 740 741 742
  return face->get_upem ();
}


void
hb_face_t::load_upem (void) const
{
743 744
  hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
  const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
B
Behdad Esfahbod 已提交
745 746
  upem = head_table->get_upem ();
  hb_blob_destroy (head_blob);
B
Behdad Esfahbod 已提交
747 748
}

749 750 751 752 753 754

/*
 * hb_font_t
 */

hb_font_t *
755
hb_font_create (hb_face_t *face)
756 757 758
{
  hb_font_t *font;

759
  if (unlikely (!face))
760
    face = hb_face_get_empty ();
761
  if (unlikely (hb_object_is_inert (face)))
762
    return hb_font_get_empty ();
763
  if (!(font = hb_object_create<hb_font_t> ()))
764
    return hb_font_get_empty ();
765

766
  hb_face_make_immutable (face);
767
  font->face = hb_face_reference (face);
768
  font->klass = hb_font_funcs_get_empty ();
B
Behdad Esfahbod 已提交
769

770 771 772
  return font;
}

773 774 775 776
hb_font_t *
hb_font_create_sub_font (hb_font_t *parent)
{
  if (unlikely (!parent))
777
    return hb_font_get_empty ();
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794

  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;

  return font;
}

795 796 797
hb_font_t *
hb_font_get_empty (void)
{
798 799 800
  static const hb_font_t _hb_font_nil = {
    HB_OBJECT_HEADER_STATIC,

801
    true, /* immutable */
802 803 804 805 806 807 808 809 810 811 812 813

    NULL, /* parent */
    const_cast<hb_face_t *> (&_hb_face_nil),

    0, /* x_scale */
    0, /* y_scale */

    0, /* x_ppem */
    0, /* y_ppem */

    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
    NULL, /* user_data */
814 815 816 817 818 819 820
    NULL, /* destroy */

    {
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
    }
821 822 823
  };

  return const_cast<hb_font_t *> (&_hb_font_nil);
824 825
}

826 827 828
hb_font_t *
hb_font_reference (hb_font_t *font)
{
829
  return hb_object_reference (font);
830 831 832 833 834
}

void
hb_font_destroy (hb_font_t *font)
{
835
  if (!hb_object_destroy (font)) return;
836

837 838 839 840 841 842 843
#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT

  if (font->destroy)
    font->destroy (font->user_data);

844
  hb_font_destroy (font->parent);
845
  hb_face_destroy (font->face);
B
Behdad Esfahbod 已提交
846
  hb_font_funcs_destroy (font->klass);
847 848 849 850

  free (font);
}

851 852 853 854
hb_bool_t
hb_font_set_user_data (hb_font_t          *font,
		       hb_user_data_key_t *key,
		       void *              data,
855 856
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace)
857
{
858
  return hb_object_set_user_data (font, key, data, destroy, replace);
859 860 861 862 863 864 865 866 867
}

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

868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
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;
}

883 884 885 886 887
hb_font_t *
hb_font_get_parent (hb_font_t *font)
{
  return font->parent;
}
888

889 890 891 892 893 894 895
hb_face_t *
hb_font_get_face (hb_font_t *font)
{
  return font->face;
}


B
Behdad Esfahbod 已提交
896
void
B
Behdad Esfahbod 已提交
897 898
hb_font_set_funcs (hb_font_t         *font,
		   hb_font_funcs_t   *klass,
899 900
		   void              *user_data,
		   hb_destroy_func_t  destroy)
901
{
B
Behdad Esfahbod 已提交
902 903 904
  if (font->immutable) {
    if (destroy)
      destroy (user_data);
B
Behdad Esfahbod 已提交
905
    return;
B
Behdad Esfahbod 已提交
906
  }
907

B
Behdad Esfahbod 已提交
908 909 910
  if (font->destroy)
    font->destroy (font->user_data);

B
Behdad Esfahbod 已提交
911
  if (!klass)
912
    klass = hb_font_funcs_get_empty ();
B
Behdad Esfahbod 已提交
913

B
Behdad Esfahbod 已提交
914 915 916
  hb_font_funcs_reference (klass);
  hb_font_funcs_destroy (font->klass);
  font->klass = klass;
B
Behdad Esfahbod 已提交
917
  font->user_data = user_data;
918
  font->destroy = destroy;
919 920
}

921 922 923 924 925
void
hb_font_set_funcs_data (hb_font_t         *font,
		        void              *user_data,
		        hb_destroy_func_t  destroy)
{
B
Behdad Esfahbod 已提交
926 927 928 929
  /* Destroy user_data? */
  if (font->immutable) {
    if (destroy)
      destroy (user_data);
930
    return;
B
Behdad Esfahbod 已提交
931
  }
932 933 934 935 936 937 938 939

  if (font->destroy)
    font->destroy (font->user_data);

  font->user_data = user_data;
  font->destroy = destroy;
}

B
Behdad Esfahbod 已提交
940

941 942
void
hb_font_set_scale (hb_font_t *font,
943 944
		   int x_scale,
		   int y_scale)
945
{
946
  if (font->immutable)
947 948 949 950 951 952
    return;

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

B
Behdad Esfahbod 已提交
953 954
void
hb_font_get_scale (hb_font_t *font,
955 956
		   int *x_scale,
		   int *y_scale)
B
Behdad Esfahbod 已提交
957 958 959 960 961
{
  if (x_scale) *x_scale = font->x_scale;
  if (y_scale) *y_scale = font->y_scale;
}

962 963 964 965 966
void
hb_font_set_ppem (hb_font_t *font,
		  unsigned int x_ppem,
		  unsigned int y_ppem)
{
967
  if (font->immutable)
968 969 970 971 972 973
    return;

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

B
Behdad Esfahbod 已提交
974 975 976 977 978 979 980 981
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;
}