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