hb-font.cc 22.7 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
#include "hb-ot-head-table.hh"
35

36 37
#include "hb-cache-private.hh"

B
Behdad Esfahbod 已提交
38 39
#include <string.h>

B
Behdad Esfahbod 已提交
40

B
Behdad Esfahbod 已提交
41

42
/*
B
Behdad Esfahbod 已提交
43
 * hb_font_funcs_t
44 45
 */

46
static hb_bool_t
47 48 49 50 51 52 53 54 55 56 57 58 59 60
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;
}

61
static hb_position_t
62 63 64 65
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)
66
{
67 68
  if (font->parent)
    return font->parent_scale_x_distance (hb_font_get_glyph_h_advance (font->parent, glyph));
69

70
  return font->x_scale;
71
}
B
Behdad Esfahbod 已提交
72

73
static hb_position_t
74 75 76 77
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)
78
{
79 80
  if (font->parent)
    return font->parent_scale_y_distance (hb_font_get_glyph_v_advance (font->parent, glyph));
81

82
  return font->y_scale;
83 84
}

B
Behdad Esfahbod 已提交
85 86 87 88
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 已提交
89 90
				hb_position_t *x,
				hb_position_t *y,
B
Behdad Esfahbod 已提交
91 92 93 94 95
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
96
						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;
B
Behdad Esfahbod 已提交
103 104 105
  return FALSE;
}

106 107 108 109
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 已提交
110 111
				hb_position_t *x,
				hb_position_t *y,
112 113 114 115 116
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
117
						x, y);
118 119
    if (ret)
      font->parent_scale_position (x, y);
120 121 122
    return ret;
  }

B
Behdad Esfahbod 已提交
123
  *x = *y = 0;
124 125 126
  return FALSE;
}

127
static hb_position_t
B
Behdad Esfahbod 已提交
128 129 130 131 132
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)
133
{
134 135
  if (font->parent)
    return font->parent_scale_x_distance (hb_font_get_glyph_h_kerning (font->parent, left_glyph, right_glyph));
136

137
  return 0;
138 139
}

140
static hb_position_t
B
Behdad Esfahbod 已提交
141 142 143 144 145
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)
146
{
147 148
  if (font->parent)
    return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, top_glyph, bottom_glyph));
149

150
  return 0;
151
}
B
Behdad Esfahbod 已提交
152

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

171
  memset (extents, 0, sizeof (*extents));
172
  return FALSE;
173
}
174

175
static hb_bool_t
B
Behdad Esfahbod 已提交
176 177 178 179 180 181 182
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)
183
{
184
  if (font->parent) {
B
Behdad Esfahbod 已提交
185 186 187
    hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
						     glyph, point_index,
						     x, y);
188 189
    if (ret)
      font->parent_scale_position (x, y);
190
    return ret;
191
  }
192

193 194
  *x = *y = 0;
  return FALSE;
195
}
B
Behdad Esfahbod 已提交
196

B
Behdad Esfahbod 已提交
197 198

static hb_font_funcs_t _hb_font_funcs_nil = {
199 200
  HB_OBJECT_HEADER_STATIC,

201
  TRUE, /* immutable */
202

203
  {
204 205 206
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
207
  }
208 209
};

B
Behdad Esfahbod 已提交
210

B
Behdad Esfahbod 已提交
211 212
hb_font_funcs_t *
hb_font_funcs_create (void)
213
{
B
Behdad Esfahbod 已提交
214
  hb_font_funcs_t *ffuncs;
215

216
  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
B
Behdad Esfahbod 已提交
217
    return &_hb_font_funcs_nil;
218

219
  ffuncs->get = _hb_font_funcs_nil.get;
220

B
Behdad Esfahbod 已提交
221
  return ffuncs;
222 223
}

224 225 226 227 228 229
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
  return &_hb_font_funcs_nil;
}

B
Behdad Esfahbod 已提交
230 231
hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
232
{
233
  return hb_object_reference (ffuncs);
234 235 236
}

void
B
Behdad Esfahbod 已提交
237
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
238
{
239
  if (!hb_object_destroy (ffuncs)) return;
240

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

B
Behdad Esfahbod 已提交
246
  free (ffuncs);
247 248
}

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

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


267 268 269
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
270
  if (hb_object_is_inert (ffuncs))
271 272 273
    return;

  ffuncs->immutable = TRUE;
B
Behdad Esfahbod 已提交
274 275 276 277 278
}

hb_bool_t
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
{
B
Behdad Esfahbod 已提交
279
  return ffuncs->immutable;
280 281
}

282

283
#define HB_FONT_FUNC_IMPLEMENT(name) \
284 285 286 287 288 289 290
                                                                         \
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 已提交
291 292 293
  if (ffuncs->immutable) {                                               \
    if (destroy)                                                         \
      destroy (user_data);                                               \
294
    return;                                                              \
B
Behdad Esfahbod 已提交
295
  }                                                                      \
296 297 298 299 300 301 302 303 304 305 306 307 308
                                                                         \
  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 已提交
309 310
}

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
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);
}

326
hb_position_t
327
hb_font_get_glyph_h_advance (hb_font_t *font,
328
			     hb_codepoint_t glyph)
329
{
330 331 332
  return font->klass->get.glyph_h_advance (font, font->user_data,
					   glyph,
					   font->klass->user_data.glyph_h_advance);
333 334
}

335
hb_position_t
336
hb_font_get_glyph_v_advance (hb_font_t *font,
337
			     hb_codepoint_t glyph)
338
{
339 340 341
  return font->klass->get.glyph_v_advance (font, font->user_data,
					   glyph,
					   font->klass->user_data.glyph_v_advance);
342 343
}

B
Behdad Esfahbod 已提交
344 345 346
hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
347
			    hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
348
{
B
Behdad Esfahbod 已提交
349
  *x = *y = 0;
B
Behdad Esfahbod 已提交
350
  return font->klass->get.glyph_h_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
351
					   glyph, x, y,
B
Behdad Esfahbod 已提交
352 353 354
					   font->klass->user_data.glyph_h_origin);
}

355 356 357
hb_bool_t
hb_font_get_glyph_v_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
358
			    hb_position_t *x, hb_position_t *y)
359
{
B
Behdad Esfahbod 已提交
360
  *x = *y = 0;
361
  return font->klass->get.glyph_v_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
362
					   glyph, x, y,
363 364 365
					   font->klass->user_data.glyph_v_origin);
}

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

375
hb_position_t
B
Behdad Esfahbod 已提交
376
hb_font_get_glyph_v_kerning (hb_font_t *font,
377
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
378
{
B
Behdad Esfahbod 已提交
379
  return font->klass->get.glyph_v_kerning (font, font->user_data,
380
				     left_glyph, right_glyph,
B
Behdad Esfahbod 已提交
381
				     font->klass->user_data.glyph_v_kerning);
382
}
B
Behdad Esfahbod 已提交
383

384 385 386 387 388 389 390 391 392 393 394
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);
}
395

396
hb_bool_t
B
Behdad Esfahbod 已提交
397 398 399
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 已提交
400
{
401
  *x = *y = 0;
B
Behdad Esfahbod 已提交
402 403 404 405
  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 已提交
406 407
}

408 409 410

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

411
void
412 413 414
hb_font_get_glyph_advance_for_direction (hb_font_t *font,
					 hb_codepoint_t glyph,
					 hb_direction_t direction,
B
Behdad Esfahbod 已提交
415
					 hb_position_t *x, hb_position_t *y)
416
{
417
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
418
    *x = hb_font_get_glyph_h_advance (font, glyph);
419
    *y = 0;
420
  } else {
421
    *x = 0;
422
    *y = hb_font_get_glyph_v_advance (font, glyph);
423
  }
424 425
}

426 427 428 429 430
static void
guess_v_origin_minus_h_origin (hb_font_t *font,
			       hb_codepoint_t glyph,
			       hb_position_t *x, hb_position_t *y)
{
431
  *x = hb_font_get_glyph_h_advance (font, glyph) / 2;
432 433 434 435 436 437

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


438
void
B
Behdad Esfahbod 已提交
439 440 441
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
					hb_codepoint_t glyph,
					hb_direction_t direction,
B
Behdad Esfahbod 已提交
442
					hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
443
{
444
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
445 446 447 448 449 450
    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;
    }
451
  } else {
B
Behdad Esfahbod 已提交
452
    hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
453 454 455 456
    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 已提交
457 458 459 460
    }
  }
}

B
Behdad Esfahbod 已提交
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
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 已提交
489 490 491 492
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 已提交
493
					 hb_position_t *x, hb_position_t *y)
494
{
495
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
496
    *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
497 498 499
    *y = 0;
  } else {
    *x = 0;
500
    *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
501
  }
502 503
}

504 505 506 507 508
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 已提交
509
{
B
Behdad Esfahbod 已提交
510
  hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
511

B
Behdad Esfahbod 已提交
512 513
  if (ret)
    hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, &extents->x_bearing, &extents->y_bearing);
514 515

  return ret;
B
Behdad Esfahbod 已提交
516 517
}

518
hb_bool_t
519 520 521 522
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 已提交
523
{
B
Behdad Esfahbod 已提交
524
  hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
525

B
Behdad Esfahbod 已提交
526 527
  if (ret)
    hb_font_subtract_glyph_origin_for_direction (font, glyph, direction, x, y);
528 529

  return ret;
B
Behdad Esfahbod 已提交
530 531
}

532

533 534 535 536 537
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
538
  HB_OBJECT_HEADER_STATIC,
539

540 541
  TRUE, /* immutable */

542
  NULL, /* reference_table */
543
  NULL, /* user_data */
544
  NULL, /* destroy */
545

546 547
  NULL, /* ot_layout */

B
Behdad Esfahbod 已提交
548 549
  0,    /* index */
  1000  /* upem */
550 551
};

552

553
hb_face_t *
554 555 556
hb_face_create_for_tables (hb_reference_table_func_t  reference_table,
			   void                      *user_data,
			   hb_destroy_func_t          destroy)
557 558 559
{
  hb_face_t *face;

560
  if (!reference_table || !(face = hb_object_create<hb_face_t> ())) {
561 562 563 564 565
    if (destroy)
      destroy (user_data);
    return &_hb_face_nil;
  }

566
  face->reference_table = reference_table;
567
  face->user_data = user_data;
568
  face->destroy = destroy;
569

570
  face->ot_layout = _hb_ot_layout_create (face);
571

B
Behdad Esfahbod 已提交
572
  face->upem = 0;
573

574 575 576
  return face;
}

577 578 579 580 581 582 583 584 585 586 587 588

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));
589
  if (unlikely (!closure))
590
    return NULL;
591

B
Behdad Esfahbod 已提交
592
  closure->blob = blob;
593 594 595 596 597 598 599 600
  closure->index = index;

  return closure;
}

static void
_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
{
601 602
  hb_blob_destroy (closure->blob);
  free (closure);
603 604 605
}

static hb_blob_t *
606
_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
607 608 609
{
  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;

B
Behdad Esfahbod 已提交
610 611 612
  if (tag == HB_TAG_NONE)
    return hb_blob_reference (data->blob);

613
  const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
614 615 616 617 618 619 620 621 622
  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;
}

623
hb_face_t *
624 625
hb_face_create (hb_blob_t    *blob,
		unsigned int  index)
626
{
B
Behdad Esfahbod 已提交
627 628
  hb_face_t *face;

B
Behdad Esfahbod 已提交
629
  if (unlikely (!blob || !hb_blob_get_length (blob)))
630 631
    return &_hb_face_nil;

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

634 635
  if (unlikely (!closure))
    return &_hb_face_nil;
636

B
Behdad Esfahbod 已提交
637
  face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
638 639
				    closure,
				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
B
Behdad Esfahbod 已提交
640 641 642 643

  hb_face_set_index (face, index);

  return face;
644 645
}

646 647 648 649 650 651
hb_face_t *
hb_face_get_empty (void)
{
  return &_hb_face_nil;
}

652

653 654 655
hb_face_t *
hb_face_reference (hb_face_t *face)
{
656
  return hb_object_reference (face);
657 658 659 660 661
}

void
hb_face_destroy (hb_face_t *face)
{
662
  if (!hb_object_destroy (face)) return;
663

664
  _hb_ot_layout_destroy (face->ot_layout);
B
Behdad Esfahbod 已提交
665

666 667 668 669 670 671
  if (face->destroy)
    face->destroy (face->user_data);

  free (face);
}

672 673 674 675
hb_bool_t
hb_face_set_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key,
		       void *              data,
676 677
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace)
678
{
679
  return hb_object_set_user_data (face, key, data, destroy, replace);
680 681 682 683 684 685 686 687 688
}

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

689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
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;
}

704

705
hb_blob_t *
706
hb_face_reference_table (hb_face_t *face,
707
			 hb_tag_t   tag)
708
{
709 710
  hb_blob_t *blob;

711
  if (unlikely (!face || !face->reference_table))
B
Behdad Esfahbod 已提交
712
    return hb_blob_get_empty ();
713

714
  blob = face->reference_table (face, tag, face->user_data);
715
  if (unlikely (!blob))
B
Behdad Esfahbod 已提交
716
    return hb_blob_get_empty ();
717

718
  return blob;
719
}
720

B
Behdad Esfahbod 已提交
721 722 723 724 725 726 727 728 729 730 731 732 733
hb_blob_t *
hb_face_reference_blob (hb_face_t *face)
{
  return hb_face_reference_table (face, HB_TAG_NONE);
}

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

B
Behdad Esfahbod 已提交
734
  face->index = index;
B
Behdad Esfahbod 已提交
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
}

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 已提交
753 754 755
unsigned int
hb_face_get_upem (hb_face_t *face)
{
B
Behdad Esfahbod 已提交
756 757 758 759 760 761 762
  if (unlikely (!face->upem)) {
    hb_blob_t *head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head));
    const head *head_table = Sanitizer<head>::lock_instance (head_blob);
    face->upem = head_table->get_upem ();
    hb_blob_destroy (head_blob);
  }
  return face->upem;
B
Behdad Esfahbod 已提交
763 764
}

765 766 767 768 769 770

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
771
  HB_OBJECT_HEADER_STATIC,
772

773
  TRUE, /* immutable */
774

775
  NULL, /* parent */
776 777
  &_hb_face_nil,

778 779 780 781
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
782 783
  0, /* y_ppem */

784
  &_hb_font_funcs_nil, /* klass */
785 786
  NULL, /* user_data */
  NULL  /* destroy */
787 788 789
};

hb_font_t *
790
hb_font_create (hb_face_t *face)
791 792 793
{
  hb_font_t *font;

794 795 796 797
  if (unlikely (!face))
    face = &_hb_face_nil;
  if (unlikely (hb_object_is_inert (face)))
    return &_hb_font_nil;
798
  if (!(font = hb_object_create<hb_font_t> ()))
799 800
    return &_hb_font_nil;

801
  hb_face_make_immutable (face);
802
  font->face = hb_face_reference (face);
B
Behdad Esfahbod 已提交
803 804
  font->klass = &_hb_font_funcs_nil;

805 806 807
  return font;
}

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
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 已提交
827
  font->klass = &_hb_font_funcs_nil;
828 829 830 831

  return font;
}

832 833 834 835 836 837
hb_font_t *
hb_font_get_empty (void)
{
  return &_hb_font_nil;
}

838 839 840
hb_font_t *
hb_font_reference (hb_font_t *font)
{
841
  return hb_object_reference (font);
842 843 844 845 846
}

void
hb_font_destroy (hb_font_t *font)
{
847
  if (!hb_object_destroy (font)) return;
848

849
  hb_font_destroy (font->parent);
850
  hb_face_destroy (font->face);
B
Behdad Esfahbod 已提交
851
  hb_font_funcs_destroy (font->klass);
B
Behdad Esfahbod 已提交
852 853
  if (font->destroy)
    font->destroy (font->user_data);
854 855 856 857

  free (font);
}

858 859 860 861
hb_bool_t
hb_font_set_user_data (hb_font_t          *font,
		       hb_user_data_key_t *key,
		       void *              data,
862 863
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace)
864
{
865
  return hb_object_set_user_data (font, key, data, destroy, replace);
866 867 868 869 870 871 872 873 874
}

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

875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
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;
}

890 891 892 893 894
hb_font_t *
hb_font_get_parent (hb_font_t *font)
{
  return font->parent;
}
895

896 897 898 899 900 901 902
hb_face_t *
hb_font_get_face (hb_font_t *font)
{
  return font->face;
}


B
Behdad Esfahbod 已提交
903
void
B
Behdad Esfahbod 已提交
904 905
hb_font_set_funcs (hb_font_t         *font,
		   hb_font_funcs_t   *klass,
906 907
		   void              *user_data,
		   hb_destroy_func_t  destroy)
908
{
B
Behdad Esfahbod 已提交
909 910 911
  if (font->immutable) {
    if (destroy)
      destroy (user_data);
B
Behdad Esfahbod 已提交
912
    return;
B
Behdad Esfahbod 已提交
913
  }
914

B
Behdad Esfahbod 已提交
915 916 917
  if (font->destroy)
    font->destroy (font->user_data);

B
Behdad Esfahbod 已提交
918 919 920
  if (!klass)
    klass = &_hb_font_funcs_nil;

B
Behdad Esfahbod 已提交
921 922 923
  hb_font_funcs_reference (klass);
  hb_font_funcs_destroy (font->klass);
  font->klass = klass;
B
Behdad Esfahbod 已提交
924
  font->user_data = user_data;
925
  font->destroy = destroy;
926 927
}

928 929 930 931 932
void
hb_font_set_funcs_data (hb_font_t         *font,
		        void              *user_data,
		        hb_destroy_func_t  destroy)
{
B
Behdad Esfahbod 已提交
933 934 935 936
  /* Destroy user_data? */
  if (font->immutable) {
    if (destroy)
      destroy (user_data);
937
    return;
B
Behdad Esfahbod 已提交
938
  }
939 940 941 942 943 944 945 946

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

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

B
Behdad Esfahbod 已提交
947

948 949
void
hb_font_set_scale (hb_font_t *font,
950 951
		   int x_scale,
		   int y_scale)
952
{
953
  if (font->immutable)
954 955 956 957 958 959
    return;

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

B
Behdad Esfahbod 已提交
960 961
void
hb_font_get_scale (hb_font_t *font,
962 963
		   int *x_scale,
		   int *y_scale)
B
Behdad Esfahbod 已提交
964 965 966 967 968
{
  if (x_scale) *x_scale = font->x_scale;
  if (y_scale) *y_scale = font->y_scale;
}

969 970 971 972 973
void
hb_font_set_ppem (hb_font_t *font,
		  unsigned int x_ppem,
		  unsigned int y_ppem)
{
974
  if (font->immutable)
975 976 977 978 979 980
    return;

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

B
Behdad Esfahbod 已提交
981 982 983 984 985 986 987 988 989
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 已提交
990