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