hb-font.cc 21.9 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"
B
Behdad Esfahbod 已提交
34
#include "hb-ot-head-private.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 251 252 253 254 255 256 257 258 259 260 261 262 263
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);
}


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

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

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

279

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

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

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

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

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

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

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

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

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

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

402 403 404

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

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

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

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


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

B
Behdad Esfahbod 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
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 已提交
483 484 485 486
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 已提交
487
					 hb_position_t *x, hb_position_t *y)
488
{
489
  if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
490
    *x = hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph);
491 492 493
    *y = 0;
  } else {
    *x = 0;
494
    *y = hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph);
495
  }
496 497
}

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

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

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

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

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

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

526

527 528 529 530 531
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
532
  HB_OBJECT_HEADER_STATIC,
533

534 535
  TRUE, /* immutable */

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

540 541
  NULL, /* ot_layout */

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

546

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

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

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

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

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

568 569 570
  return face;
}

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

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

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

  return closure;
}

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

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

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

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

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

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

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

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

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

  hb_face_set_index (face, index);

  return face;
638 639
}

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

646

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

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

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

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

  free (face);
}

666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
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);
}

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

697

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

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

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

711
  return blob;
712
}
713

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

758 759 760 761 762 763

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
764
  HB_OBJECT_HEADER_STATIC,
765

766
  TRUE, /* immutable */
767

768
  NULL, /* parent */
769 770
  &_hb_face_nil,

771 772 773 774
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
775 776
  0, /* y_ppem */

777
  &_hb_font_funcs_nil, /* klass */
778 779
  NULL, /* user_data */
  NULL  /* destroy */
780 781 782
};

hb_font_t *
783
hb_font_create (hb_face_t *face)
784 785 786
{
  hb_font_t *font;

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

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

798 799 800
  return font;
}

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

  return font;
}

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

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

void
hb_font_destroy (hb_font_t *font)
{
840
  if (!hb_object_destroy (font)) return;
841

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

  free (font);
}

851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
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);
}

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

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

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


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

B
Behdad Esfahbod 已提交
904 905 906
  if (font->destroy)
    font->destroy (font->user_data);

B
Behdad Esfahbod 已提交
907 908 909
  if (!klass)
    klass = &_hb_font_funcs_nil;

B
Behdad Esfahbod 已提交
910 911 912
  hb_font_funcs_reference (klass);
  hb_font_funcs_destroy (font->klass);
  font->klass = klass;
B
Behdad Esfahbod 已提交
913
  font->user_data = user_data;
914
  font->destroy = destroy;
915 916
}

B
Behdad Esfahbod 已提交
917

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

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

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

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

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

B
Behdad Esfahbod 已提交
951 952 953 954 955 956 957 958 959
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 已提交
960