1/*
2 * Copyright © 2009 Red Hat, Inc.
3 * Copyright © 2011 Codethink Limited
4 * Copyright © 2010,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#include "hb.hh"
32
33#include "hb-unicode.hh"
34
35
36
37/*
38 * hb_unicode_funcs_t
39 */
40
41static hb_unicode_combining_class_t
42hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
43 hb_codepoint_t unicode HB_UNUSED,
44 void *user_data HB_UNUSED)
45{
46 return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
47}
48
49static unsigned int
50hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
51 hb_codepoint_t unicode HB_UNUSED,
52 void *user_data HB_UNUSED)
53{
54 return 1;
55}
56
57static hb_unicode_general_category_t
58hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
59 hb_codepoint_t unicode HB_UNUSED,
60 void *user_data HB_UNUSED)
61{
62 return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
63}
64
65static hb_codepoint_t
66hb_unicode_mirroring_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
67 hb_codepoint_t unicode,
68 void *user_data HB_UNUSED)
69{
70 return unicode;
71}
72
73static hb_script_t
74hb_unicode_script_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
75 hb_codepoint_t unicode HB_UNUSED,
76 void *user_data HB_UNUSED)
77{
78 return HB_SCRIPT_UNKNOWN;
79}
80
81static hb_bool_t
82hb_unicode_compose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
83 hb_codepoint_t a HB_UNUSED,
84 hb_codepoint_t b HB_UNUSED,
85 hb_codepoint_t *ab HB_UNUSED,
86 void *user_data HB_UNUSED)
87{
88 return false;
89}
90
91static hb_bool_t
92hb_unicode_decompose_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
93 hb_codepoint_t ab HB_UNUSED,
94 hb_codepoint_t *a HB_UNUSED,
95 hb_codepoint_t *b HB_UNUSED,
96 void *user_data HB_UNUSED)
97{
98 return false;
99}
100
101
102static unsigned int
103hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED,
104 hb_codepoint_t u HB_UNUSED,
105 hb_codepoint_t *decomposed HB_UNUSED,
106 void *user_data HB_UNUSED)
107{
108 return 0;
109}
110
111
112#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
113 HB_UNICODE_FUNCS_IMPLEMENT (glib) \
114 HB_UNICODE_FUNCS_IMPLEMENT (icu) \
115 HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
116 HB_UNICODE_FUNCS_IMPLEMENT (nil) \
117 /* ^--- Add new callbacks before nil */
118
119#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
120
121/* Prototype them all */
122#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
123extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
124HB_UNICODE_FUNCS_IMPLEMENT_SET
125#undef HB_UNICODE_FUNCS_IMPLEMENT
126
127
128hb_unicode_funcs_t *
129hb_unicode_funcs_get_default (void)
130{
131#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
132 return hb_##set##_get_unicode_funcs ();
133
134#if defined(HAVE_UCDN)
135 HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
136#elif defined(HAVE_GLIB)
137 HB_UNICODE_FUNCS_IMPLEMENT(glib)
138#elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
139 HB_UNICODE_FUNCS_IMPLEMENT(icu)
140#else
141#define HB_UNICODE_FUNCS_NIL 1
142 HB_UNICODE_FUNCS_IMPLEMENT(nil)
143#endif
144
145#undef HB_UNICODE_FUNCS_IMPLEMENT
146}
147
148#if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
149#error "Could not find any Unicode functions implementation, you have to provide your own"
150#error "Consider building hb-ucdn.c. If you absolutely want to build without any, check the code."
151#endif
152
153/**
154 * hb_unicode_funcs_create: (Xconstructor)
155 * @parent: (nullable):
156 *
157 *
158 *
159 * Return value: (transfer full):
160 *
161 * Since: 0.9.2
162 **/
163hb_unicode_funcs_t *
164hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
165{
166 hb_unicode_funcs_t *ufuncs;
167
168 if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
169 return hb_unicode_funcs_get_empty ();
170
171 if (!parent)
172 parent = hb_unicode_funcs_get_empty ();
173
174 hb_unicode_funcs_make_immutable (parent);
175 ufuncs->parent = hb_unicode_funcs_reference (parent);
176
177 ufuncs->func = parent->func;
178
179 /* We can safely copy user_data from parent since we hold a reference
180 * onto it and it's immutable. We should not copy the destroy notifiers
181 * though. */
182 ufuncs->user_data = parent->user_data;
183
184 return ufuncs;
185}
186
187
188DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
189{
190 HB_OBJECT_HEADER_STATIC,
191
192 nullptr, /* parent */
193 true, /* immutable */
194 {
195#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
196 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
197#undef HB_UNICODE_FUNC_IMPLEMENT
198 }
199};
200
201/**
202 * hb_unicode_funcs_get_empty:
203 *
204 *
205 *
206 * Return value: (transfer full):
207 *
208 * Since: 0.9.2
209 **/
210hb_unicode_funcs_t *
211hb_unicode_funcs_get_empty (void)
212{
213 return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
214}
215
216/**
217 * hb_unicode_funcs_reference: (skip)
218 * @ufuncs: Unicode functions.
219 *
220 *
221 *
222 * Return value: (transfer full):
223 *
224 * Since: 0.9.2
225 **/
226hb_unicode_funcs_t *
227hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
228{
229 return hb_object_reference (ufuncs);
230}
231
232/**
233 * hb_unicode_funcs_destroy: (skip)
234 * @ufuncs: Unicode functions.
235 *
236 *
237 *
238 * Since: 0.9.2
239 **/
240void
241hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
242{
243 if (!hb_object_destroy (ufuncs)) return;
244
245#define HB_UNICODE_FUNC_IMPLEMENT(name) \
246 if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
247 HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
248#undef HB_UNICODE_FUNC_IMPLEMENT
249
250 hb_unicode_funcs_destroy (ufuncs->parent);
251
252 free (ufuncs);
253}
254
255/**
256 * hb_unicode_funcs_set_user_data: (skip)
257 * @ufuncs: Unicode functions.
258 * @key:
259 * @data:
260 * @destroy:
261 * @replace:
262 *
263 *
264 *
265 * Return value:
266 *
267 * Since: 0.9.2
268 **/
269hb_bool_t
270hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
271 hb_user_data_key_t *key,
272 void * data,
273 hb_destroy_func_t destroy,
274 hb_bool_t replace)
275{
276 return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
277}
278
279/**
280 * hb_unicode_funcs_get_user_data: (skip)
281 * @ufuncs: Unicode functions.
282 * @key:
283 *
284 *
285 *
286 * Return value: (transfer none):
287 *
288 * Since: 0.9.2
289 **/
290void *
291hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
292 hb_user_data_key_t *key)
293{
294 return hb_object_get_user_data (ufuncs, key);
295}
296
297
298/**
299 * hb_unicode_funcs_make_immutable:
300 * @ufuncs: Unicode functions.
301 *
302 *
303 *
304 * Since: 0.9.2
305 **/
306void
307hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
308{
309 if (unlikely (hb_object_is_inert (ufuncs)))
310 return;
311
312 ufuncs->immutable = true;
313}
314
315/**
316 * hb_unicode_funcs_is_immutable:
317 * @ufuncs: Unicode functions.
318 *
319 *
320 *
321 * Return value:
322 *
323 * Since: 0.9.2
324 **/
325hb_bool_t
326hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
327{
328 return ufuncs->immutable;
329}
330
331/**
332 * hb_unicode_funcs_get_parent:
333 * @ufuncs: Unicode functions.
334 *
335 *
336 *
337 * Return value:
338 *
339 * Since: 0.9.2
340 **/
341hb_unicode_funcs_t *
342hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
343{
344 return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
345}
346
347
348#define HB_UNICODE_FUNC_IMPLEMENT(name) \
349 \
350void \
351hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
352 hb_unicode_##name##_func_t func, \
353 void *user_data, \
354 hb_destroy_func_t destroy) \
355{ \
356 if (ufuncs->immutable) \
357 return; \
358 \
359 if (ufuncs->destroy.name) \
360 ufuncs->destroy.name (ufuncs->user_data.name); \
361 \
362 if (func) { \
363 ufuncs->func.name = func; \
364 ufuncs->user_data.name = user_data; \
365 ufuncs->destroy.name = destroy; \
366 } else { \
367 ufuncs->func.name = ufuncs->parent->func.name; \
368 ufuncs->user_data.name = ufuncs->parent->user_data.name; \
369 ufuncs->destroy.name = nullptr; \
370 } \
371}
372
373HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
374#undef HB_UNICODE_FUNC_IMPLEMENT
375
376
377#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
378 \
379return_type \
380hb_unicode_##name (hb_unicode_funcs_t *ufuncs, \
381 hb_codepoint_t unicode) \
382{ \
383 return ufuncs->name (unicode); \
384}
385HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
386#undef HB_UNICODE_FUNC_IMPLEMENT
387
388/**
389 * hb_unicode_compose:
390 * @ufuncs: Unicode functions.
391 * @a:
392 * @b:
393 * @ab: (out):
394 *
395 *
396 *
397 * Return value:
398 *
399 * Since: 0.9.2
400 **/
401hb_bool_t
402hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
403 hb_codepoint_t a,
404 hb_codepoint_t b,
405 hb_codepoint_t *ab)
406{
407 return ufuncs->compose (a, b, ab);
408}
409
410/**
411 * hb_unicode_decompose:
412 * @ufuncs: Unicode functions.
413 * @ab:
414 * @a: (out):
415 * @b: (out):
416 *
417 *
418 *
419 * Return value:
420 *
421 * Since: 0.9.2
422 **/
423hb_bool_t
424hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
425 hb_codepoint_t ab,
426 hb_codepoint_t *a,
427 hb_codepoint_t *b)
428{
429 return ufuncs->decompose (ab, a, b);
430}
431
432/**
433 * hb_unicode_decompose_compatibility:
434 * @ufuncs: Unicode functions.
435 * @u:
436 * @decomposed: (out):
437 *
438 *
439 *
440 * Return value:
441 *
442 * Since: 0.9.2
443 **/
444unsigned int
445hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
446 hb_codepoint_t u,
447 hb_codepoint_t *decomposed)
448{
449 return ufuncs->decompose_compatibility (u, decomposed);
450}
451
452
453/* See hb-unicode.hh for details. */
454const uint8_t
455_hb_modified_combining_class[256] =
456{
457 0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */
458 1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */
459 2, 3, 4, 5, 6,
460 7, /* HB_UNICODE_COMBINING_CLASS_NUKTA */
461 8, /* HB_UNICODE_COMBINING_CLASS_KANA_VOICING */
462 9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA */
463
464 /* Hebrew */
465 HB_MODIFIED_COMBINING_CLASS_CCC10,
466 HB_MODIFIED_COMBINING_CLASS_CCC11,
467 HB_MODIFIED_COMBINING_CLASS_CCC12,
468 HB_MODIFIED_COMBINING_CLASS_CCC13,
469 HB_MODIFIED_COMBINING_CLASS_CCC14,
470 HB_MODIFIED_COMBINING_CLASS_CCC15,
471 HB_MODIFIED_COMBINING_CLASS_CCC16,
472 HB_MODIFIED_COMBINING_CLASS_CCC17,
473 HB_MODIFIED_COMBINING_CLASS_CCC18,
474 HB_MODIFIED_COMBINING_CLASS_CCC19,
475 HB_MODIFIED_COMBINING_CLASS_CCC20,
476 HB_MODIFIED_COMBINING_CLASS_CCC21,
477 HB_MODIFIED_COMBINING_CLASS_CCC22,
478 HB_MODIFIED_COMBINING_CLASS_CCC23,
479 HB_MODIFIED_COMBINING_CLASS_CCC24,
480 HB_MODIFIED_COMBINING_CLASS_CCC25,
481 HB_MODIFIED_COMBINING_CLASS_CCC26,
482
483 /* Arabic */
484 HB_MODIFIED_COMBINING_CLASS_CCC27,
485 HB_MODIFIED_COMBINING_CLASS_CCC28,
486 HB_MODIFIED_COMBINING_CLASS_CCC29,
487 HB_MODIFIED_COMBINING_CLASS_CCC30,
488 HB_MODIFIED_COMBINING_CLASS_CCC31,
489 HB_MODIFIED_COMBINING_CLASS_CCC32,
490 HB_MODIFIED_COMBINING_CLASS_CCC33,
491 HB_MODIFIED_COMBINING_CLASS_CCC34,
492 HB_MODIFIED_COMBINING_CLASS_CCC35,
493
494 /* Syriac */
495 HB_MODIFIED_COMBINING_CLASS_CCC36,
496
497 37, 38, 39,
498 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
499 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
500 80, 81, 82, 83,
501
502 /* Telugu */
503 HB_MODIFIED_COMBINING_CLASS_CCC84,
504 85, 86, 87, 88, 89, 90,
505 HB_MODIFIED_COMBINING_CLASS_CCC91,
506 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
507
508 /* Thai */
509 HB_MODIFIED_COMBINING_CLASS_CCC103,
510 104, 105, 106,
511 HB_MODIFIED_COMBINING_CLASS_CCC107,
512 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
513
514 /* Lao */
515 HB_MODIFIED_COMBINING_CLASS_CCC118,
516 119, 120, 121,
517 HB_MODIFIED_COMBINING_CLASS_CCC122,
518 123, 124, 125, 126, 127, 128,
519
520 /* Tibetan */
521 HB_MODIFIED_COMBINING_CLASS_CCC129,
522 HB_MODIFIED_COMBINING_CLASS_CCC130,
523 131,
524 HB_MODIFIED_COMBINING_CLASS_CCC132,
525 133, 134, 135, 136, 137, 138, 139,
526
527
528 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
529 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
530 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
531 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
532 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
533 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
534
535 200, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT */
536 201,
537 202, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW */
538 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
539 214, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE */
540 215,
541 216, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT */
542 217,
543 218, /* HB_UNICODE_COMBINING_CLASS_BELOW_LEFT */
544 219,
545 220, /* HB_UNICODE_COMBINING_CLASS_BELOW */
546 221,
547 222, /* HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT */
548 223,
549 224, /* HB_UNICODE_COMBINING_CLASS_LEFT */
550 225,
551 226, /* HB_UNICODE_COMBINING_CLASS_RIGHT */
552 227,
553 228, /* HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT */
554 229,
555 230, /* HB_UNICODE_COMBINING_CLASS_ABOVE */
556 231,
557 232, /* HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT */
558 233, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW */
559 234, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE */
560 235, 236, 237, 238, 239,
561 240, /* HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT */
562 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
563 255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
564};
565