static void fribidi_shape_arabic_ligature ( /* input */ const PairMap *table, int size, const FriBidiLevel *embedding_levels, const FriBidiStrIndex len, /* input and output */ FriBidiArabicProp *ar_props, FriBidiChar *str ) { /* TODO: This doesn't form ligatures for even-level Arabic text. * no big problem though. */ register FriBidiStrIndex i; for (i = 0; i < len - 1; i++) { register FriBidiChar c; if (FRIBIDI_LEVEL_IS_RTL(embedding_levels[i]) && embedding_levels[i] == embedding_levels[i+1] && (c = PAIR_MATCH(table, size, str[i], str[i+1]))) { str[i] = FRIBIDI_CHAR_FILL; FRIBIDI_SET_BITS(ar_props[i], FRIBIDI_MASK_LIGATURED); str[i+1] = c; } } }
FRIBIDI_ENTRY void fribidi_join_arabic ( /* input */ const FriBidiCharType *bidi_types, const FriBidiStrIndex len, const FriBidiLevel *embedding_levels, /* input and output */ FriBidiArabicProp *ar_props ) { if UNLIKELY (len == 0) return; DBG ("in fribidi_join_arabic"); fribidi_assert (bidi_types); fribidi_assert (embedding_levels); fribidi_assert (ar_props); # if DEBUG if UNLIKELY (fribidi_debug_status ()) { print_joining_types (embedding_levels, len, ar_props); } # endif /* DEBUG */ /* The joining algorithm turned out very very dirty :(. That's what happens * when you follow the standard which has never been implemented closely * before. */ /* 8.2 Arabic - Cursive Joining */ DBG ("Arabic cursive joining"); { /* The following do not need to be initialized as long as joins is * initialized to false. We just do to turn off compiler warnings. */ register FriBidiStrIndex saved = 0; register FriBidiLevel saved_level = FRIBIDI_SENTINEL; register fribidi_boolean saved_shapes = false; register FriBidiArabicProp saved_joins_following_mask = 0; register fribidi_boolean joins = false; register FriBidiStrIndex i; for (i = 0; i < len; i++) if (!FRIBIDI_IS_JOINING_TYPE_G (ar_props[i])) { register fribidi_boolean disjoin = false; register fribidi_boolean shapes = FRIBIDI_ARAB_SHAPES (ar_props[i]); register FriBidiLevel level = FRIBIDI_CONSISTENT_LEVEL (i); if (joins && !FRIBIDI_LEVELS_MATCH (saved_level, level)) { disjoin = true; joins = false; } if (!FRIBIDI_IS_JOIN_SKIPPED (ar_props[i])) { register const FriBidiArabicProp joins_preceding_mask = FRIBIDI_JOINS_PRECEDING_MASK (level); if (!joins) { if (shapes) FRIBIDI_UNSET_BITS (ar_props[i], joins_preceding_mask); } else if (!FRIBIDI_TEST_BITS (ar_props[i], joins_preceding_mask)) { disjoin = true; } else { register FriBidiStrIndex j; /* This is a FriBidi extension: we set joining properties * for skipped characters in between, so we can put NSMs on tatweel * later if we want. Useful on console for example. */ for (j = saved + 1; j < i; j++) FRIBIDI_SET_BITS (ar_props[j], joins_preceding_mask | saved_joins_following_mask); } } if (disjoin && saved_shapes) FRIBIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask); if (!FRIBIDI_IS_JOIN_SKIPPED (ar_props[i])) { saved = i; saved_level = level; saved_shapes = shapes; saved_joins_following_mask = FRIBIDI_JOINS_FOLLOWING_MASK (level); joins = FRIBIDI_TEST_BITS (ar_props[i], saved_joins_following_mask); } } if ((joins) && saved_shapes) FRIBIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask); } # if DEBUG if UNLIKELY (fribidi_debug_status ()) { print_joining_types (embedding_levels, len, ar_props); } # endif /* DEBUG */ DBG ("leaving fribidi_join_arabic"); }