- return ufuncs->parent;
-}
-
-
-#define IMPLEMENT(return_type, name) \
- \
-void \
-hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
- hb_unicode_get_##name##_func_t func, \
- void *user_data, \
- hb_destroy_func_t destroy) \
-{ \
- if (ufuncs->immutable) \
- return; \
- \
- if (ufuncs->destroy.name) \
- ufuncs->destroy.name (ufuncs->user_data.name); \
- \
- if (func) { \
- ufuncs->get.name = func; \
- ufuncs->user_data.name = user_data; \
- ufuncs->destroy.name = destroy; \
- } else if (ufuncs->parent != NULL) { \
- ufuncs->get.name = ufuncs->parent->get.name; \
- ufuncs->user_data.name = ufuncs->parent->user_data.name; \
- ufuncs->destroy.name = NULL; \
- } else { \
- ufuncs->get.name = hb_unicode_get_##name##_nil; \
- ufuncs->user_data.name = NULL; \
- ufuncs->destroy.name = NULL; \
- } \
-} \
- \
-return_type \
-hb_unicode_get_##name (hb_unicode_funcs_t *ufuncs, \
- hb_codepoint_t unicode) \
-{ \
- return ufuncs->get.name (ufuncs, unicode, ufuncs->user_data.name); \
-}
-
-IMPLEMENT (unsigned int, combining_class)
-IMPLEMENT (unsigned int, eastasian_width)
-IMPLEMENT (hb_unicode_general_category_t, general_category)
-IMPLEMENT (hb_codepoint_t, mirroring)
-IMPLEMENT (hb_script_t, script)
-
-#undef IMPLEMENT
-
-
-HB_END_DECLS
+ return ufuncs->parent ? ufuncs->parent : hb_unicode_funcs_get_empty ();
+}
+
+
+#define HB_UNICODE_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_unicode_funcs_set_##name##_func (hb_unicode_funcs_t *ufuncs, \
+ hb_unicode_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (ufuncs->immutable) \
+ return; \
+ \
+ if (ufuncs->destroy.name) \
+ ufuncs->destroy.name (ufuncs->user_data.name); \
+ \
+ if (func) { \
+ ufuncs->func.name = func; \
+ ufuncs->user_data.name = user_data; \
+ ufuncs->destroy.name = destroy; \
+ } else { \
+ ufuncs->func.name = ufuncs->parent->func.name; \
+ ufuncs->user_data.name = ufuncs->parent->user_data.name; \
+ ufuncs->destroy.name = NULL; \
+ } \
+}
+
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+
+#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
+ \
+return_type \
+hb_unicode_##name (hb_unicode_funcs_t *ufuncs, \
+ hb_codepoint_t unicode) \
+{ \
+ return ufuncs->func.name (ufuncs, unicode, ufuncs->user_data.name); \
+}
+ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+hb_bool_t
+hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ *ab = 0;
+ return ufuncs->func.compose (ufuncs, a, b, ab, ufuncs->user_data.compose);
+}
+
+hb_bool_t
+hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b)
+{
+ *a = ab; *b = 0;
+ return ufuncs->func.decompose (ufuncs, ab, a, b, ufuncs->user_data.decompose);
+}
+
+
+
+unsigned int
+_hb_unicode_modified_combining_class (hb_unicode_funcs_t *ufuncs,
+ hb_codepoint_t unicode)
+{
+ int c = hb_unicode_combining_class (ufuncs, unicode);
+
+ if (unlikely (hb_in_range<int> (c, 27, 33)))
+ {
+ /* Modify the combining-class to suit Arabic better. See:
+ * http://unicode.org/faq/normalization.html#8
+ * http://unicode.org/faq/normalization.html#9
+ */
+ c = c == 33 ? 27 : c + 1;
+ }
+ else if (unlikely (hb_in_range<int> (c, 10, 25)))
+ {
+ /* The equivalent fix for Hebrew is more complex.
+ *
+ * We permute the "fixed-position" classes 10-25 into the order
+ * described in the SBL Hebrew manual:
+ *
+ * http://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
+ *
+ * (as recommended by:
+ * http://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering-t6751.0.html)
+ *
+ * More details here:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
+ */
+ static const int permuted_hebrew_classes[25 - 10 + 1] = {
+ /* 10 sheva */ 22,
+ /* 11 hataf segol */ 15,
+ /* 12 hataf patah */ 16,
+ /* 13 hataf qamats */ 17,
+ /* 14 hiriq */ 23,
+ /* 15 tsere */ 18,
+ /* 16 segol */ 19,
+ /* 17 patah */ 20,
+ /* 18 qamats */ 21,
+ /* 19 holam */ 14,
+ /* 20 qubuts */ 24,
+ /* 21 dagesh */ 12,
+ /* 22 meteg */ 25,
+ /* 23 rafe */ 13,
+ /* 24 shin dot */ 10,
+ /* 25 sin dot */ 11,
+ };
+ c = permuted_hebrew_classes[c - 10];
+ }
+
+ return c;
+}
+