Initial commit
[charfbuzz.git] / hb-face.c
blob4489a99ae3f4ebded37dab45f8cde0bf32cc43f1
1 // C99 port from c++ is protected by a GNU Lesser GPLv3
2 // Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
3 // <sylware@legeek.net>
4 #include <stdlib.h>
6 #include <ft2build.h>
7 #include FT_FREETYPE_H
8 #include FT_TRUETYPE_IDS_H
10 #include "hb.h"
11 #include "hb-private.h"
12 #include "hb-atomic-private.h"
13 #include "hb-shaper-private.h"
14 #include "hb-face-private.h"
15 #include "hb-blob-private.h"
16 #include "hb-open-file-private.h"
18 void
19 hb_face_make_immutable(hb_face_t *face)
21 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
22 return;
24 face->immutable = TRUE;
27 hb_face_t *
28 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 static hb_face_t hb_face_nil = {
36 REF_CNT_INVALID_VAL,//ref_cnt
37 TRUE,//immutable
38 NULL,//ft_face
39 NULL,//user_data
40 NULL,//destroy
42 #ifdef HAVE_GRAPHITE2
43 HB_SHAPER_DATA_INVALID,
44 #endif
45 #ifdef HAVE_OT
46 HB_SHAPER_DATA_INVALID,
47 #endif
48 HB_SHAPER_DATA_INVALID//fallback
50 NULL,//shape_plans
51 0,//upem
52 0,//num_glyphs
53 0,//index
54 NULL//reference_table_func
57 hb_face_t *
58 hb_face_get_empty(void)
60 return &hb_face_nil;
63 void
64 hb_face_set_index(hb_face_t *face, unsigned index)
66 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
67 return;
69 face->index = index;
72 void
73 hb_face_set_upem(hb_face_t *face,
74 unsigned upem)
76 if (hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL)
77 return;
79 face->upem = upem;
82 hb_face_t *
83 hb_face_create_for_tables(hb_reference_table_func_t reference_table_func,
84 void *user_data,
85 hb_destroy_func_t destroy)
87 hb_face_t *face = calloc(1, sizeof(*face));
88 if (!reference_table_func || !face) {
89 if (face)
90 free(face);
91 if (destroy)
92 destroy(user_data);
93 return hb_face_get_empty();
95 hb_atomic_int32_set(&face->ref_cnt, 1);
97 face->reference_table_func = reference_table_func;
98 face->user_data = user_data;
99 face->destroy = destroy;
101 face->upem = 0;
102 face->num_glyphs = (unsigned)-1;
103 return face;
106 typedef struct hb_face_for_data_closure_t {
107 hb_blob_t *blob;
108 unsigned index;
109 } hb_face_for_data_closure_t;
111 static hb_face_for_data_closure_t *
112 hb_face_for_data_closure_create(hb_blob_t *blob, unsigned 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
126 hb_face_for_data_closure_destroy(hb_face_for_data_closure_t *closure)
128 hb_blob_destroy(closure->blob);
129 free(closure);
132 static hb_blob_t *
133 hb_face_for_data_reference_table(hb_face_t *face HB_UNUSED,
134 hb_tag_t tag,
135 void *user_data)
137 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *)user_data;
139 if (tag == HB_TAG_NONE)
140 return hb_blob_reference(data->blob);
142 //XXX:carefull, we don't use a "null" object like original code
143 //be NULL pointers
144 struct ot_fnt_file *ot_fnt_file = hb_blob_lock_instance(data->blob);
145 struct ot_fnt_face *ot_fnt_face = ot_fnt_file_get_face(ot_fnt_file,
146 data->index);
147 struct ot_tbl *ot_tbl = ot_fnt_face_get_tbl_by_tag(ot_fnt_face, tag);
149 //XXX:without "null" object return the empty blob
150 if (!ot_tbl)
151 return hb_blob_get_empty();
152 hb_blob_t *blob = hb_blob_create_sub_blob(data->blob, ot_tbl->of,
153 ot_tbl->len);
154 return blob;
157 hb_face_t *
158 hb_face_create(hb_blob_t *blob,
159 unsigned index)
161 hb_face_t *face;
163 if (!blob || !hb_blob_get_length(blob))
164 return hb_face_get_empty();
166 hb_face_for_data_closure_t *closure = hb_face_for_data_closure_create(
167 hb_blob_reference(blob), index);
169 if (!closure)
170 return hb_face_get_empty();
172 face = hb_face_create_for_tables(
173 hb_face_for_data_reference_table,
174 closure,
175 (hb_destroy_func_t)hb_face_for_data_closure_destroy);
177 hb_face_set_index(face, index);
178 return face;
181 void
182 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.graphite2);
198 #endif
199 #ifdef HAVE_OT
200 if (face->shaper_data.ot
201 && face->shaper_data.ot != HB_SHAPER_DATA_INVALID
202 && face->shaper_data.ot != HB_SHAPER_DATA_SUCCEEDED)
203 hb_ot_shaper_face_data_destroy(face->shaper_data.ot);
204 #endif
205 if (face->shaper_data.fallback
206 && face->shaper_data.fallback != HB_SHAPER_DATA_INVALID
207 && face->shaper_data.fallback != HB_SHAPER_DATA_SUCCEEDED)
208 hb_fallback_shaper_face_data_destroy(face->shaper_data.fallback);
210 if (face->destroy)
211 face->destroy(face->user_data);
212 free(face);