1 /* fribidi-arabic.c - Arabic shaping
3 * Copyright (C) 2005 Behdad Esfahbod
5 * This file is part of GNU FriBidi.
7 * GNU FriBidi is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * GNU FriBidi is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with GNU FriBidi; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * For licensing issues, contact <fribidi.license@gmail.com> or write to
22 * Sharif FarsiWeb, Inc., PO Box 13445-389, Tehran, Iran.
25 * Behdad Esfahbod, 2005
39 #include <fribidi-arabic.h>
40 #include <fribidi-unicode.h>
43 typedef struct _PairMap {
44 FriBidiChar pair[2], to;
48 #define FRIBIDI_ACCESS_SHAPE_TABLE(table,min,max,x,shape) (table), (min), (max)
49 # define FRIBIDI_ACCESS_SHAPE_TABLE_REAL(table,min,max,x,shape) \
50 (((x)<(min)||(x)>(max))?(x):(table)[(x)-(min)][(shape)])
52 #include "arabic-shaping.tab.i"
53 #include "arabic-misc.tab.i"
57 fribidi_shape_arabic_joining (
59 const FriBidiChar table[][4],
62 const FriBidiStrIndex len,
63 const FriBidiArabicProp *ar_props,
64 /* input and output */
68 register FriBidiStrIndex i;
70 for (i = 0; i < len; i++)
71 if (FRIBIDI_ARAB_SHAPES(ar_props[i]))
72 str[i] = FRIBIDI_ACCESS_SHAPE_TABLE_REAL (table, min, max, str[i], FRIBIDI_JOIN_SHAPE (ar_props[i]));
78 comp_PairMap (const void *pa, const void *pb)
80 PairMap *a = (PairMap *)pa;
81 PairMap *b = (PairMap *)pb;
83 if (a->pair[0] != b->pair[0])
84 return a->pair[0] < b->pair[0] ? -1 : +1;
86 return a->pair[1] < b->pair[1] ? -1 :
87 a->pair[1] > b->pair[1] ? +1 :
92 fribidi_bsearch (const void *key, const void *base,
93 unsigned int nmemb, unsigned int size,
94 int (*compar)(const void *_key, const void *_item))
96 int min = 0, max = (int) nmemb - 1;
99 int mid = ((unsigned int) min + (unsigned int) max) / 2;
100 const void *p = (const void *) (((const char *) base) + (mid * size));
101 int c = compar (key, p);
113 find_pair_match (const PairMap *table, int size, FriBidiChar first, FriBidiChar second)
120 match = fribidi_bsearch (&x, table, size, sizeof (table[0]), comp_PairMap);
121 return match ? match->to : 0;
124 #define PAIR_MATCH(table,len,first,second) \
125 ((first)<(table[0].pair[0])||(first)>(table[len-1].pair[0])?0: \
126 find_pair_match(table, len, first, second))
129 fribidi_shape_arabic_ligature (
131 const PairMap *table,
133 const FriBidiLevel *embedding_levels,
134 const FriBidiStrIndex len,
135 /* input and output */
136 FriBidiArabicProp *ar_props,
140 /* TODO: This doesn't form ligatures for even-level Arabic text.
141 * no big problem though. */
142 register FriBidiStrIndex i;
144 for (i = 0; i < len - 1; i++) {
145 register FriBidiChar c;
146 if (FRIBIDI_LEVEL_IS_RTL(embedding_levels[i]) &&
147 embedding_levels[i] == embedding_levels[i+1] &&
148 (c = PAIR_MATCH(table, size, str[i], str[i+1])))
150 str[i] = FRIBIDI_CHAR_FILL;
151 FRIBIDI_SET_BITS(ar_props[i], FRIBIDI_MASK_LIGATURED);
157 #define DO_LIGATURING(table, levels, len, ar_props, str) \
158 fribidi_shape_arabic_ligature ((table), sizeof(table)/sizeof((table)[0]), levels, len, ar_props, str)
160 #define DO_SHAPING(tablemacro, len, ar_props, str) \
161 fribidi_shape_arabic_joining (tablemacro(,), len, ar_props, str);
167 fribidi_shape_arabic (
170 const FriBidiLevel *embedding_levels,
171 const FriBidiStrIndex len,
172 /* input and output */
173 FriBidiArabicProp *ar_props,
177 DBG ("in fribidi_shape_arabic");
180 (len == 0 || !str) return;
182 DBG ("in fribidi_shape");
184 fribidi_assert (ar_props);
186 if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_PRES))
188 DO_SHAPING (FRIBIDI_GET_ARABIC_SHAPE_PRES, len, ar_props, str);
191 if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_LIGA))
193 DO_LIGATURING (mandatory_liga_table, embedding_levels, len, ar_props, str);
196 if (FRIBIDI_TEST_BITS (flags, FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE))
198 DO_LIGATURING (console_liga_table, embedding_levels, len, ar_props, str);
199 DO_SHAPING (FRIBIDI_GET_ARABIC_SHAPE_NSM, len, ar_props, str);
203 /* Editor directions:
207 * indent-tabs-mode: t
210 * vim: textwidth=78: autoindent: cindent: shiftwidth=2: tabstop=8: