b22dc01507726cb46598cb2df438011c4c1dd989
[framework/uifw/harfbuzz.git] / src / hb-font.cc
1 /*
2  * Copyright (C) 2009  Red Hat, Inc.
3  *
4  *  This is part of HarfBuzz, an OpenType Layout engine 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-ot-layout-private.h"
31
32 #include "hb-open-file-private.hh"
33 #include "hb-blob.h"
34
35 /*
36  * hb_font_callbacks_t
37  */
38
39 static hb_font_callbacks_t _hb_font_callbacks_nil = {
40   HB_REFERENCE_COUNT_INVALID /* ref_count */
41   /*
42   hb_font_get_glyph_func_t glyph_func;
43   hb_font_get_contour_point_func_t contour_point_func;
44   hb_font_get_glyph_metrics_func_t glyph_metrics_func;
45   hb_font_get_kerning_func_t kerning_func;
46   */
47 };
48
49 hb_font_callbacks_t *
50 hb_font_callbacks_create (void)
51 {
52   hb_font_callbacks_t *fcallbacks;
53
54   if (!HB_OBJECT_DO_CREATE (hb_font_callbacks_t, fcallbacks))
55     return &_hb_font_callbacks_nil;
56
57   return fcallbacks;
58 }
59
60 hb_font_callbacks_t *
61 hb_font_callbacks_reference (hb_font_callbacks_t *fcallbacks)
62 {
63   HB_OBJECT_DO_REFERENCE (fcallbacks);
64 }
65
66 unsigned int
67 hb_font_callbacks_get_reference_count (hb_font_callbacks_t *fcallbacks)
68 {
69   HB_OBJECT_DO_GET_REFERENCE_COUNT (fcallbacks);
70 }
71
72 void
73 hb_font_callbacks_destroy (hb_font_callbacks_t *fcallbacks)
74 {
75   HB_OBJECT_DO_DESTROY (fcallbacks);
76
77   free (fcallbacks);
78 }
79
80 hb_font_callbacks_t *
81 hb_font_callbacks_copy (hb_font_callbacks_t *other_fcallbacks)
82 {
83   hb_font_callbacks_t *fcallbacks;
84
85   if (!HB_OBJECT_DO_CREATE (hb_font_callbacks_t, fcallbacks))
86     return &_hb_font_callbacks_nil;
87
88   *fcallbacks = *other_fcallbacks;
89
90   /* re-init refcount */
91   HB_OBJECT_DO_INIT (fcallbacks);
92
93   return fcallbacks;
94 }
95
96
97
98 /*
99  * hb_unicode_callbacks_t
100  */
101
102 static hb_unicode_callbacks_t _hb_unicode_callbacks_nil = {
103   HB_REFERENCE_COUNT_INVALID /* ref_count */
104   /*
105   hb_unicode_get_general_category_func_t general_category_func);
106   hb_unicode_get_combining_class_func_t combining_class_func);
107   hb_unicode_get_mirroring_char_func_t mirroring_char_func);
108   hb_unicode_get_script_func_t script_func);
109   hb_unicode_get_eastasian_width_func_t eastasian_width_func);
110   */
111 };
112
113 hb_unicode_callbacks_t *
114 hb_unicode_callbacks_create (void)
115 {
116   hb_unicode_callbacks_t *ucallbacks;
117
118   if (!HB_OBJECT_DO_CREATE (hb_unicode_callbacks_t, ucallbacks))
119     return &_hb_unicode_callbacks_nil;
120
121   return ucallbacks;
122 }
123
124 hb_unicode_callbacks_t *
125 hb_unicode_callbacks_reference (hb_unicode_callbacks_t *ucallbacks)
126 {
127   HB_OBJECT_DO_REFERENCE (ucallbacks);
128 }
129
130 unsigned int
131 hb_unicode_callbacks_get_reference_count (hb_unicode_callbacks_t *ucallbacks)
132 {
133   HB_OBJECT_DO_GET_REFERENCE_COUNT (ucallbacks);
134 }
135
136 void
137 hb_unicode_callbacks_destroy (hb_unicode_callbacks_t *ucallbacks)
138 {
139   HB_OBJECT_DO_DESTROY (ucallbacks);
140
141   free (ucallbacks);
142 }
143
144 hb_unicode_callbacks_t *
145 hb_unicode_callbacks_copy (hb_unicode_callbacks_t *other_ucallbacks)
146 {
147   hb_unicode_callbacks_t *ucallbacks;
148
149   if (!HB_OBJECT_DO_CREATE (hb_unicode_callbacks_t, ucallbacks))
150     return &_hb_unicode_callbacks_nil;
151
152   *ucallbacks = *other_ucallbacks;
153   HB_OBJECT_DO_INIT (ucallbacks);
154
155   return ucallbacks;
156 }
157
158
159
160 /*
161  * hb_face_t
162  */
163
164 static hb_blob_t *
165 _hb_face_get_table_from_blob (hb_tag_t tag, void *user_data)
166 {
167   hb_face_t *face = (hb_face_t *) user_data;
168
169   const OpenTypeFontFile &ot_file = Sanitizer<OpenTypeFontFile>::lock_instance (face->blob);
170   const OpenTypeFontFace &ot_face = ot_file.get_face (face->index);
171
172   const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
173
174   hb_blob_t *blob = hb_blob_create_sub_blob (face->blob, table.offset, table.length);
175
176   hb_blob_unlock (face->blob);
177
178   return blob;
179 }
180
181 static hb_face_t _hb_face_nil = {
182   HB_REFERENCE_COUNT_INVALID, /* ref_count */
183
184   NULL, /* blob */
185   0, /* index */
186
187   NULL, /* get_table */
188   NULL, /* destroy */
189   NULL, /* user_data */
190
191   NULL, /* fcallbacks */
192   NULL  /* ucallbacks */
193 };
194
195 hb_face_t *
196 hb_face_create_for_tables (hb_get_table_func_t  get_table,
197                            hb_destroy_func_t    destroy,
198                            void                *user_data)
199 {
200   hb_face_t *face;
201
202   if (!HB_OBJECT_DO_CREATE (hb_face_t, face)) {
203     if (destroy)
204       destroy (user_data);
205     return &_hb_face_nil;
206   }
207
208   face->get_table = get_table;
209   face->destroy = destroy;
210   face->user_data = user_data;
211
212   _hb_ot_layout_init (face);
213
214   return face;
215 }
216
217 hb_face_t *
218 hb_face_create_for_data (hb_blob_t    *blob,
219                          unsigned int  index)
220 {
221   hb_face_t *face;
222
223   if (!HB_OBJECT_DO_CREATE (hb_face_t, face))
224     return &_hb_face_nil;
225
226   face->blob = Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob));
227   face->index = index;
228   face->get_table = _hb_face_get_table_from_blob;
229   face->user_data = face;
230
231   _hb_ot_layout_init (face);
232
233   return face;
234 }
235
236 hb_face_t *
237 hb_face_reference (hb_face_t *face)
238 {
239   HB_OBJECT_DO_REFERENCE (face);
240 }
241
242 unsigned int
243 hb_face_get_reference_count (hb_face_t *face)
244 {
245   HB_OBJECT_DO_GET_REFERENCE_COUNT (face);
246 }
247
248 void
249 hb_face_destroy (hb_face_t *face)
250 {
251   HB_OBJECT_DO_DESTROY (face);
252
253   _hb_ot_layout_fini (face);
254
255   hb_blob_destroy (face->blob);
256
257   if (face->destroy)
258     face->destroy (face->user_data);
259
260   hb_font_callbacks_destroy (face->fcallbacks);
261   hb_unicode_callbacks_destroy (face->ucallbacks);
262
263   free (face);
264 }
265
266 void
267 hb_face_set_font_callbacks (hb_face_t *face,
268                             hb_font_callbacks_t *fcallbacks)
269 {
270   if (HB_OBJECT_IS_INERT (face))
271     return;
272
273   hb_font_callbacks_reference (fcallbacks);
274   hb_font_callbacks_destroy (face->fcallbacks);
275   face->fcallbacks = fcallbacks;
276 }
277
278 void
279 hb_face_set_unicode_callbacks (hb_face_t *face,
280                                hb_unicode_callbacks_t *ucallbacks)
281 {
282   if (HB_OBJECT_IS_INERT (face))
283     return;
284
285   hb_unicode_callbacks_reference (ucallbacks);
286   hb_unicode_callbacks_destroy (face->ucallbacks);
287   face->ucallbacks = ucallbacks;
288 }
289
290 hb_blob_t *
291 hb_face_get_table (hb_face_t *face,
292                    hb_tag_t tag)
293 {
294   if (HB_UNLIKELY (!face || !face->get_table))
295     return hb_blob_create_empty ();
296
297   return face->get_table (tag, face->user_data);
298 }
299
300
301 /*
302  * hb_font_t
303  */
304
305 static hb_font_t _hb_font_nil = {
306   HB_REFERENCE_COUNT_INVALID, /* ref_count */
307
308   NULL, /* face */
309
310   0, /* x_scale */
311   0, /* y_scale */
312
313   0, /* x_ppem */
314   0  /* y_ppem */
315 };
316
317 hb_font_t *
318 hb_font_create (hb_face_t *face)
319 {
320   hb_font_t *font;
321
322   if (!HB_OBJECT_DO_CREATE (hb_font_t, font))
323     return &_hb_font_nil;
324
325   font->face = hb_face_reference (face);
326
327   return font;
328 }
329
330 hb_font_t *
331 hb_font_reference (hb_font_t *font)
332 {
333   HB_OBJECT_DO_REFERENCE (font);
334 }
335
336 unsigned int
337 hb_font_get_reference_count (hb_font_t *font)
338 {
339   HB_OBJECT_DO_GET_REFERENCE_COUNT (font);
340 }
341
342 void
343 hb_font_destroy (hb_font_t *font)
344 {
345   HB_OBJECT_DO_DESTROY (font);
346
347   hb_face_destroy (font->face);
348
349   free (font);
350 }
351
352 hb_face_t *
353 hb_font_get_face (hb_font_t *font)
354 {
355   if (HB_OBJECT_IS_INERT (font))
356     return &_hb_face_nil;
357
358   return font->face;
359 }
360
361 void
362 hb_font_set_scale (hb_font_t *font,
363                    hb_16dot16_t x_scale,
364                    hb_16dot16_t y_scale)
365 {
366   if (HB_OBJECT_IS_INERT (font))
367     return;
368
369   font->x_scale = x_scale;
370   font->y_scale = y_scale;
371 }
372
373 void
374 hb_font_set_ppem (hb_font_t *font,
375                   unsigned int x_ppem,
376                   unsigned int y_ppem)
377 {
378   if (HB_OBJECT_IS_INERT (font))
379     return;
380
381   font->x_ppem = x_ppem;
382   font->y_ppem = y_ppem;
383 }
384