hb-font.cc 20.8 KB
Newer Older
1
/*
B
Behdad Esfahbod 已提交
2
 * Copyright © 2009  Red Hat, Inc.
3
 *
B
Behdad Esfahbod 已提交
4
 *  This is part of HarfBuzz, a text shaping library.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Red Hat Author(s): Behdad Esfahbod
 */

27
#include "hb-private.hh"
28

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

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

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

B
Behdad Esfahbod 已提交
37 38
HB_BEGIN_DECLS

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 59 60 61 62
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;
}

static hb_bool_t
hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
63 64
				 hb_position_t *x,
				 hb_position_t *y,
65
				 void *user_data HB_UNUSED)
66
{
67
  if (font->parent) {
68 69
    hb_bool_t ret = hb_font_get_glyph_h_advance (font->parent,
						 glyph,
B
Behdad Esfahbod 已提交
70 71
						 x, y);
    font->parent_scale_distance (x, y);
72 73
    return ret;
  }
74

B
Behdad Esfahbod 已提交
75
  *x = *y = 0;
76
  return FALSE;
77
}
B
Behdad Esfahbod 已提交
78

79 80 81 82
static hb_bool_t
hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
				 void *font_data HB_UNUSED,
				 hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
83 84
				 hb_position_t *x,
				 hb_position_t *y,
85
				 void *user_data HB_UNUSED)
86 87
{
  if (font->parent) {
88 89
    hb_bool_t ret = hb_font_get_glyph_v_advance (font->parent,
						 glyph,
B
Behdad Esfahbod 已提交
90 91
						 x, y);
    font->parent_scale_distance (x, y);
92
    return ret;
93 94
  }

B
Behdad Esfahbod 已提交
95
  *x = *y = 0;
96 97 98
  return FALSE;
}

B
Behdad Esfahbod 已提交
99 100 101 102
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 已提交
103 104
				hb_position_t *x,
				hb_position_t *y,
B
Behdad Esfahbod 已提交
105 106 107 108 109
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_h_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
110 111
						x, y);
    font->parent_scale_distance (x, y);
B
Behdad Esfahbod 已提交
112 113 114
    return ret;
  }

B
Behdad Esfahbod 已提交
115
  *x = *y = 0;
B
Behdad Esfahbod 已提交
116 117 118
  return FALSE;
}

119 120 121 122
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 已提交
123 124
				hb_position_t *x,
				hb_position_t *y,
125 126 127 128 129
				void *user_data HB_UNUSED)
{
  if (font->parent) {
    hb_bool_t ret = hb_font_get_glyph_v_origin (font->parent,
						glyph,
B
Behdad Esfahbod 已提交
130 131
						x, y);
    font->parent_scale_distance (x, y);
132 133 134
    return ret;
  }

B
Behdad Esfahbod 已提交
135
  *x = *y = 0;
136 137 138 139
  return FALSE;
}

static hb_bool_t
B
Behdad Esfahbod 已提交
140 141 142 143
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,
B
Behdad Esfahbod 已提交
144 145
				 hb_position_t *x,
				 hb_position_t *y,
B
Behdad Esfahbod 已提交
146
				 void *user_data HB_UNUSED)
147 148
{
  if (font->parent) {
B
Behdad Esfahbod 已提交
149 150
    hb_bool_t ret = hb_font_get_glyph_h_kerning (font->parent,
						 left_glyph, right_glyph,
B
Behdad Esfahbod 已提交
151 152
						 x, y);
    font->parent_scale_distance (x, y);
153 154 155
    return ret;
  }

B
Behdad Esfahbod 已提交
156
  *x = *y = 0;
157 158 159 160
  return FALSE;
}

static hb_bool_t
B
Behdad Esfahbod 已提交
161 162 163 164
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,
B
Behdad Esfahbod 已提交
165 166
				 hb_position_t *x,
				 hb_position_t *y,
B
Behdad Esfahbod 已提交
167
				 void *user_data HB_UNUSED)
168 169
{
  if (font->parent) {
B
Behdad Esfahbod 已提交
170 171
    hb_bool_t ret = hb_font_get_glyph_v_kerning (font->parent,
						 top_glyph, bottom_glyph,
B
Behdad Esfahbod 已提交
172 173
						 x, y);
    font->parent_scale_distance (x, y);
174 175 176
    return ret;
  }

B
Behdad Esfahbod 已提交
177
  *x = *y = 0;
178
  return FALSE;
179
}
B
Behdad Esfahbod 已提交
180

181
static hb_bool_t
182
hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
183
			       void *font_data HB_UNUSED,
184 185
			       hb_codepoint_t glyph,
			       hb_glyph_extents_t *extents,
186
			       void *user_data HB_UNUSED)
187 188
{
  if (font->parent) {
189 190 191
    hb_bool_t ret = hb_font_get_glyph_extents (font->parent,
					       glyph,
					       extents);
192 193
    font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
    font->parent_scale_distance (&extents->width, &extents->height);
194
    return ret;
195 196 197 198
  }

  extents->x_bearing = extents->y_bearing = 0;
  extents->width = extents->height = 0;
199
  return FALSE;
200
}
201

202
static hb_bool_t
B
Behdad Esfahbod 已提交
203 204 205 206 207 208 209
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)
210
{
211
  if (font->parent) {
B
Behdad Esfahbod 已提交
212 213 214
    hb_bool_t ret = hb_font_get_glyph_contour_point (font->parent,
						     glyph, point_index,
						     x, y);
215 216
    font->parent_scale_position (x, y);
    return ret;
217
  }
218

219 220
  *x = *y = 0;
  return FALSE;
221
}
B
Behdad Esfahbod 已提交
222

B
Behdad Esfahbod 已提交
223 224

static hb_font_funcs_t _hb_font_funcs_nil = {
225 226
  HB_OBJECT_HEADER_STATIC,

227
  TRUE, /* immutable */
228

229
  {
230 231 232
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
233
  }
234 235
};

B
Behdad Esfahbod 已提交
236

B
Behdad Esfahbod 已提交
237 238
hb_font_funcs_t *
hb_font_funcs_create (void)
239
{
B
Behdad Esfahbod 已提交
240
  hb_font_funcs_t *ffuncs;
241

242
  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
B
Behdad Esfahbod 已提交
243
    return &_hb_font_funcs_nil;
244

245
  ffuncs->get = _hb_font_funcs_nil.get;
246

B
Behdad Esfahbod 已提交
247
  return ffuncs;
248 249
}

250 251 252 253 254 255
hb_font_funcs_t *
hb_font_funcs_get_empty (void)
{
  return &_hb_font_funcs_nil;
}

B
Behdad Esfahbod 已提交
256 257
hb_font_funcs_t *
hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
258
{
259
  return hb_object_reference (ffuncs);
260 261 262
}

void
B
Behdad Esfahbod 已提交
263
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
264
{
265
  if (!hb_object_destroy (ffuncs)) return;
266

267 268 269
#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name);
  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
270

B
Behdad Esfahbod 已提交
271
  free (ffuncs);
272 273
}

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
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);
}


291 292 293
void
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
{
294
  if (hb_object_is_inert (ffuncs))
295 296 297
    return;

  ffuncs->immutable = TRUE;
B
Behdad Esfahbod 已提交
298 299 300 301 302
}

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

306

307
#define HB_FONT_FUNC_IMPLEMENT(name) \
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
                                                                         \
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 已提交
330 331
}

332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
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);
}

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

hb_bool_t
hb_font_get_glyph_v_advance (hb_font_t *font,
			     hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
361
			     hb_position_t *x, hb_position_t *y)
362
{
B
Behdad Esfahbod 已提交
363
  *x = *y = 0;
364
  return font->klass->get.glyph_v_advance (font, font->user_data,
B
Behdad Esfahbod 已提交
365
					   glyph, x, y,
366 367 368
					   font->klass->user_data.glyph_v_advance);
}

B
Behdad Esfahbod 已提交
369 370 371
hb_bool_t
hb_font_get_glyph_h_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
372
			    hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
373
{
B
Behdad Esfahbod 已提交
374
  *x = *y = 0;
B
Behdad Esfahbod 已提交
375
  return font->klass->get.glyph_h_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
376
					   glyph, x, y,
B
Behdad Esfahbod 已提交
377 378 379
					   font->klass->user_data.glyph_h_origin);
}

380 381 382
hb_bool_t
hb_font_get_glyph_v_origin (hb_font_t *font,
			    hb_codepoint_t glyph,
B
Behdad Esfahbod 已提交
383
			    hb_position_t *x, hb_position_t *y)
384
{
B
Behdad Esfahbod 已提交
385
  *x = *y = 0;
386
  return font->klass->get.glyph_v_origin (font, font->user_data,
B
Behdad Esfahbod 已提交
387
					   glyph, x, y,
388 389 390 391
					   font->klass->user_data.glyph_v_origin);
}

hb_bool_t
B
Behdad Esfahbod 已提交
392 393
hb_font_get_glyph_h_kerning (hb_font_t *font,
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
B
Behdad Esfahbod 已提交
394
			     hb_position_t *x, hb_position_t *y)
395
{
B
Behdad Esfahbod 已提交
396
  *x = *y = 0;
B
Behdad Esfahbod 已提交
397 398
  return font->klass->get.glyph_h_kerning (font, font->user_data,
					   left_glyph, right_glyph,
B
Behdad Esfahbod 已提交
399
					   x, y,
B
Behdad Esfahbod 已提交
400
					   font->klass->user_data.glyph_h_kerning);
401
}
B
Behdad Esfahbod 已提交
402

403
hb_bool_t
B
Behdad Esfahbod 已提交
404 405
hb_font_get_glyph_v_kerning (hb_font_t *font,
			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
B
Behdad Esfahbod 已提交
406
			     hb_position_t *x, hb_position_t *y)
407
{
B
Behdad Esfahbod 已提交
408
  *x = *y = 0;
B
Behdad Esfahbod 已提交
409
  return font->klass->get.glyph_v_kerning (font, font->user_data,
410
				     left_glyph, right_glyph,
B
Behdad Esfahbod 已提交
411
				     x, y,
B
Behdad Esfahbod 已提交
412
				     font->klass->user_data.glyph_v_kerning);
413
}
B
Behdad Esfahbod 已提交
414

415 416 417 418 419 420 421 422 423 424 425
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);
}
426

427
hb_bool_t
B
Behdad Esfahbod 已提交
428 429 430
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 已提交
431
{
432
  *x = *y = 0;
B
Behdad Esfahbod 已提交
433 434 435 436
  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 已提交
437 438
}

439 440 441

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

442
void
443 444 445
hb_font_get_glyph_advance_for_direction (hb_font_t *font,
					 hb_codepoint_t glyph,
					 hb_direction_t direction,
B
Behdad Esfahbod 已提交
446
					 hb_position_t *x, hb_position_t *y)
447
{
448
  if (HB_DIRECTION_IS_VERTICAL (direction)) {
B
Behdad Esfahbod 已提交
449
    hb_bool_t ret = hb_font_get_glyph_v_advance (font, glyph, x, y);
450
    if (!ret) {
B
Minor  
Behdad Esfahbod 已提交
451
      /* TODO return font_extents.ascent + font_extents.descent? */
452 453
    }
  } else {
B
Behdad Esfahbod 已提交
454
    hb_font_get_glyph_h_advance (font, glyph, x, y);
455
  }
456 457 458
}

void
B
Behdad Esfahbod 已提交
459 460 461
hb_font_get_glyph_origin_for_direction (hb_font_t *font,
					hb_codepoint_t glyph,
					hb_direction_t direction,
B
Behdad Esfahbod 已提交
462
					hb_position_t *x, hb_position_t *y)
B
Behdad Esfahbod 已提交
463 464
{
  if (HB_DIRECTION_IS_VERTICAL (direction)) {
B
Behdad Esfahbod 已提交
465
    hb_bool_t ret = hb_font_get_glyph_v_origin (font, glyph, x, y);
B
Behdad Esfahbod 已提交
466
    if (!ret) {
B
Minor  
Behdad Esfahbod 已提交
467
      /* TODO return h_origin/2. and font_extents.ascent */
B
Behdad Esfahbod 已提交
468 469
    }
  } else {
B
Behdad Esfahbod 已提交
470
    hb_font_get_glyph_h_origin (font, glyph, x, y);
B
Behdad Esfahbod 已提交
471 472 473 474 475 476 477
  }
}

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 已提交
478
					 hb_position_t *x, hb_position_t *y)
479
{
480 481 482
  switch (direction) {
    case HB_DIRECTION_LTR:
    case HB_DIRECTION_RTL:
B
Behdad Esfahbod 已提交
483
      hb_font_get_glyph_h_kerning (font, first_glyph, second_glyph, x, y);
484 485 486 487
      break;

    case HB_DIRECTION_TTB:
    case HB_DIRECTION_BTT:
B
Behdad Esfahbod 已提交
488
      hb_font_get_glyph_v_kerning (font, first_glyph, second_glyph, x, y);
489 490 491 492 493 494
      break;

    case HB_DIRECTION_INVALID:
    default:
      break;
  }
495 496
}

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

  if (ret) {
506 507 508 509
    hb_position_t origin_x, origin_y;
    hb_font_get_glyph_origin_for_direction (font, glyph, direction, &origin_x, &origin_y);
    extents->x_bearing += origin_x;
    extents->y_bearing += origin_y;
510
  }
B
Behdad Esfahbod 已提交
511 512
}

513
hb_bool_t
B
Behdad Esfahbod 已提交
514 515 516 517
hb_font_get_glyph_contour_point_for_direction (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
  if (ret) {
522 523 524 525
    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;
526 527 528
  }

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

531

532 533 534 535 536
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
537
  HB_OBJECT_HEADER_STATIC,
538

539 540
  TRUE, /* immutable */

541 542
  NULL, /* get_table */
  NULL, /* user_data */
543
  NULL, /* destroy */
544

545 546 547
  NULL, /* ot_layout */

  1000
548 549
};

550

551 552
hb_face_t *
hb_face_create_for_tables (hb_get_table_func_t  get_table,
553 554
			   void                *user_data,
			   hb_destroy_func_t    destroy)
555 556 557
{
  hb_face_t *face;

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

  face->get_table = get_table;
  face->user_data = user_data;
566
  face->destroy = destroy;
567

568
  face->ot_layout = _hb_ot_layout_create (face);
569

570 571
  face->upem = _hb_ot_layout_get_upem (face);

572 573 574
  return face;
}

575 576 577 578 579 580 581 582 583 584 585 586

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

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

  return closure;
}

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

static hb_blob_t *
B
Behdad Esfahbod 已提交
604
_hb_face_for_data_get_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
605 606 607
{
  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;

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
  if (unlikely (!blob || !hb_blob_get_length (blob)))
623 624
    return &_hb_face_nil;

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

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

630
  return hb_face_create_for_tables (_hb_face_for_data_get_table,
631 632
				    closure,
				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
633 634
}

635 636 637 638 639 640
hb_face_t *
hb_face_get_empty (void)
{
  return &_hb_face_nil;
}

641

642 643 644
hb_face_t *
hb_face_reference (hb_face_t *face)
{
645
  return hb_object_reference (face);
646 647 648 649 650
}

void
hb_face_destroy (hb_face_t *face)
{
651
  if (!hb_object_destroy (face)) return;
652

653
  _hb_ot_layout_destroy (face->ot_layout);
B
Behdad Esfahbod 已提交
654

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

  free (face);
}

661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
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);
}

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

692

693
hb_blob_t *
694
hb_face_reference_table (hb_face_t *face,
695
			 hb_tag_t   tag)
696
{
697 698
  hb_blob_t *blob;

699
  if (unlikely (!face || !face->get_table))
B
Behdad Esfahbod 已提交
700
    return hb_blob_get_empty ();
701

B
Behdad Esfahbod 已提交
702
  blob = face->get_table (face, tag, face->user_data);
703
  if (unlikely (!blob))
B
Behdad Esfahbod 已提交
704
    return hb_blob_get_empty ();
705

706
  return blob;
707
}
708

B
Behdad Esfahbod 已提交
709 710 711
unsigned int
hb_face_get_upem (hb_face_t *face)
{
712
  return _hb_ot_layout_get_upem (face);
B
Behdad Esfahbod 已提交
713 714
}

715 716 717 718 719 720

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
721
  HB_OBJECT_HEADER_STATIC,
722

723
  TRUE, /* immutable */
724

725
  NULL, /* parent */
726 727
  &_hb_face_nil,

728 729 730 731
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
732 733
  0, /* y_ppem */

734
  &_hb_font_funcs_nil, /* klass */
735 736
  NULL, /* user_data */
  NULL  /* destroy */
737 738 739
};

hb_font_t *
740
hb_font_create (hb_face_t *face)
741 742 743
{
  hb_font_t *font;

744 745 746 747
  if (unlikely (!face))
    face = &_hb_face_nil;
  if (unlikely (hb_object_is_inert (face)))
    return &_hb_font_nil;
748
  if (!(font = hb_object_create<hb_font_t> ()))
749 750
    return &_hb_font_nil;

751
  hb_face_make_immutable (face);
752
  font->face = hb_face_reference (face);
B
Behdad Esfahbod 已提交
753 754
  font->klass = &_hb_font_funcs_nil;

755 756 757
  return font;
}

758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
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 已提交
777
  font->klass = &_hb_font_funcs_nil;
778 779 780 781

  return font;
}

782 783 784 785 786 787
hb_font_t *
hb_font_get_empty (void)
{
  return &_hb_font_nil;
}

788 789 790
hb_font_t *
hb_font_reference (hb_font_t *font)
{
791
  return hb_object_reference (font);
792 793 794 795 796
}

void
hb_font_destroy (hb_font_t *font)
{
797
  if (!hb_object_destroy (font)) return;
798

799
  hb_font_destroy (font->parent);
800
  hb_face_destroy (font->face);
B
Behdad Esfahbod 已提交
801
  hb_font_funcs_destroy (font->klass);
B
Behdad Esfahbod 已提交
802 803
  if (font->destroy)
    font->destroy (font->user_data);
804 805 806 807

  free (font);
}

808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823
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);
}

824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
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;
}

839 840 841 842 843
hb_font_t *
hb_font_get_parent (hb_font_t *font)
{
  return font->parent;
}
844

845 846 847 848 849 850 851
hb_face_t *
hb_font_get_face (hb_font_t *font)
{
  return font->face;
}


B
Behdad Esfahbod 已提交
852
void
B
Behdad Esfahbod 已提交
853 854
hb_font_set_funcs (hb_font_t         *font,
		   hb_font_funcs_t   *klass,
855 856
		   void              *user_data,
		   hb_destroy_func_t  destroy)
857
{
858
  if (font->immutable)
B
Behdad Esfahbod 已提交
859
    return;
860

B
Behdad Esfahbod 已提交
861 862 863
  if (font->destroy)
    font->destroy (font->user_data);

B
Behdad Esfahbod 已提交
864 865 866
  if (!klass)
    klass = &_hb_font_funcs_nil;

B
Behdad Esfahbod 已提交
867 868 869
  hb_font_funcs_reference (klass);
  hb_font_funcs_destroy (font->klass);
  font->klass = klass;
B
Behdad Esfahbod 已提交
870
  font->user_data = user_data;
871
  font->destroy = destroy;
872 873
}

B
Behdad Esfahbod 已提交
874

875 876
void
hb_font_set_scale (hb_font_t *font,
877 878
		   int x_scale,
		   int y_scale)
879
{
880
  if (font->immutable)
881 882 883 884 885 886
    return;

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

B
Behdad Esfahbod 已提交
887 888
void
hb_font_get_scale (hb_font_t *font,
889 890
		   int *x_scale,
		   int *y_scale)
B
Behdad Esfahbod 已提交
891 892 893 894 895
{
  if (x_scale) *x_scale = font->x_scale;
  if (y_scale) *y_scale = font->y_scale;
}

896 897 898 899 900
void
hb_font_set_ppem (hb_font_t *font,
		  unsigned int x_ppem,
		  unsigned int y_ppem)
{
901
  if (font->immutable)
902 903 904 905 906 907
    return;

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

B
Behdad Esfahbod 已提交
908 909 910 911 912 913 914 915 916
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 已提交
917 918

HB_END_DECLS