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)
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#pragma message("Could not find any Unicode functions implementation, you have to provide your own.")
150#pragma message("To suppress this warnings, define HB_NO_UNICODE_FUNCS.")
151#endif
152
153hb_unicode_funcs_t *
154hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
155{
156  hb_unicode_funcs_t *ufuncs;
157
158  if (!(ufuncs = hb_object_create<hb_unicode_funcs_t> ()))
159    return hb_unicode_funcs_get_empty ();
160
161  if (!parent)
162    parent = hb_unicode_funcs_get_empty ();
163
164  hb_unicode_funcs_make_immutable (parent);
165  ufuncs->parent = hb_unicode_funcs_reference (parent);
166
167  ufuncs->func = parent->func;
168
169  /* We can safely copy user_data from parent since we hold a reference
170   * onto it and it's immutable.  We should not copy the destroy notifiers
171   * though. */
172  ufuncs->user_data = parent->user_data;
173
174  return ufuncs;
175}
176
177
178const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
179  HB_OBJECT_HEADER_STATIC,
180
181  NULL, /* parent */
182  true, /* immutable */
183  {
184#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
185    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
186#undef HB_UNICODE_FUNC_IMPLEMENT
187  }
188};
189
190hb_unicode_funcs_t *
191hb_unicode_funcs_get_empty (void)
192{
193  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
194}
195
196hb_unicode_funcs_t *
197hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs)
198{
199  return hb_object_reference (ufuncs);
200}
201
202void
203hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
204{
205  if (!hb_object_destroy (ufuncs)) return;
206
207#define HB_UNICODE_FUNC_IMPLEMENT(name) \
208  if (ufuncs->destroy.name) ufuncs->destroy.name (ufuncs->user_data.name);
209    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
210#undef HB_UNICODE_FUNC_IMPLEMENT
211
212  hb_unicode_funcs_destroy (ufuncs->parent);
213
214  free (ufuncs);
215}
216
217hb_bool_t
218hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
219			        hb_user_data_key_t *key,
220			        void *              data,
221			        hb_destroy_func_t   destroy,
222				hb_bool_t           replace)
223{
224  return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
225}
226
227void *
228hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
229			        hb_user_data_key_t *key)
230{
231  return hb_object_get_user_data (ufuncs, key);
232}
233
234
235void
236hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
237{
238  if (hb_object_is_inert (ufuncs))
239    return;
240
241  ufuncs->immutable = true;
242}
243
244hb_bool_t
245hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
246{
247  return ufuncs->immutable;
248}
249
250hb_unicode_funcs_t *
251hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs)
252{
253  return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
254}
255
256
257#define HB_UNICODE_FUNC_IMPLEMENT(name)						\
258										\
259void										\
260hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t		   *ufuncs,	\
261				    hb_unicode_##name##_func_t	    func,	\
262				    void			   *user_data,	\
263				    hb_destroy_func_t		    destroy)	\
264{										\
265  if (ufuncs->immutable)							\
266    return;									\
267										\
268  if (ufuncs->destroy.name)							\
269    ufuncs->destroy.name (ufuncs->user_data.name);				\
270										\
271  if (func) {									\
272    ufuncs->func.name = func;							\
273    ufuncs->user_data.name = user_data;						\
274    ufuncs->destroy.name = destroy;						\
275  } else {									\
276    ufuncs->func.name = ufuncs->parent->func.name;				\
277    ufuncs->user_data.name = ufuncs->parent->user_data.name;			\
278    ufuncs->destroy.name = NULL;						\
279  }										\
280}
281
282HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
283#undef HB_UNICODE_FUNC_IMPLEMENT
284
285
286#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name)				\
287										\
288return_type									\
289hb_unicode_##name (hb_unicode_funcs_t *ufuncs,					\
290		   hb_codepoint_t      unicode)					\
291{										\
292  return ufuncs->name (unicode);						\
293}
294HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
295#undef HB_UNICODE_FUNC_IMPLEMENT
296
297hb_bool_t
298hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
299		    hb_codepoint_t      a,
300		    hb_codepoint_t      b,
301		    hb_codepoint_t     *ab)
302{
303  return ufuncs->compose (a, b, ab);
304}
305
306hb_bool_t
307hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
308		      hb_codepoint_t      ab,
309		      hb_codepoint_t     *a,
310		      hb_codepoint_t     *b)
311{
312  return ufuncs->decompose (ab, a, b);
313}
314
315unsigned int
316hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
317				    hb_codepoint_t      u,
318				    hb_codepoint_t     *decomposed)
319{
320  return ufuncs->decompose_compatibility (u, decomposed);
321}
322
323
324/* See hb-unicode-private.hh for details. */
325const uint8_t
326_hb_modified_combining_class[256] =
327{
328  0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */
329  1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */
330  2, 3, 4, 5, 6,
331  7, /* HB_UNICODE_COMBINING_CLASS_NUKTA */
332  8, /* HB_UNICODE_COMBINING_CLASS_KANA_VOICING */
333  9, /* HB_UNICODE_COMBINING_CLASS_VIRAMA */
334
335  /* Hebrew */
336  HB_MODIFIED_COMBINING_CLASS_CCC10,
337  HB_MODIFIED_COMBINING_CLASS_CCC11,
338  HB_MODIFIED_COMBINING_CLASS_CCC12,
339  HB_MODIFIED_COMBINING_CLASS_CCC13,
340  HB_MODIFIED_COMBINING_CLASS_CCC14,
341  HB_MODIFIED_COMBINING_CLASS_CCC15,
342  HB_MODIFIED_COMBINING_CLASS_CCC16,
343  HB_MODIFIED_COMBINING_CLASS_CCC17,
344  HB_MODIFIED_COMBINING_CLASS_CCC18,
345  HB_MODIFIED_COMBINING_CLASS_CCC19,
346  HB_MODIFIED_COMBINING_CLASS_CCC20,
347  HB_MODIFIED_COMBINING_CLASS_CCC21,
348  HB_MODIFIED_COMBINING_CLASS_CCC22,
349  HB_MODIFIED_COMBINING_CLASS_CCC23,
350  HB_MODIFIED_COMBINING_CLASS_CCC24,
351  HB_MODIFIED_COMBINING_CLASS_CCC25,
352  HB_MODIFIED_COMBINING_CLASS_CCC26,
353
354  /* Arabic */
355  HB_MODIFIED_COMBINING_CLASS_CCC27,
356  HB_MODIFIED_COMBINING_CLASS_CCC28,
357  HB_MODIFIED_COMBINING_CLASS_CCC29,
358  HB_MODIFIED_COMBINING_CLASS_CCC30,
359  HB_MODIFIED_COMBINING_CLASS_CCC31,
360  HB_MODIFIED_COMBINING_CLASS_CCC32,
361  HB_MODIFIED_COMBINING_CLASS_CCC33,
362  HB_MODIFIED_COMBINING_CLASS_CCC34,
363  HB_MODIFIED_COMBINING_CLASS_CCC35,
364
365  /* Syriac */
366  HB_MODIFIED_COMBINING_CLASS_CCC36,
367
368  37, 38, 39,
369  40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
370  60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
371  80, 81, 82, 83,
372
373  /* Telugu */
374  HB_MODIFIED_COMBINING_CLASS_CCC84,
375  85, 86, 87, 88, 89, 90,
376  HB_MODIFIED_COMBINING_CLASS_CCC91,
377  92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102,
378
379  /* Thai */
380  HB_MODIFIED_COMBINING_CLASS_CCC103,
381  104, 105, 106,
382  HB_MODIFIED_COMBINING_CLASS_CCC107,
383  108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
384
385  /* Lao */
386  HB_MODIFIED_COMBINING_CLASS_CCC118,
387  119, 120, 121,
388  HB_MODIFIED_COMBINING_CLASS_CCC122,
389  123, 124, 125, 126, 127, 128,
390
391  /* Tibetan */
392  HB_MODIFIED_COMBINING_CLASS_CCC129,
393  HB_MODIFIED_COMBINING_CLASS_CCC130,
394  131,
395  HB_MODIFIED_COMBINING_CLASS_CCC132,
396  133, 134, 135, 136, 137, 138, 139,
397
398
399  140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
400  150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
401  160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
402  170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
403  180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
404  190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
405
406  200, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT */
407  201,
408  202, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW */
409  203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213,
410  214, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE */
411  215,
412  216, /* HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT */
413  217,
414  218, /* HB_UNICODE_COMBINING_CLASS_BELOW_LEFT */
415  219,
416  220, /* HB_UNICODE_COMBINING_CLASS_BELOW */
417  221,
418  222, /* HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT */
419  223,
420  224, /* HB_UNICODE_COMBINING_CLASS_LEFT */
421  225,
422  226, /* HB_UNICODE_COMBINING_CLASS_RIGHT */
423  227,
424  228, /* HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT */
425  229,
426  230, /* HB_UNICODE_COMBINING_CLASS_ABOVE */
427  231,
428  232, /* HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT */
429  233, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW */
430  234, /* HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE */
431  235, 236, 237, 238, 239,
432  240, /* HB_UNICODE_COMBINING_CLASS_IOTA_SUBSCRIPT */
433  241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
434  255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
435};
436