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