hb-font.cc revision 2409d5f8d7dd8b535ce5ea29e933f7db27d33793
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-font-private.hh"
30#include "hb-blob-private.hh"
31#include "hb-open-file-private.hh"
32
33#include "hb-ot-layout-private.hh"
34
35#include <string.h>
36
37HB_BEGIN_DECLS
38
39
40/*
41 * hb_font_funcs_t
42 */
43
44static hb_codepoint_t
45hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
46		       hb_face_t *face HB_UNUSED,
47		       const void *user_data HB_UNUSED,
48		       hb_codepoint_t unicode HB_UNUSED,
49		       hb_codepoint_t variation_selector HB_UNUSED)
50{ return 0; }
51
52static void
53hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
54			       hb_face_t *face HB_UNUSED,
55			       const void *user_data HB_UNUSED,
56			       hb_codepoint_t glyph HB_UNUSED,
57			       hb_position_t *x_advance HB_UNUSED,
58			       hb_position_t *y_advance HB_UNUSED)
59{ }
60
61static void
62hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
63			       hb_face_t *face HB_UNUSED,
64			       const void *user_data HB_UNUSED,
65			       hb_codepoint_t glyph HB_UNUSED,
66			       hb_glyph_extents_t *extents HB_UNUSED)
67{ }
68
69static hb_bool_t
70hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
71			       hb_face_t *face HB_UNUSED,
72			       const void *user_data HB_UNUSED,
73			       unsigned int point_index HB_UNUSED,
74			       hb_codepoint_t glyph HB_UNUSED,
75			       hb_position_t *x HB_UNUSED,
76			       hb_position_t *y HB_UNUSED)
77{ return false; }
78
79static hb_position_t
80hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
81			 hb_face_t *face HB_UNUSED,
82			 const void *user_data HB_UNUSED,
83			 hb_codepoint_t first_glyph HB_UNUSED,
84			 hb_codepoint_t second_glyph HB_UNUSED)
85{ return 0; }
86
87hb_font_funcs_t _hb_font_funcs_nil = {
88  HB_REFERENCE_COUNT_INVALID, /* ref_count */
89  TRUE,  /* immutable */
90  {
91    hb_font_get_glyph_nil,
92    hb_font_get_glyph_advance_nil,
93    hb_font_get_glyph_extents_nil,
94    hb_font_get_contour_point_nil,
95    hb_font_get_kerning_nil
96  }
97};
98
99hb_font_funcs_t *
100hb_font_funcs_create (void)
101{
102  hb_font_funcs_t *ffuncs;
103
104  if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
105    return &_hb_font_funcs_nil;
106
107  ffuncs->v = _hb_font_funcs_nil.v;
108
109  return ffuncs;
110}
111
112hb_font_funcs_t *
113hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
114{
115  HB_OBJECT_DO_REFERENCE (ffuncs);
116}
117
118void
119hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
120{
121  HB_OBJECT_DO_DESTROY (ffuncs);
122
123  free (ffuncs);
124}
125
126hb_font_funcs_t *
127hb_font_funcs_copy (hb_font_funcs_t *other_ffuncs)
128{
129  hb_font_funcs_t *ffuncs;
130
131  if (!HB_OBJECT_DO_CREATE (hb_font_funcs_t, ffuncs))
132    return &_hb_font_funcs_nil;
133
134  ffuncs->v = other_ffuncs->v;
135
136  return ffuncs;
137}
138
139void
140hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
141{
142  if (HB_OBJECT_IS_INERT (ffuncs))
143    return;
144
145  ffuncs->immutable = TRUE;
146}
147
148hb_bool_t
149hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
150{
151  return ffuncs->immutable;
152}
153
154
155void
156hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
157			      hb_font_get_glyph_func_t glyph_func)
158{
159  if (ffuncs->immutable)
160    return;
161
162  ffuncs->v.get_glyph = glyph_func ? glyph_func : hb_font_get_glyph_nil;
163}
164
165void
166hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
167				      hb_font_get_glyph_advance_func_t glyph_advance_func)
168{
169  if (ffuncs->immutable)
170    return;
171
172  ffuncs->v.get_glyph_advance = glyph_advance_func ? glyph_advance_func : hb_font_get_glyph_advance_nil;
173}
174
175void
176hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
177				      hb_font_get_glyph_extents_func_t glyph_extents_func)
178{
179  if (ffuncs->immutable)
180    return;
181
182  ffuncs->v.get_glyph_extents = glyph_extents_func ? glyph_extents_func : hb_font_get_glyph_extents_nil;
183}
184
185void
186hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
187				      hb_font_get_contour_point_func_t contour_point_func)
188{
189  if (ffuncs->immutable)
190    return;
191
192  ffuncs->v.get_contour_point = contour_point_func ? contour_point_func : hb_font_get_contour_point_nil;
193}
194
195void
196hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
197				hb_font_get_kerning_func_t kerning_func)
198{
199  if (ffuncs->immutable)
200    return;
201
202  ffuncs->v.get_kerning = kerning_func ? kerning_func : hb_font_get_kerning_nil;
203}
204
205
206hb_font_get_glyph_func_t
207hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs)
208{
209  return ffuncs->v.get_glyph;
210}
211
212hb_font_get_glyph_advance_func_t
213hb_font_funcs_get_glyph_advance_func (hb_font_funcs_t *ffuncs)
214{
215  return ffuncs->v.get_glyph_advance;
216}
217
218hb_font_get_glyph_extents_func_t
219hb_font_funcs_get_glyph_extents_func (hb_font_funcs_t *ffuncs)
220{
221  return ffuncs->v.get_glyph_extents;
222}
223
224hb_font_get_contour_point_func_t
225hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs)
226{
227  return ffuncs->v.get_contour_point;
228}
229
230hb_font_get_kerning_func_t
231hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs)
232{
233  return ffuncs->v.get_kerning;
234}
235
236
237
238hb_codepoint_t
239hb_font_get_glyph (hb_font_t *font, hb_face_t *face,
240		   hb_codepoint_t unicode, hb_codepoint_t variation_selector)
241{
242  return font->klass->v.get_glyph (font, face, font->user_data,
243				   unicode, variation_selector);
244}
245
246void
247hb_font_get_glyph_advance (hb_font_t *font, hb_face_t *face,
248			   hb_codepoint_t glyph,
249			   hb_position_t *x_advance, hb_position_t *y_advance)
250{
251  *x_advance = *y_advance = 0;
252  return font->klass->v.get_glyph_advance (font, face, font->user_data,
253					   glyph, x_advance, y_advance);
254}
255
256void
257hb_font_get_glyph_extents (hb_font_t *font, hb_face_t *face,
258			   hb_codepoint_t glyph, hb_glyph_extents_t *extents)
259{
260  memset (extents, 0, sizeof (*extents));
261  return font->klass->v.get_glyph_extents (font, face, font->user_data,
262					   glyph, extents);
263}
264
265hb_bool_t
266hb_font_get_contour_point (hb_font_t *font, hb_face_t *face,
267			   unsigned int point_index,
268			   hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
269{
270  *x = 0; *y = 0;
271  return font->klass->v.get_contour_point (font, face, font->user_data,
272					   point_index,
273					   glyph, x, y);
274}
275
276hb_position_t
277hb_font_get_kerning (hb_font_t *font, hb_face_t *face,
278		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph)
279{
280  return font->klass->v.get_kerning (font, face, font->user_data,
281				     first_glyph, second_glyph);
282}
283
284
285/*
286 * hb_face_t
287 */
288
289static hb_face_t _hb_face_nil = {
290  HB_REFERENCE_COUNT_INVALID, /* ref_count */
291
292  NULL, /* get_table */
293  NULL, /* user_data */
294  NULL, /* destroy */
295
296  NULL, /* head_blob */
297  NULL, /* head_table */
298
299  NULL  /* ot_layout */
300};
301
302
303hb_face_t *
304hb_face_create_for_tables (hb_get_table_func_t  get_table,
305			   void                *user_data,
306			   hb_destroy_func_t    destroy)
307{
308  hb_face_t *face;
309
310  if (!HB_OBJECT_DO_CREATE (hb_face_t, face)) {
311    if (destroy)
312      destroy (user_data);
313    return &_hb_face_nil;
314  }
315
316  face->get_table = get_table;
317  face->user_data = user_data;
318  face->destroy = destroy;
319
320  face->ot_layout = _hb_ot_layout_new (face);
321
322  face->head_blob = Sanitizer<head>::sanitize (hb_face_reference_table (face, HB_OT_TAG_head));
323  face->head_table = Sanitizer<head>::lock_instance (face->head_blob);
324
325  return face;
326}
327
328
329typedef struct _hb_face_for_data_closure_t {
330  hb_blob_t *blob;
331  unsigned int  index;
332} hb_face_for_data_closure_t;
333
334static hb_face_for_data_closure_t *
335_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
336{
337  hb_face_for_data_closure_t *closure;
338
339  closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
340  if (unlikely (!closure))
341    return NULL;
342
343  closure->blob = blob;
344  closure->index = index;
345
346  return closure;
347}
348
349static void
350_hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
351{
352  hb_blob_destroy (closure->blob);
353  free (closure);
354}
355
356static hb_blob_t *
357_hb_face_for_data_get_table (hb_tag_t tag, void *user_data)
358{
359  hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
360
361  const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
362  const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
363
364  const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
365
366  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
367
368  hb_blob_unlock (data->blob);
369
370  return blob;
371}
372
373hb_face_t *
374hb_face_create_for_data (hb_blob_t    *blob,
375			 unsigned int  index)
376{
377  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
378
379  if (unlikely (!closure))
380    return &_hb_face_nil;
381
382  return hb_face_create_for_tables (_hb_face_for_data_get_table,
383				    closure,
384				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
385}
386
387
388hb_face_t *
389hb_face_reference (hb_face_t *face)
390{
391  HB_OBJECT_DO_REFERENCE (face);
392}
393
394void
395hb_face_destroy (hb_face_t *face)
396{
397  HB_OBJECT_DO_DESTROY (face);
398
399  _hb_ot_layout_free (face->ot_layout);
400
401  hb_blob_unlock (face->head_blob);
402  hb_blob_destroy (face->head_blob);
403
404  if (face->destroy)
405    face->destroy (face->user_data);
406
407  free (face);
408}
409
410hb_blob_t *
411hb_face_reference_table (hb_face_t *face,
412		   hb_tag_t   tag)
413{
414  hb_blob_t *blob;
415
416  if (unlikely (!face || !face->get_table))
417    return &_hb_blob_nil;
418
419  blob = face->get_table (tag, face->user_data);
420  if (unlikely (!blob))
421    blob = hb_blob_create_empty();
422
423  return blob;
424}
425
426unsigned int
427hb_face_get_upem (hb_face_t *face)
428{
429  return (face->head_table ? face->head_table : &Null(head))->get_upem ();
430}
431
432
433/*
434 * hb_font_t
435 */
436
437static hb_font_t _hb_font_nil = {
438  HB_REFERENCE_COUNT_INVALID, /* ref_count */
439
440  0, /* x_scale */
441  0, /* y_scale */
442
443  0, /* x_ppem */
444  0, /* y_ppem */
445
446  NULL, /* klass */
447  NULL, /* user_data */
448  NULL  /* destroy */
449};
450
451hb_font_t *
452hb_font_create (void)
453{
454  hb_font_t *font;
455
456  if (!HB_OBJECT_DO_CREATE (hb_font_t, font))
457    return &_hb_font_nil;
458
459  font->klass = &_hb_font_funcs_nil;
460
461  return font;
462}
463
464hb_font_t *
465hb_font_reference (hb_font_t *font)
466{
467  HB_OBJECT_DO_REFERENCE (font);
468}
469
470void
471hb_font_destroy (hb_font_t *font)
472{
473  HB_OBJECT_DO_DESTROY (font);
474
475  hb_font_funcs_destroy (font->klass);
476  if (font->destroy)
477    font->destroy (font->user_data);
478
479  free (font);
480}
481
482void
483hb_font_set_funcs (hb_font_t         *font,
484		   hb_font_funcs_t   *klass,
485		   void              *user_data,
486		   hb_destroy_func_t  destroy)
487{
488  if (HB_OBJECT_IS_INERT (font))
489    return;
490
491  if (font->destroy)
492    font->destroy (font->user_data);
493
494  if (!klass)
495    klass = &_hb_font_funcs_nil;
496
497  hb_font_funcs_reference (klass);
498  hb_font_funcs_destroy (font->klass);
499  font->klass = klass;
500  font->user_data = user_data;
501  font->destroy = destroy;
502}
503
504void
505hb_font_unset_funcs (hb_font_t          *font,
506		     hb_font_funcs_t   **klass,
507		     void              **user_data,
508		     hb_destroy_func_t  *destroy)
509{
510  /* None of the input arguments can be NULL. */
511
512  *klass = font->klass;
513  *user_data = font->user_data;
514  *destroy = font->destroy;
515
516  if (HB_OBJECT_IS_INERT (font))
517    return;
518
519  font->klass = NULL;
520  font->user_data = NULL;
521  font->destroy = NULL;
522}
523
524void
525hb_font_set_scale (hb_font_t *font,
526		   int x_scale,
527		   int y_scale)
528{
529  if (HB_OBJECT_IS_INERT (font))
530    return;
531
532  font->x_scale = x_scale;
533  font->y_scale = y_scale;
534}
535
536void
537hb_font_get_scale (hb_font_t *font,
538		   int *x_scale,
539		   int *y_scale)
540{
541  if (x_scale) *x_scale = font->x_scale;
542  if (y_scale) *y_scale = font->y_scale;
543}
544
545void
546hb_font_set_ppem (hb_font_t *font,
547		  unsigned int x_ppem,
548		  unsigned int y_ppem)
549{
550  if (HB_OBJECT_IS_INERT (font))
551    return;
552
553  font->x_ppem = x_ppem;
554  font->y_ppem = y_ppem;
555}
556
557void
558hb_font_get_ppem (hb_font_t *font,
559		  unsigned int *x_ppem,
560		  unsigned int *y_ppem)
561{
562  if (x_ppem) *x_ppem = font->x_ppem;
563  if (y_ppem) *y_ppem = font->y_ppem;
564}
565
566
567HB_END_DECLS
568