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

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
                                                                         \
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 已提交
289 290 291
  if (ffuncs->immutable) {                                               \
    if (destroy)                                                         \
      destroy (user_data);                                               \
292
    return;                                                              \
B
Behdad Esfahbod 已提交
293
  }                                                                      \
294 295 296 297 298 299 300 301 302 303 304 305 306
                                                                         \
  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 已提交
307 308
}

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

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

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

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

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

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

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

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

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

406 407 408

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

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

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

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


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

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

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

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

  return ret;
B
Behdad Esfahbod 已提交
514 515
}

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

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

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

530

531 532 533 534 535
/*
 * hb_face_t
 */

static hb_face_t _hb_face_nil = {
536
  HB_OBJECT_HEADER_STATIC,
537

538 539
  TRUE, /* immutable */

540
  NULL, /* reference_table */
541
  NULL, /* user_data */
542
  NULL, /* destroy */
543

544 545
  NULL, /* ot_layout */

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

550

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

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

564
  face->reference_table = reference_table;
565
  face->user_data = user_data;
566
  face->destroy = destroy;
567

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

B
Behdad Esfahbod 已提交
570
  face->upem = 0;
571

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 *
604
_hb_face_for_data_reference_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;

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

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

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

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

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

632 633
  if (unlikely (!closure))
    return &_hb_face_nil;
634

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

  hb_face_set_index (face, index);

  return face;
642 643
}

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

650

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

void
hb_face_destroy (hb_face_t *face)
{
660
  if (!hb_object_destroy (face)) return;
661

662
  _hb_ot_layout_destroy (face->ot_layout);
B
Behdad Esfahbod 已提交
663

664 665 666 667 668 669
  if (face->destroy)
    face->destroy (face->user_data);

  free (face);
}

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

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

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

702

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

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

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

716
  return blob;
717
}
718

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

763 764 765 766 767 768

/*
 * hb_font_t
 */

static hb_font_t _hb_font_nil = {
769
  HB_OBJECT_HEADER_STATIC,
770

771
  TRUE, /* immutable */
772

773
  NULL, /* parent */
774 775
  &_hb_face_nil,

776 777 778 779
  0, /* x_scale */
  0, /* y_scale */

  0, /* x_ppem */
B
Behdad Esfahbod 已提交
780 781
  0, /* y_ppem */

782
  &_hb_font_funcs_nil, /* klass */
783 784
  NULL, /* user_data */
  NULL  /* destroy */
785 786 787
};

hb_font_t *
788
hb_font_create (hb_face_t *face)
789 790 791
{
  hb_font_t *font;

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

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

803 804 805
  return font;
}

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

  return font;
}

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

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

void
hb_font_destroy (hb_font_t *font)
{
845
  if (!hb_object_destroy (font)) return;
846

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

  free (font);
}

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

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

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

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

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


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

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

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

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

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

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

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

B
Behdad Esfahbod 已提交
945

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

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

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

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

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

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