hb-font.cc revision b9d975b931d6310f25fab5ac280f523cdc27bf94
1/*
2 * Copyright © 2009  Red Hat, Inc.
3 *
4 *  This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Red Hat Author(s): Behdad Esfahbod
25 */
26
27#include "hb-private.hh"
28
29#include "hb-ot-layout-private.hh"
30
31#include "hb-font-private.hh"
32#include "hb-blob.h"
33#include "hb-open-file-private.hh"
34
35#include <string.h>
36
37HB_BEGIN_DECLS
38
39
40/*
41 * hb_font_funcs_t
42 */
43
44static hb_bool_t
45hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
46			       const void *font_data HB_UNUSED,
47			       unsigned int point_index HB_UNUSED,
48			       hb_codepoint_t glyph HB_UNUSED,
49			       hb_position_t *x HB_UNUSED,
50			       hb_position_t *y HB_UNUSED,
51			       const void *user_data HB_UNUSED)
52{ return false; }
53
54static void
55hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
56			       const void *font_data HB_UNUSED,
57			       hb_codepoint_t glyph HB_UNUSED,
58			       hb_position_t *x_advance HB_UNUSED,
59			       hb_position_t *y_advance HB_UNUSED,
60			       const void *user_data HB_UNUSED)
61{ }
62
63static void
64hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
65			       const void *font_data HB_UNUSED,
66			       hb_codepoint_t glyph HB_UNUSED,
67			       hb_glyph_extents_t *extents HB_UNUSED,
68			       const void *user_data HB_UNUSED)
69{ }
70
71static hb_codepoint_t
72hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
73		       const void *font_data HB_UNUSED,
74		       hb_codepoint_t unicode HB_UNUSED,
75		       hb_codepoint_t variation_selector HB_UNUSED,
76		       const void *user_data HB_UNUSED)
77{ return 0; }
78
79static hb_position_t
80hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
81			 const void *font_data HB_UNUSED,
82			 hb_codepoint_t first_glyph HB_UNUSED,
83			 hb_codepoint_t second_glyph HB_UNUSED,
84			 const void *user_data HB_UNUSED)
85{ return 0; }
86
87
88static hb_font_funcs_t _hb_font_funcs_nil = {
89  HB_OBJECT_HEADER_STATIC,
90
91  TRUE, /* immutable */
92
93  {
94    hb_font_get_contour_point_nil,
95    hb_font_get_glyph_advance_nil,
96    hb_font_get_glyph_extents_nil,
97    hb_font_get_glyph_nil,
98    hb_font_get_kerning_nil
99  }
100};
101
102
103hb_font_funcs_t *
104hb_font_funcs_create (void)
105{
106  hb_font_funcs_t *ffuncs;
107
108  if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
109    return &_hb_font_funcs_nil;
110
111  ffuncs->get = _hb_font_funcs_nil.get;
112
113  return ffuncs;
114}
115
116hb_font_funcs_t *
117hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
118{
119  return hb_object_reference (ffuncs);
120}
121
122void
123hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
124{
125  if (!hb_object_destroy (ffuncs)) return;
126
127#define DESTROY(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name)
128  DESTROY (contour_point);
129  DESTROY (glyph_advance);
130  DESTROY (glyph_extents);
131  DESTROY (glyph);
132  DESTROY (kerning);
133#undef DESTROY
134
135  free (ffuncs);
136}
137
138hb_bool_t
139hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
140			     hb_user_data_key_t *key,
141			     void *              data,
142			     hb_destroy_func_t   destroy)
143{
144  return hb_object_set_user_data (ffuncs, key, data, destroy);
145}
146
147void *
148hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
149			     hb_user_data_key_t *key)
150{
151  return hb_object_get_user_data (ffuncs, key);
152}
153
154
155void
156hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
157{
158  if (hb_object_is_inert (ffuncs))
159    return;
160
161  ffuncs->immutable = TRUE;
162}
163
164hb_bool_t
165hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
166{
167  return ffuncs->immutable;
168}
169
170
171#define IMPLEMENT(name)                                                  \
172                                                                         \
173void                                                                     \
174hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
175                                 hb_font_get_##name##_func_t  func,      \
176                                 void                        *user_data, \
177                                 hb_destroy_func_t            destroy)   \
178{                                                                        \
179  if (ffuncs->immutable)                                                 \
180    return;                                                              \
181                                                                         \
182  if (ffuncs->destroy.name)                                              \
183    ffuncs->destroy.name (ffuncs->user_data.name);                       \
184                                                                         \
185  if (func) {                                                            \
186    ffuncs->get.name = func;                                             \
187    ffuncs->user_data.name = user_data;                                  \
188    ffuncs->destroy.name = destroy;                                      \
189  } else {                                                               \
190    ffuncs->get.name = hb_font_get_##name##_nil;                         \
191    ffuncs->user_data.name = NULL;                                       \
192    ffuncs->destroy.name = NULL;                                         \
193  }                                                                      \
194}
195
196IMPLEMENT (contour_point);
197IMPLEMENT (glyph_advance);
198IMPLEMENT (glyph_extents);
199IMPLEMENT (glyph);
200IMPLEMENT (kerning);
201
202#undef IMPLEMENT
203
204
205hb_bool_t
206hb_font_get_contour_point (hb_font_t *font,
207			   unsigned int point_index,
208			   hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
209{
210  *x = 0; *y = 0;
211  return font->klass->get.contour_point (font, font->user_data,
212					 point_index,
213					 glyph, x, y,
214					 font->klass->user_data.contour_point);
215}
216
217void
218hb_font_get_glyph_advance (hb_font_t *font,
219			   hb_codepoint_t glyph,
220			   hb_position_t *x_advance, hb_position_t *y_advance)
221{
222  *x_advance = *y_advance = 0;
223  return font->klass->get.glyph_advance (font, font->user_data,
224					 glyph, x_advance, y_advance,
225					 font->klass->user_data.glyph_advance);
226}
227
228void
229hb_font_get_glyph_extents (hb_font_t *font,
230			   hb_codepoint_t glyph, hb_glyph_extents_t *extents)
231{
232  memset (extents, 0, sizeof (*extents));
233  return font->klass->get.glyph_extents (font, font->user_data,
234					 glyph, extents,
235					 font->klass->user_data.glyph_extents);
236}
237
238hb_codepoint_t
239hb_font_get_glyph (hb_font_t *font,
240		   hb_codepoint_t unicode, hb_codepoint_t variation_selector)
241{
242  return font->klass->get.glyph (font, font->user_data,
243				 unicode, variation_selector,
244				 font->klass->user_data.glyph);
245}
246
247hb_position_t
248hb_font_get_kerning (hb_font_t *font,
249		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph)
250{
251  return font->klass->get.kerning (font, font->user_data,
252				   first_glyph, second_glyph,
253				   font->klass->user_data.kerning);
254}
255
256
257/*
258 * hb_face_t
259 */
260
261static hb_face_t _hb_face_nil = {
262  HB_OBJECT_HEADER_STATIC,
263
264  NULL, /* get_table */
265  NULL, /* user_data */
266  NULL, /* destroy */
267
268  NULL  /* ot_layout */
269};
270
271
272hb_face_t *
273hb_face_create_for_tables (hb_get_table_func_t  get_table,
274			   void                *user_data,
275			   hb_destroy_func_t    destroy)
276{
277  hb_face_t *face;
278
279  if (!get_table || !(face = hb_object_create<hb_face_t> ())) {
280    if (destroy)
281      destroy (user_data);
282    return &_hb_face_nil;
283  }
284
285  face->get_table = get_table;
286  face->user_data = user_data;
287  face->destroy = destroy;
288
289  face->ot_layout = _hb_ot_layout_create (face);
290
291  return face;
292}
293
294
295typedef struct _hb_face_for_data_closure_t {
296  hb_blob_t *blob;
297  unsigned int  index;
298} hb_face_for_data_closure_t;
299
300static hb_face_for_data_closure_t *
301_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
302{
303  hb_face_for_data_closure_t *closure;
304
305  closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
306  if (unlikely (!closure))
307    return NULL;
308
309  closure->blob = blob;
310  closure->index = index;
311
312  return closure;
313}
314
315static void
316_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
317{
318  hb_blob_destroy (closure->blob);
319  free (closure);
320}
321
322static hb_blob_t *
323_hb_face_for_data_get_table (hb_tag_t tag, void *user_data)
324{
325  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
326
327  const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
328  const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
329
330  const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
331
332  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
333
334  return blob;
335}
336
337hb_face_t *
338hb_face_create_for_data (hb_blob_t    *blob,
339			 unsigned int  index)
340{
341  if (unlikely (!blob || !hb_blob_get_length (blob)))
342    return &_hb_face_nil;
343
344  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
345
346  if (unlikely (!closure))
347    return &_hb_face_nil;
348
349  return hb_face_create_for_tables (_hb_face_for_data_get_table,
350				    closure,
351				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
352}
353
354
355hb_face_t *
356hb_face_reference (hb_face_t *face)
357{
358  return hb_object_reference (face);
359}
360
361void
362hb_face_destroy (hb_face_t *face)
363{
364  if (!hb_object_destroy (face)) return;
365
366  _hb_ot_layout_destroy (face->ot_layout);
367
368  if (face->destroy)
369    face->destroy (face->user_data);
370
371  free (face);
372}
373
374hb_bool_t
375hb_face_set_user_data (hb_face_t          *face,
376		       hb_user_data_key_t *key,
377		       void *              data,
378		       hb_destroy_func_t   destroy)
379{
380  return hb_object_set_user_data (face, key, data, destroy);
381}
382
383void *
384hb_face_get_user_data (hb_face_t          *face,
385		       hb_user_data_key_t *key)
386{
387  return hb_object_get_user_data (face, key);
388}
389
390
391hb_blob_t *
392hb_face_reference_table (hb_face_t *face,
393			 hb_tag_t   tag)
394{
395  hb_blob_t *blob;
396
397  if (unlikely (!face || !face->get_table))
398    return hb_blob_get_empty ();
399
400  blob = face->get_table (tag, face->user_data);
401  if (unlikely (!blob))
402    return hb_blob_get_empty ();
403
404  return blob;
405}
406
407unsigned int
408hb_face_get_upem (hb_face_t *face)
409{
410  return _hb_ot_layout_get_upem (face);
411}
412
413
414/*
415 * hb_font_t
416 */
417
418static hb_font_t _hb_font_nil = {
419  HB_OBJECT_HEADER_STATIC,
420
421  TRUE, /* immutable */
422
423  NULL, /* parent */
424  &_hb_face_nil,
425
426  0, /* x_scale */
427  0, /* y_scale */
428
429  0, /* x_ppem */
430  0, /* y_ppem */
431
432  &_hb_font_funcs_nil, /* klass */
433  NULL, /* user_data */
434  NULL  /* destroy */
435};
436
437hb_font_t *
438hb_font_create (hb_face_t *face)
439{
440  hb_font_t *font;
441
442  if (unlikely (!face))
443    face = &_hb_face_nil;
444  if (unlikely (hb_object_is_inert (face)))
445    return &_hb_font_nil;
446  if (!(font = hb_object_create<hb_font_t> ()))
447    return &_hb_font_nil;
448
449  font->face = hb_face_reference (face);
450  font->klass = &_hb_font_funcs_nil;
451
452  return font;
453}
454
455hb_font_t *
456hb_font_create_sub_font (hb_font_t *parent)
457{
458  if (unlikely (!parent))
459    return &_hb_font_nil;
460
461  hb_font_t *font = hb_font_create (parent->face);
462
463  if (unlikely (hb_object_is_inert (font)))
464    return font;
465
466  hb_font_make_immutable (parent);
467  font->parent = hb_font_reference (parent);
468
469  font->x_scale = parent->x_scale;
470  font->y_scale = parent->y_scale;
471  font->x_ppem = parent->x_ppem;
472  font->y_ppem = parent->y_ppem;
473
474  /* We can safely copy user_data from parent since we hold a reference
475   * onto it and it's immutable.  We should not copy the destroy notifiers
476   * though. */
477  font->klass = hb_font_funcs_reference (parent->klass);
478  font->user_data = parent->user_data;
479
480  return font;
481}
482
483hb_font_t *
484hb_font_reference (hb_font_t *font)
485{
486  return hb_object_reference (font);
487}
488
489void
490hb_font_destroy (hb_font_t *font)
491{
492  if (!hb_object_destroy (font)) return;
493
494  hb_font_destroy (font->parent);
495  hb_face_destroy (font->face);
496  hb_font_funcs_destroy (font->klass);
497  if (font->destroy)
498    font->destroy (font->user_data);
499
500  free (font);
501}
502
503hb_bool_t
504hb_font_set_user_data (hb_font_t          *font,
505		       hb_user_data_key_t *key,
506		       void *              data,
507		       hb_destroy_func_t   destroy)
508{
509  return hb_object_set_user_data (font, key, data, destroy);
510}
511
512void *
513hb_font_get_user_data (hb_font_t          *font,
514		       hb_user_data_key_t *key)
515{
516  return hb_object_get_user_data (font, key);
517}
518
519void
520hb_font_make_immutable (hb_font_t *font)
521{
522  if (hb_object_is_inert (font))
523    return;
524
525  font->immutable = true;
526}
527
528hb_bool_t
529hb_font_is_immutable (hb_font_t *font)
530{
531  return font->immutable;
532}
533
534hb_font_t *
535hb_font_get_parent (hb_font_t *font)
536{
537  return font->parent;
538}
539
540hb_face_t *
541hb_font_get_face (hb_font_t *font)
542{
543  return font->face;
544}
545
546
547void
548hb_font_set_funcs (hb_font_t         *font,
549		   hb_font_funcs_t   *klass,
550		   void              *user_data,
551		   hb_destroy_func_t  destroy)
552{
553  if (font->immutable)
554    return;
555
556  if (font->destroy)
557    font->destroy (font->user_data);
558
559  if (!klass)
560    klass = &_hb_font_funcs_nil;
561
562  hb_font_funcs_reference (klass);
563  hb_font_funcs_destroy (font->klass);
564  font->klass = klass;
565  font->user_data = user_data;
566  font->destroy = destroy;
567}
568
569
570void
571hb_font_set_scale (hb_font_t *font,
572		   int x_scale,
573		   int y_scale)
574{
575  if (font->immutable)
576    return;
577
578  font->x_scale = x_scale;
579  font->y_scale = y_scale;
580}
581
582void
583hb_font_get_scale (hb_font_t *font,
584		   int *x_scale,
585		   int *y_scale)
586{
587  if (x_scale) *x_scale = font->x_scale;
588  if (y_scale) *y_scale = font->y_scale;
589}
590
591void
592hb_font_set_ppem (hb_font_t *font,
593		  unsigned int x_ppem,
594		  unsigned int y_ppem)
595{
596  if (font->immutable)
597    return;
598
599  font->x_ppem = x_ppem;
600  font->y_ppem = y_ppem;
601}
602
603void
604hb_font_get_ppem (hb_font_t *font,
605		  unsigned int *x_ppem,
606		  unsigned int *y_ppem)
607{
608  if (x_ppem) *x_ppem = font->x_ppem;
609  if (y_ppem) *y_ppem = font->y_ppem;
610}
611
612
613HB_END_DECLS
614