File hb-buffer.c added (mode: 100644) (index 0000000..a3b6dec) |
|
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 <string.h> |
|
5 |
|
#include <stdlib.h> |
|
6 |
|
#include <assert.h> |
|
7 |
|
|
|
8 |
|
#include "hb.h" |
|
9 |
|
#include "hb-private.h" |
|
10 |
|
#include "hb-atomic-private.h" |
|
11 |
|
#include "hb-buffer-private.h" |
|
12 |
|
#include "hb-unicode-private.h" |
|
13 |
|
#include "hb-utf-private.h" |
|
14 |
|
|
|
15 |
|
hb_bool_t |
|
16 |
|
hb_segment_properties_equal(const hb_segment_properties_t *a, |
|
17 |
|
const hb_segment_properties_t *b) |
|
18 |
|
{ |
|
19 |
|
return a->direction == b->direction && |
|
20 |
|
a->script == b->script && |
|
21 |
|
a->language == b->language && |
|
22 |
|
a->reserved1 == b->reserved1 && |
|
23 |
|
a->reserved2 == b->reserved2; |
|
24 |
|
} |
|
25 |
|
|
|
26 |
|
unsigned |
|
27 |
|
hb_buffer_get_length(hb_buffer_t *buffer) |
|
28 |
|
{ |
|
29 |
|
return buffer->len; |
|
30 |
|
} |
|
31 |
|
|
|
32 |
|
hb_glyph_info_t * |
|
33 |
|
hb_buffer_get_glyph_infos(hb_buffer_t *buffer, unsigned *length) |
|
34 |
|
{ |
|
35 |
|
if (length) |
|
36 |
|
*length = buffer->len; |
|
37 |
|
return buffer->info; |
|
38 |
|
} |
|
39 |
|
|
|
40 |
|
hb_glyph_position_t * |
|
41 |
|
hb_buffer_get_glyph_positions(hb_buffer_t *buffer, unsigned *length) |
|
42 |
|
{ |
|
43 |
|
if (!buffer->have_positions) |
|
44 |
|
hb_buffer_clear_positions(buffer); |
|
45 |
|
|
|
46 |
|
if (length) |
|
47 |
|
*length = buffer->len; |
|
48 |
|
return buffer->pos; |
|
49 |
|
} |
|
50 |
|
|
|
51 |
|
void |
|
52 |
|
hb_buffer_set_unicode_funcs(hb_buffer_t *buffer, |
|
53 |
|
hb_unicode_funcs_t *unicode_funcs) |
|
54 |
|
{ |
|
55 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
56 |
|
return; |
|
57 |
|
|
|
58 |
|
if (!unicode_funcs) |
|
59 |
|
unicode_funcs = hb_unicode_funcs_get_default(); |
|
60 |
|
|
|
61 |
|
hb_unicode_funcs_reference(unicode_funcs); |
|
62 |
|
hb_unicode_funcs_destroy(buffer->unicode); |
|
63 |
|
buffer->unicode = unicode_funcs; |
|
64 |
|
} |
|
65 |
|
|
|
66 |
|
static void |
|
67 |
|
hb_buffer_reverse_range(hb_buffer_t *buffer, |
|
68 |
|
unsigned start, |
|
69 |
|
unsigned end) |
|
70 |
|
{ |
|
71 |
|
unsigned i, j; |
|
72 |
|
|
|
73 |
|
if (start == end - 1) |
|
74 |
|
return; |
|
75 |
|
|
|
76 |
|
for (i = start, j = end - 1; i < j; i++, j--) { |
|
77 |
|
hb_glyph_info_t t; |
|
78 |
|
|
|
79 |
|
t = buffer->info[i]; |
|
80 |
|
buffer->info[i] = buffer->info[j]; |
|
81 |
|
buffer->info[j] = t; |
|
82 |
|
} |
|
83 |
|
|
|
84 |
|
if (buffer->pos) { |
|
85 |
|
for (i = start, j = end - 1; i < j; i++, j--) { |
|
86 |
|
hb_glyph_position_t t; |
|
87 |
|
|
|
88 |
|
t = buffer->pos[i]; |
|
89 |
|
buffer->pos[i] = buffer->pos[j]; |
|
90 |
|
buffer->pos[j] = t; |
|
91 |
|
} |
|
92 |
|
} |
|
93 |
|
} |
|
94 |
|
|
|
95 |
|
void |
|
96 |
|
hb_buffer_reverse(hb_buffer_t *buffer) |
|
97 |
|
{ |
|
98 |
|
if (!buffer->len) |
|
99 |
|
return; |
|
100 |
|
|
|
101 |
|
hb_buffer_reverse_range(buffer, 0, buffer->len); |
|
102 |
|
} |
|
103 |
|
|
|
104 |
|
void |
|
105 |
|
hb_buffer_set_direction(hb_buffer_t *buffer, |
|
106 |
|
hb_direction_t direction) |
|
107 |
|
|
|
108 |
|
{ |
|
109 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
110 |
|
return; |
|
111 |
|
|
|
112 |
|
buffer->props.direction = direction; |
|
113 |
|
} |
|
114 |
|
|
|
115 |
|
void |
|
116 |
|
hb_buffer_clear_positions(hb_buffer_t *buffer) |
|
117 |
|
{ |
|
118 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
119 |
|
return; |
|
120 |
|
|
|
121 |
|
buffer->have_output = FALSE; |
|
122 |
|
buffer->have_positions = TRUE; |
|
123 |
|
|
|
124 |
|
buffer->out_len = 0; |
|
125 |
|
buffer->out_info = buffer->info; |
|
126 |
|
|
|
127 |
|
memset(buffer->pos, 0, sizeof(buffer->pos[0]) * buffer->len); |
|
128 |
|
} |
|
129 |
|
|
|
130 |
|
static hb_buffer_t hb_buffer_nil = { |
|
131 |
|
REF_CNT_INVALID_VAL,//ref_cnt |
|
132 |
|
&_hb_unicode_funcs_nil,//unicode |
|
133 |
|
HB_SEGMENT_PROPERTIES_DEFAULT, |
|
134 |
|
HB_BUFFER_FLAG_DEFAULT, |
|
135 |
|
|
|
136 |
|
HB_BUFFER_CONTENT_TYPE_INVALID, |
|
137 |
|
FALSE,//in_error |
|
138 |
|
FALSE,//have_output |
|
139 |
|
FALSE//have_positions |
|
140 |
|
|
|
141 |
|
//Zero is good enough for everything else. |
|
142 |
|
}; |
|
143 |
|
|
|
144 |
|
hb_buffer_t * |
|
145 |
|
hb_buffer_get_empty(void) |
|
146 |
|
{ |
|
147 |
|
return &hb_buffer_nil; |
|
148 |
|
} |
|
149 |
|
|
|
150 |
|
void |
|
151 |
|
hb_buffer_clear(hb_buffer_t *buffer) |
|
152 |
|
{ |
|
153 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
154 |
|
return; |
|
155 |
|
|
|
156 |
|
hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; |
|
157 |
|
buffer->props = default_props; |
|
158 |
|
buffer->flags = HB_BUFFER_FLAG_DEFAULT; |
|
159 |
|
|
|
160 |
|
buffer->content_type = HB_BUFFER_CONTENT_TYPE_INVALID; |
|
161 |
|
buffer->in_error = FALSE; |
|
162 |
|
buffer->have_output = FALSE; |
|
163 |
|
buffer->have_positions = FALSE; |
|
164 |
|
|
|
165 |
|
buffer->idx = 0; |
|
166 |
|
buffer->len = 0; |
|
167 |
|
buffer->out_len = 0; |
|
168 |
|
buffer->out_info = buffer->info; |
|
169 |
|
|
|
170 |
|
buffer->serial = 0; |
|
171 |
|
memset(buffer->allocated_var_bytes, 0, sizeof(buffer->allocated_var_bytes)); |
|
172 |
|
memset(buffer->allocated_var_owner, 0, sizeof(buffer->allocated_var_owner)); |
|
173 |
|
|
|
174 |
|
memset(buffer->context, 0, sizeof(buffer->context)); |
|
175 |
|
memset(buffer->context_len, 0, sizeof(buffer->context_len)); |
|
176 |
|
} |
|
177 |
|
|
|
178 |
|
void |
|
179 |
|
hb_buffer_reset(hb_buffer_t *buffer) |
|
180 |
|
{ |
|
181 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
182 |
|
return; |
|
183 |
|
|
|
184 |
|
hb_unicode_funcs_destroy(buffer->unicode); |
|
185 |
|
buffer->unicode = hb_unicode_funcs_get_default(); |
|
186 |
|
|
|
187 |
|
hb_buffer_clear(buffer); |
|
188 |
|
} |
|
189 |
|
|
|
190 |
|
void |
|
191 |
|
hb_buffer_destroy(hb_buffer_t *buffer) |
|
192 |
|
{ |
|
193 |
|
if (!buffer) |
|
194 |
|
return; |
|
195 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
196 |
|
return; |
|
197 |
|
hb_atomic_int32_add(&buffer->ref_cnt, -1); |
|
198 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) > 0) |
|
199 |
|
return; |
|
200 |
|
hb_atomic_int32_set(&buffer->ref_cnt, REF_CNT_INVALID_VAL); |
|
201 |
|
|
|
202 |
|
hb_unicode_funcs_destroy(buffer->unicode); |
|
203 |
|
|
|
204 |
|
free(buffer->info); |
|
205 |
|
free(buffer->pos); |
|
206 |
|
free(buffer); |
|
207 |
|
} |
|
208 |
|
|
|
209 |
|
hb_buffer_t * |
|
210 |
|
hb_buffer_create(void) |
|
211 |
|
{ |
|
212 |
|
hb_buffer_t *buffer = calloc(1, sizeof(*buffer)); |
|
213 |
|
if (!buffer) |
|
214 |
|
return hb_buffer_get_empty(); |
|
215 |
|
|
|
216 |
|
hb_atomic_int32_set(&buffer->ref_cnt, 1); |
|
217 |
|
buffer->unicode = hb_unicode_funcs_get_empty(); |
|
218 |
|
|
|
219 |
|
hb_buffer_reset(buffer); |
|
220 |
|
return buffer; |
|
221 |
|
} |
|
222 |
|
|
|
223 |
|
void |
|
224 |
|
hb_buffer_set_script(hb_buffer_t *buffer, |
|
225 |
|
hb_script_t script) |
|
226 |
|
{ |
|
227 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
228 |
|
return; |
|
229 |
|
|
|
230 |
|
buffer->props.script = script; |
|
231 |
|
} |
|
232 |
|
|
|
233 |
|
//Here is how the buffer works internally: |
|
234 |
|
// |
|
235 |
|
//There are two info pointers: info and out_info. They always have |
|
236 |
|
//the same allocated size, but different lengths. |
|
237 |
|
// |
|
238 |
|
//As an optimization, both info and out_info may point to the |
|
239 |
|
//same piece of memory, which is owned by info. This remains the |
|
240 |
|
//case as long as out_len doesn't exceed i at any time. |
|
241 |
|
//In that case, swap_buffers() is no-op and the glyph operations operate |
|
242 |
|
//mostly in-place. |
|
243 |
|
// |
|
244 |
|
//As soon as out_info gets longer than info, out_info is moved over |
|
245 |
|
//to an alternate buffer (which we reuse the pos buffer for!), and its |
|
246 |
|
//current contents (out_len entries) are copied to the new place. |
|
247 |
|
//This should all remain transparent to the user. swap_buffers() then |
|
248 |
|
//switches info and out_info. |
|
249 |
|
|
|
250 |
|
static hb_bool_t |
|
251 |
|
enlarge(hb_buffer_t *buffer, unsigned int size) |
|
252 |
|
{ |
|
253 |
|
if (buffer->in_error) |
|
254 |
|
return FALSE; |
|
255 |
|
|
|
256 |
|
unsigned int new_allocated = buffer->allocated; |
|
257 |
|
hb_glyph_position_t *new_pos = NULL; |
|
258 |
|
hb_glyph_info_t *new_info = NULL; |
|
259 |
|
hb_bool_t separate_out = buffer->out_info != buffer->info; |
|
260 |
|
|
|
261 |
|
if (hb_unsigned_int_mul_overflows(size, sizeof(buffer->info[0]))) |
|
262 |
|
goto done; |
|
263 |
|
|
|
264 |
|
while (size >= new_allocated) |
|
265 |
|
new_allocated += (new_allocated >> 1) + 32; |
|
266 |
|
|
|
267 |
|
//ASSERT_STATIC (sizeof (info[0]) == sizeof (pos[0])); |
|
268 |
|
if (hb_unsigned_int_mul_overflows(new_allocated, sizeof(buffer->info[0]))) |
|
269 |
|
goto done; |
|
270 |
|
|
|
271 |
|
new_pos = (hb_glyph_position_t*)realloc(buffer->pos, new_allocated |
|
272 |
|
* sizeof(buffer->pos[0])); |
|
273 |
|
new_info = (hb_glyph_info_t*)realloc(buffer->info, new_allocated |
|
274 |
|
* sizeof(buffer->info[0])); |
|
275 |
|
|
|
276 |
|
done: |
|
277 |
|
if (!new_pos || !new_info) |
|
278 |
|
buffer->in_error = TRUE; |
|
279 |
|
|
|
280 |
|
if (new_pos) |
|
281 |
|
buffer->pos = new_pos; |
|
282 |
|
|
|
283 |
|
if (new_info) |
|
284 |
|
buffer->info = new_info; |
|
285 |
|
|
|
286 |
|
buffer->out_info = separate_out ? (hb_glyph_info_t*)buffer->pos |
|
287 |
|
: buffer->info; |
|
288 |
|
if (!buffer->in_error) |
|
289 |
|
buffer->allocated = new_allocated; |
|
290 |
|
return !buffer->in_error; |
|
291 |
|
} |
|
292 |
|
|
|
293 |
|
static hb_bool_t |
|
294 |
|
ensure(hb_buffer_t *buffer, unsigned int size) |
|
295 |
|
{ |
|
296 |
|
return (size < buffer->allocated) ? TRUE : enlarge(buffer, size); |
|
297 |
|
} |
|
298 |
|
|
|
299 |
|
static void |
|
300 |
|
clear_context(hb_buffer_t *buffer, unsigned int side) |
|
301 |
|
{ |
|
302 |
|
buffer->context_len[side] = 0; |
|
303 |
|
} |
|
304 |
|
|
|
305 |
|
static void |
|
306 |
|
add(hb_buffer_t *buffer, hb_codepoint_t codepoint, unsigned int cluster) |
|
307 |
|
{ |
|
308 |
|
hb_glyph_info_t *glyph; |
|
309 |
|
|
|
310 |
|
if (!ensure(buffer, buffer->len + 1)) return; |
|
311 |
|
|
|
312 |
|
glyph = &buffer->info[buffer->len]; |
|
313 |
|
|
|
314 |
|
memset(glyph, 0, sizeof(*glyph)); |
|
315 |
|
glyph->codepoint = codepoint; |
|
316 |
|
glyph->mask = 1; |
|
317 |
|
glyph->cluster = cluster; |
|
318 |
|
|
|
319 |
|
buffer->len++; |
|
320 |
|
} |
|
321 |
|
|
|
322 |
|
struct utf { |
|
323 |
|
unsigned bytes_n; |
|
324 |
|
unsigned (*len)(void *text); |
|
325 |
|
void *(*ptr_offset)(void *text, unsigned offset); |
|
326 |
|
void *(*prev)(void *text, void *start, hb_codepoint_t *unicode); |
|
327 |
|
unsigned (*diff)(void *a, void *b); |
|
328 |
|
void *(*next)(void *text, void *end, hb_codepoint_t *unicode); |
|
329 |
|
}; |
|
330 |
|
|
|
331 |
|
static struct utf utf8 = { |
|
332 |
|
sizeof(uint8_t), |
|
333 |
|
hb_utf_strlen_utf8, |
|
334 |
|
hb_utf_ptr_offset_utf8, |
|
335 |
|
hb_utf_prev_utf8, |
|
336 |
|
hb_utf_diff_utf8, |
|
337 |
|
hb_utf_next_utf8 |
|
338 |
|
}; |
|
339 |
|
|
|
340 |
|
static HB_UNUSED struct utf utf16 = { |
|
341 |
|
sizeof(uint16_t), |
|
342 |
|
hb_utf_strlen_utf16, |
|
343 |
|
hb_utf_ptr_offset_utf16, |
|
344 |
|
hb_utf_prev_utf16, |
|
345 |
|
hb_utf_diff_utf16, |
|
346 |
|
hb_utf_next_utf16 |
|
347 |
|
}; |
|
348 |
|
|
|
349 |
|
static HB_UNUSED struct utf utf32 = { |
|
350 |
|
sizeof(uint32_t), |
|
351 |
|
hb_utf_strlen_utf32, |
|
352 |
|
hb_utf_ptr_offset_utf32, |
|
353 |
|
hb_utf_prev_utf32, |
|
354 |
|
hb_utf_diff_utf32, |
|
355 |
|
hb_utf_next_utf32 |
|
356 |
|
}; |
|
357 |
|
|
|
358 |
|
//to unroll the original c++, could have used a macro |
|
359 |
|
//ASSEMBLY:maybe worth to be unrolled to fine tuned assembly |
|
360 |
|
static void |
|
361 |
|
hb_buffer_add_utf(hb_buffer_t *buffer, |
|
362 |
|
struct utf *utf, |
|
363 |
|
void *text, |
|
364 |
|
int text_length, |
|
365 |
|
unsigned item_offset, |
|
366 |
|
int item_length) |
|
367 |
|
{ |
|
368 |
|
assert(buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE || |
|
369 |
|
(!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID)); |
|
370 |
|
|
|
371 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
372 |
|
return; |
|
373 |
|
|
|
374 |
|
if (text_length == -1) |
|
375 |
|
text_length = utf->len(text); |
|
376 |
|
|
|
377 |
|
if (item_length == -1) |
|
378 |
|
item_length = text_length - item_offset; |
|
379 |
|
|
|
380 |
|
ensure(buffer, buffer->len + item_length * utf->bytes_n / 4); |
|
381 |
|
|
|
382 |
|
//If buffer is empty and pre-context provided, install it. |
|
383 |
|
//This check is written this way, to make sure people can |
|
384 |
|
//provide pre-context in one add_utf() call, then provide |
|
385 |
|
//text in a follow-up call. See: |
|
386 |
|
// |
|
387 |
|
//https://bugzilla.mozilla.org/show_bug.cgi?id=801410#c13 |
|
388 |
|
if (!buffer->len && item_offset > 0) { |
|
389 |
|
//Add pre-context |
|
390 |
|
clear_context(buffer, 0); |
|
391 |
|
void *prev = utf->ptr_offset(text, item_offset); |
|
392 |
|
void *start = text; |
|
393 |
|
while (start < prev && buffer->context_len[0] < HB_BUFFER_CONTEXT_LENGTH) { |
|
394 |
|
hb_codepoint_t u; |
|
395 |
|
prev = utf->prev(prev, start, &u); |
|
396 |
|
buffer->context[0][buffer->context_len[0]++] = u; |
|
397 |
|
} |
|
398 |
|
} |
|
399 |
|
|
|
400 |
|
void *next = utf->ptr_offset(text, item_offset); |
|
401 |
|
void *end = utf->ptr_offset(next, item_length); |
|
402 |
|
while (next < end) { |
|
403 |
|
hb_codepoint_t u; |
|
404 |
|
void *old_next = next; |
|
405 |
|
next = utf->next(next, end, &u); |
|
406 |
|
add(buffer, u, utf->diff(old_next, text)); |
|
407 |
|
} |
|
408 |
|
|
|
409 |
|
//Add post-context |
|
410 |
|
clear_context(buffer, 1); |
|
411 |
|
end = utf->ptr_offset(text, text_length); |
|
412 |
|
end = text + text_length; |
|
413 |
|
while (next < end && buffer->context_len[1] < HB_BUFFER_CONTEXT_LENGTH) { |
|
414 |
|
hb_codepoint_t u; |
|
415 |
|
next = utf->next(next, end, &u); |
|
416 |
|
buffer->context[1][buffer->context_len[1]++] = u; |
|
417 |
|
} |
|
418 |
|
|
|
419 |
|
buffer->content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; |
|
420 |
|
} |
|
421 |
|
|
|
422 |
|
void |
|
423 |
|
hb_buffer_add_utf8(hb_buffer_t *buffer, |
|
424 |
|
const char *text, |
|
425 |
|
int text_length, |
|
426 |
|
unsigned int item_offset, |
|
427 |
|
int item_length) |
|
428 |
|
{ |
|
429 |
|
hb_buffer_add_utf(buffer, |
|
430 |
|
&utf8, |
|
431 |
|
(void*)text, |
|
432 |
|
text_length, |
|
433 |
|
item_offset, |
|
434 |
|
item_length); |
|
435 |
|
} |
|
436 |
|
|
|
437 |
|
void |
|
438 |
|
hb_buffer_set_flags(hb_buffer_t *buffer, |
|
439 |
|
hb_buffer_flags_t flags) |
|
440 |
|
{ |
|
441 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
442 |
|
return; |
|
443 |
|
|
|
444 |
|
buffer->flags = flags; |
|
445 |
|
} |
|
446 |
|
|
|
447 |
|
void |
|
448 |
|
hb_buffer_set_language(hb_buffer_t *buffer, |
|
449 |
|
hb_language_t language) |
|
450 |
|
{ |
|
451 |
|
if (hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
452 |
|
return; |
|
453 |
|
|
|
454 |
|
buffer->props.language = language; |
|
455 |
|
} |
|
456 |
|
|
|
457 |
|
hb_direction_t |
|
458 |
|
hb_buffer_get_direction(hb_buffer_t *buffer) |
|
459 |
|
{ |
|
460 |
|
return buffer->props.direction; |
|
461 |
|
} |
|
462 |
|
|
|
463 |
|
void |
|
464 |
|
hb_buffer_add(hb_buffer_t *buffer, |
|
465 |
|
hb_codepoint_t codepoint, |
|
466 |
|
unsigned int cluster) |
|
467 |
|
{ |
|
468 |
|
add(buffer, codepoint, cluster); |
|
469 |
|
clear_context(buffer, 1); |
|
470 |
|
} |
File hb-buffer.h added (mode: 100644) (index 0000000..87c4ce5) |
|
1 |
|
/* |
|
2 |
|
* Copyright © 1998-2004 David Turner and Werner Lemberg |
|
3 |
|
* Copyright © 2004,2007,2009 Red Hat, Inc. |
|
4 |
|
* Copyright © 2011,2012 Google, Inc. |
|
5 |
|
* |
|
6 |
|
* This is part of HarfBuzz, a text shaping library. |
|
7 |
|
* |
|
8 |
|
* Permission is hereby granted, without written agreement and without |
|
9 |
|
* license or royalty fees, to use, copy, modify, and distribute this |
|
10 |
|
* software and its documentation for any purpose, provided that the |
|
11 |
|
* above copyright notice and the following two paragraphs appear in |
|
12 |
|
* all copies of this software. |
|
13 |
|
* |
|
14 |
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
|
15 |
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
|
16 |
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
|
17 |
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
|
18 |
|
* DAMAGE. |
|
19 |
|
* |
|
20 |
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
|
21 |
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|
22 |
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
|
23 |
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
|
24 |
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
|
25 |
|
* |
|
26 |
|
* Red Hat Author(s): Owen Taylor, Behdad Esfahbod |
|
27 |
|
* Google Author(s): Behdad Esfahbod |
|
28 |
|
*/ |
|
29 |
|
|
|
30 |
|
#ifndef HB_H_IN |
|
31 |
|
#error "Include <hb.h> instead." |
|
32 |
|
#endif |
|
33 |
|
|
|
34 |
|
#ifndef HB_BUFFER_H |
|
35 |
|
#define HB_BUFFER_H |
|
36 |
|
|
|
37 |
|
#include "hb-common.h" |
|
38 |
|
#include "hb-unicode.h" |
|
39 |
|
#include "hb-font.h" |
|
40 |
|
|
|
41 |
|
HB_BEGIN_DECLS |
|
42 |
|
|
|
43 |
|
|
|
44 |
|
typedef struct hb_glyph_info_t { |
|
45 |
|
hb_codepoint_t codepoint; |
|
46 |
|
hb_mask_t mask; |
|
47 |
|
uint32_t cluster; |
|
48 |
|
|
|
49 |
|
/*< private >*/ |
|
50 |
|
hb_var_int_t var1; |
|
51 |
|
hb_var_int_t var2; |
|
52 |
|
} hb_glyph_info_t; |
|
53 |
|
|
|
54 |
|
typedef struct hb_glyph_position_t { |
|
55 |
|
hb_position_t x_advance; |
|
56 |
|
hb_position_t y_advance; |
|
57 |
|
hb_position_t x_offset; |
|
58 |
|
hb_position_t y_offset; |
|
59 |
|
|
|
60 |
|
/*< private >*/ |
|
61 |
|
hb_var_int_t var; |
|
62 |
|
} hb_glyph_position_t; |
|
63 |
|
|
|
64 |
|
|
|
65 |
|
typedef struct hb_segment_properties_t { |
|
66 |
|
hb_direction_t direction; |
|
67 |
|
hb_script_t script; |
|
68 |
|
hb_language_t language; |
|
69 |
|
/*< private >*/ |
|
70 |
|
void *reserved1; |
|
71 |
|
void *reserved2; |
|
72 |
|
} hb_segment_properties_t; |
|
73 |
|
|
|
74 |
|
#define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ |
|
75 |
|
HB_SCRIPT_INVALID, \ |
|
76 |
|
HB_LANGUAGE_INVALID, \ |
|
77 |
|
NULL, \ |
|
78 |
|
NULL} |
|
79 |
|
|
|
80 |
|
hb_bool_t |
|
81 |
|
hb_segment_properties_equal (const hb_segment_properties_t *a, |
|
82 |
|
const hb_segment_properties_t *b); |
|
83 |
|
|
|
84 |
|
unsigned int |
|
85 |
|
hb_segment_properties_hash (const hb_segment_properties_t *p); |
|
86 |
|
|
|
87 |
|
|
|
88 |
|
|
|
89 |
|
/* |
|
90 |
|
* hb_buffer_t |
|
91 |
|
*/ |
|
92 |
|
|
|
93 |
|
typedef struct hb_buffer_t hb_buffer_t; |
|
94 |
|
|
|
95 |
|
hb_buffer_t * |
|
96 |
|
hb_buffer_create (void); |
|
97 |
|
|
|
98 |
|
hb_buffer_t * |
|
99 |
|
hb_buffer_get_empty (void); |
|
100 |
|
|
|
101 |
|
hb_buffer_t * |
|
102 |
|
hb_buffer_reference (hb_buffer_t *buffer); |
|
103 |
|
|
|
104 |
|
void |
|
105 |
|
hb_buffer_destroy (hb_buffer_t *buffer); |
|
106 |
|
|
|
107 |
|
hb_bool_t |
|
108 |
|
hb_buffer_set_user_data (hb_buffer_t *buffer, |
|
109 |
|
hb_user_data_key_t *key, |
|
110 |
|
void * data, |
|
111 |
|
hb_destroy_func_t destroy, |
|
112 |
|
hb_bool_t replace); |
|
113 |
|
|
|
114 |
|
void * |
|
115 |
|
hb_buffer_get_user_data (hb_buffer_t *buffer, |
|
116 |
|
hb_user_data_key_t *key); |
|
117 |
|
|
|
118 |
|
|
|
119 |
|
typedef enum { |
|
120 |
|
HB_BUFFER_CONTENT_TYPE_INVALID = 0, |
|
121 |
|
HB_BUFFER_CONTENT_TYPE_UNICODE, |
|
122 |
|
HB_BUFFER_CONTENT_TYPE_GLYPHS |
|
123 |
|
} hb_buffer_content_type_t; |
|
124 |
|
|
|
125 |
|
void |
|
126 |
|
hb_buffer_set_content_type (hb_buffer_t *buffer, |
|
127 |
|
hb_buffer_content_type_t content_type); |
|
128 |
|
|
|
129 |
|
hb_buffer_content_type_t |
|
130 |
|
hb_buffer_get_content_type (hb_buffer_t *buffer); |
|
131 |
|
|
|
132 |
|
|
|
133 |
|
void |
|
134 |
|
hb_buffer_set_unicode_funcs (hb_buffer_t *buffer, |
|
135 |
|
hb_unicode_funcs_t *unicode_funcs); |
|
136 |
|
|
|
137 |
|
hb_unicode_funcs_t * |
|
138 |
|
hb_buffer_get_unicode_funcs (hb_buffer_t *buffer); |
|
139 |
|
|
|
140 |
|
void |
|
141 |
|
hb_buffer_set_direction (hb_buffer_t *buffer, |
|
142 |
|
hb_direction_t direction); |
|
143 |
|
|
|
144 |
|
hb_direction_t |
|
145 |
|
hb_buffer_get_direction (hb_buffer_t *buffer); |
|
146 |
|
|
|
147 |
|
void |
|
148 |
|
hb_buffer_set_script (hb_buffer_t *buffer, |
|
149 |
|
hb_script_t script); |
|
150 |
|
|
|
151 |
|
hb_script_t |
|
152 |
|
hb_buffer_get_script (hb_buffer_t *buffer); |
|
153 |
|
|
|
154 |
|
void |
|
155 |
|
hb_buffer_set_language (hb_buffer_t *buffer, |
|
156 |
|
hb_language_t language); |
|
157 |
|
|
|
158 |
|
|
|
159 |
|
hb_language_t |
|
160 |
|
hb_buffer_get_language (hb_buffer_t *buffer); |
|
161 |
|
|
|
162 |
|
void |
|
163 |
|
hb_buffer_set_segment_properties (hb_buffer_t *buffer, |
|
164 |
|
const hb_segment_properties_t *props); |
|
165 |
|
|
|
166 |
|
void |
|
167 |
|
hb_buffer_get_segment_properties (hb_buffer_t *buffer, |
|
168 |
|
hb_segment_properties_t *props); |
|
169 |
|
|
|
170 |
|
void |
|
171 |
|
hb_buffer_guess_segment_properties (hb_buffer_t *buffer); |
|
172 |
|
|
|
173 |
|
|
|
174 |
|
typedef enum { /*< flags >*/ |
|
175 |
|
HB_BUFFER_FLAG_DEFAULT = 0x00000000, |
|
176 |
|
HB_BUFFER_FLAG_BOT = 0x00000001, /* Beginning-of-text */ |
|
177 |
|
HB_BUFFER_FLAG_EOT = 0x00000002, /* End-of-text */ |
|
178 |
|
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004 |
|
179 |
|
} hb_buffer_flags_t; |
|
180 |
|
|
|
181 |
|
void |
|
182 |
|
hb_buffer_set_flags (hb_buffer_t *buffer, |
|
183 |
|
hb_buffer_flags_t flags); |
|
184 |
|
|
|
185 |
|
hb_buffer_flags_t |
|
186 |
|
hb_buffer_get_flags (hb_buffer_t *buffer); |
|
187 |
|
|
|
188 |
|
|
|
189 |
|
/* Resets the buffer. Afterwards it's as if it was just created, |
|
190 |
|
* except that it has a larger buffer allocated perhaps... */ |
|
191 |
|
void |
|
192 |
|
hb_buffer_reset (hb_buffer_t *buffer); |
|
193 |
|
|
|
194 |
|
/* Like reset, but does NOT clear unicode_funcs. */ |
|
195 |
|
void |
|
196 |
|
hb_buffer_clear_contents (hb_buffer_t *buffer); |
|
197 |
|
|
|
198 |
|
/* Returns false if allocation failed */ |
|
199 |
|
hb_bool_t |
|
200 |
|
hb_buffer_pre_allocate (hb_buffer_t *buffer, |
|
201 |
|
unsigned int size); |
|
202 |
|
|
|
203 |
|
|
|
204 |
|
/* Returns false if allocation has failed before */ |
|
205 |
|
hb_bool_t |
|
206 |
|
hb_buffer_allocation_successful (hb_buffer_t *buffer); |
|
207 |
|
|
|
208 |
|
void |
|
209 |
|
hb_buffer_reverse (hb_buffer_t *buffer); |
|
210 |
|
|
|
211 |
|
void |
|
212 |
|
hb_buffer_reverse_clusters (hb_buffer_t *buffer); |
|
213 |
|
|
|
214 |
|
|
|
215 |
|
/* Filling the buffer in */ |
|
216 |
|
|
|
217 |
|
void |
|
218 |
|
hb_buffer_add (hb_buffer_t *buffer, |
|
219 |
|
hb_codepoint_t codepoint, |
|
220 |
|
unsigned int cluster); |
|
221 |
|
|
|
222 |
|
void |
|
223 |
|
hb_buffer_add_utf8 (hb_buffer_t *buffer, |
|
224 |
|
const char *text, |
|
225 |
|
int text_length, |
|
226 |
|
unsigned int item_offset, |
|
227 |
|
int item_length); |
|
228 |
|
|
|
229 |
|
void |
|
230 |
|
hb_buffer_add_utf16 (hb_buffer_t *buffer, |
|
231 |
|
const uint16_t *text, |
|
232 |
|
int text_length, |
|
233 |
|
unsigned int item_offset, |
|
234 |
|
int item_length); |
|
235 |
|
|
|
236 |
|
void |
|
237 |
|
hb_buffer_add_utf32 (hb_buffer_t *buffer, |
|
238 |
|
const uint32_t *text, |
|
239 |
|
int text_length, |
|
240 |
|
unsigned int item_offset, |
|
241 |
|
int item_length); |
|
242 |
|
|
|
243 |
|
|
|
244 |
|
/* Clears any new items added at the end */ |
|
245 |
|
hb_bool_t |
|
246 |
|
hb_buffer_set_length (hb_buffer_t *buffer, |
|
247 |
|
unsigned int length); |
|
248 |
|
|
|
249 |
|
/* Return value valid as long as buffer not modified */ |
|
250 |
|
unsigned int |
|
251 |
|
hb_buffer_get_length (hb_buffer_t *buffer); |
|
252 |
|
|
|
253 |
|
/* Getting glyphs out of the buffer */ |
|
254 |
|
|
|
255 |
|
/* Return value valid as long as buffer not modified */ |
|
256 |
|
hb_glyph_info_t * |
|
257 |
|
hb_buffer_get_glyph_infos (hb_buffer_t *buffer, |
|
258 |
|
unsigned int *length); |
|
259 |
|
|
|
260 |
|
/* Return value valid as long as buffer not modified */ |
|
261 |
|
hb_glyph_position_t * |
|
262 |
|
hb_buffer_get_glyph_positions (hb_buffer_t *buffer, |
|
263 |
|
unsigned int *length); |
|
264 |
|
|
|
265 |
|
|
|
266 |
|
/* Reorders a glyph buffer to have canonical in-cluster glyph order / position. |
|
267 |
|
* The resulting clusters should behave identical to pre-reordering clusters. |
|
268 |
|
* NOTE: This has nothing to do with Unicode normalization. */ |
|
269 |
|
void |
|
270 |
|
hb_buffer_normalize_glyphs (hb_buffer_t *buffer); |
|
271 |
|
|
|
272 |
|
|
|
273 |
|
/* |
|
274 |
|
* Serialize |
|
275 |
|
*/ |
|
276 |
|
|
|
277 |
|
typedef enum { /*< flags >*/ |
|
278 |
|
HB_BUFFER_SERIALIZE_FLAG_DEFAULT = 0x00000000, |
|
279 |
|
HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS = 0x00000001, |
|
280 |
|
HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS = 0x00000002, |
|
281 |
|
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004 |
|
282 |
|
} hb_buffer_serialize_flags_t; |
|
283 |
|
|
|
284 |
|
typedef enum { |
|
285 |
|
HB_BUFFER_SERIALIZE_FORMAT_TEXT = HB_TAG('T','E','X','T'), |
|
286 |
|
HB_BUFFER_SERIALIZE_FORMAT_JSON = HB_TAG('J','S','O','N'), |
|
287 |
|
HB_BUFFER_SERIALIZE_FORMAT_INVALID = HB_TAG_NONE |
|
288 |
|
} hb_buffer_serialize_format_t; |
|
289 |
|
|
|
290 |
|
/* len=-1 means str is NUL-terminated. */ |
|
291 |
|
hb_buffer_serialize_format_t |
|
292 |
|
hb_buffer_serialize_format_from_string (const char *str, int len); |
|
293 |
|
|
|
294 |
|
const char * |
|
295 |
|
hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format); |
|
296 |
|
|
|
297 |
|
const char ** |
|
298 |
|
hb_buffer_serialize_list_formats (void); |
|
299 |
|
|
|
300 |
|
/* Returns number of items, starting at start, that were serialized. */ |
|
301 |
|
unsigned int |
|
302 |
|
hb_buffer_serialize_glyphs (hb_buffer_t *buffer, |
|
303 |
|
unsigned int start, |
|
304 |
|
unsigned int end, |
|
305 |
|
char *buf, |
|
306 |
|
unsigned int buf_size, |
|
307 |
|
unsigned int *buf_consumed, /* May be NULL */ |
|
308 |
|
hb_font_t *font, /* May be NULL */ |
|
309 |
|
hb_buffer_serialize_format_t format, |
|
310 |
|
hb_buffer_serialize_flags_t flags); |
|
311 |
|
|
|
312 |
|
hb_bool_t |
|
313 |
|
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, |
|
314 |
|
const char *buf, |
|
315 |
|
int buf_len, /* -1 means nul-terminated */ |
|
316 |
|
const char **end_ptr, /* May be NULL */ |
|
317 |
|
hb_font_t *font, /* May be NULL */ |
|
318 |
|
hb_buffer_serialize_format_t format); |
|
319 |
|
|
|
320 |
|
|
|
321 |
|
HB_END_DECLS |
|
322 |
|
|
|
323 |
|
#endif /* HB_BUFFER_H */ |
File hb-common.c added (mode: 100644) (index 0000000..f5141f5) |
|
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 |
|
#define _GNU_SOURCE |
|
5 |
|
#include <string.h> |
|
6 |
|
#include <stdlib.h> |
|
7 |
|
|
|
8 |
|
#include "hb.h" |
|
9 |
|
#include "hb-private.h" |
|
10 |
|
#include "hb-atomic-private.h" |
|
11 |
|
|
|
12 |
|
//this is actually hb_language_t type |
|
13 |
|
struct hb_language_impl_t { |
|
14 |
|
const char s[1]; |
|
15 |
|
}; |
|
16 |
|
|
|
17 |
|
static const char canon_map[256] = { |
|
18 |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
19 |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
20 |
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', 0, 0, |
|
21 |
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, |
|
22 |
|
'-', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
|
23 |
|
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, '-', |
|
24 |
|
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', |
|
25 |
|
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, 0 |
|
26 |
|
}; |
|
27 |
|
|
|
28 |
|
static hb_bool_t |
|
29 |
|
lang_equal(hb_language_t v1, |
|
30 |
|
const void *v2) |
|
31 |
|
{ |
|
32 |
|
const unsigned char *p1 = (const unsigned char*)v1; |
|
33 |
|
const unsigned char *p2 = (const unsigned char*)v2; |
|
34 |
|
|
|
35 |
|
while (*p1 && *p1 == canon_map[*p2]) |
|
36 |
|
p1++, p2++; |
|
37 |
|
return *p1 == canon_map[*p2]; |
|
38 |
|
} |
|
39 |
|
|
|
40 |
|
struct hb_language_item_t { |
|
41 |
|
|
|
42 |
|
struct hb_language_item_t *next; |
|
43 |
|
hb_language_t lang; |
|
44 |
|
}; |
|
45 |
|
|
|
46 |
|
static hb_language_t |
|
47 |
|
lang_assign(const char *s) |
|
48 |
|
{ |
|
49 |
|
hb_language_t lang = (hb_language_t)strdup(s); |
|
50 |
|
for (unsigned char *p = (unsigned char *)lang; *p; p++) |
|
51 |
|
*p = canon_map[*p]; |
|
52 |
|
return lang; |
|
53 |
|
} |
|
54 |
|
|
|
55 |
|
/* Thread-safe lock-free language list */ |
|
56 |
|
|
|
57 |
|
static struct hb_language_item_t *lang_items; |
|
58 |
|
|
|
59 |
|
static struct hb_language_item_t * |
|
60 |
|
language_item_find_or_insert(const char *key) |
|
61 |
|
{ |
|
62 |
|
struct hb_language_item_t *first_lang_item = hb_atomic_ptr_get(&lang_items); |
|
63 |
|
|
|
64 |
|
while (1) { |
|
65 |
|
for (struct hb_language_item_t *lang_item = first_lang_item; lang_item; |
|
66 |
|
lang_item = lang_item->next) |
|
67 |
|
if (lang_equal(lang_item->lang, key)) |
|
68 |
|
return lang_item; |
|
69 |
|
|
|
70 |
|
//Not found; allocate one. |
|
71 |
|
struct hb_language_item_t *lang_item = calloc(1, sizeof(*lang_item)); |
|
72 |
|
if (!lang_item) |
|
73 |
|
return NULL; |
|
74 |
|
lang_item->next = first_lang_item; |
|
75 |
|
lang_item->lang = lang_assign(key); |
|
76 |
|
|
|
77 |
|
if (hb_atomic_ptr_cmpexch(&lang_items, &first_lang_item, &lang_item)) |
|
78 |
|
return lang_item; |
|
79 |
|
free (lang_item); |
|
80 |
|
} |
|
81 |
|
} |
|
82 |
|
|
|
83 |
|
hb_language_t |
|
84 |
|
hb_language_from_string(const char *str, int len) |
|
85 |
|
{ |
|
86 |
|
if (!str || !len || !*str) |
|
87 |
|
return HB_LANGUAGE_INVALID; |
|
88 |
|
|
|
89 |
|
if (len >= 0) { |
|
90 |
|
char strbuf[64]; |
|
91 |
|
len = MIN(len, (int)sizeof(strbuf) - 1); |
|
92 |
|
str = (char*)memcpy(strbuf, str, len); |
|
93 |
|
strbuf[len] = '\0'; |
|
94 |
|
} |
|
95 |
|
|
|
96 |
|
struct hb_language_item_t *item = language_item_find_or_insert(str); |
|
97 |
|
|
|
98 |
|
return item ? item->lang : HB_LANGUAGE_INVALID; |
|
99 |
|
} |
|
100 |
|
|
|
101 |
|
hb_tag_t |
|
102 |
|
hb_tag_from_string(const char *str, int len) |
|
103 |
|
{ |
|
104 |
|
char tag[4]; |
|
105 |
|
unsigned i; |
|
106 |
|
|
|
107 |
|
if (!str || !len || !*str) |
|
108 |
|
return HB_TAG_NONE; |
|
109 |
|
|
|
110 |
|
if (len < 0 || len > 4) |
|
111 |
|
len = 4; |
|
112 |
|
for (i = 0; i < (unsigned)len && str[i]; ++i) |
|
113 |
|
tag[i] = str[i]; |
|
114 |
|
for (; i < 4; ++i) |
|
115 |
|
tag[i] = ' '; |
|
116 |
|
return HB_TAG_CHAR4(tag); |
|
117 |
|
} |
|
118 |
|
|
|
119 |
|
const char * |
|
120 |
|
hb_language_to_string(hb_language_t language) |
|
121 |
|
{ |
|
122 |
|
//This is actually NULL-safe! |
|
123 |
|
return language->s; |
|
124 |
|
} |
File hb-common.h added (mode: 100644) (index 0000000..40c1887) |
|
1 |
|
/* |
|
2 |
|
* Copyright © 2007,2008,2009 Red Hat, Inc. |
|
3 |
|
* Copyright © 2011,2012 Google, Inc. |
|
4 |
|
* |
|
5 |
|
* This is part of HarfBuzz, a text shaping library. |
|
6 |
|
* |
|
7 |
|
* Permission is hereby granted, without written agreement and without |
|
8 |
|
* license or royalty fees, to use, copy, modify, and distribute this |
|
9 |
|
* software and its documentation for any purpose, provided that the |
|
10 |
|
* above copyright notice and the following two paragraphs appear in |
|
11 |
|
* all copies of this software. |
|
12 |
|
* |
|
13 |
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
|
14 |
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
|
15 |
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
|
16 |
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
|
17 |
|
* DAMAGE. |
|
18 |
|
* |
|
19 |
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
|
20 |
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|
21 |
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
|
22 |
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
|
23 |
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
|
24 |
|
* |
|
25 |
|
* Red Hat Author(s): Behdad Esfahbod |
|
26 |
|
* Google Author(s): Behdad Esfahbod |
|
27 |
|
*/ |
|
28 |
|
|
|
29 |
|
#ifndef HB_H_IN |
|
30 |
|
#error "Include <hb.h> instead." |
|
31 |
|
#endif |
|
32 |
|
|
|
33 |
|
#ifndef HB_COMMON_H |
|
34 |
|
#define HB_COMMON_H |
|
35 |
|
|
|
36 |
|
#ifndef HB_BEGIN_DECLS |
|
37 |
|
# ifdef __cplusplus |
|
38 |
|
# define HB_BEGIN_DECLS extern "C" { |
|
39 |
|
# define HB_END_DECLS } |
|
40 |
|
# else /* !__cplusplus */ |
|
41 |
|
# define HB_BEGIN_DECLS |
|
42 |
|
# define HB_END_DECLS |
|
43 |
|
# endif /* !__cplusplus */ |
|
44 |
|
#endif |
|
45 |
|
|
|
46 |
|
#if !defined (HB_DONT_DEFINE_STDINT) |
|
47 |
|
|
|
48 |
|
#if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \ |
|
49 |
|
defined (_sgi) || defined (__sun) || defined (sun) || \ |
|
50 |
|
defined (__digital__) || defined (__HP_cc) |
|
51 |
|
# include <inttypes.h> |
|
52 |
|
#elif defined (_AIX) |
|
53 |
|
# include <sys/inttypes.h> |
|
54 |
|
/* VS 2010 (_MSC_VER 1600) has stdint.h */ |
|
55 |
|
#elif defined (_MSC_VER) && _MSC_VER < 1600 |
|
56 |
|
typedef __int8 int8_t; |
|
57 |
|
typedef unsigned __int8 uint8_t; |
|
58 |
|
typedef __int16 int16_t; |
|
59 |
|
typedef unsigned __int16 uint16_t; |
|
60 |
|
typedef __int32 int32_t; |
|
61 |
|
typedef unsigned __int32 uint32_t; |
|
62 |
|
typedef __int64 int64_t; |
|
63 |
|
typedef unsigned __int64 uint64_t; |
|
64 |
|
#else |
|
65 |
|
# include <stdint.h> |
|
66 |
|
#endif |
|
67 |
|
|
|
68 |
|
#endif |
|
69 |
|
|
|
70 |
|
HB_BEGIN_DECLS |
|
71 |
|
|
|
72 |
|
|
|
73 |
|
typedef int hb_bool_t; |
|
74 |
|
|
|
75 |
|
typedef uint32_t hb_codepoint_t; |
|
76 |
|
typedef int32_t hb_position_t; |
|
77 |
|
typedef uint32_t hb_mask_t; |
|
78 |
|
|
|
79 |
|
typedef union _hb_var_int_t { |
|
80 |
|
uint32_t u32; |
|
81 |
|
int32_t i32; |
|
82 |
|
uint16_t u16[2]; |
|
83 |
|
int16_t i16[2]; |
|
84 |
|
uint8_t u8[4]; |
|
85 |
|
int8_t i8[4]; |
|
86 |
|
} hb_var_int_t; |
|
87 |
|
|
|
88 |
|
|
|
89 |
|
/* hb_tag_t */ |
|
90 |
|
|
|
91 |
|
typedef uint32_t hb_tag_t; |
|
92 |
|
|
|
93 |
|
#define HB_TAG(a,b,c,d) ((hb_tag_t)((((uint8_t)(a))<<24)|(((uint8_t)(b))<<16)|(((uint8_t)(c))<<8)|((uint8_t)(d)))) |
|
94 |
|
#define HB_UNTAG(tag) ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag)) |
|
95 |
|
|
|
96 |
|
#define HB_TAG_NONE HB_TAG(0,0,0,0) |
|
97 |
|
|
|
98 |
|
/* len=-1 means str is NUL-terminated. */ |
|
99 |
|
hb_tag_t |
|
100 |
|
hb_tag_from_string (const char *str, int len); |
|
101 |
|
|
|
102 |
|
/* buf should have 4 bytes. */ |
|
103 |
|
void |
|
104 |
|
hb_tag_to_string (hb_tag_t tag, char *buf); |
|
105 |
|
|
|
106 |
|
|
|
107 |
|
/* hb_direction_t */ |
|
108 |
|
|
|
109 |
|
typedef enum { |
|
110 |
|
HB_DIRECTION_INVALID = 0, |
|
111 |
|
HB_DIRECTION_LTR = 4, |
|
112 |
|
HB_DIRECTION_RTL, |
|
113 |
|
HB_DIRECTION_TTB, |
|
114 |
|
HB_DIRECTION_BTT |
|
115 |
|
} hb_direction_t; |
|
116 |
|
|
|
117 |
|
/* len=-1 means str is NUL-terminated */ |
|
118 |
|
hb_direction_t |
|
119 |
|
hb_direction_from_string (const char *str, int len); |
|
120 |
|
|
|
121 |
|
const char * |
|
122 |
|
hb_direction_to_string (hb_direction_t direction); |
|
123 |
|
|
|
124 |
|
#define HB_DIRECTION_IS_HORIZONTAL(dir) ((((unsigned int) (dir)) & ~1U) == 4) |
|
125 |
|
#define HB_DIRECTION_IS_VERTICAL(dir) ((((unsigned int) (dir)) & ~1U) == 6) |
|
126 |
|
#define HB_DIRECTION_IS_FORWARD(dir) ((((unsigned int) (dir)) & ~2U) == 4) |
|
127 |
|
#define HB_DIRECTION_IS_BACKWARD(dir) ((((unsigned int) (dir)) & ~2U) == 5) |
|
128 |
|
#define HB_DIRECTION_IS_VALID(dir) ((((unsigned int) (dir)) & ~3U) == 4) |
|
129 |
|
#define HB_DIRECTION_REVERSE(dir) ((hb_direction_t) (((unsigned int) (dir)) ^ 1)) /* Direction must be valid */ |
|
130 |
|
|
|
131 |
|
|
|
132 |
|
/* hb_language_t */ |
|
133 |
|
|
|
134 |
|
typedef const struct hb_language_impl_t *hb_language_t; |
|
135 |
|
|
|
136 |
|
/* len=-1 means str is NUL-terminated */ |
|
137 |
|
hb_language_t |
|
138 |
|
hb_language_from_string (const char *str, int len); |
|
139 |
|
|
|
140 |
|
const char * |
|
141 |
|
hb_language_to_string (hb_language_t language); |
|
142 |
|
|
|
143 |
|
#define HB_LANGUAGE_INVALID ((hb_language_t) NULL) |
|
144 |
|
|
|
145 |
|
hb_language_t |
|
146 |
|
hb_language_get_default (void); |
|
147 |
|
|
|
148 |
|
|
|
149 |
|
/* hb_script_t */ |
|
150 |
|
|
|
151 |
|
/* http://unicode.org/iso15924/ */ |
|
152 |
|
/* http://goo.gl/x9ilM */ |
|
153 |
|
/* Unicode Character Database property: Script (sc) */ |
|
154 |
|
typedef enum |
|
155 |
|
{ |
|
156 |
|
/*1.1*/ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), |
|
157 |
|
/*1.1*/ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), |
|
158 |
|
/*5.0*/ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), |
|
159 |
|
|
|
160 |
|
/*1.1*/ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), |
|
161 |
|
/*1.1*/ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), |
|
162 |
|
/*1.1*/ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), |
|
163 |
|
/*1.1*/ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), |
|
164 |
|
/*1.1*/ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), |
|
165 |
|
/*1.1*/ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), |
|
166 |
|
/*1.1*/ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), |
|
167 |
|
/*1.1*/ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), |
|
168 |
|
/*1.1*/ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), |
|
169 |
|
/*1.1*/ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), |
|
170 |
|
/*1.1*/ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), |
|
171 |
|
/*1.1*/ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), |
|
172 |
|
/*1.1*/ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), |
|
173 |
|
/*1.1*/ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), |
|
174 |
|
/*1.1*/ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), |
|
175 |
|
/*1.1*/ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), |
|
176 |
|
/*1.1*/ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), |
|
177 |
|
/*1.1*/ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), |
|
178 |
|
/*1.1*/ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), |
|
179 |
|
/*1.1*/ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), |
|
180 |
|
/*1.1*/ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), |
|
181 |
|
/*1.1*/ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), |
|
182 |
|
|
|
183 |
|
/*2.0*/ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), |
|
184 |
|
|
|
185 |
|
/*3.0*/ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), |
|
186 |
|
/*3.0*/ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), |
|
187 |
|
/*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), |
|
188 |
|
/*3.0*/ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), |
|
189 |
|
/*3.0*/ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), |
|
190 |
|
/*3.0*/ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), |
|
191 |
|
/*3.0*/ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), |
|
192 |
|
/*3.0*/ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), |
|
193 |
|
/*3.0*/ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), |
|
194 |
|
/*3.0*/ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), |
|
195 |
|
/*3.0*/ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), |
|
196 |
|
/*3.0*/ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), |
|
197 |
|
/*3.0*/ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), |
|
198 |
|
/*3.0*/ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), |
|
199 |
|
|
|
200 |
|
/*3.1*/ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), |
|
201 |
|
/*3.1*/ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), |
|
202 |
|
/*3.1*/ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), |
|
203 |
|
|
|
204 |
|
/*3.2*/ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), |
|
205 |
|
/*3.2*/ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), |
|
206 |
|
/*3.2*/ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), |
|
207 |
|
/*3.2*/ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), |
|
208 |
|
|
|
209 |
|
/*4.0*/ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), |
|
210 |
|
/*4.0*/ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), |
|
211 |
|
/*4.0*/ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), |
|
212 |
|
/*4.0*/ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), |
|
213 |
|
/*4.0*/ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), |
|
214 |
|
/*4.0*/ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), |
|
215 |
|
/*4.0*/ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), |
|
216 |
|
|
|
217 |
|
/*4.1*/ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), |
|
218 |
|
/*4.1*/ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), |
|
219 |
|
/*4.1*/ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), |
|
220 |
|
/*4.1*/ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), |
|
221 |
|
/*4.1*/ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), |
|
222 |
|
/*4.1*/ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), |
|
223 |
|
/*4.1*/ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), |
|
224 |
|
/*4.1*/ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), |
|
225 |
|
|
|
226 |
|
/*5.0*/ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), |
|
227 |
|
/*5.0*/ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), |
|
228 |
|
/*5.0*/ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), |
|
229 |
|
/*5.0*/ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), |
|
230 |
|
/*5.0*/ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), |
|
231 |
|
|
|
232 |
|
/*5.1*/ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), |
|
233 |
|
/*5.1*/ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), |
|
234 |
|
/*5.1*/ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), |
|
235 |
|
/*5.1*/ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), |
|
236 |
|
/*5.1*/ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), |
|
237 |
|
/*5.1*/ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), |
|
238 |
|
/*5.1*/ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), |
|
239 |
|
/*5.1*/ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), |
|
240 |
|
/*5.1*/ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), |
|
241 |
|
/*5.1*/ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), |
|
242 |
|
/*5.1*/ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), |
|
243 |
|
|
|
244 |
|
/*5.2*/ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), |
|
245 |
|
/*5.2*/ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), |
|
246 |
|
/*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), |
|
247 |
|
/*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), |
|
248 |
|
/*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), |
|
249 |
|
/*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), |
|
250 |
|
/*5.2*/ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), |
|
251 |
|
/*5.2*/ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), |
|
252 |
|
/*5.2*/ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), |
|
253 |
|
/*5.2*/ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), |
|
254 |
|
/*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), |
|
255 |
|
/*5.2*/ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), |
|
256 |
|
/*5.2*/ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), |
|
257 |
|
/*5.2*/ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), |
|
258 |
|
/*5.2*/ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), |
|
259 |
|
|
|
260 |
|
/*6.0*/ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), |
|
261 |
|
/*6.0*/ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), |
|
262 |
|
/*6.0*/ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), |
|
263 |
|
|
|
264 |
|
/*6.1*/ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), |
|
265 |
|
/*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), |
|
266 |
|
/*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), |
|
267 |
|
/*6.1*/ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), |
|
268 |
|
/*6.1*/ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), |
|
269 |
|
/*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), |
|
270 |
|
/*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), |
|
271 |
|
|
|
272 |
|
/* No script set. */ |
|
273 |
|
/*---*/ HB_SCRIPT_INVALID = HB_TAG_NONE |
|
274 |
|
} hb_script_t; |
|
275 |
|
|
|
276 |
|
/* These are moved out of hb_script_t because glib-mkenums chokes otherwise. */ |
|
277 |
|
#if 0 |
|
278 |
|
/*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), |
|
279 |
|
/*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), |
|
280 |
|
/*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), |
|
281 |
|
/*7.0*/ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), |
|
282 |
|
/*7.0*/ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), |
|
283 |
|
/*7.0*/ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), |
|
284 |
|
/*7.0*/ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), |
|
285 |
|
/*7.0*/ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), |
|
286 |
|
/*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), |
|
287 |
|
/*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), |
|
288 |
|
/*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), |
|
289 |
|
/*7.0*/ HB_SCRIPT_MODI = ??? |
|
290 |
|
/*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), |
|
291 |
|
/*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), |
|
292 |
|
/*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), |
|
293 |
|
/*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), |
|
294 |
|
/*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), |
|
295 |
|
/*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), |
|
296 |
|
/*7.0*/ HB_SCRIPT_PAU_CIN_HAU = ??? |
|
297 |
|
/*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), |
|
298 |
|
/*7.0*/ HB_SCRIPT_SIDDHAM = ??? |
|
299 |
|
/*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), |
|
300 |
|
/*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), |
|
301 |
|
#endif |
|
302 |
|
|
|
303 |
|
|
|
304 |
|
/* Script functions */ |
|
305 |
|
|
|
306 |
|
hb_script_t |
|
307 |
|
hb_script_from_iso15924_tag (hb_tag_t tag); |
|
308 |
|
|
|
309 |
|
/* suger for tag_from_string() then script_from_iso15924_tag */ |
|
310 |
|
/* len=-1 means s is NUL-terminated */ |
|
311 |
|
hb_script_t |
|
312 |
|
hb_script_from_string (const char *s, int len); |
|
313 |
|
|
|
314 |
|
hb_tag_t |
|
315 |
|
hb_script_to_iso15924_tag (hb_script_t script); |
|
316 |
|
|
|
317 |
|
hb_direction_t |
|
318 |
|
hb_script_get_horizontal_direction (hb_script_t script); |
|
319 |
|
|
|
320 |
|
|
|
321 |
|
/* User data */ |
|
322 |
|
|
|
323 |
|
typedef struct hb_user_data_key_t { |
|
324 |
|
/*< private >*/ |
|
325 |
|
char unused; |
|
326 |
|
} hb_user_data_key_t; |
|
327 |
|
|
|
328 |
|
typedef void (*hb_destroy_func_t) (void *user_data); |
|
329 |
|
|
|
330 |
|
|
|
331 |
|
HB_END_DECLS |
|
332 |
|
|
|
333 |
|
#endif /* HB_COMMON_H */ |
File hb-font.c added (mode: 100644) (index 0000000..ba271fa) |
|
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> |
|
5 |
|
#include <string.h> |
|
6 |
|
|
|
7 |
|
#include <ft2build.h> |
|
8 |
|
#include FT_FREETYPE_H |
|
9 |
|
|
|
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-font-private.h" |
|
16 |
|
|
|
17 |
|
void |
|
18 |
|
hb_font_destroy(hb_font_t *font) |
|
19 |
|
{ |
|
20 |
|
if (!font) |
|
21 |
|
return; |
|
22 |
|
if (hb_atomic_int32_get(&font->ref_cnt) == REF_CNT_INVALID_VAL) |
|
23 |
|
return; |
|
24 |
|
hb_atomic_int32_add(&font->ref_cnt, -1); |
|
25 |
|
if (hb_atomic_int32_get(&font->ref_cnt) > 0) |
|
26 |
|
return; |
|
27 |
|
hb_atomic_int32_set(&font->ref_cnt, REF_CNT_INVALID_VAL); |
|
28 |
|
|
|
29 |
|
#ifdef HAVE_GRAPHITE2 |
|
30 |
|
if (font->shaper_data.graphite2 |
|
31 |
|
&& font->shaper_data.graphite2 != HB_SHAPER_DATA_INVALID |
|
32 |
|
&& font->shaper_data.graphite2 != HB_SHAPER_DATA_SUCCEEDED) |
|
33 |
|
hb_graphite2_shaper_font_data_destroy(font->shaper_data.graphite2); |
|
34 |
|
#endif |
|
35 |
|
#ifdef HAVE_OT |
|
36 |
|
if (font->shaper_data.ot |
|
37 |
|
&& font->shaper_data.ot != HB_SHAPER_DATA_INVALID |
|
38 |
|
&& font->shaper_data.ot != HB_SHAPER_DATA_SUCCEEDED) |
|
39 |
|
hb_ot_shaper_font_data_destroy(font->shaper_data.ot); |
|
40 |
|
#endif |
|
41 |
|
if (font->shaper_data.fallback |
|
42 |
|
&& font->shaper_data.fallback != HB_SHAPER_DATA_INVALID |
|
43 |
|
&& font->shaper_data.fallback != HB_SHAPER_DATA_SUCCEEDED) |
|
44 |
|
hb_fallback_shaper_font_data_destroy(font->shaper_data.fallback); |
|
45 |
|
|
|
46 |
|
if (font->destroy) |
|
47 |
|
font->destroy(font->user_data); |
|
48 |
|
|
|
49 |
|
hb_font_destroy(font->parent); |
|
50 |
|
hb_face_destroy(font->face); |
|
51 |
|
hb_font_funcs_destroy(font->klass); |
|
52 |
|
free(font); |
|
53 |
|
} |
|
54 |
|
|
|
55 |
|
hb_bool_t |
|
56 |
|
hb_font_get_glyph(hb_font_t *font, |
|
57 |
|
hb_codepoint_t unicode, |
|
58 |
|
hb_codepoint_t variation_selector, |
|
59 |
|
hb_codepoint_t *glyph) |
|
60 |
|
{ |
|
61 |
|
*glyph = 0; |
|
62 |
|
return font->klass->get.glyph(font, |
|
63 |
|
font->user_data, |
|
64 |
|
unicode, |
|
65 |
|
variation_selector, |
|
66 |
|
glyph, |
|
67 |
|
font->klass->user_data.glyph); |
|
68 |
|
} |
|
69 |
|
|
|
70 |
|
//Convert from parent-font user-space to our user-space |
|
71 |
|
hb_position_t |
|
72 |
|
hb_font_parent_scale_x_distance(hb_font_t *font, |
|
73 |
|
hb_position_t v) |
|
74 |
|
{ |
|
75 |
|
if (font->parent && font->parent->x_scale != font->x_scale) |
|
76 |
|
return v * (int64_t) font->x_scale / font->parent->x_scale; |
|
77 |
|
return v; |
|
78 |
|
} |
|
79 |
|
|
|
80 |
|
hb_position_t |
|
81 |
|
hb_font_parent_scale_y_distance(hb_font_t *font, |
|
82 |
|
hb_position_t v) |
|
83 |
|
{ |
|
84 |
|
if (font->parent && font->parent->y_scale != font->y_scale) |
|
85 |
|
return v * (int64_t) font->y_scale / font->parent->y_scale; |
|
86 |
|
return v; |
|
87 |
|
} |
|
88 |
|
|
|
89 |
|
hb_position_t |
|
90 |
|
hb_font_parent_scale_x_position(hb_font_t *font, |
|
91 |
|
hb_position_t v) |
|
92 |
|
{ |
|
93 |
|
return hb_font_parent_scale_x_distance(font, v); |
|
94 |
|
} |
|
95 |
|
|
|
96 |
|
hb_position_t |
|
97 |
|
hb_font_parent_scale_y_position(hb_font_t *font, |
|
98 |
|
hb_position_t v) |
|
99 |
|
{ |
|
100 |
|
return hb_font_parent_scale_y_distance(font, v); |
|
101 |
|
} |
|
102 |
|
|
|
103 |
|
void |
|
104 |
|
hb_font_parent_scale_position(hb_font_t *font, |
|
105 |
|
hb_position_t *x, |
|
106 |
|
hb_position_t *y) |
|
107 |
|
{ |
|
108 |
|
*x = hb_font_parent_scale_x_position(font, *x); |
|
109 |
|
*y = hb_font_parent_scale_y_position(font, *y); |
|
110 |
|
} |
|
111 |
|
|
|
112 |
|
void |
|
113 |
|
hb_font_parent_scale_distance(hb_font_t *font, |
|
114 |
|
hb_position_t *x, |
|
115 |
|
hb_position_t *y) |
|
116 |
|
{ |
|
117 |
|
*x = hb_font_parent_scale_x_distance(font, *x); |
|
118 |
|
*y = hb_font_parent_scale_y_distance(font, *y); |
|
119 |
|
} |
|
120 |
|
|
|
121 |
|
hb_position_t |
|
122 |
|
hb_font_get_glyph_h_advance(hb_font_t *font, |
|
123 |
|
hb_codepoint_t glyph) |
|
124 |
|
{ |
|
125 |
|
return font->klass->get.glyph_h_advance( |
|
126 |
|
font, |
|
127 |
|
font->user_data, |
|
128 |
|
glyph, |
|
129 |
|
font->klass->user_data.glyph_h_advance); |
|
130 |
|
} |
|
131 |
|
|
|
132 |
|
|
|
133 |
|
hb_position_t |
|
134 |
|
hb_font_get_glyph_v_advance(hb_font_t *font, |
|
135 |
|
hb_codepoint_t glyph) |
|
136 |
|
{ |
|
137 |
|
return font->klass->get.glyph_v_advance( |
|
138 |
|
font, |
|
139 |
|
font->user_data, |
|
140 |
|
glyph, |
|
141 |
|
font->klass->user_data.glyph_v_advance); |
|
142 |
|
} |
|
143 |
|
|
|
144 |
|
hb_bool_t |
|
145 |
|
hb_font_get_glyph_h_origin(hb_font_t *font, |
|
146 |
|
hb_codepoint_t glyph, |
|
147 |
|
hb_position_t *x, |
|
148 |
|
hb_position_t *y) |
|
149 |
|
{ |
|
150 |
|
*x = *y = 0; |
|
151 |
|
return font->klass->get.glyph_h_origin(font, |
|
152 |
|
font->user_data, |
|
153 |
|
glyph, |
|
154 |
|
x, y, |
|
155 |
|
font->klass->user_data.glyph_h_origin); |
|
156 |
|
} |
|
157 |
|
|
|
158 |
|
hb_bool_t |
|
159 |
|
hb_font_get_glyph_v_origin(hb_font_t *font, |
|
160 |
|
hb_codepoint_t glyph, |
|
161 |
|
hb_position_t *x, |
|
162 |
|
hb_position_t *y) |
|
163 |
|
{ |
|
164 |
|
*x = *y = 0; |
|
165 |
|
return font->klass->get.glyph_v_origin(font, |
|
166 |
|
font->user_data, |
|
167 |
|
glyph, |
|
168 |
|
x, y, |
|
169 |
|
font->klass->user_data.glyph_v_origin); |
|
170 |
|
} |
|
171 |
|
|
|
172 |
|
hb_position_t |
|
173 |
|
hb_font_get_glyph_h_kerning(hb_font_t *font, |
|
174 |
|
hb_codepoint_t left_glyph, |
|
175 |
|
hb_codepoint_t right_glyph) |
|
176 |
|
{ |
|
177 |
|
return font->klass->get.glyph_h_kerning( |
|
178 |
|
font, |
|
179 |
|
font->user_data, |
|
180 |
|
left_glyph, |
|
181 |
|
right_glyph, |
|
182 |
|
font->klass->user_data.glyph_h_kerning); |
|
183 |
|
} |
|
184 |
|
|
|
185 |
|
hb_position_t |
|
186 |
|
hb_font_get_glyph_v_kerning(hb_font_t *font, |
|
187 |
|
hb_codepoint_t top_glyph, |
|
188 |
|
hb_codepoint_t bottom_glyph) |
|
189 |
|
{ |
|
190 |
|
return font->klass->get.glyph_v_kerning( |
|
191 |
|
font, |
|
192 |
|
font->user_data, |
|
193 |
|
top_glyph, |
|
194 |
|
bottom_glyph, |
|
195 |
|
font->klass->user_data.glyph_v_kerning); |
|
196 |
|
} |
|
197 |
|
|
|
198 |
|
hb_bool_t |
|
199 |
|
hb_font_get_glyph_extents(hb_font_t *font, |
|
200 |
|
hb_codepoint_t glyph, |
|
201 |
|
hb_glyph_extents_t *extents) |
|
202 |
|
{ |
|
203 |
|
memset(extents, 0, sizeof(*extents)); |
|
204 |
|
return font->klass->get.glyph_extents(font, |
|
205 |
|
font->user_data, |
|
206 |
|
glyph, |
|
207 |
|
extents, |
|
208 |
|
font->klass->user_data.glyph_extents); |
|
209 |
|
} |
|
210 |
|
|
|
211 |
|
hb_bool_t |
|
212 |
|
hb_font_get_glyph_contour_point(hb_font_t *font, |
|
213 |
|
hb_codepoint_t glyph, |
|
214 |
|
unsigned int point_index, |
|
215 |
|
hb_position_t *x, |
|
216 |
|
hb_position_t *y) |
|
217 |
|
{ |
|
218 |
|
*x = *y = 0; |
|
219 |
|
return font->klass->get.glyph_contour_point( |
|
220 |
|
font, |
|
221 |
|
font->user_data, |
|
222 |
|
glyph, point_index, |
|
223 |
|
x, y, |
|
224 |
|
font->klass->user_data.glyph_contour_point); |
|
225 |
|
} |
|
226 |
|
|
|
227 |
|
hb_bool_t |
|
228 |
|
hb_font_get_glyph_name(hb_font_t *font, |
|
229 |
|
hb_codepoint_t glyph, |
|
230 |
|
char *name, |
|
231 |
|
unsigned int size) |
|
232 |
|
{ |
|
233 |
|
if (size) *name = '\0'; |
|
234 |
|
return font->klass->get.glyph_name(font, |
|
235 |
|
font->user_data, |
|
236 |
|
glyph, |
|
237 |
|
name, |
|
238 |
|
size, |
|
239 |
|
font->klass->user_data.glyph_name); |
|
240 |
|
} |
|
241 |
|
|
|
242 |
|
hb_bool_t |
|
243 |
|
hb_font_get_glyph_from_name(hb_font_t *font, |
|
244 |
|
const char *name, |
|
245 |
|
int len,//-1 means nul-terminated |
|
246 |
|
hb_codepoint_t *glyph) |
|
247 |
|
{ |
|
248 |
|
*glyph = 0; |
|
249 |
|
if (len == -1) len = strlen(name); |
|
250 |
|
return font->klass->get.glyph_from_name( |
|
251 |
|
font, |
|
252 |
|
font->user_data, |
|
253 |
|
name, |
|
254 |
|
len, |
|
255 |
|
glyph, |
|
256 |
|
font->klass->user_data.glyph_from_name); |
|
257 |
|
} |
|
258 |
|
|
|
259 |
|
static hb_bool_t |
|
260 |
|
hb_font_get_glyph_nil(hb_font_t *font, |
|
261 |
|
void *font_data HB_UNUSED, |
|
262 |
|
hb_codepoint_t unicode, |
|
263 |
|
hb_codepoint_t variation_selector, |
|
264 |
|
hb_codepoint_t *glyph, |
|
265 |
|
void *user_data HB_UNUSED) |
|
266 |
|
{ |
|
267 |
|
if (font->parent) |
|
268 |
|
return hb_font_get_glyph(font->parent, |
|
269 |
|
unicode, |
|
270 |
|
variation_selector, |
|
271 |
|
glyph); |
|
272 |
|
|
|
273 |
|
*glyph = 0; |
|
274 |
|
return FALSE; |
|
275 |
|
} |
|
276 |
|
|
|
277 |
|
static hb_position_t |
|
278 |
|
hb_font_get_glyph_h_advance_nil(hb_font_t *font, |
|
279 |
|
void *font_data HB_UNUSED, |
|
280 |
|
hb_codepoint_t glyph, |
|
281 |
|
void *user_data HB_UNUSED) |
|
282 |
|
{ |
|
283 |
|
if (font->parent) |
|
284 |
|
return hb_font_parent_scale_x_distance(font, hb_font_get_glyph_h_advance( |
|
285 |
|
font->parent, |
|
286 |
|
glyph)); |
|
287 |
|
return font->x_scale; |
|
288 |
|
} |
|
289 |
|
|
|
290 |
|
static hb_position_t |
|
291 |
|
hb_font_get_glyph_v_advance_nil(hb_font_t *font, |
|
292 |
|
void *font_data HB_UNUSED, |
|
293 |
|
hb_codepoint_t glyph, |
|
294 |
|
void *user_data HB_UNUSED) |
|
295 |
|
{ |
|
296 |
|
if (font->parent) |
|
297 |
|
return hb_font_parent_scale_y_distance(font, hb_font_get_glyph_v_advance( |
|
298 |
|
font->parent, |
|
299 |
|
glyph)); |
|
300 |
|
return font->y_scale; |
|
301 |
|
} |
|
302 |
|
|
|
303 |
|
static hb_bool_t |
|
304 |
|
hb_font_get_glyph_h_origin_nil(hb_font_t *font, |
|
305 |
|
void *font_data HB_UNUSED, |
|
306 |
|
hb_codepoint_t glyph, |
|
307 |
|
hb_position_t *x, |
|
308 |
|
hb_position_t *y, |
|
309 |
|
void *user_data HB_UNUSED) |
|
310 |
|
{ |
|
311 |
|
if (font->parent) { |
|
312 |
|
hb_bool_t ret = hb_font_get_glyph_h_origin(font->parent, glyph, x, y); |
|
313 |
|
if (ret) |
|
314 |
|
hb_font_parent_scale_position(font, x, y); |
|
315 |
|
return ret; |
|
316 |
|
} |
|
317 |
|
|
|
318 |
|
*x = *y = 0; |
|
319 |
|
return FALSE; |
|
320 |
|
} |
|
321 |
|
|
|
322 |
|
static hb_bool_t |
|
323 |
|
hb_font_get_glyph_v_origin_nil(hb_font_t *font, |
|
324 |
|
void *font_data HB_UNUSED, |
|
325 |
|
hb_codepoint_t glyph, |
|
326 |
|
hb_position_t *x, |
|
327 |
|
hb_position_t *y, |
|
328 |
|
void *user_data HB_UNUSED) |
|
329 |
|
{ |
|
330 |
|
if (font->parent) { |
|
331 |
|
hb_bool_t ret = hb_font_get_glyph_v_origin(font->parent, glyph, x, y); |
|
332 |
|
if (ret) |
|
333 |
|
hb_font_parent_scale_position(font, x, y); |
|
334 |
|
return ret; |
|
335 |
|
} |
|
336 |
|
|
|
337 |
|
*x = *y = 0; |
|
338 |
|
return FALSE; |
|
339 |
|
} |
|
340 |
|
|
|
341 |
|
static hb_position_t |
|
342 |
|
hb_font_get_glyph_h_kerning_nil(hb_font_t *font, |
|
343 |
|
void *font_data HB_UNUSED, |
|
344 |
|
hb_codepoint_t left_glyph, |
|
345 |
|
hb_codepoint_t right_glyph, |
|
346 |
|
void *user_data HB_UNUSED) |
|
347 |
|
{ |
|
348 |
|
if (font->parent) |
|
349 |
|
return hb_font_parent_scale_x_distance(font, hb_font_get_glyph_h_kerning( |
|
350 |
|
font->parent, |
|
351 |
|
left_glyph, |
|
352 |
|
right_glyph)); |
|
353 |
|
return 0; |
|
354 |
|
} |
|
355 |
|
|
|
356 |
|
static hb_position_t |
|
357 |
|
hb_font_get_glyph_v_kerning_nil(hb_font_t *font, |
|
358 |
|
void *font_data HB_UNUSED, |
|
359 |
|
hb_codepoint_t top_glyph, |
|
360 |
|
hb_codepoint_t bottom_glyph, |
|
361 |
|
void *user_data HB_UNUSED) |
|
362 |
|
{ |
|
363 |
|
if (font->parent) |
|
364 |
|
return hb_font_parent_scale_y_distance(font, hb_font_get_glyph_v_kerning( |
|
365 |
|
font->parent, |
|
366 |
|
top_glyph, |
|
367 |
|
bottom_glyph)); |
|
368 |
|
return 0; |
|
369 |
|
} |
|
370 |
|
|
|
371 |
|
static hb_bool_t |
|
372 |
|
hb_font_get_glyph_extents_nil(hb_font_t *font, |
|
373 |
|
void *font_data HB_UNUSED, |
|
374 |
|
hb_codepoint_t glyph, |
|
375 |
|
hb_glyph_extents_t *extents, |
|
376 |
|
void *user_data HB_UNUSED) |
|
377 |
|
{ |
|
378 |
|
if (font->parent) { |
|
379 |
|
hb_bool_t ret = hb_font_get_glyph_extents(font->parent, glyph, extents); |
|
380 |
|
if (ret) { |
|
381 |
|
hb_font_parent_scale_position(font, |
|
382 |
|
&extents->x_bearing, |
|
383 |
|
&extents->y_bearing); |
|
384 |
|
hb_font_parent_scale_distance(font, &extents->width, &extents->height); |
|
385 |
|
} |
|
386 |
|
return ret; |
|
387 |
|
} |
|
388 |
|
|
|
389 |
|
memset(extents, 0, sizeof(*extents)); |
|
390 |
|
return FALSE; |
|
391 |
|
} |
|
392 |
|
|
|
393 |
|
static hb_bool_t |
|
394 |
|
hb_font_get_glyph_contour_point_nil(hb_font_t *font, |
|
395 |
|
void *font_data HB_UNUSED, |
|
396 |
|
hb_codepoint_t glyph, |
|
397 |
|
unsigned int point_index, |
|
398 |
|
hb_position_t *x, |
|
399 |
|
hb_position_t *y, |
|
400 |
|
void *user_data HB_UNUSED) |
|
401 |
|
{ |
|
402 |
|
if (font->parent) { |
|
403 |
|
hb_bool_t ret = hb_font_get_glyph_contour_point(font->parent, |
|
404 |
|
glyph, |
|
405 |
|
point_index, |
|
406 |
|
x, y); |
|
407 |
|
if (ret) |
|
408 |
|
hb_font_parent_scale_position(font, x, y); |
|
409 |
|
return ret; |
|
410 |
|
} |
|
411 |
|
|
|
412 |
|
*x = *y = 0; |
|
413 |
|
return FALSE; |
|
414 |
|
} |
|
415 |
|
|
|
416 |
|
static hb_bool_t |
|
417 |
|
hb_font_get_glyph_name_nil(hb_font_t *font, |
|
418 |
|
void *font_data HB_UNUSED, |
|
419 |
|
hb_codepoint_t glyph, |
|
420 |
|
char *name, unsigned int size, |
|
421 |
|
void *user_data HB_UNUSED) |
|
422 |
|
{ |
|
423 |
|
if (font->parent) |
|
424 |
|
return hb_font_get_glyph_name(font->parent, glyph, name, size); |
|
425 |
|
|
|
426 |
|
if (size) *name = '\0'; |
|
427 |
|
return FALSE; |
|
428 |
|
} |
|
429 |
|
|
|
430 |
|
static hb_bool_t |
|
431 |
|
hb_font_get_glyph_from_name_nil(hb_font_t *font, |
|
432 |
|
void *font_data HB_UNUSED, |
|
433 |
|
const char *name, |
|
434 |
|
int len,//-1 means nul-terminated |
|
435 |
|
hb_codepoint_t *glyph, |
|
436 |
|
void *user_data HB_UNUSED) |
|
437 |
|
{ |
|
438 |
|
if (font->parent) |
|
439 |
|
return hb_font_get_glyph_from_name(font->parent, name, len, glyph); |
|
440 |
|
|
|
441 |
|
*glyph = 0; |
|
442 |
|
return FALSE; |
|
443 |
|
} |
|
444 |
|
|
|
445 |
|
//A bit higher-level, and with fallback |
|
446 |
|
|
|
447 |
|
void |
|
448 |
|
hb_font_get_glyph_advance_for_direction(hb_font_t *font, |
|
449 |
|
hb_codepoint_t glyph, |
|
450 |
|
hb_direction_t direction, |
|
451 |
|
hb_position_t *x, hb_position_t *y) |
|
452 |
|
{ |
|
453 |
|
if (HB_DIRECTION_IS_HORIZONTAL(direction)) { |
|
454 |
|
*x = hb_font_get_glyph_h_advance(font, glyph); |
|
455 |
|
*y = 0; |
|
456 |
|
} else { |
|
457 |
|
*x = 0; |
|
458 |
|
*y = hb_font_get_glyph_v_advance(font, glyph); |
|
459 |
|
} |
|
460 |
|
} |
|
461 |
|
|
|
462 |
|
//Internal only |
|
463 |
|
static void |
|
464 |
|
hb_font_guess_v_origin_minus_h_origin(hb_font_t *font, |
|
465 |
|
hb_codepoint_t glyph, |
|
466 |
|
hb_position_t *x, hb_position_t *y) |
|
467 |
|
{ |
|
468 |
|
*x = hb_font_get_glyph_h_advance(font, glyph) / 2; |
|
469 |
|
|
|
470 |
|
//TODO:use font_metics.ascent |
|
471 |
|
*y = font->y_scale; |
|
472 |
|
} |
|
473 |
|
|
|
474 |
|
void |
|
475 |
|
hb_font_get_glyph_origin_for_direction(hb_font_t *font, |
|
476 |
|
hb_codepoint_t glyph, |
|
477 |
|
hb_direction_t direction, |
|
478 |
|
hb_position_t *x, hb_position_t *y) |
|
479 |
|
{ |
|
480 |
|
if (HB_DIRECTION_IS_HORIZONTAL(direction)) { |
|
481 |
|
if (!hb_font_get_glyph_h_origin(font, glyph, x, y) |
|
482 |
|
&& hb_font_get_glyph_v_origin(font, glyph, x, y)) { |
|
483 |
|
hb_position_t dx, dy; |
|
484 |
|
hb_font_guess_v_origin_minus_h_origin(font, glyph, &dx, &dy); |
|
485 |
|
*x -= dx; *y -= dy; |
|
486 |
|
} |
|
487 |
|
} else { |
|
488 |
|
if (!hb_font_get_glyph_v_origin(font, glyph, x, y) |
|
489 |
|
&& hb_font_get_glyph_h_origin(font, glyph, x, y)) { |
|
490 |
|
hb_position_t dx, dy; |
|
491 |
|
hb_font_guess_v_origin_minus_h_origin(font, glyph, &dx, &dy); |
|
492 |
|
*x += dx; *y += dy; |
|
493 |
|
} |
|
494 |
|
} |
|
495 |
|
} |
|
496 |
|
|
|
497 |
|
void |
|
498 |
|
hb_font_subtract_glyph_origin_for_direction(hb_font_t *font, |
|
499 |
|
hb_codepoint_t glyph, |
|
500 |
|
hb_direction_t direction, |
|
501 |
|
hb_position_t *x, hb_position_t *y) |
|
502 |
|
{ |
|
503 |
|
hb_position_t origin_x, origin_y; |
|
504 |
|
|
|
505 |
|
hb_font_get_glyph_origin_for_direction(font, glyph, direction, &origin_x, |
|
506 |
|
&origin_y); |
|
507 |
|
|
|
508 |
|
*x -= origin_x; |
|
509 |
|
*y -= origin_y; |
|
510 |
|
} |
|
511 |
|
|
|
512 |
|
static hb_font_funcs_t hb_font_funcs_nil = { |
|
513 |
|
REF_CNT_INVALID_VAL,//ref_cnt |
|
514 |
|
TRUE,//immutable |
|
515 |
|
{//get |
|
516 |
|
hb_font_get_glyph_nil, |
|
517 |
|
hb_font_get_glyph_h_advance_nil, |
|
518 |
|
hb_font_get_glyph_v_advance_nil, |
|
519 |
|
hb_font_get_glyph_h_origin_nil, |
|
520 |
|
hb_font_get_glyph_v_origin_nil, |
|
521 |
|
hb_font_get_glyph_h_kerning_nil, |
|
522 |
|
hb_font_get_glyph_v_kerning_nil, |
|
523 |
|
hb_font_get_glyph_extents_nil, |
|
524 |
|
hb_font_get_glyph_contour_point_nil, |
|
525 |
|
hb_font_get_glyph_name_nil, |
|
526 |
|
hb_font_get_glyph_from_name_nil, |
|
527 |
|
}, |
|
528 |
|
{//user_data |
|
529 |
|
NULL,//glyph |
|
530 |
|
NULL,//glyph_h_advance |
|
531 |
|
NULL,//glyph_v_advance |
|
532 |
|
NULL,//glyph_h_origin |
|
533 |
|
NULL,//glyph_v_origin |
|
534 |
|
NULL,//glyph_h_kerning |
|
535 |
|
NULL,//glyph_v_kerning |
|
536 |
|
NULL,//glyph_extents |
|
537 |
|
NULL,//glyph_contour_po |
|
538 |
|
NULL,//glyph_name |
|
539 |
|
NULL,//glyph_from_name |
|
540 |
|
}, |
|
541 |
|
{//destroy |
|
542 |
|
NULL,//glyph |
|
543 |
|
NULL,//glyph_h_advance |
|
544 |
|
NULL,//glyph_v_advance |
|
545 |
|
NULL,//glyph_h_origin |
|
546 |
|
NULL,//glyph_v_origin |
|
547 |
|
NULL,//glyph_h_kerning |
|
548 |
|
NULL,//glyph_v_kerning |
|
549 |
|
NULL,//glyph_extents |
|
550 |
|
NULL,//glyph_contour_po |
|
551 |
|
NULL,//glyph_name |
|
552 |
|
NULL,//glyph_from_name |
|
553 |
|
} |
|
554 |
|
}; |
|
555 |
|
|
|
556 |
|
static hb_font_t hb_font_nil = { |
|
557 |
|
REF_CNT_INVALID_VAL,//ref_cnt |
|
558 |
|
TRUE,//immutable |
|
559 |
|
NULL,//parent |
|
560 |
|
NULL,//face |
|
561 |
|
0,//x_scale |
|
562 |
|
0,//y_scale |
|
563 |
|
0,//x_ppem |
|
564 |
|
0,//y_ppem |
|
565 |
|
NULL,//klass |
|
566 |
|
NULL,//user_data |
|
567 |
|
NULL,//destroy |
|
568 |
|
{ |
|
569 |
|
#ifdef HAVE_GRAPHITE2 |
|
570 |
|
HB_SHAPER_DATA_INVALID, |
|
571 |
|
#endif |
|
572 |
|
#ifdef HAVE_OT |
|
573 |
|
HB_SHAPER_DATA_INVALID, |
|
574 |
|
#endif |
|
575 |
|
HB_SHAPER_DATA_INVALID//fallback |
|
576 |
|
}, |
|
577 |
|
}; |
|
578 |
|
|
|
579 |
|
hb_font_funcs_t * |
|
580 |
|
hb_font_funcs_get_empty(void) |
|
581 |
|
{ |
|
582 |
|
return &hb_font_funcs_nil; |
|
583 |
|
} |
|
584 |
|
|
|
585 |
|
hb_font_t * |
|
586 |
|
hb_font_get_empty(void) |
|
587 |
|
{ |
|
588 |
|
return &hb_font_nil; |
|
589 |
|
} |
|
590 |
|
|
|
591 |
|
void |
|
592 |
|
hb_font_funcs_destroy(hb_font_funcs_t *ffuncs) |
|
593 |
|
{ |
|
594 |
|
if (!ffuncs) |
|
595 |
|
return; |
|
596 |
|
if (hb_atomic_int32_get(&ffuncs->ref_cnt) == REF_CNT_INVALID_VAL) |
|
597 |
|
return; |
|
598 |
|
hb_atomic_int32_add(&ffuncs->ref_cnt, -1); |
|
599 |
|
if (hb_atomic_int32_get(&ffuncs->ref_cnt) > 0) |
|
600 |
|
return; |
|
601 |
|
hb_atomic_int32_set(&ffuncs->ref_cnt, REF_CNT_INVALID_VAL); |
|
602 |
|
|
|
603 |
|
if (ffuncs->destroy.glyph) |
|
604 |
|
ffuncs->destroy.glyph(ffuncs->user_data.glyph); |
|
605 |
|
if (ffuncs->destroy.glyph_h_advance) |
|
606 |
|
ffuncs->destroy.glyph_h_advance(ffuncs->user_data.glyph_h_advance); |
|
607 |
|
if (ffuncs->destroy.glyph_v_advance) |
|
608 |
|
ffuncs->destroy.glyph_v_advance(ffuncs->user_data.glyph_v_advance); |
|
609 |
|
if (ffuncs->destroy.glyph_h_origin) |
|
610 |
|
ffuncs->destroy.glyph_h_origin(ffuncs->user_data.glyph_h_origin); |
|
611 |
|
if (ffuncs->destroy.glyph_v_origin) |
|
612 |
|
ffuncs->destroy.glyph_v_origin(ffuncs->user_data.glyph_v_origin); |
|
613 |
|
if (ffuncs->destroy.glyph_h_kerning) |
|
614 |
|
ffuncs->destroy.glyph_h_kerning(ffuncs->user_data.glyph_h_kerning); |
|
615 |
|
if (ffuncs->destroy.glyph_v_kerning) |
|
616 |
|
ffuncs->destroy.glyph_v_kerning(ffuncs->user_data.glyph_v_kerning); |
|
617 |
|
if (ffuncs->destroy.glyph_extents) |
|
618 |
|
ffuncs->destroy.glyph_extents(ffuncs->user_data.glyph_extents); |
|
619 |
|
if (ffuncs->destroy.glyph_contour_point) |
|
620 |
|
ffuncs->destroy.glyph_contour_point(ffuncs->user_data.glyph_contour_point); |
|
621 |
|
if (ffuncs->destroy.glyph_name) |
|
622 |
|
ffuncs->destroy.glyph_name(ffuncs->user_data.glyph_name); |
|
623 |
|
if (ffuncs->destroy.glyph_from_name) |
|
624 |
|
ffuncs->destroy.glyph_from_name(ffuncs->user_data.glyph_from_name); |
|
625 |
|
|
|
626 |
|
free(ffuncs); |
|
627 |
|
} |
|
628 |
|
|
|
629 |
|
hb_font_t * |
|
630 |
|
hb_font_create(hb_face_t *face) |
|
631 |
|
{ |
|
632 |
|
if (!face) |
|
633 |
|
face = hb_face_get_empty(); |
|
634 |
|
|
|
635 |
|
if (face->ref_cnt == REF_CNT_INVALID_VAL) |
|
636 |
|
return hb_font_get_empty(); |
|
637 |
|
|
|
638 |
|
hb_font_t *font = calloc(1, sizeof(*font)); |
|
639 |
|
if (!font) |
|
640 |
|
return hb_font_get_empty(); |
|
641 |
|
|
|
642 |
|
hb_atomic_int32_set(&font->ref_cnt, 1); |
|
643 |
|
hb_face_make_immutable(face); |
|
644 |
|
font->face = hb_face_reference(face); |
|
645 |
|
font->klass = hb_font_funcs_get_empty(); |
|
646 |
|
return font; |
|
647 |
|
} |
|
648 |
|
|
|
649 |
|
void |
|
650 |
|
hb_font_funcs_set_glyph_func(hb_font_funcs_t *ffuncs, |
|
651 |
|
hb_font_get_glyph_func_t func, |
|
652 |
|
void *user_data, |
|
653 |
|
hb_destroy_func_t destroy) |
|
654 |
|
{ |
|
655 |
|
if (ffuncs->immutable) { |
|
656 |
|
if (destroy) |
|
657 |
|
destroy(user_data); |
|
658 |
|
return; |
|
659 |
|
} |
|
660 |
|
|
|
661 |
|
if (ffuncs->destroy.glyph) |
|
662 |
|
ffuncs->destroy.glyph(ffuncs->user_data.glyph); |
|
663 |
|
|
|
664 |
|
if (func) { |
|
665 |
|
ffuncs->get.glyph = func; |
|
666 |
|
ffuncs->user_data.glyph = user_data; |
|
667 |
|
ffuncs->destroy.glyph = destroy; |
|
668 |
|
} else { |
|
669 |
|
ffuncs->get.glyph = hb_font_get_glyph_nil; |
|
670 |
|
ffuncs->user_data.glyph = NULL; |
|
671 |
|
ffuncs->destroy.glyph = NULL; |
|
672 |
|
} |
|
673 |
|
} |
|
674 |
|
|
|
675 |
|
void |
|
676 |
|
hb_font_funcs_set_glyph_h_advance_func(hb_font_funcs_t *ffuncs, |
|
677 |
|
hb_font_get_glyph_h_advance_func_t func, |
|
678 |
|
void *user_data, |
|
679 |
|
hb_destroy_func_t destroy) |
|
680 |
|
{ |
|
681 |
|
if (ffuncs->immutable) { |
|
682 |
|
if (destroy) |
|
683 |
|
destroy(user_data); |
|
684 |
|
return; |
|
685 |
|
} |
|
686 |
|
|
|
687 |
|
if (ffuncs->destroy.glyph_h_advance) |
|
688 |
|
ffuncs->destroy.glyph_h_advance(ffuncs->user_data.glyph_h_advance); |
|
689 |
|
|
|
690 |
|
if (func) { |
|
691 |
|
ffuncs->get.glyph_h_advance = func; |
|
692 |
|
ffuncs->user_data.glyph_h_advance = user_data; |
|
693 |
|
ffuncs->destroy.glyph_h_advance = destroy; |
|
694 |
|
} else { |
|
695 |
|
ffuncs->get.glyph_h_advance = hb_font_get_glyph_h_advance_nil; |
|
696 |
|
ffuncs->user_data.glyph_h_advance = NULL; |
|
697 |
|
ffuncs->destroy.glyph_h_advance = NULL; |
|
698 |
|
} |
|
699 |
|
} |
|
700 |
|
|
|
701 |
|
void |
|
702 |
|
hb_font_funcs_set_glyph_v_advance_func(hb_font_funcs_t *ffuncs, |
|
703 |
|
hb_font_get_glyph_v_advance_func_t func, |
|
704 |
|
void *user_data, |
|
705 |
|
hb_destroy_func_t destroy) |
|
706 |
|
{ |
|
707 |
|
if (ffuncs->immutable) { |
|
708 |
|
if (destroy) |
|
709 |
|
destroy(user_data); |
|
710 |
|
return; |
|
711 |
|
} |
|
712 |
|
|
|
713 |
|
if (ffuncs->destroy.glyph_v_advance) |
|
714 |
|
ffuncs->destroy.glyph_v_advance(ffuncs->user_data.glyph_v_advance); |
|
715 |
|
|
|
716 |
|
if (func) { |
|
717 |
|
ffuncs->get.glyph_v_advance = func; |
|
718 |
|
ffuncs->user_data.glyph_v_advance = user_data; |
|
719 |
|
ffuncs->destroy.glyph_v_advance = destroy; |
|
720 |
|
} else { |
|
721 |
|
ffuncs->get.glyph_v_advance = hb_font_get_glyph_v_advance_nil; |
|
722 |
|
ffuncs->user_data.glyph_v_advance = NULL; |
|
723 |
|
ffuncs->destroy.glyph_v_advance = NULL; |
|
724 |
|
} |
|
725 |
|
} |
|
726 |
|
|
|
727 |
|
void |
|
728 |
|
hb_font_funcs_set_glyph_h_origin_func(hb_font_funcs_t *ffuncs, |
|
729 |
|
hb_font_get_glyph_h_origin_func_t func, |
|
730 |
|
void *user_data, |
|
731 |
|
hb_destroy_func_t destroy) |
|
732 |
|
{ |
|
733 |
|
if (ffuncs->immutable) { |
|
734 |
|
if (destroy) |
|
735 |
|
destroy(user_data); |
|
736 |
|
return; |
|
737 |
|
} |
|
738 |
|
|
|
739 |
|
if (ffuncs->destroy.glyph_h_origin) |
|
740 |
|
ffuncs->destroy.glyph_h_origin(ffuncs->user_data.glyph_h_origin); |
|
741 |
|
|
|
742 |
|
if (func) { |
|
743 |
|
ffuncs->get.glyph_h_origin = func; |
|
744 |
|
ffuncs->user_data.glyph_h_origin = user_data; |
|
745 |
|
ffuncs->destroy.glyph_h_origin = destroy; |
|
746 |
|
} else { |
|
747 |
|
ffuncs->get.glyph_h_origin = hb_font_get_glyph_h_origin_nil; |
|
748 |
|
ffuncs->user_data.glyph_h_origin = NULL; |
|
749 |
|
ffuncs->destroy.glyph_h_origin = NULL; |
|
750 |
|
} |
|
751 |
|
} |
|
752 |
|
|
|
753 |
|
void |
|
754 |
|
hb_font_funcs_set_glyph_v_origin_func(hb_font_funcs_t *ffuncs, |
|
755 |
|
hb_font_get_glyph_v_origin_func_t func, |
|
756 |
|
void *user_data, |
|
757 |
|
hb_destroy_func_t destroy) |
|
758 |
|
{ |
|
759 |
|
if (ffuncs->immutable) { |
|
760 |
|
if (destroy) |
|
761 |
|
destroy(user_data); |
|
762 |
|
return; |
|
763 |
|
} |
|
764 |
|
|
|
765 |
|
if (ffuncs->destroy.glyph_v_origin) |
|
766 |
|
ffuncs->destroy.glyph_v_origin(ffuncs->user_data.glyph_v_origin); |
|
767 |
|
|
|
768 |
|
if (func) { |
|
769 |
|
ffuncs->get.glyph_v_origin = func; |
|
770 |
|
ffuncs->user_data.glyph_v_origin = user_data; |
|
771 |
|
ffuncs->destroy.glyph_v_origin = destroy; |
|
772 |
|
} else { |
|
773 |
|
ffuncs->get.glyph_v_origin = hb_font_get_glyph_v_origin_nil; |
|
774 |
|
ffuncs->user_data.glyph_v_origin = NULL; |
|
775 |
|
ffuncs->destroy.glyph_v_origin = NULL; |
|
776 |
|
} |
|
777 |
|
} |
|
778 |
|
|
|
779 |
|
void |
|
780 |
|
hb_font_funcs_set_glyph_h_kerning_func(hb_font_funcs_t *ffuncs, |
|
781 |
|
hb_font_get_glyph_h_kerning_func_t func, |
|
782 |
|
void *user_data, |
|
783 |
|
hb_destroy_func_t destroy) |
|
784 |
|
{ |
|
785 |
|
if (ffuncs->immutable) { |
|
786 |
|
if (destroy) |
|
787 |
|
destroy(user_data); |
|
788 |
|
return; |
|
789 |
|
} |
|
790 |
|
|
|
791 |
|
if (ffuncs->destroy.glyph_h_kerning) |
|
792 |
|
ffuncs->destroy.glyph_h_kerning(ffuncs->user_data.glyph_h_kerning); |
|
793 |
|
|
|
794 |
|
if (func) { |
|
795 |
|
ffuncs->get.glyph_h_kerning = func; |
|
796 |
|
ffuncs->user_data.glyph_h_kerning = user_data; |
|
797 |
|
ffuncs->destroy.glyph_h_kerning = destroy; |
|
798 |
|
} else { |
|
799 |
|
ffuncs->get.glyph_h_kerning = hb_font_get_glyph_h_kerning_nil; |
|
800 |
|
ffuncs->user_data.glyph_h_kerning = NULL; |
|
801 |
|
ffuncs->destroy.glyph_h_kerning = NULL; |
|
802 |
|
} |
|
803 |
|
} |
|
804 |
|
|
|
805 |
|
void |
|
806 |
|
hb_font_funcs_set_glyph_v_kerning_func(hb_font_funcs_t *ffuncs, |
|
807 |
|
hb_font_get_glyph_v_kerning_func_t func, |
|
808 |
|
void *user_data, |
|
809 |
|
hb_destroy_func_t destroy) |
|
810 |
|
{ |
|
811 |
|
if (ffuncs->immutable) { |
|
812 |
|
if (destroy) |
|
813 |
|
destroy(user_data); |
|
814 |
|
return; |
|
815 |
|
} |
|
816 |
|
|
|
817 |
|
if (ffuncs->destroy.glyph_v_kerning) |
|
818 |
|
ffuncs->destroy.glyph_v_kerning(ffuncs->user_data.glyph_v_kerning); |
|
819 |
|
|
|
820 |
|
if (func) { |
|
821 |
|
ffuncs->get.glyph_v_kerning = func; |
|
822 |
|
ffuncs->user_data.glyph_v_kerning = user_data; |
|
823 |
|
ffuncs->destroy.glyph_v_kerning = destroy; |
|
824 |
|
} else { |
|
825 |
|
ffuncs->get.glyph_v_kerning = hb_font_get_glyph_v_kerning_nil; |
|
826 |
|
ffuncs->user_data.glyph_v_kerning = NULL; |
|
827 |
|
ffuncs->destroy.glyph_v_kerning = NULL; |
|
828 |
|
} |
|
829 |
|
} |
|
830 |
|
|
|
831 |
|
void |
|
832 |
|
hb_font_funcs_set_glyph_extents_func(hb_font_funcs_t *ffuncs, |
|
833 |
|
hb_font_get_glyph_extents_func_t func, |
|
834 |
|
void *user_data, |
|
835 |
|
hb_destroy_func_t destroy) |
|
836 |
|
{ |
|
837 |
|
if (ffuncs->immutable) { |
|
838 |
|
if (destroy) |
|
839 |
|
destroy(user_data); |
|
840 |
|
return; |
|
841 |
|
} |
|
842 |
|
|
|
843 |
|
if (ffuncs->destroy.glyph_extents) |
|
844 |
|
ffuncs->destroy.glyph_extents(ffuncs->user_data.glyph_extents); |
|
845 |
|
|
|
846 |
|
if (func) { |
|
847 |
|
ffuncs->get.glyph_extents = func; |
|
848 |
|
ffuncs->user_data.glyph_extents = user_data; |
|
849 |
|
ffuncs->destroy.glyph_extents = destroy; |
|
850 |
|
} else { |
|
851 |
|
ffuncs->get.glyph_extents = hb_font_get_glyph_extents_nil; |
|
852 |
|
ffuncs->user_data.glyph_extents = NULL; |
|
853 |
|
ffuncs->destroy.glyph_extents = NULL; |
|
854 |
|
} |
|
855 |
|
} |
|
856 |
|
|
|
857 |
|
void |
|
858 |
|
hb_font_funcs_set_glyph_contour_point_func( |
|
859 |
|
hb_font_funcs_t *ffuncs, |
|
860 |
|
hb_font_get_glyph_contour_point_func_t func, |
|
861 |
|
void *user_data, |
|
862 |
|
hb_destroy_func_t destroy) |
|
863 |
|
{ |
|
864 |
|
if (ffuncs->immutable) { |
|
865 |
|
if (destroy) |
|
866 |
|
destroy(user_data); |
|
867 |
|
return; |
|
868 |
|
} |
|
869 |
|
|
|
870 |
|
if (ffuncs->destroy.glyph_contour_point) |
|
871 |
|
ffuncs->destroy.glyph_contour_point(ffuncs->user_data.glyph_contour_point); |
|
872 |
|
|
|
873 |
|
if (func) { |
|
874 |
|
ffuncs->get.glyph_contour_point = func; |
|
875 |
|
ffuncs->user_data.glyph_contour_point = user_data; |
|
876 |
|
ffuncs->destroy.glyph_contour_point = destroy; |
|
877 |
|
} else { |
|
878 |
|
ffuncs->get.glyph_contour_point = hb_font_get_glyph_contour_point_nil; |
|
879 |
|
ffuncs->user_data.glyph_contour_point = NULL; |
|
880 |
|
ffuncs->destroy.glyph_contour_point = NULL; |
|
881 |
|
} |
|
882 |
|
} |
|
883 |
|
|
|
884 |
|
void |
|
885 |
|
hb_font_funcs_set_glyph_name_func(hb_font_funcs_t *ffuncs, |
|
886 |
|
hb_font_get_glyph_name_func_t func, |
|
887 |
|
void *user_data, |
|
888 |
|
hb_destroy_func_t destroy) |
|
889 |
|
{ |
|
890 |
|
if (ffuncs->immutable) { |
|
891 |
|
if (destroy) |
|
892 |
|
destroy(user_data); |
|
893 |
|
return; |
|
894 |
|
} |
|
895 |
|
|
|
896 |
|
if (ffuncs->destroy.glyph_name) |
|
897 |
|
ffuncs->destroy.glyph_name(ffuncs->user_data.glyph_name); |
|
898 |
|
|
|
899 |
|
if (func) { |
|
900 |
|
ffuncs->get.glyph_name = func; |
|
901 |
|
ffuncs->user_data.glyph_name = user_data; |
|
902 |
|
ffuncs->destroy.glyph_name = destroy; |
|
903 |
|
} else { |
|
904 |
|
ffuncs->get.glyph_name = hb_font_get_glyph_name_nil; |
|
905 |
|
ffuncs->user_data.glyph_name = NULL; |
|
906 |
|
ffuncs->destroy.glyph_name = NULL; |
|
907 |
|
} |
|
908 |
|
} |
|
909 |
|
|
|
910 |
|
void |
|
911 |
|
hb_font_funcs_set_glyph_from_name_func(hb_font_funcs_t *ffuncs, |
|
912 |
|
hb_font_get_glyph_from_name_func_t func, |
|
913 |
|
void *user_data, |
|
914 |
|
hb_destroy_func_t destroy) |
|
915 |
|
{ |
|
916 |
|
if (ffuncs->immutable) { |
|
917 |
|
if (destroy) |
|
918 |
|
destroy(user_data); |
|
919 |
|
return; |
|
920 |
|
} |
|
921 |
|
|
|
922 |
|
if (ffuncs->destroy.glyph_from_name) |
|
923 |
|
ffuncs->destroy.glyph_from_name(ffuncs->user_data.glyph_from_name); |
|
924 |
|
|
|
925 |
|
if (func) { |
|
926 |
|
ffuncs->get.glyph_from_name = func; |
|
927 |
|
ffuncs->user_data.glyph_from_name = user_data; |
|
928 |
|
ffuncs->destroy.glyph_from_name = destroy; |
|
929 |
|
} else { |
|
930 |
|
ffuncs->get.glyph_from_name = hb_font_get_glyph_from_name_nil; |
|
931 |
|
ffuncs->user_data.glyph_from_name = NULL; |
|
932 |
|
ffuncs->destroy.glyph_from_name = NULL; |
|
933 |
|
} |
|
934 |
|
} |
|
935 |
|
|
|
936 |
|
hb_font_funcs_t * |
|
937 |
|
hb_font_funcs_create(void) |
|
938 |
|
{ |
|
939 |
|
hb_font_funcs_t *ffuncs = calloc(1, sizeof(*ffuncs)); |
|
940 |
|
if (!ffuncs) |
|
941 |
|
return hb_font_funcs_get_empty(); |
|
942 |
|
hb_atomic_int32_set(&ffuncs->ref_cnt, 1); |
|
943 |
|
|
|
944 |
|
ffuncs->get = hb_font_funcs_nil.get; |
|
945 |
|
return ffuncs; |
|
946 |
|
} |
|
947 |
|
|
|
948 |
|
void |
|
949 |
|
hb_font_set_funcs(hb_font_t *font, |
|
950 |
|
hb_font_funcs_t *klass, |
|
951 |
|
void *font_data, |
|
952 |
|
hb_destroy_func_t destroy) |
|
953 |
|
{ |
|
954 |
|
if (font->immutable) { |
|
955 |
|
if (destroy) |
|
956 |
|
destroy(font_data); |
|
957 |
|
return; |
|
958 |
|
} |
|
959 |
|
|
|
960 |
|
if (font->destroy) |
|
961 |
|
font->destroy(font->user_data); |
|
962 |
|
|
|
963 |
|
if (!klass) |
|
964 |
|
klass = hb_font_funcs_get_empty(); |
|
965 |
|
|
|
966 |
|
hb_font_funcs_reference(klass); |
|
967 |
|
hb_font_funcs_destroy(font->klass); |
|
968 |
|
font->klass = klass; |
|
969 |
|
font->user_data = font_data; |
|
970 |
|
font->destroy = destroy; |
|
971 |
|
} |
|
972 |
|
|
|
973 |
|
hb_font_funcs_t * |
|
974 |
|
hb_font_funcs_reference(hb_font_funcs_t *ffuncs) |
|
975 |
|
{ |
|
976 |
|
if (hb_atomic_int32_get(&ffuncs->ref_cnt) != REF_CNT_INVALID_VAL) |
|
977 |
|
hb_atomic_int32_add(&ffuncs->ref_cnt, 1); |
|
978 |
|
return ffuncs; |
|
979 |
|
} |
|
980 |
|
|
|
981 |
|
void |
|
982 |
|
hb_font_set_scale(hb_font_t *font, |
|
983 |
|
int x_scale, |
|
984 |
|
int y_scale) |
|
985 |
|
{ |
|
986 |
|
if (font->immutable) |
|
987 |
|
return; |
|
988 |
|
|
|
989 |
|
font->x_scale = x_scale; |
|
990 |
|
font->y_scale = y_scale; |
|
991 |
|
} |
|
992 |
|
|
|
993 |
|
void |
|
994 |
|
hb_font_set_ppem(hb_font_t *font, |
|
995 |
|
unsigned int x_ppem, |
|
996 |
|
unsigned int y_ppem) |
|
997 |
|
{ |
|
998 |
|
if (font->immutable) |
|
999 |
|
return; |
|
1000 |
|
|
|
1001 |
|
font->x_ppem = x_ppem; |
|
1002 |
|
font->y_ppem = y_ppem; |
|
1003 |
|
} |
File hb-font.h added (mode: 100644) (index 0000000..7273db4) |
|
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 |
|
#ifndef HB_H_IN |
|
28 |
|
#error "Include <hb.h> instead." |
|
29 |
|
#endif |
|
30 |
|
|
|
31 |
|
#ifndef HB_FONT_H |
|
32 |
|
#define HB_FONT_H |
|
33 |
|
|
|
34 |
|
#include "hb-common.h" |
|
35 |
|
#include "hb-face.h" |
|
36 |
|
|
|
37 |
|
HB_BEGIN_DECLS |
|
38 |
|
|
|
39 |
|
|
|
40 |
|
typedef struct hb_font_t hb_font_t; |
|
41 |
|
|
|
42 |
|
|
|
43 |
|
/* |
|
44 |
|
* hb_font_funcs_t |
|
45 |
|
*/ |
|
46 |
|
|
|
47 |
|
typedef struct hb_font_funcs_t hb_font_funcs_t; |
|
48 |
|
|
|
49 |
|
hb_font_funcs_t * |
|
50 |
|
hb_font_funcs_create (void); |
|
51 |
|
|
|
52 |
|
hb_font_funcs_t * |
|
53 |
|
hb_font_funcs_get_empty (void); |
|
54 |
|
|
|
55 |
|
hb_font_funcs_t * |
|
56 |
|
hb_font_funcs_reference (hb_font_funcs_t *ffuncs); |
|
57 |
|
|
|
58 |
|
void |
|
59 |
|
hb_font_funcs_destroy (hb_font_funcs_t *ffuncs); |
|
60 |
|
|
|
61 |
|
hb_bool_t |
|
62 |
|
hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, |
|
63 |
|
hb_user_data_key_t *key, |
|
64 |
|
void * data, |
|
65 |
|
hb_destroy_func_t destroy, |
|
66 |
|
hb_bool_t replace); |
|
67 |
|
|
|
68 |
|
|
|
69 |
|
void * |
|
70 |
|
hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs, |
|
71 |
|
hb_user_data_key_t *key); |
|
72 |
|
|
|
73 |
|
|
|
74 |
|
void |
|
75 |
|
hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs); |
|
76 |
|
|
|
77 |
|
hb_bool_t |
|
78 |
|
hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs); |
|
79 |
|
|
|
80 |
|
|
|
81 |
|
/* glyph extents */ |
|
82 |
|
|
|
83 |
|
typedef struct hb_glyph_extents_t |
|
84 |
|
{ |
|
85 |
|
hb_position_t x_bearing; |
|
86 |
|
hb_position_t y_bearing; |
|
87 |
|
hb_position_t width; |
|
88 |
|
hb_position_t height; |
|
89 |
|
} hb_glyph_extents_t; |
|
90 |
|
|
|
91 |
|
|
|
92 |
|
/* func types */ |
|
93 |
|
|
|
94 |
|
typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, |
|
95 |
|
hb_codepoint_t unicode, hb_codepoint_t variation_selector, |
|
96 |
|
hb_codepoint_t *glyph, |
|
97 |
|
void *user_data); |
|
98 |
|
|
|
99 |
|
|
|
100 |
|
typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, |
|
101 |
|
hb_codepoint_t glyph, |
|
102 |
|
void *user_data); |
|
103 |
|
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t; |
|
104 |
|
typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t; |
|
105 |
|
|
|
106 |
|
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, |
|
107 |
|
hb_codepoint_t glyph, |
|
108 |
|
hb_position_t *x, hb_position_t *y, |
|
109 |
|
void *user_data); |
|
110 |
|
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t; |
|
111 |
|
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t; |
|
112 |
|
|
|
113 |
|
typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, |
|
114 |
|
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, |
|
115 |
|
void *user_data); |
|
116 |
|
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; |
|
117 |
|
typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; |
|
118 |
|
|
|
119 |
|
|
|
120 |
|
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, |
|
121 |
|
hb_codepoint_t glyph, |
|
122 |
|
hb_glyph_extents_t *extents, |
|
123 |
|
void *user_data); |
|
124 |
|
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data, |
|
125 |
|
hb_codepoint_t glyph, unsigned int point_index, |
|
126 |
|
hb_position_t *x, hb_position_t *y, |
|
127 |
|
void *user_data); |
|
128 |
|
|
|
129 |
|
|
|
130 |
|
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data, |
|
131 |
|
hb_codepoint_t glyph, |
|
132 |
|
char *name, unsigned int size, |
|
133 |
|
void *user_data); |
|
134 |
|
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data, |
|
135 |
|
const char *name, int len, /* -1 means nul-terminated */ |
|
136 |
|
hb_codepoint_t *glyph, |
|
137 |
|
void *user_data); |
|
138 |
|
|
|
139 |
|
|
|
140 |
|
/* func setters */ |
|
141 |
|
|
|
142 |
|
/** |
|
143 |
|
* hb_font_funcs_set_glyph_func: |
|
144 |
|
* @ffuncs: font functions. |
|
145 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
146 |
|
* @user_data: |
|
147 |
|
* @destroy: |
|
148 |
|
* |
|
149 |
|
* |
|
150 |
|
* |
|
151 |
|
* Since: 1.0 |
|
152 |
|
**/ |
|
153 |
|
void |
|
154 |
|
hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs, |
|
155 |
|
hb_font_get_glyph_func_t func, |
|
156 |
|
void *user_data, hb_destroy_func_t destroy); |
|
157 |
|
|
|
158 |
|
/** |
|
159 |
|
* hb_font_funcs_set_glyph_h_advance_func: |
|
160 |
|
* @ffuncs: font functions. |
|
161 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
162 |
|
* @user_data: |
|
163 |
|
* @destroy: |
|
164 |
|
* |
|
165 |
|
* |
|
166 |
|
* |
|
167 |
|
* Since: 1.0 |
|
168 |
|
**/ |
|
169 |
|
void |
|
170 |
|
hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, |
|
171 |
|
hb_font_get_glyph_h_advance_func_t func, |
|
172 |
|
void *user_data, hb_destroy_func_t destroy); |
|
173 |
|
|
|
174 |
|
/** |
|
175 |
|
* hb_font_funcs_set_glyph_v_advance_func: |
|
176 |
|
* @ffuncs: font functions. |
|
177 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
178 |
|
* @user_data: |
|
179 |
|
* @destroy: |
|
180 |
|
* |
|
181 |
|
* |
|
182 |
|
* |
|
183 |
|
* Since: 1.0 |
|
184 |
|
**/ |
|
185 |
|
void |
|
186 |
|
hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, |
|
187 |
|
hb_font_get_glyph_v_advance_func_t func, |
|
188 |
|
void *user_data, hb_destroy_func_t destroy); |
|
189 |
|
|
|
190 |
|
/** |
|
191 |
|
* hb_font_funcs_set_glyph_h_origin_func: |
|
192 |
|
* @ffuncs: font functions. |
|
193 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
194 |
|
* @user_data: |
|
195 |
|
* @destroy: |
|
196 |
|
* |
|
197 |
|
* |
|
198 |
|
* |
|
199 |
|
* Since: 1.0 |
|
200 |
|
**/ |
|
201 |
|
void |
|
202 |
|
hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, |
|
203 |
|
hb_font_get_glyph_h_origin_func_t func, |
|
204 |
|
void *user_data, hb_destroy_func_t destroy); |
|
205 |
|
|
|
206 |
|
/** |
|
207 |
|
* hb_font_funcs_set_glyph_v_origin_func: |
|
208 |
|
* @ffuncs: font functions. |
|
209 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
210 |
|
* @user_data: |
|
211 |
|
* @destroy: |
|
212 |
|
* |
|
213 |
|
* |
|
214 |
|
* |
|
215 |
|
* Since: 1.0 |
|
216 |
|
**/ |
|
217 |
|
void |
|
218 |
|
hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, |
|
219 |
|
hb_font_get_glyph_v_origin_func_t func, |
|
220 |
|
void *user_data, hb_destroy_func_t destroy); |
|
221 |
|
|
|
222 |
|
/** |
|
223 |
|
* hb_font_funcs_set_glyph_h_kerning_func: |
|
224 |
|
* @ffuncs: font functions. |
|
225 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
226 |
|
* @user_data: |
|
227 |
|
* @destroy: |
|
228 |
|
* |
|
229 |
|
* |
|
230 |
|
* |
|
231 |
|
* Since: 1.0 |
|
232 |
|
**/ |
|
233 |
|
void |
|
234 |
|
hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, |
|
235 |
|
hb_font_get_glyph_h_kerning_func_t func, |
|
236 |
|
void *user_data, hb_destroy_func_t destroy); |
|
237 |
|
|
|
238 |
|
/** |
|
239 |
|
* hb_font_funcs_set_glyph_v_kerning_func: |
|
240 |
|
* @ffuncs: font functions. |
|
241 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
242 |
|
* @user_data: |
|
243 |
|
* @destroy: |
|
244 |
|
* |
|
245 |
|
* |
|
246 |
|
* |
|
247 |
|
* Since: 1.0 |
|
248 |
|
**/ |
|
249 |
|
void |
|
250 |
|
hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs, |
|
251 |
|
hb_font_get_glyph_v_kerning_func_t func, |
|
252 |
|
void *user_data, hb_destroy_func_t destroy); |
|
253 |
|
|
|
254 |
|
/** |
|
255 |
|
* hb_font_funcs_set_glyph_extents_func: |
|
256 |
|
* @ffuncs: font functions. |
|
257 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
258 |
|
* @user_data: |
|
259 |
|
* @destroy: |
|
260 |
|
* |
|
261 |
|
* |
|
262 |
|
* |
|
263 |
|
* Since: 1.0 |
|
264 |
|
**/ |
|
265 |
|
void |
|
266 |
|
hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, |
|
267 |
|
hb_font_get_glyph_extents_func_t func, |
|
268 |
|
void *user_data, hb_destroy_func_t destroy); |
|
269 |
|
|
|
270 |
|
/** |
|
271 |
|
* hb_font_funcs_set_glyph_contour_point_func: |
|
272 |
|
* @ffuncs: font functions. |
|
273 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
274 |
|
* @user_data: |
|
275 |
|
* @destroy: |
|
276 |
|
* |
|
277 |
|
* |
|
278 |
|
* |
|
279 |
|
* Since: 1.0 |
|
280 |
|
**/ |
|
281 |
|
void |
|
282 |
|
hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, |
|
283 |
|
hb_font_get_glyph_contour_point_func_t func, |
|
284 |
|
void *user_data, hb_destroy_func_t destroy); |
|
285 |
|
|
|
286 |
|
/** |
|
287 |
|
* hb_font_funcs_set_glyph_name_func: |
|
288 |
|
* @ffuncs: font functions. |
|
289 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
290 |
|
* @user_data: |
|
291 |
|
* @destroy: |
|
292 |
|
* |
|
293 |
|
* |
|
294 |
|
* |
|
295 |
|
* Since: 1.0 |
|
296 |
|
**/ |
|
297 |
|
void |
|
298 |
|
hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, |
|
299 |
|
hb_font_get_glyph_name_func_t func, |
|
300 |
|
void *user_data, hb_destroy_func_t destroy); |
|
301 |
|
|
|
302 |
|
/** |
|
303 |
|
* hb_font_funcs_set_glyph_from_name_func: |
|
304 |
|
* @ffuncs: font functions. |
|
305 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
306 |
|
* @user_data: |
|
307 |
|
* @destroy: |
|
308 |
|
* |
|
309 |
|
* |
|
310 |
|
* |
|
311 |
|
* Since: 1.0 |
|
312 |
|
**/ |
|
313 |
|
void |
|
314 |
|
hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs, |
|
315 |
|
hb_font_get_glyph_from_name_func_t func, |
|
316 |
|
void *user_data, hb_destroy_func_t destroy); |
|
317 |
|
|
|
318 |
|
|
|
319 |
|
/* func dispatch */ |
|
320 |
|
|
|
321 |
|
hb_bool_t |
|
322 |
|
hb_font_get_glyph (hb_font_t *font, |
|
323 |
|
hb_codepoint_t unicode, hb_codepoint_t variation_selector, |
|
324 |
|
hb_codepoint_t *glyph); |
|
325 |
|
|
|
326 |
|
hb_position_t |
|
327 |
|
hb_font_get_glyph_h_advance (hb_font_t *font, |
|
328 |
|
hb_codepoint_t glyph); |
|
329 |
|
hb_position_t |
|
330 |
|
hb_font_get_glyph_v_advance (hb_font_t *font, |
|
331 |
|
hb_codepoint_t glyph); |
|
332 |
|
|
|
333 |
|
hb_bool_t |
|
334 |
|
hb_font_get_glyph_h_origin (hb_font_t *font, |
|
335 |
|
hb_codepoint_t glyph, |
|
336 |
|
hb_position_t *x, hb_position_t *y); |
|
337 |
|
hb_bool_t |
|
338 |
|
hb_font_get_glyph_v_origin (hb_font_t *font, |
|
339 |
|
hb_codepoint_t glyph, |
|
340 |
|
hb_position_t *x, hb_position_t *y); |
|
341 |
|
|
|
342 |
|
hb_position_t |
|
343 |
|
hb_font_get_glyph_h_kerning (hb_font_t *font, |
|
344 |
|
hb_codepoint_t left_glyph, hb_codepoint_t right_glyph); |
|
345 |
|
hb_position_t |
|
346 |
|
hb_font_get_glyph_v_kerning (hb_font_t *font, |
|
347 |
|
hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph); |
|
348 |
|
|
|
349 |
|
hb_bool_t |
|
350 |
|
hb_font_get_glyph_extents (hb_font_t *font, |
|
351 |
|
hb_codepoint_t glyph, |
|
352 |
|
hb_glyph_extents_t *extents); |
|
353 |
|
|
|
354 |
|
hb_bool_t |
|
355 |
|
hb_font_get_glyph_contour_point (hb_font_t *font, |
|
356 |
|
hb_codepoint_t glyph, unsigned int point_index, |
|
357 |
|
hb_position_t *x, hb_position_t *y); |
|
358 |
|
|
|
359 |
|
hb_bool_t |
|
360 |
|
hb_font_get_glyph_name (hb_font_t *font, |
|
361 |
|
hb_codepoint_t glyph, |
|
362 |
|
char *name, unsigned int size); |
|
363 |
|
hb_bool_t |
|
364 |
|
hb_font_get_glyph_from_name (hb_font_t *font, |
|
365 |
|
const char *name, int len, /* -1 means nul-terminated */ |
|
366 |
|
hb_codepoint_t *glyph); |
|
367 |
|
|
|
368 |
|
|
|
369 |
|
/* high-level funcs, with fallback */ |
|
370 |
|
|
|
371 |
|
void |
|
372 |
|
hb_font_get_glyph_advance_for_direction (hb_font_t *font, |
|
373 |
|
hb_codepoint_t glyph, |
|
374 |
|
hb_direction_t direction, |
|
375 |
|
hb_position_t *x, hb_position_t *y); |
|
376 |
|
void |
|
377 |
|
hb_font_get_glyph_origin_for_direction (hb_font_t *font, |
|
378 |
|
hb_codepoint_t glyph, |
|
379 |
|
hb_direction_t direction, |
|
380 |
|
hb_position_t *x, hb_position_t *y); |
|
381 |
|
void |
|
382 |
|
hb_font_add_glyph_origin_for_direction (hb_font_t *font, |
|
383 |
|
hb_codepoint_t glyph, |
|
384 |
|
hb_direction_t direction, |
|
385 |
|
hb_position_t *x, hb_position_t *y); |
|
386 |
|
void |
|
387 |
|
hb_font_subtract_glyph_origin_for_direction (hb_font_t *font, |
|
388 |
|
hb_codepoint_t glyph, |
|
389 |
|
hb_direction_t direction, |
|
390 |
|
hb_position_t *x, hb_position_t *y); |
|
391 |
|
|
|
392 |
|
void |
|
393 |
|
hb_font_get_glyph_kerning_for_direction (hb_font_t *font, |
|
394 |
|
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, |
|
395 |
|
hb_direction_t direction, |
|
396 |
|
hb_position_t *x, hb_position_t *y); |
|
397 |
|
|
|
398 |
|
hb_bool_t |
|
399 |
|
hb_font_get_glyph_extents_for_origin (hb_font_t *font, |
|
400 |
|
hb_codepoint_t glyph, |
|
401 |
|
hb_direction_t direction, |
|
402 |
|
hb_glyph_extents_t *extents); |
|
403 |
|
|
|
404 |
|
hb_bool_t |
|
405 |
|
hb_font_get_glyph_contour_point_for_origin (hb_font_t *font, |
|
406 |
|
hb_codepoint_t glyph, unsigned int point_index, |
|
407 |
|
hb_direction_t direction, |
|
408 |
|
hb_position_t *x, hb_position_t *y); |
|
409 |
|
|
|
410 |
|
/* Generates gidDDD if glyph has no name. */ |
|
411 |
|
void |
|
412 |
|
hb_font_glyph_to_string (hb_font_t *font, |
|
413 |
|
hb_codepoint_t glyph, |
|
414 |
|
char *s, unsigned int size); |
|
415 |
|
/* Parses gidDDD and uniUUUU strings automatically. */ |
|
416 |
|
hb_bool_t |
|
417 |
|
hb_font_glyph_from_string (hb_font_t *font, |
|
418 |
|
const char *s, int len, /* -1 means nul-terminated */ |
|
419 |
|
hb_codepoint_t *glyph); |
|
420 |
|
|
|
421 |
|
|
|
422 |
|
/* |
|
423 |
|
* hb_font_t |
|
424 |
|
*/ |
|
425 |
|
|
|
426 |
|
/* Fonts are very light-weight objects */ |
|
427 |
|
|
|
428 |
|
hb_font_t * |
|
429 |
|
hb_font_create (hb_face_t *face); |
|
430 |
|
|
|
431 |
|
hb_font_t * |
|
432 |
|
hb_font_create_sub_font (hb_font_t *parent); |
|
433 |
|
|
|
434 |
|
hb_font_t * |
|
435 |
|
hb_font_get_empty (void); |
|
436 |
|
|
|
437 |
|
hb_font_t * |
|
438 |
|
hb_font_reference (hb_font_t *font); |
|
439 |
|
|
|
440 |
|
void |
|
441 |
|
hb_font_destroy (hb_font_t *font); |
|
442 |
|
|
|
443 |
|
hb_bool_t |
|
444 |
|
hb_font_set_user_data (hb_font_t *font, |
|
445 |
|
hb_user_data_key_t *key, |
|
446 |
|
void * data, |
|
447 |
|
hb_destroy_func_t destroy, |
|
448 |
|
hb_bool_t replace); |
|
449 |
|
|
|
450 |
|
|
|
451 |
|
void * |
|
452 |
|
hb_font_get_user_data (hb_font_t *font, |
|
453 |
|
hb_user_data_key_t *key); |
|
454 |
|
|
|
455 |
|
void |
|
456 |
|
hb_font_make_immutable (hb_font_t *font); |
|
457 |
|
|
|
458 |
|
hb_bool_t |
|
459 |
|
hb_font_is_immutable (hb_font_t *font); |
|
460 |
|
|
|
461 |
|
hb_font_t * |
|
462 |
|
hb_font_get_parent (hb_font_t *font); |
|
463 |
|
|
|
464 |
|
hb_face_t * |
|
465 |
|
hb_font_get_face (hb_font_t *font); |
|
466 |
|
|
|
467 |
|
|
|
468 |
|
void |
|
469 |
|
hb_font_set_funcs (hb_font_t *font, |
|
470 |
|
hb_font_funcs_t *klass, |
|
471 |
|
void *font_data, |
|
472 |
|
hb_destroy_func_t destroy); |
|
473 |
|
|
|
474 |
|
/* Be *very* careful with this function! */ |
|
475 |
|
void |
|
476 |
|
hb_font_set_funcs_data (hb_font_t *font, |
|
477 |
|
void *font_data, |
|
478 |
|
hb_destroy_func_t destroy); |
|
479 |
|
|
|
480 |
|
|
|
481 |
|
void |
|
482 |
|
hb_font_set_scale (hb_font_t *font, |
|
483 |
|
int x_scale, |
|
484 |
|
int y_scale); |
|
485 |
|
|
|
486 |
|
void |
|
487 |
|
hb_font_get_scale (hb_font_t *font, |
|
488 |
|
int *x_scale, |
|
489 |
|
int *y_scale); |
|
490 |
|
|
|
491 |
|
/* |
|
492 |
|
* A zero value means "no hinting in that direction" |
|
493 |
|
*/ |
|
494 |
|
void |
|
495 |
|
hb_font_set_ppem (hb_font_t *font, |
|
496 |
|
unsigned int x_ppem, |
|
497 |
|
unsigned int y_ppem); |
|
498 |
|
|
|
499 |
|
void |
|
500 |
|
hb_font_get_ppem (hb_font_t *font, |
|
501 |
|
unsigned int *x_ppem, |
|
502 |
|
unsigned int *y_ppem); |
|
503 |
|
|
|
504 |
|
|
|
505 |
|
HB_END_DECLS |
|
506 |
|
|
|
507 |
|
#endif /* HB_FONT_H */ |
File hb-ot-layout.h added (mode: 100644) (index 0000000..d2a314c) |
|
1 |
|
/* |
|
2 |
|
* Copyright © 2007,2008,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 |
|
#ifndef HB_OT_H_IN |
|
28 |
|
#error "Include <hb-ot.h> instead." |
|
29 |
|
#endif |
|
30 |
|
|
|
31 |
|
#ifndef HB_OT_LAYOUT_H |
|
32 |
|
#define HB_OT_LAYOUT_H |
|
33 |
|
|
|
34 |
|
#include "hb.h" |
|
35 |
|
|
|
36 |
|
#include "hb-ot-tag.h" |
|
37 |
|
|
|
38 |
|
HB_BEGIN_DECLS |
|
39 |
|
|
|
40 |
|
|
|
41 |
|
#define HB_OT_TAG_GDEF HB_TAG('G','D','E','F') |
|
42 |
|
#define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') |
|
43 |
|
#define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') |
|
44 |
|
#define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') |
|
45 |
|
|
|
46 |
|
|
|
47 |
|
/* |
|
48 |
|
* GDEF |
|
49 |
|
*/ |
|
50 |
|
|
|
51 |
|
hb_bool_t |
|
52 |
|
hb_ot_layout_has_glyph_classes (hb_face_t *face); |
|
53 |
|
|
|
54 |
|
typedef enum { |
|
55 |
|
HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0, |
|
56 |
|
HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH = 1, |
|
57 |
|
HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE = 2, |
|
58 |
|
HB_OT_LAYOUT_GLYPH_CLASS_MARK = 3, |
|
59 |
|
HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 4 |
|
60 |
|
} hb_ot_layout_glyph_class_t; |
|
61 |
|
|
|
62 |
|
hb_ot_layout_glyph_class_t |
|
63 |
|
hb_ot_layout_get_glyph_class (hb_face_t *face, |
|
64 |
|
hb_codepoint_t glyph); |
|
65 |
|
|
|
66 |
|
void |
|
67 |
|
hb_ot_layout_get_glyphs_in_class (hb_face_t *face, |
|
68 |
|
hb_ot_layout_glyph_class_t klass, |
|
69 |
|
hb_set_t *glyphs /* OUT */); |
|
70 |
|
|
|
71 |
|
|
|
72 |
|
/* Not that useful. Provides list of attach points for a glyph that a |
|
73 |
|
* client may want to cache */ |
|
74 |
|
unsigned int |
|
75 |
|
hb_ot_layout_get_attach_points (hb_face_t *face, |
|
76 |
|
hb_codepoint_t glyph, |
|
77 |
|
unsigned int start_offset, |
|
78 |
|
unsigned int *point_count /* IN/OUT */, |
|
79 |
|
unsigned int *point_array /* OUT */); |
|
80 |
|
|
|
81 |
|
/* Ligature caret positions */ |
|
82 |
|
unsigned int |
|
83 |
|
hb_ot_layout_get_ligature_carets (hb_font_t *font, |
|
84 |
|
hb_direction_t direction, |
|
85 |
|
hb_codepoint_t glyph, |
|
86 |
|
unsigned int start_offset, |
|
87 |
|
unsigned int *caret_count /* IN/OUT */, |
|
88 |
|
hb_position_t *caret_array /* OUT */); |
|
89 |
|
|
|
90 |
|
|
|
91 |
|
/* |
|
92 |
|
* GSUB/GPOS feature query and enumeration interface |
|
93 |
|
*/ |
|
94 |
|
|
|
95 |
|
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX ((unsigned int) 0xFFFF) |
|
96 |
|
#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF) |
|
97 |
|
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF) |
|
98 |
|
|
|
99 |
|
unsigned int |
|
100 |
|
hb_ot_layout_table_get_script_tags (hb_face_t *face, |
|
101 |
|
hb_tag_t table_tag, |
|
102 |
|
unsigned int start_offset, |
|
103 |
|
unsigned int *script_count /* IN/OUT */, |
|
104 |
|
hb_tag_t *script_tags /* OUT */); |
|
105 |
|
|
|
106 |
|
hb_bool_t |
|
107 |
|
hb_ot_layout_table_find_script (hb_face_t *face, |
|
108 |
|
hb_tag_t table_tag, |
|
109 |
|
hb_tag_t script_tag, |
|
110 |
|
unsigned int *script_index); |
|
111 |
|
|
|
112 |
|
/* Like find_script, but takes zero-terminated array of scripts to test */ |
|
113 |
|
hb_bool_t |
|
114 |
|
hb_ot_layout_table_choose_script (hb_face_t *face, |
|
115 |
|
hb_tag_t table_tag, |
|
116 |
|
const hb_tag_t *script_tags, |
|
117 |
|
unsigned int *script_index, |
|
118 |
|
hb_tag_t *chosen_script); |
|
119 |
|
|
|
120 |
|
unsigned int |
|
121 |
|
hb_ot_layout_table_get_feature_tags (hb_face_t *face, |
|
122 |
|
hb_tag_t table_tag, |
|
123 |
|
unsigned int start_offset, |
|
124 |
|
unsigned int *feature_count /* IN/OUT */, |
|
125 |
|
hb_tag_t *feature_tags /* OUT */); |
|
126 |
|
|
|
127 |
|
unsigned int |
|
128 |
|
hb_ot_layout_script_get_language_tags (hb_face_t *face, |
|
129 |
|
hb_tag_t table_tag, |
|
130 |
|
unsigned int script_index, |
|
131 |
|
unsigned int start_offset, |
|
132 |
|
unsigned int *language_count /* IN/OUT */, |
|
133 |
|
hb_tag_t *language_tags /* OUT */); |
|
134 |
|
|
|
135 |
|
hb_bool_t |
|
136 |
|
hb_ot_layout_script_find_language (hb_face_t *face, |
|
137 |
|
hb_tag_t table_tag, |
|
138 |
|
unsigned int script_index, |
|
139 |
|
hb_tag_t language_tag, |
|
140 |
|
unsigned int *language_index); |
|
141 |
|
|
|
142 |
|
hb_bool_t |
|
143 |
|
hb_ot_layout_language_get_required_feature_index (hb_face_t *face, |
|
144 |
|
hb_tag_t table_tag, |
|
145 |
|
unsigned int script_index, |
|
146 |
|
unsigned int language_index, |
|
147 |
|
unsigned int *feature_index); |
|
148 |
|
|
|
149 |
|
unsigned int |
|
150 |
|
hb_ot_layout_language_get_feature_indexes (hb_face_t *face, |
|
151 |
|
hb_tag_t table_tag, |
|
152 |
|
unsigned int script_index, |
|
153 |
|
unsigned int language_index, |
|
154 |
|
unsigned int start_offset, |
|
155 |
|
unsigned int *feature_count /* IN/OUT */, |
|
156 |
|
unsigned int *feature_indexes /* OUT */); |
|
157 |
|
|
|
158 |
|
unsigned int |
|
159 |
|
hb_ot_layout_language_get_feature_tags (hb_face_t *face, |
|
160 |
|
hb_tag_t table_tag, |
|
161 |
|
unsigned int script_index, |
|
162 |
|
unsigned int language_index, |
|
163 |
|
unsigned int start_offset, |
|
164 |
|
unsigned int *feature_count /* IN/OUT */, |
|
165 |
|
hb_tag_t *feature_tags /* OUT */); |
|
166 |
|
|
|
167 |
|
hb_bool_t |
|
168 |
|
hb_ot_layout_language_find_feature (hb_face_t *face, |
|
169 |
|
hb_tag_t table_tag, |
|
170 |
|
unsigned int script_index, |
|
171 |
|
unsigned int language_index, |
|
172 |
|
hb_tag_t feature_tag, |
|
173 |
|
unsigned int *feature_index); |
|
174 |
|
|
|
175 |
|
unsigned int |
|
176 |
|
hb_ot_layout_feature_get_lookups (hb_face_t *face, |
|
177 |
|
hb_tag_t table_tag, |
|
178 |
|
unsigned int feature_index, |
|
179 |
|
unsigned int start_offset, |
|
180 |
|
unsigned int *lookup_count /* IN/OUT */, |
|
181 |
|
unsigned int *lookup_indexes /* OUT */); |
|
182 |
|
|
|
183 |
|
void |
|
184 |
|
hb_ot_layout_collect_lookups (hb_face_t *face, |
|
185 |
|
hb_tag_t table_tag, |
|
186 |
|
const hb_tag_t *scripts, |
|
187 |
|
const hb_tag_t *languages, |
|
188 |
|
const hb_tag_t *features, |
|
189 |
|
hb_set_t *lookup_indexes /* OUT */); |
|
190 |
|
|
|
191 |
|
void |
|
192 |
|
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan, |
|
193 |
|
hb_tag_t table_tag, |
|
194 |
|
hb_set_t *lookup_indexes /* OUT */); |
|
195 |
|
|
|
196 |
|
void |
|
197 |
|
hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, |
|
198 |
|
hb_tag_t table_tag, |
|
199 |
|
unsigned int lookup_index, |
|
200 |
|
hb_set_t *glyphs_before, /* OUT. May be NULL */ |
|
201 |
|
hb_set_t *glyphs_input, /* OUT. May be NULL */ |
|
202 |
|
hb_set_t *glyphs_after, /* OUT. May be NULL */ |
|
203 |
|
hb_set_t *glyphs_output /* OUT. May be NULL */); |
|
204 |
|
|
|
205 |
|
#ifdef HB_NOT_IMPLEMENTED |
|
206 |
|
typedef struct |
|
207 |
|
{ |
|
208 |
|
const hb_codepoint_t *before, |
|
209 |
|
unsigned int before_length, |
|
210 |
|
const hb_codepoint_t *input, |
|
211 |
|
unsigned int input_length, |
|
212 |
|
const hb_codepoint_t *after, |
|
213 |
|
unsigned int after_length, |
|
214 |
|
} hb_ot_layout_glyph_sequence_t; |
|
215 |
|
|
|
216 |
|
typedef hb_bool_t |
|
217 |
|
(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font, |
|
218 |
|
hb_tag_t table_tag, |
|
219 |
|
unsigned int lookup_index, |
|
220 |
|
const hb_ot_layout_glyph_sequence_t *sequence, |
|
221 |
|
void *user_data); |
|
222 |
|
|
|
223 |
|
void |
|
224 |
|
Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face, |
|
225 |
|
hb_tag_t table_tag, |
|
226 |
|
unsigned int lookup_index, |
|
227 |
|
hb_ot_layout_glyph_sequence_func_t callback, |
|
228 |
|
void *user_data); |
|
229 |
|
#endif |
|
230 |
|
|
|
231 |
|
|
|
232 |
|
/* |
|
233 |
|
* GSUB |
|
234 |
|
*/ |
|
235 |
|
|
|
236 |
|
hb_bool_t |
|
237 |
|
hb_ot_layout_has_substitution (hb_face_t *face); |
|
238 |
|
|
|
239 |
|
hb_bool_t |
|
240 |
|
hb_ot_layout_lookup_would_substitute (hb_face_t *face, |
|
241 |
|
unsigned int lookup_index, |
|
242 |
|
const hb_codepoint_t *glyphs, |
|
243 |
|
unsigned int glyphs_length, |
|
244 |
|
hb_bool_t zero_context); |
|
245 |
|
|
|
246 |
|
void |
|
247 |
|
hb_ot_layout_lookup_substitute_closure (hb_face_t *face, |
|
248 |
|
unsigned int lookup_index, |
|
249 |
|
hb_set_t *glyphs |
|
250 |
|
/*TODO , hb_bool_t inclusive */); |
|
251 |
|
|
|
252 |
|
#ifdef HB_NOT_IMPLEMENTED |
|
253 |
|
/* Note: You better have GDEF when using this API, or marks won't do much. */ |
|
254 |
|
hb_bool_t |
|
255 |
|
Xhb_ot_layout_lookup_substitute (hb_font_t *font, |
|
256 |
|
unsigned int lookup_index, |
|
257 |
|
const hb_ot_layout_glyph_sequence_t *sequence, |
|
258 |
|
unsigned int out_size, |
|
259 |
|
hb_codepoint_t *glyphs_out, /* OUT */ |
|
260 |
|
unsigned int *clusters_out, /* OUT */ |
|
261 |
|
unsigned int *out_length /* OUT */); |
|
262 |
|
#endif |
|
263 |
|
|
|
264 |
|
|
|
265 |
|
/* |
|
266 |
|
* GPOS |
|
267 |
|
*/ |
|
268 |
|
|
|
269 |
|
hb_bool_t |
|
270 |
|
hb_ot_layout_has_positioning (hb_face_t *face); |
|
271 |
|
|
|
272 |
|
#ifdef HB_NOT_IMPLEMENTED |
|
273 |
|
/* Note: You better have GDEF when using this API, or marks won't do much. */ |
|
274 |
|
hb_bool_t |
|
275 |
|
Xhb_ot_layout_lookup_position (hb_font_t *font, |
|
276 |
|
unsigned int lookup_index, |
|
277 |
|
const hb_ot_layout_glyph_sequence_t *sequence, |
|
278 |
|
hb_glyph_position_t *positions /* IN / OUT */); |
|
279 |
|
#endif |
|
280 |
|
|
|
281 |
|
/* Optical 'size' feature info. Returns true if found. |
|
282 |
|
* http://www.microsoft.com/typography/otspec/features_pt.htm#size */ |
|
283 |
|
hb_bool_t |
|
284 |
|
hb_ot_layout_get_size_params (hb_face_t *face, |
|
285 |
|
unsigned int *design_size, /* OUT. May be NULL */ |
|
286 |
|
unsigned int *subfamily_id, /* OUT. May be NULL */ |
|
287 |
|
unsigned int *subfamily_name_id, /* OUT. May be NULL */ |
|
288 |
|
unsigned int *range_start, /* OUT. May be NULL */ |
|
289 |
|
unsigned int *range_end /* OUT. May be NULL */); |
|
290 |
|
|
|
291 |
|
|
|
292 |
|
HB_END_DECLS |
|
293 |
|
|
|
294 |
|
#endif /* HB_OT_LAYOUT_H */ |
File hb-shape-plan.c added (mode: 100644) (index 0000000..929804a) |
|
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 <stddef.h> |
|
5 |
|
#include <assert.h> |
|
6 |
|
|
|
7 |
|
#include <ft2build.h> |
|
8 |
|
#include FT_FREETYPE_H |
|
9 |
|
|
|
10 |
|
#include "hb.h" |
|
11 |
|
#include "hb-private.h" |
|
12 |
|
#include "hb-atomic-private.h" |
|
13 |
|
#include "hb-buffer-private.h" |
|
14 |
|
#include "hb-shaper-private.h" |
|
15 |
|
#include "hb-face-private.h" |
|
16 |
|
#include "hb-font-private.h" |
|
17 |
|
#include "hb-shape-plan-private.h" |
|
18 |
|
|
|
19 |
|
static hb_shape_plan_t hb_shape_plan_nil = { |
|
20 |
|
REF_CNT_INVALID_VAL, |
|
21 |
|
TRUE,//default_shaper_list |
|
22 |
|
NULL,//face |
|
23 |
|
HB_SEGMENT_PROPERTIES_DEFAULT,//props |
|
24 |
|
NULL,//shaper_func |
|
25 |
|
NULL,//shaper_name |
|
26 |
|
{ |
|
27 |
|
#ifdef HAVE_GRAPHITE2 |
|
28 |
|
HB_SHAPER_DATA_INVALID, |
|
29 |
|
#endif |
|
30 |
|
#ifdef HAVE_OT |
|
31 |
|
HB_SHAPER_DATA_INVALID, |
|
32 |
|
#endif |
|
33 |
|
HB_SHAPER_DATA_INVALID//fallback |
|
34 |
|
} |
|
35 |
|
}; |
|
36 |
|
|
|
37 |
|
//TODO no user-feature caching for now. |
|
38 |
|
struct hb_shape_plan_proposal_t |
|
39 |
|
{ |
|
40 |
|
const hb_segment_properties_t props; |
|
41 |
|
const char * const *shaper_list; |
|
42 |
|
hb_shape_func_t *shaper_func; |
|
43 |
|
}; |
|
44 |
|
|
|
45 |
|
hb_shape_plan_t * |
|
46 |
|
hb_shape_plan_get_empty(void) |
|
47 |
|
{ |
|
48 |
|
return &hb_shape_plan_nil; |
|
49 |
|
} |
|
50 |
|
|
|
51 |
|
#ifdef HAVE_GRAPHITE2 |
|
52 |
|
static inline hb_bool_t |
|
53 |
|
hb_graphite2_shaper_face_data_ensure(hb_face_t *face) |
|
54 |
|
{ |
|
55 |
|
while (1) { |
|
56 |
|
struct hb_graphite2_shaper_face_data_t *data = hb_atomic_ptr_get( |
|
57 |
|
&face->shaper_data.graphite2); |
|
58 |
|
if (data) |
|
59 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
60 |
|
|
|
61 |
|
if (!data) |
|
62 |
|
data = hb_graphite2_shaper_face_data_create(face); |
|
63 |
|
|
|
64 |
|
if (!data) |
|
65 |
|
data = HB_SHAPER_DATA_INVALID; |
|
66 |
|
|
|
67 |
|
void *expected = NULL; |
|
68 |
|
if (hb_atomic_ptr_cmpexch(&face->shaper_data.graphite2, &expected, &data)) |
|
69 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
70 |
|
|
|
71 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
72 |
|
hb_graphite2_shaper_face_data_destroy(data); |
|
73 |
|
} |
|
74 |
|
} |
|
75 |
|
|
|
76 |
|
static inline hb_bool_t |
|
77 |
|
hb_graphite2_shaper_font_data_ensure(hb_font_t *font) |
|
78 |
|
{ |
|
79 |
|
while (1) { |
|
80 |
|
struct hb_graphite2_shaper_font_data_t *data = hb_atomic_ptr_get( |
|
81 |
|
&font->shaper_data.graphite2); |
|
82 |
|
if (data) |
|
83 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
84 |
|
|
|
85 |
|
if (!data) |
|
86 |
|
data = hb_graphite2_shaper_font_data_create(font); |
|
87 |
|
|
|
88 |
|
if (!data) |
|
89 |
|
data = HB_SHAPER_DATA_INVALID; |
|
90 |
|
|
|
91 |
|
void *expected = NULL; |
|
92 |
|
if (hb_atomic_ptr_cmpexch(&font->shaper_data.graphite2, &expected, &data)) |
|
93 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
94 |
|
|
|
95 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
96 |
|
hb_graphite2_shaper_font_data_destroy(data); |
|
97 |
|
} |
|
98 |
|
} |
|
99 |
|
#endif |
|
100 |
|
|
|
101 |
|
#ifdef HAVE_OT |
|
102 |
|
static inline hb_bool_t |
|
103 |
|
hb_ot_shaper_face_data_ensure(hb_face_t *face) |
|
104 |
|
{ |
|
105 |
|
while (1) { |
|
106 |
|
struct hb_ot_shaper_face_data_t *data = hb_atomic_ptr_get( |
|
107 |
|
&face->shaper_data.ot); |
|
108 |
|
if (data) |
|
109 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
110 |
|
|
|
111 |
|
if (!data) |
|
112 |
|
data = hb_ot_shaper_face_data_create(face); |
|
113 |
|
|
|
114 |
|
if (!data) |
|
115 |
|
data = HB_SHAPER_DATA_INVALID; |
|
116 |
|
|
|
117 |
|
void *expected = NULL; |
|
118 |
|
if (hb_atomic_ptr_cmpexch(&face->shaper_data.ot, &expected, &data)) |
|
119 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
120 |
|
|
|
121 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
122 |
|
hb_ot_shaper_face_data_destroy(data); |
|
123 |
|
} |
|
124 |
|
} |
|
125 |
|
|
|
126 |
|
static inline hb_bool_t |
|
127 |
|
hb_ot_shaper_font_data_ensure(hb_font_t *font) |
|
128 |
|
{ |
|
129 |
|
while (1) { |
|
130 |
|
struct hb_ot_shaper_font_data_t *data = hb_atomic_ptr_get( |
|
131 |
|
&font->shaper_data.ot); |
|
132 |
|
if (data) |
|
133 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
134 |
|
|
|
135 |
|
if (!data) |
|
136 |
|
data = hb_ot_shaper_font_data_create(font); |
|
137 |
|
|
|
138 |
|
if (!data) |
|
139 |
|
data = HB_SHAPER_DATA_INVALID; |
|
140 |
|
|
|
141 |
|
void *expected = NULL; |
|
142 |
|
if (hb_atomic_ptr_cmpexch(&font->shaper_data.ot, &expected, &data)) |
|
143 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
144 |
|
|
|
145 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
146 |
|
hb_ot_shaper_font_data_destroy(data); |
|
147 |
|
} |
|
148 |
|
} |
|
149 |
|
#endif |
|
150 |
|
|
|
151 |
|
static inline hb_bool_t |
|
152 |
|
hb_fallback_shaper_face_data_ensure(hb_face_t *face) |
|
153 |
|
{ |
|
154 |
|
while (1) { |
|
155 |
|
struct hb_fallback_shaper_face_data_t *data = hb_atomic_ptr_get( |
|
156 |
|
&face->shaper_data.fallback); |
|
157 |
|
if (data) |
|
158 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
159 |
|
|
|
160 |
|
if (!data) |
|
161 |
|
data = hb_fallback_shaper_face_data_create(face); |
|
162 |
|
|
|
163 |
|
if (!data) |
|
164 |
|
data = HB_SHAPER_DATA_INVALID; |
|
165 |
|
|
|
166 |
|
void *expected = NULL; |
|
167 |
|
if (hb_atomic_ptr_cmpexch(&face->shaper_data.fallback, &expected, &data)) |
|
168 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
169 |
|
|
|
170 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
171 |
|
hb_fallback_shaper_face_data_destroy(data); |
|
172 |
|
} |
|
173 |
|
} |
|
174 |
|
|
|
175 |
|
static inline hb_bool_t |
|
176 |
|
hb_fallback_shaper_font_data_ensure(hb_font_t *font) |
|
177 |
|
{ |
|
178 |
|
while (1) { |
|
179 |
|
struct hb_fallback_shaper_font_data_t *data = hb_atomic_ptr_get( |
|
180 |
|
&font->shaper_data.fallback); |
|
181 |
|
if (data) |
|
182 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
183 |
|
|
|
184 |
|
if (!data) |
|
185 |
|
data = hb_fallback_shaper_font_data_create(font); |
|
186 |
|
|
|
187 |
|
if (!data) |
|
188 |
|
data = HB_SHAPER_DATA_INVALID; |
|
189 |
|
|
|
190 |
|
void *expected = NULL; |
|
191 |
|
if (hb_atomic_ptr_cmpexch(&font->shaper_data.fallback, &expected, &data)) |
|
192 |
|
return !HB_SHAPER_DATA_IS_INVALID(data); |
|
193 |
|
|
|
194 |
|
if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) |
|
195 |
|
hb_fallback_shaper_font_data_destroy(data); |
|
196 |
|
} |
|
197 |
|
} |
|
198 |
|
|
|
199 |
|
static void |
|
200 |
|
hb_shape_plan_plan(hb_shape_plan_t *shape_plan, |
|
201 |
|
const hb_feature_t *user_features, |
|
202 |
|
unsigned num_user_features, |
|
203 |
|
const char * const *shaper_list) |
|
204 |
|
{ |
|
205 |
|
struct hb_shaper_pair_t *shapers = hb_shapers_get(); |
|
206 |
|
|
|
207 |
|
if (!shaper_list) { |
|
208 |
|
for (unsigned i = 0; i < HB_SHAPERS_COUNT; ++i) |
|
209 |
|
if (0) |
|
210 |
|
; |
|
211 |
|
#ifdef HAVE_GRAPHITE2 |
|
212 |
|
else if (shapers[i].func == hb_graphite2_shape) { |
|
213 |
|
if (hb_graphite2_shaper_face_data_ensure(shape_plan->face)) { |
|
214 |
|
shape_plan->shaper_data.graphite2 = |
|
215 |
|
hb_graphite2_shaper_shape_plan_data_create(shape_plan, |
|
216 |
|
user_features, |
|
217 |
|
num_user_features); |
|
218 |
|
shape_plan->shaper_func = hb_graphite2_shape; |
|
219 |
|
shape_plan->shaper_name ="graphite2"; |
|
220 |
|
return; |
|
221 |
|
} |
|
222 |
|
} |
|
223 |
|
#endif |
|
224 |
|
#ifdef HAVE_OT |
|
225 |
|
else if (shapers[i].func == hb_ot_shape) { |
|
226 |
|
if (hb_ot_shaper_face_data_ensure(shape_plan->face)) { |
|
227 |
|
shape_plan->shaper_data.ot = hb_ot_shaper_shape_plan_data_create( |
|
228 |
|
shape_plan, |
|
229 |
|
user_features, |
|
230 |
|
num_user_features); |
|
231 |
|
shape_plan->shaper_func = hb_ot_shape; |
|
232 |
|
shape_plan->shaper_name ="ot"; |
|
233 |
|
return; |
|
234 |
|
} |
|
235 |
|
} |
|
236 |
|
#endif |
|
237 |
|
else if (shapers[i].func == hb_fallback_shape) { |
|
238 |
|
if (hb_fallback_shaper_face_data_ensure(shape_plan->face)) { |
|
239 |
|
shape_plan->shaper_data.fallback = |
|
240 |
|
hb_fallback_shaper_shape_plan_data_create(shape_plan, |
|
241 |
|
user_features, |
|
242 |
|
num_user_features); |
|
243 |
|
shape_plan->shaper_func = hb_fallback_shape; |
|
244 |
|
shape_plan->shaper_name = "fallback"; |
|
245 |
|
return; |
|
246 |
|
} |
|
247 |
|
} |
|
248 |
|
} else { |
|
249 |
|
for (; *shaper_list; ++shaper_list) |
|
250 |
|
if (0) |
|
251 |
|
; |
|
252 |
|
#ifdef HAVE_GRAPHITE2 |
|
253 |
|
else if (0 == strcmp(*shaper_list, "graphite2")) { |
|
254 |
|
if (hb_graphite2_shaper_face_data_ensure(shape_plan->face)) { |
|
255 |
|
shape_plan->shaper_data.graphite2 = |
|
256 |
|
hb_graphite2_shaper_shape_plan_data_create(shape_plan, |
|
257 |
|
user_features, |
|
258 |
|
num_user_features); |
|
259 |
|
shape_plan->shaper_func = hb_graphite2_shape; |
|
260 |
|
shape_plan->shaper_name = "graphite2"; |
|
261 |
|
return; |
|
262 |
|
} |
|
263 |
|
} |
|
264 |
|
#endif |
|
265 |
|
#ifdef HAVE_OT |
|
266 |
|
else if (0 == strcmp(*shaper_list, "ot")) { |
|
267 |
|
if (hb_ot_shaper_face_data_ensure(shape_plan->face)) { |
|
268 |
|
shape_plan->shaper_data.ot = hb_ot_shaper_shape_plan_data_create( |
|
269 |
|
shape_plan, |
|
270 |
|
user_features, |
|
271 |
|
num_user_features); |
|
272 |
|
shape_plan->shaper_func = hb_ot_shape; |
|
273 |
|
shape_plan->shaper_name = "ot"; |
|
274 |
|
return; |
|
275 |
|
} |
|
276 |
|
} |
|
277 |
|
#endif |
|
278 |
|
else if (0 == strcmp(*shaper_list, "fallback")) { |
|
279 |
|
if (hb_fallback_shaper_face_data_ensure(shape_plan->face)) { |
|
280 |
|
shape_plan->shaper_data.fallback = |
|
281 |
|
hb_fallback_shaper_shape_plan_data_create(shape_plan, |
|
282 |
|
user_features, |
|
283 |
|
num_user_features); |
|
284 |
|
shape_plan->shaper_func = hb_fallback_shape; |
|
285 |
|
shape_plan->shaper_name = "fallback"; |
|
286 |
|
return; |
|
287 |
|
} |
|
288 |
|
} |
|
289 |
|
} |
|
290 |
|
} |
|
291 |
|
|
|
292 |
|
hb_shape_plan_t * |
|
293 |
|
hb_shape_plan_create(hb_face_t *face, |
|
294 |
|
const hb_segment_properties_t *props, |
|
295 |
|
const hb_feature_t *user_features, |
|
296 |
|
unsigned int num_user_features, |
|
297 |
|
const char * const *shaper_list) |
|
298 |
|
{ |
|
299 |
|
assert(props->direction != HB_DIRECTION_INVALID); |
|
300 |
|
|
|
301 |
|
if (!face) |
|
302 |
|
face = hb_face_get_empty(); |
|
303 |
|
|
|
304 |
|
if (!props || hb_atomic_int32_get(&face->ref_cnt) == REF_CNT_INVALID_VAL) |
|
305 |
|
return hb_shape_plan_get_empty(); |
|
306 |
|
|
|
307 |
|
hb_shape_plan_t *shape_plan = calloc(1, sizeof(*shape_plan)); |
|
308 |
|
if (!shape_plan) |
|
309 |
|
return hb_shape_plan_get_empty(); |
|
310 |
|
hb_atomic_int32_set(&shape_plan->ref_cnt, 1); |
|
311 |
|
|
|
312 |
|
shape_plan->default_shaper_list = shaper_list == NULL; |
|
313 |
|
hb_face_make_immutable(face); |
|
314 |
|
shape_plan->face = hb_face_reference(face); |
|
315 |
|
shape_plan->props = *props; |
|
316 |
|
|
|
317 |
|
hb_shape_plan_plan(shape_plan, user_features, num_user_features, shaper_list); |
|
318 |
|
return shape_plan; |
|
319 |
|
} |
|
320 |
|
|
|
321 |
|
static hb_bool_t |
|
322 |
|
hb_shape_plan_matches(hb_shape_plan_t *shape_plan, |
|
323 |
|
struct hb_shape_plan_proposal_t *proposal) |
|
324 |
|
{ |
|
325 |
|
return hb_segment_properties_equal(&shape_plan->props, &proposal->props) && |
|
326 |
|
((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || |
|
327 |
|
(shape_plan->shaper_func == proposal->shaper_func)); |
|
328 |
|
} |
|
329 |
|
|
|
330 |
|
hb_shape_plan_t * |
|
331 |
|
hb_shape_plan_reference(hb_shape_plan_t *shape_plan) |
|
332 |
|
{ |
|
333 |
|
if (hb_atomic_int32_get(&shape_plan->ref_cnt) != REF_CNT_INVALID_VAL) |
|
334 |
|
hb_atomic_int32_add(&shape_plan->ref_cnt, 1); |
|
335 |
|
return shape_plan; |
|
336 |
|
} |
|
337 |
|
|
|
338 |
|
void |
|
339 |
|
hb_shape_plan_destroy(hb_shape_plan_t *shape_plan) |
|
340 |
|
{ |
|
341 |
|
if (!shape_plan) |
|
342 |
|
return; |
|
343 |
|
if (hb_atomic_int32_get(&shape_plan->ref_cnt) == REF_CNT_INVALID_VAL) |
|
344 |
|
return; |
|
345 |
|
hb_atomic_int32_add(&shape_plan->ref_cnt, -1); |
|
346 |
|
if (hb_atomic_int32_get(&shape_plan->ref_cnt) > 0) |
|
347 |
|
return; |
|
348 |
|
hb_atomic_int32_set(&shape_plan->ref_cnt, REF_CNT_INVALID_VAL); |
|
349 |
|
|
|
350 |
|
#ifdef HAVE_GRAPHITE2 |
|
351 |
|
if (shape_plan->shaper_data.graphite2 && |
|
352 |
|
shape_plan->shaper_data.graphite2 != HB_SHAPER_DATA_INVALID && |
|
353 |
|
shape_plan->shaper_data.graphite2 != HB_SHAPER_DATA_SUCCEEDED) |
|
354 |
|
hb_graphite2_shaper_shape_plan_data_destroy( |
|
355 |
|
shape_plan->shaper_data.graphite2); |
|
356 |
|
#endif |
|
357 |
|
#ifdef HAVE_OT |
|
358 |
|
if (shape_plan->shaper_data.ot && |
|
359 |
|
shape_plan->shaper_data.ot != HB_SHAPER_DATA_INVALID && |
|
360 |
|
shape_plan->shaper_data.ot != HB_SHAPER_DATA_SUCCEEDED) |
|
361 |
|
hb_ot_shaper_shape_plan_data_destroy(shape_plan->shaper_data.ot); |
|
362 |
|
#endif |
|
363 |
|
if (shape_plan->shaper_data.fallback && |
|
364 |
|
shape_plan->shaper_data.fallback != HB_SHAPER_DATA_INVALID && |
|
365 |
|
shape_plan->shaper_data.fallback != HB_SHAPER_DATA_SUCCEEDED) |
|
366 |
|
hb_fallback_shaper_shape_plan_data_destroy( |
|
367 |
|
shape_plan->shaper_data.fallback); |
|
368 |
|
|
|
369 |
|
hb_face_destroy(shape_plan->face); |
|
370 |
|
free(shape_plan); |
|
371 |
|
} |
|
372 |
|
|
|
373 |
|
hb_shape_plan_t * |
|
374 |
|
hb_shape_plan_create_cached(hb_face_t *face, |
|
375 |
|
const hb_segment_properties_t *props, |
|
376 |
|
const hb_feature_t *user_features, |
|
377 |
|
unsigned int num_user_features, |
|
378 |
|
const char * const *shaper_list) |
|
379 |
|
{ |
|
380 |
|
if (num_user_features) |
|
381 |
|
return hb_shape_plan_create(face, props, user_features, num_user_features, |
|
382 |
|
shaper_list); |
|
383 |
|
|
|
384 |
|
struct hb_shape_plan_proposal_t proposal = { |
|
385 |
|
*props, |
|
386 |
|
shaper_list, |
|
387 |
|
NULL |
|
388 |
|
}; |
|
389 |
|
|
|
390 |
|
if (shaper_list) { |
|
391 |
|
//Choose shaper. Adapted from hb_shape_plan_plan(). |
|
392 |
|
for (const char * const *shaper_item = shaper_list; *shaper_item; |
|
393 |
|
shaper_item++) |
|
394 |
|
if (0) |
|
395 |
|
; |
|
396 |
|
#ifdef HAVE_GRAPHITE2 |
|
397 |
|
else if (0 == strcmp(*shaper_item, "graphite2")) { |
|
398 |
|
if (hb_graphite2_shaper_face_data_ensure(face)) |
|
399 |
|
proposal.shaper_func = hb_graphite2_shape; |
|
400 |
|
} |
|
401 |
|
#endif |
|
402 |
|
#ifdef HAVE_OT |
|
403 |
|
else if (0 == strcmp(*shaper_item, "ot")) { |
|
404 |
|
if (hb_ot_shaper_face_data_ensure(face)) |
|
405 |
|
proposal.shaper_func = hb_ot_shape; |
|
406 |
|
} |
|
407 |
|
#endif |
|
408 |
|
else if (0 == strcmp(*shaper_item, "fallback")) { |
|
409 |
|
if (hb_fallback_shaper_face_data_ensure(face)) |
|
410 |
|
proposal.shaper_func = hb_fallback_shape; |
|
411 |
|
} |
|
412 |
|
|
|
413 |
|
if (!proposal.shaper_list) |
|
414 |
|
return hb_shape_plan_get_empty(); |
|
415 |
|
} |
|
416 |
|
|
|
417 |
|
struct plan_node_t *cached_plan_nodes = hb_atomic_ptr_get(&face->shape_plans); |
|
418 |
|
hb_shape_plan_t *shape_plan; |
|
419 |
|
while (1) { |
|
420 |
|
for (struct plan_node_t *node = cached_plan_nodes; node; node = node->next) |
|
421 |
|
if (hb_shape_plan_matches(node->shape_plan, &proposal)) |
|
422 |
|
return hb_shape_plan_reference(node->shape_plan); |
|
423 |
|
|
|
424 |
|
//Not found. |
|
425 |
|
|
|
426 |
|
shape_plan = hb_shape_plan_create(face, props, user_features, |
|
427 |
|
num_user_features, shaper_list); |
|
428 |
|
|
|
429 |
|
struct plan_node_t *node = calloc(1, sizeof(*node)); |
|
430 |
|
if (!node) |
|
431 |
|
return shape_plan; |
|
432 |
|
|
|
433 |
|
node->shape_plan = shape_plan; |
|
434 |
|
node->next = cached_plan_nodes; |
|
435 |
|
|
|
436 |
|
if (hb_atomic_ptr_cmpexch(&face->shape_plans, &cached_plan_nodes, &node)) |
|
437 |
|
break; |
|
438 |
|
|
|
439 |
|
hb_shape_plan_destroy(shape_plan); |
|
440 |
|
free(node); |
|
441 |
|
} |
|
442 |
|
|
|
443 |
|
//Release our reference on face. |
|
444 |
|
hb_face_destroy(face); |
|
445 |
|
return hb_shape_plan_reference(shape_plan); |
|
446 |
|
} |
|
447 |
|
|
|
448 |
|
hb_bool_t |
|
449 |
|
hb_shape_plan_execute(hb_shape_plan_t *shape_plan, |
|
450 |
|
hb_font_t *font, |
|
451 |
|
hb_buffer_t *buffer, |
|
452 |
|
const hb_feature_t *features, |
|
453 |
|
unsigned num_features) |
|
454 |
|
{ |
|
455 |
|
if (hb_atomic_int32_get(&shape_plan->ref_cnt) == REF_CNT_INVALID_VAL |
|
456 |
|
|| hb_atomic_int32_get(&font->ref_cnt) == REF_CNT_INVALID_VAL |
|
457 |
|
|| hb_atomic_int32_get(&buffer->ref_cnt) == REF_CNT_INVALID_VAL) |
|
458 |
|
return FALSE; |
|
459 |
|
|
|
460 |
|
assert(shape_plan->face == font->face); |
|
461 |
|
assert(hb_segment_properties_equal(&shape_plan->props, &buffer->props)); |
|
462 |
|
|
|
463 |
|
if (0) |
|
464 |
|
; |
|
465 |
|
#ifdef HAVE_GRAPHITE2 |
|
466 |
|
else if (shape_plan->shaper_func == hb_graphite2_shape) |
|
467 |
|
return shape_plan->shaper_data.graphite2 |
|
468 |
|
&& hb_graphite2_shaper_font_data_ensure(font) |
|
469 |
|
&& hb_graphite2_shape(shape_plan, font, buffer, features, |
|
470 |
|
num_features); |
|
471 |
|
#endif |
|
472 |
|
#ifdef HAVE_OT |
|
473 |
|
else if (shape_plan->shaper_func == hb_ot_shape) |
|
474 |
|
return shape_plan->shaper_data.ot |
|
475 |
|
&& hb_ot_shaper_font_data_ensure(font) |
|
476 |
|
&& hb_ot_shape(shape_plan, font, buffer, features, num_features); |
|
477 |
|
#endif |
|
478 |
|
else if (shape_plan->shaper_func == hb_fallback_shape) |
|
479 |
|
return shape_plan->shaper_data.fallback |
|
480 |
|
&& hb_fallback_shaper_font_data_ensure(font) |
|
481 |
|
&& hb_fallback_shape(shape_plan, font, buffer, features, |
|
482 |
|
num_features); |
|
483 |
|
return FALSE; |
|
484 |
|
} |
|
485 |
|
|
File hb-unicode.c added (mode: 100644) (index 0000000..462ddc1) |
|
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> |
|
5 |
|
|
|
6 |
|
#include "hb.h" |
|
7 |
|
#include "hb-private.h" |
|
8 |
|
#include "hb-atomic-private.h" |
|
9 |
|
#include "hb-unicode-private.h" |
|
10 |
|
|
|
11 |
|
static hb_unicode_combining_class_t |
|
12 |
|
hb_unicode_combining_class_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
13 |
|
hb_codepoint_t unicode HB_UNUSED, |
|
14 |
|
void *user_data HB_UNUSED) |
|
15 |
|
{ |
|
16 |
|
return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED; |
|
17 |
|
} |
|
18 |
|
|
|
19 |
|
static unsigned int |
|
20 |
|
hb_unicode_eastasian_width_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
21 |
|
hb_codepoint_t unicode HB_UNUSED, |
|
22 |
|
void *user_data HB_UNUSED) |
|
23 |
|
{ |
|
24 |
|
return 1; |
|
25 |
|
} |
|
26 |
|
|
|
27 |
|
static hb_unicode_general_category_t |
|
28 |
|
hb_unicode_general_category_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
29 |
|
hb_codepoint_t unicode HB_UNUSED, |
|
30 |
|
void *user_data HB_UNUSED) |
|
31 |
|
{ |
|
32 |
|
return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER; |
|
33 |
|
} |
|
34 |
|
|
|
35 |
|
static hb_codepoint_t |
|
36 |
|
hb_unicode_mirroring_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
37 |
|
hb_codepoint_t unicode HB_UNUSED, |
|
38 |
|
void *user_data HB_UNUSED) |
|
39 |
|
{ |
|
40 |
|
return unicode; |
|
41 |
|
} |
|
42 |
|
|
|
43 |
|
static hb_script_t |
|
44 |
|
hb_unicode_script_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
45 |
|
hb_codepoint_t unicode HB_UNUSED, |
|
46 |
|
void *user_data HB_UNUSED) |
|
47 |
|
{ |
|
48 |
|
return HB_SCRIPT_UNKNOWN; |
|
49 |
|
} |
|
50 |
|
|
|
51 |
|
static hb_bool_t |
|
52 |
|
hb_unicode_compose_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
53 |
|
hb_codepoint_t a HB_UNUSED, |
|
54 |
|
hb_codepoint_t b HB_UNUSED, |
|
55 |
|
hb_codepoint_t *ab HB_UNUSED, |
|
56 |
|
void *user_data HB_UNUSED) |
|
57 |
|
{ |
|
58 |
|
return FALSE; |
|
59 |
|
} |
|
60 |
|
|
|
61 |
|
static hb_bool_t |
|
62 |
|
hb_unicode_decompose_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
63 |
|
hb_codepoint_t ab HB_UNUSED, |
|
64 |
|
hb_codepoint_t *a HB_UNUSED, |
|
65 |
|
hb_codepoint_t *b HB_UNUSED, |
|
66 |
|
void *user_data HB_UNUSED) |
|
67 |
|
{ |
|
68 |
|
return FALSE; |
|
69 |
|
} |
|
70 |
|
|
|
71 |
|
static unsigned int |
|
72 |
|
hb_unicode_decompose_compatibility_nil(hb_unicode_funcs_t *ufuncs HB_UNUSED, |
|
73 |
|
hb_codepoint_t u HB_UNUSED, |
|
74 |
|
hb_codepoint_t *decomposed HB_UNUSED, |
|
75 |
|
void *user_data HB_UNUSED) |
|
76 |
|
{ |
|
77 |
|
return 0; |
|
78 |
|
} |
|
79 |
|
|
|
80 |
|
//must be public |
|
81 |
|
hb_unicode_funcs_t _hb_unicode_funcs_nil = { |
|
82 |
|
REF_CNT_INVALID_VAL,//ref_cnt |
|
83 |
|
NULL,//parent |
|
84 |
|
TRUE,//immutable |
|
85 |
|
{//func |
|
86 |
|
hb_unicode_combining_class_nil, |
|
87 |
|
hb_unicode_eastasian_width_nil, |
|
88 |
|
hb_unicode_general_category_nil, |
|
89 |
|
hb_unicode_mirroring_nil, |
|
90 |
|
hb_unicode_script_nil, |
|
91 |
|
hb_unicode_compose_nil, |
|
92 |
|
hb_unicode_decompose_nil, |
|
93 |
|
hb_unicode_decompose_compatibility_nil |
|
94 |
|
}, |
|
95 |
|
{//user_data |
|
96 |
|
NULL,//combining_class |
|
97 |
|
NULL,//eastasian_width |
|
98 |
|
NULL,//general_category |
|
99 |
|
NULL,//mirroring |
|
100 |
|
NULL,//script |
|
101 |
|
NULL,//compose |
|
102 |
|
NULL,//decompose |
|
103 |
|
NULL//decompose_compatibility |
|
104 |
|
}, |
|
105 |
|
{//destroy |
|
106 |
|
NULL,//combining_class |
|
107 |
|
NULL,//eastasian_width |
|
108 |
|
NULL,//general_category |
|
109 |
|
NULL,//mirroring |
|
110 |
|
NULL,//script |
|
111 |
|
NULL,//compose |
|
112 |
|
NULL,//decompose |
|
113 |
|
NULL//decompose_compatibility |
|
114 |
|
} |
|
115 |
|
}; |
|
116 |
|
|
|
117 |
|
//Default_Ignorable codepoints: |
|
118 |
|
// |
|
119 |
|
//Note that as of Oct 2012 (Unicode 6.2), U+180E MONGOLIAN VOWEL SEPARATOR |
|
120 |
|
//is NOT Default_Ignorable, but it really behaves in a way that it should |
|
121 |
|
//be. That has been reported to the Unicode Technical Committee for |
|
122 |
|
//consideration. As such, we include it here, since Uniscribe removes it. |
|
123 |
|
//It *is* in Unicode 6.3 however. U+061C ARABIC LETTER MARK from Unicode |
|
124 |
|
//6.3 is also added manually. The new Unicode 6.3 bidi formatting |
|
125 |
|
//characters are encoded in a block that was Default_Ignorable already. |
|
126 |
|
// |
|
127 |
|
//Note: While U+115F and U+1160 are Default_Ignorable, we do NOT want to |
|
128 |
|
//hide them, as the way Uniscribe has implemented them is with regular |
|
129 |
|
//spacing glyphs, and that's the way fonts are made to work. As such, |
|
130 |
|
//we make exceptions for those two. |
|
131 |
|
// |
|
132 |
|
//Gathered from: |
|
133 |
|
//http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:DI:]&abb=on&ucd=on&esc=on |
|
134 |
|
// |
|
135 |
|
//Last updated to the page with the following versions: |
|
136 |
|
//Version 3.6; ICU version: 50.0.1.0; Unicode version: 6.1.0.0 |
|
137 |
|
// |
|
138 |
|
//4,167 Code Points |
|
139 |
|
// |
|
140 |
|
//[\u00AD\u034F\u115F\u1160\u17B4\u17B5\u180B-\u180D\u200B-\u200F\u202A-\u202E\u2060-\u206F\u3164\uFE00-\uFE0F\uFEFF\uFFA0\uFFF0-\uFFF8\U0001D173-\U0001D17A\U000E0000-\U000E0FFF] |
|
141 |
|
// |
|
142 |
|
//00AD ;SOFT HYPHEN |
|
143 |
|
//034F ;COMBINING GRAPHEME JOINER |
|
144 |
|
//#115F ;HANGUL CHOSEONG FILLER |
|
145 |
|
//#1160 ;HANGUL JUNGSEONG FILLER |
|
146 |
|
//17B4 ;KHMER VOWEL INHERENT AQ |
|
147 |
|
//17B5 ;KHMER VOWEL INHERENT AA |
|
148 |
|
//180B..180D ;MONGOLIAN FREE VARIATION SELECTOR THREE |
|
149 |
|
//200B..200F ;RIGHT-TO-LEFT MARK |
|
150 |
|
//202A..202E ;RIGHT-TO-LEFT OVERRIDE |
|
151 |
|
//2060..206F ;NOMINAL DIGIT SHAPES |
|
152 |
|
//3164 ;HANGUL FILLER |
|
153 |
|
//FE00..FE0F ;VARIATION SELECTOR-16 |
|
154 |
|
//FEFF ;ZERO WIDTH NO-BREAK SPACE |
|
155 |
|
//FFA0 ;HALFWIDTH HANGUL FILLER |
|
156 |
|
//FFF0..FFF8 ;<unassigned-FFF8> |
|
157 |
|
//1D173..1D17A ;MUSICAL SYMBOL END PHRASE |
|
158 |
|
//E0000..E0FFF ;<unassigned-E0FFF> |
|
159 |
|
|
|
160 |
|
hb_bool_t |
|
161 |
|
hb_unicode_is_default_ignorable(hb_codepoint_t ch) |
|
162 |
|
{ |
|
163 |
|
hb_codepoint_t plane = ch >> 16; |
|
164 |
|
if (plane == 0) { |
|
165 |
|
//BMP |
|
166 |
|
hb_codepoint_t page = ch >> 8; |
|
167 |
|
switch (page) { |
|
168 |
|
case 0x00: return ch == 0x00AD; |
|
169 |
|
case 0x03: return ch == 0x034F; |
|
170 |
|
case 0x06: return ch == 0x061C; |
|
171 |
|
case 0x17: return hb_codepoint_in_range(ch, 0x17B4, 0x17B5); |
|
172 |
|
case 0x18: return hb_codepoint_in_range(ch, 0x180B, 0x180E); |
|
173 |
|
case 0x20: return hb_codepoint_in_ranges(ch, 0x200B, 0x200F, |
|
174 |
|
0x202A, 0x202E, |
|
175 |
|
0x2060, 0x206F); |
|
176 |
|
case 0x31: return ch == 0x3164; |
|
177 |
|
case 0xFE: return hb_codepoint_in_range(ch, 0xFE00, 0xFE0F) || ch == 0xFEFF; |
|
178 |
|
case 0xFF: return hb_codepoint_in_range(ch, 0xFFF0, 0xFFF8) || ch == 0xFFA0; |
|
179 |
|
default: return FALSE; |
|
180 |
|
} |
|
181 |
|
} else { |
|
182 |
|
//Other planes |
|
183 |
|
switch (plane) { |
|
184 |
|
case 0x01: return hb_codepoint_in_range(ch, 0x0001D173, 0x0001D17A); |
|
185 |
|
case 0x0E: return hb_codepoint_in_range(ch, 0x000E0000, 0x000E0FFF); |
|
186 |
|
default: return FALSE; |
|
187 |
|
} |
|
188 |
|
} |
|
189 |
|
} |
|
190 |
|
|
|
191 |
|
hb_unicode_funcs_t * |
|
192 |
|
hb_unicode_funcs_get_empty(void) |
|
193 |
|
{ |
|
194 |
|
return &_hb_unicode_funcs_nil; |
|
195 |
|
} |
|
196 |
|
|
|
197 |
|
hb_unicode_funcs_t * |
|
198 |
|
hb_unicode_funcs_reference(hb_unicode_funcs_t *ufuncs) |
|
199 |
|
{ |
|
200 |
|
if (hb_atomic_int32_get(&ufuncs->ref_cnt) != REF_CNT_INVALID_VAL) |
|
201 |
|
hb_atomic_int32_add(&ufuncs->ref_cnt, 1); |
|
202 |
|
return ufuncs; |
|
203 |
|
} |
|
204 |
|
|
|
205 |
|
extern hb_unicode_funcs_t *hb_glib_get_unicode_funcs(void); |
|
206 |
|
extern hb_unicode_funcs_t *hb_nil_get_unicode_funcs(void); |
|
207 |
|
|
|
208 |
|
hb_unicode_funcs_t * |
|
209 |
|
hb_unicode_funcs_get_default(void) |
|
210 |
|
{ |
|
211 |
|
#ifdef HAVE_GLIB |
|
212 |
|
return hb_glib_get_unicode_funcs(); |
|
213 |
|
#else |
|
214 |
|
return hb_unicode_funcs_get_empty(); |
|
215 |
|
#endif |
|
216 |
|
} |
|
217 |
|
|
|
218 |
|
void |
|
219 |
|
hb_unicode_funcs_destroy(hb_unicode_funcs_t *ufuncs) |
|
220 |
|
{ |
|
221 |
|
if (!ufuncs) |
|
222 |
|
return; |
|
223 |
|
if (hb_atomic_int32_get(&ufuncs->ref_cnt) == REF_CNT_INVALID_VAL) |
|
224 |
|
return; |
|
225 |
|
hb_atomic_int32_add(&ufuncs->ref_cnt, -1); |
|
226 |
|
if (hb_atomic_int32_get(&ufuncs->ref_cnt) > 0) |
|
227 |
|
return; |
|
228 |
|
hb_atomic_int32_set(&ufuncs->ref_cnt, REF_CNT_INVALID_VAL); |
|
229 |
|
|
|
230 |
|
if (ufuncs->destroy.combining_class) |
|
231 |
|
ufuncs->destroy.combining_class(ufuncs->user_data.combining_class); |
|
232 |
|
if (ufuncs->destroy.eastasian_width) |
|
233 |
|
ufuncs->destroy.eastasian_width(ufuncs->user_data.eastasian_width); |
|
234 |
|
if (ufuncs->destroy.general_category) |
|
235 |
|
ufuncs->destroy.general_category(ufuncs->user_data.general_category); |
|
236 |
|
if (ufuncs->destroy.mirroring) |
|
237 |
|
ufuncs->destroy.mirroring(ufuncs->user_data.mirroring); |
|
238 |
|
if (ufuncs->destroy.script) |
|
239 |
|
ufuncs->destroy.script(ufuncs->user_data.script); |
|
240 |
|
if (ufuncs->destroy.compose) |
|
241 |
|
ufuncs->destroy.compose(ufuncs->user_data.compose); |
|
242 |
|
if (ufuncs->destroy.decompose) |
|
243 |
|
ufuncs->destroy.decompose(ufuncs->user_data.decompose); |
|
244 |
|
if (ufuncs->destroy.decompose_compatibility) |
|
245 |
|
ufuncs->destroy.decompose_compatibility( |
|
246 |
|
ufuncs->user_data.decompose_compatibility); |
|
247 |
|
|
|
248 |
|
hb_unicode_funcs_destroy(ufuncs->parent); |
|
249 |
|
free (ufuncs); |
|
250 |
|
} |
File hb-unicode.h added (mode: 100644) (index 0000000..1c4e097) |
|
1 |
|
/* |
|
2 |
|
* Copyright © 2009 Red Hat, Inc. |
|
3 |
|
* Copyright © 2011 Codethink Limited |
|
4 |
|
* Copyright © 2011,2012 Google, Inc. |
|
5 |
|
* |
|
6 |
|
* This is part of HarfBuzz, a text shaping library. |
|
7 |
|
* |
|
8 |
|
* Permission is hereby granted, without written agreement and without |
|
9 |
|
* license or royalty fees, to use, copy, modify, and distribute this |
|
10 |
|
* software and its documentation for any purpose, provided that the |
|
11 |
|
* above copyright notice and the following two paragraphs appear in |
|
12 |
|
* all copies of this software. |
|
13 |
|
* |
|
14 |
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
|
15 |
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
|
16 |
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
|
17 |
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
|
18 |
|
* DAMAGE. |
|
19 |
|
* |
|
20 |
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
|
21 |
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
|
22 |
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
|
23 |
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
|
24 |
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
|
25 |
|
* |
|
26 |
|
* Red Hat Author(s): Behdad Esfahbod |
|
27 |
|
* Codethink Author(s): Ryan Lortie |
|
28 |
|
* Google Author(s): Behdad Esfahbod |
|
29 |
|
*/ |
|
30 |
|
|
|
31 |
|
#ifndef HB_H_IN |
|
32 |
|
#error "Include <hb.h> instead." |
|
33 |
|
#endif |
|
34 |
|
|
|
35 |
|
#ifndef HB_UNICODE_H |
|
36 |
|
#define HB_UNICODE_H |
|
37 |
|
|
|
38 |
|
#include "hb-common.h" |
|
39 |
|
|
|
40 |
|
HB_BEGIN_DECLS |
|
41 |
|
|
|
42 |
|
|
|
43 |
|
/* hb_unicode_general_category_t */ |
|
44 |
|
|
|
45 |
|
/* Unicode Character Database property: General_Category (gc) */ |
|
46 |
|
typedef enum |
|
47 |
|
{ |
|
48 |
|
HB_UNICODE_GENERAL_CATEGORY_CONTROL, /* Cc */ |
|
49 |
|
HB_UNICODE_GENERAL_CATEGORY_FORMAT, /* Cf */ |
|
50 |
|
HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED, /* Cn */ |
|
51 |
|
HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE, /* Co */ |
|
52 |
|
HB_UNICODE_GENERAL_CATEGORY_SURROGATE, /* Cs */ |
|
53 |
|
HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER, /* Ll */ |
|
54 |
|
HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER, /* Lm */ |
|
55 |
|
HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER, /* Lo */ |
|
56 |
|
HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER, /* Lt */ |
|
57 |
|
HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER, /* Lu */ |
|
58 |
|
HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK, /* Mc */ |
|
59 |
|
HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK, /* Me */ |
|
60 |
|
HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK, /* Mn */ |
|
61 |
|
HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER, /* Nd */ |
|
62 |
|
HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER, /* Nl */ |
|
63 |
|
HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER, /* No */ |
|
64 |
|
HB_UNICODE_GENERAL_CATEGORY_CONNECT_PUNCTUATION, /* Pc */ |
|
65 |
|
HB_UNICODE_GENERAL_CATEGORY_DASH_PUNCTUATION, /* Pd */ |
|
66 |
|
HB_UNICODE_GENERAL_CATEGORY_CLOSE_PUNCTUATION, /* Pe */ |
|
67 |
|
HB_UNICODE_GENERAL_CATEGORY_FINAL_PUNCTUATION, /* Pf */ |
|
68 |
|
HB_UNICODE_GENERAL_CATEGORY_INITIAL_PUNCTUATION, /* Pi */ |
|
69 |
|
HB_UNICODE_GENERAL_CATEGORY_OTHER_PUNCTUATION, /* Po */ |
|
70 |
|
HB_UNICODE_GENERAL_CATEGORY_OPEN_PUNCTUATION, /* Ps */ |
|
71 |
|
HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL, /* Sc */ |
|
72 |
|
HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL, /* Sk */ |
|
73 |
|
HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL, /* Sm */ |
|
74 |
|
HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL, /* So */ |
|
75 |
|
HB_UNICODE_GENERAL_CATEGORY_LINE_SEPARATOR, /* Zl */ |
|
76 |
|
HB_UNICODE_GENERAL_CATEGORY_PARAGRAPH_SEPARATOR, /* Zp */ |
|
77 |
|
HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR /* Zs */ |
|
78 |
|
} hb_unicode_general_category_t; |
|
79 |
|
|
|
80 |
|
/* hb_unicode_combining_class_t */ |
|
81 |
|
|
|
82 |
|
/* Note: newer versions of Unicode may add new values. Clients should be ready to handle |
|
83 |
|
* any value in the 0..254 range being returned from hb_unicode_combining_class(). |
|
84 |
|
*/ |
|
85 |
|
|
|
86 |
|
/* Unicode Character Database property: Canonical_Combining_Class (ccc) */ |
|
87 |
|
typedef enum |
|
88 |
|
{ |
|
89 |
|
HB_UNICODE_COMBINING_CLASS_NOT_REORDERED = 0, |
|
90 |
|
HB_UNICODE_COMBINING_CLASS_OVERLAY = 1, |
|
91 |
|
HB_UNICODE_COMBINING_CLASS_NUKTA = 7, |
|
92 |
|
HB_UNICODE_COMBINING_CLASS_KANA_VOICING = 8, |
|
93 |
|
HB_UNICODE_COMBINING_CLASS_VIRAMA = 9, |
|
94 |
|
|
|
95 |
|
/* Hebrew */ |
|
96 |
|
HB_UNICODE_COMBINING_CLASS_CCC10 = 10, |
|
97 |
|
HB_UNICODE_COMBINING_CLASS_CCC11 = 11, |
|
98 |
|
HB_UNICODE_COMBINING_CLASS_CCC12 = 12, |
|
99 |
|
HB_UNICODE_COMBINING_CLASS_CCC13 = 13, |
|
100 |
|
HB_UNICODE_COMBINING_CLASS_CCC14 = 14, |
|
101 |
|
HB_UNICODE_COMBINING_CLASS_CCC15 = 15, |
|
102 |
|
HB_UNICODE_COMBINING_CLASS_CCC16 = 16, |
|
103 |
|
HB_UNICODE_COMBINING_CLASS_CCC17 = 17, |
|
104 |
|
HB_UNICODE_COMBINING_CLASS_CCC18 = 18, |
|
105 |
|
HB_UNICODE_COMBINING_CLASS_CCC19 = 19, |
|
106 |
|
HB_UNICODE_COMBINING_CLASS_CCC20 = 20, |
|
107 |
|
HB_UNICODE_COMBINING_CLASS_CCC21 = 21, |
|
108 |
|
HB_UNICODE_COMBINING_CLASS_CCC22 = 22, |
|
109 |
|
HB_UNICODE_COMBINING_CLASS_CCC23 = 23, |
|
110 |
|
HB_UNICODE_COMBINING_CLASS_CCC24 = 24, |
|
111 |
|
HB_UNICODE_COMBINING_CLASS_CCC25 = 25, |
|
112 |
|
HB_UNICODE_COMBINING_CLASS_CCC26 = 26, |
|
113 |
|
|
|
114 |
|
/* Arabic */ |
|
115 |
|
HB_UNICODE_COMBINING_CLASS_CCC27 = 27, |
|
116 |
|
HB_UNICODE_COMBINING_CLASS_CCC28 = 28, |
|
117 |
|
HB_UNICODE_COMBINING_CLASS_CCC29 = 29, |
|
118 |
|
HB_UNICODE_COMBINING_CLASS_CCC30 = 30, |
|
119 |
|
HB_UNICODE_COMBINING_CLASS_CCC31 = 31, |
|
120 |
|
HB_UNICODE_COMBINING_CLASS_CCC32 = 32, |
|
121 |
|
HB_UNICODE_COMBINING_CLASS_CCC33 = 33, |
|
122 |
|
HB_UNICODE_COMBINING_CLASS_CCC34 = 34, |
|
123 |
|
HB_UNICODE_COMBINING_CLASS_CCC35 = 35, |
|
124 |
|
|
|
125 |
|
/* Syriac */ |
|
126 |
|
HB_UNICODE_COMBINING_CLASS_CCC36 = 36, |
|
127 |
|
|
|
128 |
|
/* Telugu */ |
|
129 |
|
HB_UNICODE_COMBINING_CLASS_CCC84 = 84, |
|
130 |
|
HB_UNICODE_COMBINING_CLASS_CCC91 = 91, |
|
131 |
|
|
|
132 |
|
/* Thai */ |
|
133 |
|
HB_UNICODE_COMBINING_CLASS_CCC103 = 103, |
|
134 |
|
HB_UNICODE_COMBINING_CLASS_CCC107 = 107, |
|
135 |
|
|
|
136 |
|
/* Lao */ |
|
137 |
|
HB_UNICODE_COMBINING_CLASS_CCC118 = 118, |
|
138 |
|
HB_UNICODE_COMBINING_CLASS_CCC122 = 122, |
|
139 |
|
|
|
140 |
|
/* Tibetan */ |
|
141 |
|
HB_UNICODE_COMBINING_CLASS_CCC129 = 129, |
|
142 |
|
HB_UNICODE_COMBINING_CLASS_CCC130 = 130, |
|
143 |
|
HB_UNICODE_COMBINING_CLASS_CCC133 = 132, |
|
144 |
|
|
|
145 |
|
|
|
146 |
|
HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT = 200, |
|
147 |
|
HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW = 202, |
|
148 |
|
HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE = 214, |
|
149 |
|
HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT = 216, |
|
150 |
|
HB_UNICODE_COMBINING_CLASS_BELOW_LEFT = 218, |
|
151 |
|
HB_UNICODE_COMBINING_CLASS_BELOW = 220, |
|
152 |
|
HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT = 222, |
|
153 |
|
HB_UNICODE_COMBINING_CLASS_LEFT = 224, |
|
154 |
|
HB_UNICODE_COMBINING_CLASS_RIGHT = 226, |
|
155 |
|
HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT = 228, |
|
156 |
|
HB_UNICODE_COMBINING_CLASS_ABOVE = 230, |
|
157 |
|
HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT = 232, |
|
158 |
|
HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW = 233, |
|
159 |
|
HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE = 234, |
|
160 |
|
|
|
161 |
|
HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT = 240, |
|
162 |
|
|
|
163 |
|
HB_UNICODE_COMBINING_CLASS_INVALID = 255 |
|
164 |
|
} hb_unicode_combining_class_t; |
|
165 |
|
|
|
166 |
|
|
|
167 |
|
/* |
|
168 |
|
* hb_unicode_funcs_t |
|
169 |
|
*/ |
|
170 |
|
|
|
171 |
|
typedef struct hb_unicode_funcs_t hb_unicode_funcs_t; |
|
172 |
|
|
|
173 |
|
|
|
174 |
|
/* |
|
175 |
|
* just give me the best implementation you've got there. |
|
176 |
|
*/ |
|
177 |
|
hb_unicode_funcs_t * |
|
178 |
|
hb_unicode_funcs_get_default (void); |
|
179 |
|
|
|
180 |
|
|
|
181 |
|
hb_unicode_funcs_t * |
|
182 |
|
hb_unicode_funcs_create (hb_unicode_funcs_t *parent); |
|
183 |
|
|
|
184 |
|
hb_unicode_funcs_t * |
|
185 |
|
hb_unicode_funcs_get_empty (void); |
|
186 |
|
|
|
187 |
|
hb_unicode_funcs_t * |
|
188 |
|
hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs); |
|
189 |
|
|
|
190 |
|
void |
|
191 |
|
hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs); |
|
192 |
|
|
|
193 |
|
hb_bool_t |
|
194 |
|
hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, |
|
195 |
|
hb_user_data_key_t *key, |
|
196 |
|
void * data, |
|
197 |
|
hb_destroy_func_t destroy, |
|
198 |
|
hb_bool_t replace); |
|
199 |
|
|
|
200 |
|
|
|
201 |
|
void * |
|
202 |
|
hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs, |
|
203 |
|
hb_user_data_key_t *key); |
|
204 |
|
|
|
205 |
|
|
|
206 |
|
void |
|
207 |
|
hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs); |
|
208 |
|
|
|
209 |
|
hb_bool_t |
|
210 |
|
hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs); |
|
211 |
|
|
|
212 |
|
hb_unicode_funcs_t * |
|
213 |
|
hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs); |
|
214 |
|
|
|
215 |
|
|
|
216 |
|
/* |
|
217 |
|
* funcs |
|
218 |
|
*/ |
|
219 |
|
|
|
220 |
|
/* typedefs */ |
|
221 |
|
|
|
222 |
|
typedef hb_unicode_combining_class_t (*hb_unicode_combining_class_func_t) (hb_unicode_funcs_t *ufuncs, |
|
223 |
|
hb_codepoint_t unicode, |
|
224 |
|
void *user_data); |
|
225 |
|
typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t *ufuncs, |
|
226 |
|
hb_codepoint_t unicode, |
|
227 |
|
void *user_data); |
|
228 |
|
typedef hb_unicode_general_category_t (*hb_unicode_general_category_func_t) (hb_unicode_funcs_t *ufuncs, |
|
229 |
|
hb_codepoint_t unicode, |
|
230 |
|
void *user_data); |
|
231 |
|
typedef hb_codepoint_t (*hb_unicode_mirroring_func_t) (hb_unicode_funcs_t *ufuncs, |
|
232 |
|
hb_codepoint_t unicode, |
|
233 |
|
void *user_data); |
|
234 |
|
typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs, |
|
235 |
|
hb_codepoint_t unicode, |
|
236 |
|
void *user_data); |
|
237 |
|
|
|
238 |
|
typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs, |
|
239 |
|
hb_codepoint_t a, |
|
240 |
|
hb_codepoint_t b, |
|
241 |
|
hb_codepoint_t *ab, |
|
242 |
|
void *user_data); |
|
243 |
|
typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, |
|
244 |
|
hb_codepoint_t ab, |
|
245 |
|
hb_codepoint_t *a, |
|
246 |
|
hb_codepoint_t *b, |
|
247 |
|
void *user_data); |
|
248 |
|
|
|
249 |
|
/** |
|
250 |
|
* hb_unicode_decompose_compatibility_func_t: |
|
251 |
|
* @ufuncs: a Unicode function structure |
|
252 |
|
* @u: codepoint to decompose |
|
253 |
|
* @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into |
|
254 |
|
* @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() |
|
255 |
|
* |
|
256 |
|
* Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed. |
|
257 |
|
* The complete length of the decomposition will be returned. |
|
258 |
|
* |
|
259 |
|
* If @u has no compatibility decomposition, zero should be returned. |
|
260 |
|
* |
|
261 |
|
* The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any |
|
262 |
|
* compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations |
|
263 |
|
* of this function type must ensure that they do not write past the provided array. |
|
264 |
|
* |
|
265 |
|
* Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available. |
|
266 |
|
*/ |
|
267 |
|
typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_funcs_t *ufuncs, |
|
268 |
|
hb_codepoint_t u, |
|
269 |
|
hb_codepoint_t *decomposed, |
|
270 |
|
void *user_data); |
|
271 |
|
|
|
272 |
|
/* See Unicode 6.1 for details on the maximum decomposition length. */ |
|
273 |
|
#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */ |
|
274 |
|
|
|
275 |
|
/* setters */ |
|
276 |
|
|
|
277 |
|
/** |
|
278 |
|
* hb_unicode_funcs_set_combining_class_func: |
|
279 |
|
* @ufuncs: a Unicode function structure |
|
280 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
281 |
|
* @user_data: |
|
282 |
|
* @destroy: |
|
283 |
|
* |
|
284 |
|
* |
|
285 |
|
* |
|
286 |
|
* Since: 1.0 |
|
287 |
|
**/ |
|
288 |
|
void |
|
289 |
|
hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, |
|
290 |
|
hb_unicode_combining_class_func_t func, |
|
291 |
|
void *user_data, hb_destroy_func_t destroy); |
|
292 |
|
|
|
293 |
|
/** |
|
294 |
|
* hb_unicode_funcs_set_eastasian_width_func: |
|
295 |
|
* @ufuncs: a Unicode function structure |
|
296 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
297 |
|
* @user_data: |
|
298 |
|
* @destroy: |
|
299 |
|
* |
|
300 |
|
* |
|
301 |
|
* |
|
302 |
|
* Since: 1.0 |
|
303 |
|
**/ |
|
304 |
|
void |
|
305 |
|
hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, |
|
306 |
|
hb_unicode_eastasian_width_func_t func, |
|
307 |
|
void *user_data, hb_destroy_func_t destroy); |
|
308 |
|
|
|
309 |
|
/** |
|
310 |
|
* hb_unicode_funcs_set_general_category_func: |
|
311 |
|
* @ufuncs: a Unicode function structure |
|
312 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
313 |
|
* @user_data: |
|
314 |
|
* @destroy: |
|
315 |
|
* |
|
316 |
|
* |
|
317 |
|
* |
|
318 |
|
* Since: 1.0 |
|
319 |
|
**/ |
|
320 |
|
void |
|
321 |
|
hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, |
|
322 |
|
hb_unicode_general_category_func_t func, |
|
323 |
|
void *user_data, hb_destroy_func_t destroy); |
|
324 |
|
|
|
325 |
|
/** |
|
326 |
|
* hb_unicode_funcs_set_mirroring_func: |
|
327 |
|
* @ufuncs: a Unicode function structure |
|
328 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
329 |
|
* @user_data: |
|
330 |
|
* @destroy: |
|
331 |
|
* |
|
332 |
|
* |
|
333 |
|
* |
|
334 |
|
* Since: 1.0 |
|
335 |
|
**/ |
|
336 |
|
void |
|
337 |
|
hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, |
|
338 |
|
hb_unicode_mirroring_func_t func, |
|
339 |
|
void *user_data, hb_destroy_func_t destroy); |
|
340 |
|
|
|
341 |
|
/** |
|
342 |
|
* hb_unicode_funcs_set_script_func: |
|
343 |
|
* @ufuncs: a Unicode function structure |
|
344 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
345 |
|
* @user_data: |
|
346 |
|
* @destroy: |
|
347 |
|
* |
|
348 |
|
* |
|
349 |
|
* |
|
350 |
|
* Since: 1.0 |
|
351 |
|
**/ |
|
352 |
|
void |
|
353 |
|
hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, |
|
354 |
|
hb_unicode_script_func_t func, |
|
355 |
|
void *user_data, hb_destroy_func_t destroy); |
|
356 |
|
|
|
357 |
|
/** |
|
358 |
|
* hb_unicode_funcs_set_compose_func: |
|
359 |
|
* @ufuncs: a Unicode function structure |
|
360 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
361 |
|
* @user_data: |
|
362 |
|
* @destroy: |
|
363 |
|
* |
|
364 |
|
* |
|
365 |
|
* |
|
366 |
|
* Since: 1.0 |
|
367 |
|
**/ |
|
368 |
|
void |
|
369 |
|
hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, |
|
370 |
|
hb_unicode_compose_func_t func, |
|
371 |
|
void *user_data, hb_destroy_func_t destroy); |
|
372 |
|
|
|
373 |
|
/** |
|
374 |
|
* hb_unicode_funcs_set_decompose_func: |
|
375 |
|
* @ufuncs: a Unicode function structure |
|
376 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
377 |
|
* @user_data: |
|
378 |
|
* @destroy: |
|
379 |
|
* |
|
380 |
|
* |
|
381 |
|
* |
|
382 |
|
* Since: 1.0 |
|
383 |
|
**/ |
|
384 |
|
void |
|
385 |
|
hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t *ufuncs, |
|
386 |
|
hb_unicode_decompose_func_t func, |
|
387 |
|
void *user_data, hb_destroy_func_t destroy); |
|
388 |
|
|
|
389 |
|
/** |
|
390 |
|
* hb_unicode_funcs_set_decompose_compatibility_func: |
|
391 |
|
* @ufuncs: a Unicode function structure |
|
392 |
|
* @func: (closure user_data) (destroy destroy) (scope notified): |
|
393 |
|
* @user_data: |
|
394 |
|
* @destroy: |
|
395 |
|
* |
|
396 |
|
* |
|
397 |
|
* |
|
398 |
|
* Since: 1.0 |
|
399 |
|
**/ |
|
400 |
|
void |
|
401 |
|
hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs, |
|
402 |
|
hb_unicode_decompose_compatibility_func_t func, |
|
403 |
|
void *user_data, hb_destroy_func_t destroy); |
|
404 |
|
|
|
405 |
|
/* accessors */ |
|
406 |
|
|
|
407 |
|
hb_unicode_combining_class_t |
|
408 |
|
hb_unicode_combining_class (hb_unicode_funcs_t *ufuncs, |
|
409 |
|
hb_codepoint_t unicode); |
|
410 |
|
|
|
411 |
|
unsigned int |
|
412 |
|
hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, |
|
413 |
|
hb_codepoint_t unicode); |
|
414 |
|
|
|
415 |
|
hb_unicode_general_category_t |
|
416 |
|
hb_unicode_general_category (hb_unicode_funcs_t *ufuncs, |
|
417 |
|
hb_codepoint_t unicode); |
|
418 |
|
|
|
419 |
|
hb_codepoint_t |
|
420 |
|
hb_unicode_mirroring (hb_unicode_funcs_t *ufuncs, |
|
421 |
|
hb_codepoint_t unicode); |
|
422 |
|
|
|
423 |
|
hb_script_t |
|
424 |
|
hb_unicode_script (hb_unicode_funcs_t *ufuncs, |
|
425 |
|
hb_codepoint_t unicode); |
|
426 |
|
|
|
427 |
|
hb_bool_t |
|
428 |
|
hb_unicode_compose (hb_unicode_funcs_t *ufuncs, |
|
429 |
|
hb_codepoint_t a, |
|
430 |
|
hb_codepoint_t b, |
|
431 |
|
hb_codepoint_t *ab); |
|
432 |
|
hb_bool_t |
|
433 |
|
hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, |
|
434 |
|
hb_codepoint_t ab, |
|
435 |
|
hb_codepoint_t *a, |
|
436 |
|
hb_codepoint_t *b); |
|
437 |
|
|
|
438 |
|
unsigned int |
|
439 |
|
hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, |
|
440 |
|
hb_codepoint_t u, |
|
441 |
|
hb_codepoint_t *decomposed); |
|
442 |
|
|
|
443 |
|
HB_END_DECLS |
|
444 |
|
|
|
445 |
|
#endif /* HB_UNICODE_H */ |
File license.md added (mode: 100644) (index 0000000..65c5ca8) |
|
1 |
|
GNU LESSER GENERAL PUBLIC LICENSE |
|
2 |
|
Version 3, 29 June 2007 |
|
3 |
|
|
|
4 |
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
|
5 |
|
Everyone is permitted to copy and distribute verbatim copies |
|
6 |
|
of this license document, but changing it is not allowed. |
|
7 |
|
|
|
8 |
|
|
|
9 |
|
This version of the GNU Lesser General Public License incorporates |
|
10 |
|
the terms and conditions of version 3 of the GNU General Public |
|
11 |
|
License, supplemented by the additional permissions listed below. |
|
12 |
|
|
|
13 |
|
0. Additional Definitions. |
|
14 |
|
|
|
15 |
|
As used herein, "this License" refers to version 3 of the GNU Lesser |
|
16 |
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU |
|
17 |
|
General Public License. |
|
18 |
|
|
|
19 |
|
"The Library" refers to a covered work governed by this License, |
|
20 |
|
other than an Application or a Combined Work as defined below. |
|
21 |
|
|
|
22 |
|
An "Application" is any work that makes use of an interface provided |
|
23 |
|
by the Library, but which is not otherwise based on the Library. |
|
24 |
|
Defining a subclass of a class defined by the Library is deemed a mode |
|
25 |
|
of using an interface provided by the Library. |
|
26 |
|
|
|
27 |
|
A "Combined Work" is a work produced by combining or linking an |
|
28 |
|
Application with the Library. The particular version of the Library |
|
29 |
|
with which the Combined Work was made is also called the "Linked |
|
30 |
|
Version". |
|
31 |
|
|
|
32 |
|
The "Minimal Corresponding Source" for a Combined Work means the |
|
33 |
|
Corresponding Source for the Combined Work, excluding any source code |
|
34 |
|
for portions of the Combined Work that, considered in isolation, are |
|
35 |
|
based on the Application, and not on the Linked Version. |
|
36 |
|
|
|
37 |
|
The "Corresponding Application Code" for a Combined Work means the |
|
38 |
|
object code and/or source code for the Application, including any data |
|
39 |
|
and utility programs needed for reproducing the Combined Work from the |
|
40 |
|
Application, but excluding the System Libraries of the Combined Work. |
|
41 |
|
|
|
42 |
|
1. Exception to Section 3 of the GNU GPL. |
|
43 |
|
|
|
44 |
|
You may convey a covered work under sections 3 and 4 of this License |
|
45 |
|
without being bound by section 3 of the GNU GPL. |
|
46 |
|
|
|
47 |
|
2. Conveying Modified Versions. |
|
48 |
|
|
|
49 |
|
If you modify a copy of the Library, and, in your modifications, a |
|
50 |
|
facility refers to a function or data to be supplied by an Application |
|
51 |
|
that uses the facility (other than as an argument passed when the |
|
52 |
|
facility is invoked), then you may convey a copy of the modified |
|
53 |
|
version: |
|
54 |
|
|
|
55 |
|
a) under this License, provided that you make a good faith effort to |
|
56 |
|
ensure that, in the event an Application does not supply the |
|
57 |
|
function or data, the facility still operates, and performs |
|
58 |
|
whatever part of its purpose remains meaningful, or |
|
59 |
|
|
|
60 |
|
b) under the GNU GPL, with none of the additional permissions of |
|
61 |
|
this License applicable to that copy. |
|
62 |
|
|
|
63 |
|
3. Object Code Incorporating Material from Library Header Files. |
|
64 |
|
|
|
65 |
|
The object code form of an Application may incorporate material from |
|
66 |
|
a header file that is part of the Library. You may convey such object |
|
67 |
|
code under terms of your choice, provided that, if the incorporated |
|
68 |
|
material is not limited to numerical parameters, data structure |
|
69 |
|
layouts and accessors, or small macros, inline functions and templates |
|
70 |
|
(ten or fewer lines in length), you do both of the following: |
|
71 |
|
|
|
72 |
|
a) Give prominent notice with each copy of the object code that the |
|
73 |
|
Library is used in it and that the Library and its use are |
|
74 |
|
covered by this License. |
|
75 |
|
|
|
76 |
|
b) Accompany the object code with a copy of the GNU GPL and this license |
|
77 |
|
document. |
|
78 |
|
|
|
79 |
|
4. Combined Works. |
|
80 |
|
|
|
81 |
|
You may convey a Combined Work under terms of your choice that, |
|
82 |
|
taken together, effectively do not restrict modification of the |
|
83 |
|
portions of the Library contained in the Combined Work and reverse |
|
84 |
|
engineering for debugging such modifications, if you also do each of |
|
85 |
|
the following: |
|
86 |
|
|
|
87 |
|
a) Give prominent notice with each copy of the Combined Work that |
|
88 |
|
the Library is used in it and that the Library and its use are |
|
89 |
|
covered by this License. |
|
90 |
|
|
|
91 |
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license |
|
92 |
|
document. |
|
93 |
|
|
|
94 |
|
c) For a Combined Work that displays copyright notices during |
|
95 |
|
execution, include the copyright notice for the Library among |
|
96 |
|
these notices, as well as a reference directing the user to the |
|
97 |
|
copies of the GNU GPL and this license document. |
|
98 |
|
|
|
99 |
|
d) Do one of the following: |
|
100 |
|
|
|
101 |
|
0) Convey the Minimal Corresponding Source under the terms of this |
|
102 |
|
License, and the Corresponding Application Code in a form |
|
103 |
|
suitable for, and under terms that permit, the user to |
|
104 |
|
recombine or relink the Application with a modified version of |
|
105 |
|
the Linked Version to produce a modified Combined Work, in the |
|
106 |
|
manner specified by section 6 of the GNU GPL for conveying |
|
107 |
|
Corresponding Source. |
|
108 |
|
|
|
109 |
|
1) Use a suitable shared library mechanism for linking with the |
|
110 |
|
Library. A suitable mechanism is one that (a) uses at run time |
|
111 |
|
a copy of the Library already present on the user's computer |
|
112 |
|
system, and (b) will operate properly with a modified version |
|
113 |
|
of the Library that is interface-compatible with the Linked |
|
114 |
|
Version. |
|
115 |
|
|
|
116 |
|
e) Provide Installation Information, but only if you would otherwise |
|
117 |
|
be required to provide such information under section 6 of the |
|
118 |
|
GNU GPL, and only to the extent that such information is |
|
119 |
|
necessary to install and execute a modified version of the |
|
120 |
|
Combined Work produced by recombining or relinking the |
|
121 |
|
Application with a modified version of the Linked Version. (If |
|
122 |
|
you use option 4d0, the Installation Information must accompany |
|
123 |
|
the Minimal Corresponding Source and Corresponding Application |
|
124 |
|
Code. If you use option 4d1, you must provide the Installation |
|
125 |
|
Information in the manner specified by section 6 of the GNU GPL |
|
126 |
|
for conveying Corresponding Source.) |
|
127 |
|
|
|
128 |
|
5. Combined Libraries. |
|
129 |
|
|
|
130 |
|
You may place library facilities that are a work based on the |
|
131 |
|
Library side by side in a single library together with other library |
|
132 |
|
facilities that are not Applications and are not covered by this |
|
133 |
|
License, and convey such a combined library under terms of your |
|
134 |
|
choice, if you do both of the following: |
|
135 |
|
|
|
136 |
|
a) Accompany the combined library with a copy of the same work based |
|
137 |
|
on the Library, uncombined with any other library facilities, |
|
138 |
|
conveyed under the terms of this License. |
|
139 |
|
|
|
140 |
|
b) Give prominent notice with the combined library that part of it |
|
141 |
|
is a work based on the Library, and explaining where to find the |
|
142 |
|
accompanying uncombined form of the same work. |
|
143 |
|
|
|
144 |
|
6. Revised Versions of the GNU Lesser General Public License. |
|
145 |
|
|
|
146 |
|
The Free Software Foundation may publish revised and/or new versions |
|
147 |
|
of the GNU Lesser General Public License from time to time. Such new |
|
148 |
|
versions will be similar in spirit to the present version, but may |
|
149 |
|
differ in detail to address new problems or concerns. |
|
150 |
|
|
|
151 |
|
Each version is given a distinguishing version number. If the |
|
152 |
|
Library as you received it specifies that a certain numbered version |
|
153 |
|
of the GNU Lesser General Public License "or any later version" |
|
154 |
|
applies to it, you have the option of following the terms and |
|
155 |
|
conditions either of that published version or of any later version |
|
156 |
|
published by the Free Software Foundation. If the Library as you |
|
157 |
|
received it does not specify a version number of the GNU Lesser |
|
158 |
|
General Public License, you may choose any version of the GNU Lesser |
|
159 |
|
General Public License ever published by the Free Software Foundation. |
|
160 |
|
|
|
161 |
|
If the Library as you received it specifies that a proxy can decide |
|
162 |
|
whether future versions of the GNU Lesser General Public License shall |
|
163 |
|
apply, that proxy's public statement of acceptance of any version is |
|
164 |
|
permanent authorization for you to choose that version for the |
|
165 |
|
Library. |