hb-font.cc 22.0 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

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

B
Behdad Esfahbod 已提交
38

B
Behdad Esfahbod 已提交
39

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

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

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

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

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

80
  return font->y_scale;
81 82
}

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

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

104 105 106 107
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 已提交
108 109
				hb_position_t *x,
				hb_position_t *y,
110 111 112 113 114
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
115
						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 123 124
  return FALSE;
}

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

135
  return 0;
136 137
}

138
static hb_position_t
B
Behdad Esfahbod 已提交
139 140 141 142 143
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)
144
{
145 146
  if (font->parent)
    return font->parent_scale_y_distance (hb_font_get_glyph_v_kerning (font->parent, 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 HB_UNUSED,
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) {
159 160 161
    hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
					       glyph,
					       extents);
162 163 164 165
    if (ret) {
      font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
      font->parent_scale_distance (&extents->width, &extents->height);
    }
166
    return ret;
167 168
  }

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

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

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

B
Behdad Esfahbod 已提交
195 196

static hb_font_funcs_t _hb_font_funcs_nil = {
197 198
  HB_OBJECT_HEADER_STATIC,

199
  TRUE, /* immutable */
200

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

B
Behdad Esfahbod 已提交
208

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

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

217
  ffuncs->get = _hb_font_funcs_nil.get;
218

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

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

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

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

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

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

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

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


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

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

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

280

281
#define HB_FONT_FUNC_IMPLEMENT(name) \
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
                                                                         \
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 已提交
304 305
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
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);
}

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

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

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

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

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

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

379 380 381 382 383 384 385 386 387 388 389
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);
}
390

391
hb_bool_t
B
Behdad Esfahbod 已提交
392 393 394
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 已提交
395
{
396
  *x = *y = 0;
B
Behdad Esfahbod 已提交
397 398 399 400
  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 已提交
401 402
}

403 404 405

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

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

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

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


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

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

499 500 501 502 503
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 已提交
504
{
B
Behdad Esfahbod 已提交
505
  hb_bool_t ret = hb_font_get_glyph_extents (font, glyph, extents);
506

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

  return ret;
B
Behdad Esfahbod 已提交
511 512
}

513
hb_bool_t
514 515 516 517
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 已提交
518
{
B
Behdad Esfahbod 已提交
519
  hb_bool_t ret = hb_font_get_glyph_contour_point (font, glyph, point_index, x, y);
520

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

  return ret;
B
Behdad Esfahbod 已提交
525 526
}

527

528 529 530 531 532
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
533
  HB_OBJECT_HEADER_STATIC,
534

535 536
  TRUE, /* immutable */

537
  NULL, /* reference_table */
538
  NULL, /* user_data */
539
  NULL, /* destroy */
540

541 542
  NULL, /* ot_layout */

B
Behdad Esfahbod 已提交
543 544
  0,    /* index */
  1000  /* upem */
545 546
};

547

548
hb_face_t *
549 550 551
hb_face_create_for_tables (hb_reference_table_func_t  reference_table,
			   void                      *user_data,
			   hb_destroy_func_t          destroy)
552 553 554
{
  hb_face_t *face;

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

561
  face->reference_table = reference_table;
562
  face->user_data = user_data;
563
  face->destroy = destroy;
564

565
  face->ot_layout = _hb_ot_layout_create (face);
566

B
Behdad Esfahbod 已提交
567
  face->upem = 0;
568

569 570 571
  return face;
}

572 573 574 575 576 577 578 579 580 581 582 583

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));
584
  if (unlikely (!closure))
585
    return NULL;
586

B
Behdad Esfahbod 已提交
587
  closure->blob = blob;
588 589 590 591 592 593 594 595
  closure->index = index;

  return closure;
}

static void
_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
{
596 597
  hb_blob_destroy (closure->blob);
  free (closure);
598 599 600
}

static hb_blob_t *
601
_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
602 603 604
{
  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;

B
Behdad Esfahbod 已提交
605 606 607
  if (tag == HB_TAG_NONE)
    return hb_blob_reference (data->blob);

608
  const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
609 610 611 612 613 614 615 616 617
  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;
}

618
hb_face_t *
619 620
hb_face_create (hb_blob_t    *blob,
		unsigned int  index)
621
{
B
Behdad Esfahbod 已提交
622 623
  hb_face_t *face;

B
Behdad Esfahbod 已提交
624
  if (unlikely (!blob || !hb_blob_get_length (blob)))
625 626
    return &_hb_face_nil;

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

629 630
  if (unlikely (!closure))
    return &_hb_face_nil;
631

B
Behdad Esfahbod 已提交
632
  face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
633 634
				    closure,
				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
B
Behdad Esfahbod 已提交
635 636 637 638

  hb_face_set_index (face, index);

  return face;
639 640
}

641 642 643 644 645 646
hb_face_t *
hb_face_get_empty (void)
{
  return &_hb_face_nil;
}

647

648 649 650
hb_face_t *
hb_face_reference (hb_face_t *face)
{
651
  return hb_object_reference (face);
652 653 654 655 656
}

void
hb_face_destroy (hb_face_t *face)
{
657
  if (!hb_object_destroy (face)) return;
658

659
  _hb_ot_layout_destroy (face->ot_layout);
B
Behdad Esfahbod 已提交
660

661 662 663 664 665 666
  if (face->destroy)
    face->destroy (face->user_data);

  free (face);
}

667 668 669 670
hb_bool_t
hb_face_set_user_data (hb_face_t          *face,
		       hb_user_data_key_t *key,
		       void *              data,
671 672
		       hb_destroy_func_t   destroy,
		       hb_bool_t           replace)
673
{
674
  return hb_object_set_user_data (face, key, data, destroy, replace);
675 676 677 678 679 680 681 682 683
}

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

684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
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;
}

699

700
hb_blob_t *
701
hb_face_reference_table (hb_face_t *face,
702
			 hb_tag_t   tag)
703
{
704 705
  hb_blob_t *blob;

706
  if (unlikely (!face || !face->reference_table))
B
Behdad Esfahbod 已提交
707
    return hb_blob_get_empty ();
708

709
  blob = face->reference_table (face, tag, face->user_data);
710
  if (unlikely (!blob))
B
Behdad Esfahbod 已提交
711
    return hb_blob_get_empty ();
712

713
  return blob;
714
}
715

B
Behdad Esfahbod 已提交
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
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;

  face->index = 0;
}

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 已提交
748 749 750
unsigned int
hb_face_get_upem (hb_face_t *face)
{
B
Behdad Esfahbod 已提交
751 752 753 754 755 756 757
  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 已提交
758 759
}

760 761 762 763 764 765

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
766
  HB_OBJECT_HEADER_STATIC,
767

768
  TRUE, /* immutable */
769

770
  NULL, /* parent */
771 772
  &_hb_face_nil,

773 774 775 776
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
777 778
  0, /* y_ppem */

779
  &_hb_font_funcs_nil, /* klass */
780 781
  NULL, /* user_data */
  NULL  /* destroy */
782 783 784
};

hb_font_t *
785
hb_font_create (hb_face_t *face)
786 787 788
{
  hb_font_t *font;

789 790 791 792
  if (unlikely (!face))
    face = &_hb_face_nil;
  if (unlikely (hb_object_is_inert (face)))
    return &_hb_font_nil;
793
  if (!(font = hb_object_create<hb_font_t> ()))
794 795
    return &_hb_font_nil;

796
  hb_face_make_immutable (face);
797
  font->face = hb_face_reference (face);
B
Behdad Esfahbod 已提交
798 799
  font->klass = &_hb_font_funcs_nil;

800 801 802
  return font;
}

803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
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 已提交
822
  font->klass = &_hb_font_funcs_nil;
823 824 825 826

  return font;
}

827 828 829 830 831 832
hb_font_t *
hb_font_get_empty (void)
{
  return &_hb_font_nil;
}

833 834 835
hb_font_t *
hb_font_reference (hb_font_t *font)
{
836
  return hb_object_reference (font);
837 838 839 840 841
}

void
hb_font_destroy (hb_font_t *font)
{
842
  if (!hb_object_destroy (font)) return;
843

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

  free (font);
}

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

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

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

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

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


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

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

B
Behdad Esfahbod 已提交
910 911 912
  if (!klass)
    klass = &_hb_font_funcs_nil;

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

B
Behdad Esfahbod 已提交
920

921 922
void
hb_font_set_scale (hb_font_t *font,
923 924
		   int x_scale,
		   int y_scale)
925
{
926
  if (font->immutable)
927 928 929 930 931 932
    return;

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

B
Behdad Esfahbod 已提交
933 934
void
hb_font_get_scale (hb_font_t *font,
935 936
		   int *x_scale,
		   int *y_scale)
B
Behdad Esfahbod 已提交
937 938 939 940 941
{
  if (x_scale) *x_scale = font->x_scale;
  if (y_scale) *y_scale = font->y_scale;
}

942 943 944 945 946
void
hb_font_set_ppem (hb_font_t *font,
		  unsigned int x_ppem,
		  unsigned int y_ppem)
{
947
  if (font->immutable)
948 949 950 951 952 953
    return;

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

B
Behdad Esfahbod 已提交
954 955 956 957 958 959 960 961 962
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 已提交
963