add explicit freetype2 linking
[charfbuzz.git] / hb-face.c
blob770d81b8c6b9bafd4c9eb018f1420e369ba09647
1 /*
2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
4 <sylware@legeek.net>
5 */
6 #include <stdlib.h>
8 #include <ft2build.h>
9 #include FT_FREETYPE_H
10 #include FT_TRUETYPE_IDS_H
12 #include "hb.h"
13 #include "hb-private.h"
14 #include "hb-atomic-private.h"
15 #include "hb-shaper-private.h"
16 #include "hb-face-private.h"
17 #include "hb-blob-private.h"
18 #include "hb-open-file-private.h"
20 void hb_face_make_immutable(hb_face_t * face)
22 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
23 return;
25 face->immutable = TRUE;
28 hb_face_t *hb_face_reference(hb_face_t * face)
30 if (hb_atomic_int32_get(&face->ref_cnt) != REF_CNT_INVALID_VAL)
31 hb_atomic_int32_add(&face->ref_cnt, 1);
32 return face;
35 /*XXX:should go in lib "global init"*/
36 static hb_face_t hb_face_nil = {
37 REF_CNT_INVALID_VAL, /*ref_cnt */
38 TRUE, /*immutable */
39 NULL, /*ft_face */
40 NULL, /*user_data */
41 NULL, /*destroy */
43 #ifdef HAVE_GRAPHITE2
44 HB_SHAPER_DATA_INVALID,
45 #endif
46 #ifdef HAVE_OT
47 HB_SHAPER_DATA_INVALID,
48 #endif
49 HB_SHAPER_DATA_INVALID /*fallback */
51 NULL, /*shape_plans */
52 0, /*upem */
53 0, /*num_glyphs */
54 0, /*index */
55 NULL /*reference_table_func */
58 hb_face_t *hb_face_get_empty(void)
60 return &hb_face_nil;
63 void hb_face_set_index(hb_face_t * face, unsigned index)
65 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
66 return;
68 face->index = index;
71 void hb_face_set_upem(hb_face_t * face, unsigned upem)
73 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
74 return;
76 face->upem = upem;
79 hb_face_t *hb_face_create_for_tables(hb_reference_table_func_t
80 reference_table_func, void *user_data,
81 hb_destroy_func_t destroy)
83 hb_face_t *face;
85 face = calloc(1, sizeof(*face));
86 if (!reference_table_func || !face) {
87 if (face)
88 free(face);
89 if (destroy)
90 destroy(user_data);
91 return hb_face_get_empty();
93 hb_atomic_int32_set(&face->ref_cnt, 1);
95 face->reference_table_func = reference_table_func;
96 face->user_data = user_data;
97 face->destroy = destroy;
99 face->upem = 0;
100 face->num_glyphs = (unsigned)-1;
101 return face;
104 typedef struct hb_face_for_data_closure_t {
105 hb_blob_t *blob;
106 unsigned index;
107 } hb_face_for_data_closure_t;
109 static hb_face_for_data_closure_t *hb_face_for_data_closure_create(hb_blob_t *
110 blob,
111 unsigned
112 index)
114 hb_face_for_data_closure_t *closure;
116 closure = malloc(sizeof(*closure));
117 if (!closure)
118 return NULL;
120 closure->blob = blob;
121 closure->index = index;
122 return closure;
125 static void hb_face_for_data_closure_destroy(hb_face_for_data_closure_t *
126 closure)
128 hb_blob_destroy(closure->blob);
129 free(closure);
132 static hb_blob_t *hb_face_for_data_reference_table(hb_face_t * face HB_UNUSED,
133 hb_tag_t tag,
134 void *user_data)
136 hb_face_for_data_closure_t *data;
137 struct ot_fnt_file *ot_fnt_file;
138 struct ot_fnt_face *ot_fnt_face;
139 struct ot_tbl *ot_tbl;
140 hb_blob_t *blob;
142 data = (hb_face_for_data_closure_t *) user_data;
143 if (tag == HB_TAG_NONE)
144 return hb_blob_reference(data->blob);
146 /*XXX:carefull, we don't use a "null" object like original code
147 be NULL pointers */
148 ot_fnt_file = hb_blob_lock_instance(data->blob);
149 ot_fnt_face = ot_fnt_file_get_face(ot_fnt_file, data->index);
150 ot_tbl = ot_fnt_face_get_tbl_by_tag(ot_fnt_face, tag);
152 /*XXX:without "null" object return the empty blob */
153 if (!ot_tbl)
154 return hb_blob_get_empty();
155 blob = hb_blob_create_sub_blob(data->blob, ot_tbl->of, ot_tbl->len);
156 return blob;
159 hb_face_t *hb_face_create(hb_blob_t * blob, unsigned index)
161 hb_face_t *face;
162 hb_face_for_data_closure_t *closure;
164 if (!blob || !hb_blob_get_length(blob))
165 return hb_face_get_empty();
167 closure =
168 hb_face_for_data_closure_create(hb_blob_reference(blob), index);
170 if (!closure)
171 return hb_face_get_empty();
173 face =
174 hb_face_create_for_tables(hb_face_for_data_reference_table, closure,
175 (hb_destroy_func_t)
176 hb_face_for_data_closure_destroy);
178 hb_face_set_index(face, index);
179 return face;
182 void hb_face_destroy(hb_face_t * face)
184 if (!face)
185 return;
186 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
187 return;
188 hb_atomic_int32_add(&face->ref_cnt, -1);
189 if (hb_atomic_int32_get(&face->ref_cnt) > 0)
190 return;
191 hb_atomic_int32_set(&face->ref_cnt, REF_CNT_INVALID_VAL);
193 #ifdef HAVE_GRAPHITE2
194 if (face->shaper_data.graphite2
195 && face->shaper_data.graphite2 != HB_SHAPER_DATA_INVALID
196 && face->shaper_data.graphite2 != HB_SHAPER_DATA_SUCCEEDED)
197 hb_graphite2_shaper_face_data_destroy(face->shaper_data.
198 graphite2);
199 #endif
200 #ifdef HAVE_OT
201 if (face->shaper_data.ot
202 && face->shaper_data.ot != HB_SHAPER_DATA_INVALID
203 && face->shaper_data.ot != HB_SHAPER_DATA_SUCCEEDED)
204 hb_ot_shaper_face_data_destroy(face->shaper_data.ot);
205 #endif
206 if (face->shaper_data.fallback
207 && face->shaper_data.fallback != HB_SHAPER_DATA_INVALID
208 && face->shaper_data.fallback != HB_SHAPER_DATA_SUCCEEDED)
209 hb_fallback_shaper_face_data_destroy(face->shaper_data.
210 fallback);
212 if (face->destroy)
213 face->destroy(face->user_data);
214 free(face);