8ed92d5d7da50aea881ce93adaa51d34a156bf5e
[WebKit-https.git] / WebKit / Misc.subproj / WebUnicode.m
1 /*      
2         WebUnicode.m
3         Copyright 2001, 2002, Apple Computer, Inc.
4 */
5 #import <WebKit/WebUnicode.h>
6 #import <WebCore/WebCoreUnicode.h>
7
8 #define HAVE_ICU_LIBRARY 1
9
10 #if HAVE_ICU_LIBRARY
11 #import <unicode/uchar.h>
12 #endif
13
14 static int _unicodeDigitValue(UniChar c)
15 {
16     const char *dec_row = decimal_info[WK_ROW(c)];
17     if( !dec_row )
18         return -1;
19     return dec_row[WK_CELL(c)];
20 }
21
22 static WebCoreUnicodeCategory _unicodeCategory(UniChar c)
23 {
24     return (WebCoreUnicodeCategory)(unicode_info[WK_ROW(c)][WK_CELL(c)]);
25 }
26
27 static WebCoreUnicodeDirection _unicodeDirection(UniChar c)
28 {
29     const unsigned char *rowp = _WebDirectionInfo[WK_ROW(c)];
30     
31     if(!rowp) 
32         return DirectionL;
33     return (WebCoreUnicodeDirection) ( *(rowp+WK_CELL(c)) &0x1f );
34 }
35
36 static WebCoreUnicodeJoining _unicodeJoining(UniChar c)
37 {
38     const unsigned char *rowp = _WebDirectionInfo[WK_ROW(c)];
39     if ( !rowp )
40         return JoiningOther;
41     return (WebCoreUnicodeJoining) ((*(rowp+WK_CELL(c)) >> 5) &0x3);
42 }
43
44 static WebCoreUnicodeDecomposition _unicodeDecompositionTag(UniChar c)
45 {
46     const unsigned short *r = decomposition_info[WK_ROW(c)];
47     if(!r)
48         return DecompositionSingle;
49
50     unsigned short pos = r[WK_CELL(c)];
51     if(!pos)
52         return DecompositionSingle;
53
54     return (WebCoreUnicodeDecomposition) decomposition_map[pos];
55 }
56
57 static bool _unicodeMirrored(UniChar c)
58 {
59     const unsigned char *rowp = _WebDirectionInfo[WK_ROW(c)];
60     if ( !rowp )
61         return FALSE;
62     return *(rowp+WK_CELL(c))>128;
63 }
64
65 static UniChar _unicodeMirroredChar(UniChar c)
66 {
67     if(!_unicodeMirrored(c))
68         return c;
69
70     int i;
71     for (i = 0; i < symmetricPairsSize; i ++) {
72         if (symmetricPairs[i] == c)
73           return symmetricPairs[(i%2) ? (i-1) : (i+1)];
74     }
75     return c;
76 }
77
78 static WebCoreUnicodeCombiningClass _unicodeCombiningClass (UniChar c)
79 {
80     const unsigned char *rowp = combining_info[WK_ROW(c)];
81     if ( !rowp )
82         return 0;
83     return *(rowp+WK_CELL(c));
84 }
85
86 static UniChar _unicodeLower(UniChar c)
87 {
88 #if HAVE_ICU_LIBRARY
89     return u_tolower(c);
90 #else
91     if ( _unicodeCategory(c) != Letter_Uppercase )
92         return c;
93     unsigned short lower = *( case_info[WK_ROW(c)] + WK_CELL(c) );
94     if ( lower == 0 )
95         return c;
96     return lower;
97 #endif
98 }
99
100 static UniChar _unicodeUpper(UniChar c)
101 {
102 #if HAVE_ICU_LIBRARY
103     return u_toupper(c);
104 #else
105     if ( _unicodeCategory(c) != Letter_Lowercase )
106         return c;
107     unsigned short upper = *(case_info[WK_ROW(c)]+WK_CELL(c));
108     if ( upper == 0 )
109         return c;
110     return upper;
111 #endif
112 }
113
114 static bool _unicodeIsMark(UniChar c)
115 {
116     WebCoreUnicodeCategory category = _unicodeDigitValue(c);
117     return category >= Mark_NonSpacing && category <= Mark_Enclosing;
118 }
119
120 void WebKitInitializeUnicode(void)
121 {
122     WebCoreUnicodeDigitValueFunction = _unicodeDigitValue;
123     WebCoreUnicodeCategoryFunction = _unicodeCategory;
124     WebCoreUnicodeDirectionFunction = _unicodeDirection;
125     WebCoreUnicodeJoiningFunction = _unicodeJoining;
126     WebCoreUnicodeDecompositionTagFunction = _unicodeDecompositionTag;
127     WebCoreUnicodeMirroredFunction = _unicodeMirrored;
128     WebCoreUnicodeMirroredCharFunction = _unicodeMirroredChar;
129     WebCoreUnicodeCombiningClassFunction = _unicodeCombiningClass;
130     WebCoreUnicodeLowerFunction = _unicodeLower;
131     WebCoreUnicodeUpperFunction = _unicodeUpper;
132     WebCoreDirectionInfo = _WebDirectionInfo;
133 }
134
135 // The unicode to unicode shaping codec.
136 // does only presentation forms B at the moment, but that should be enough for
137 // simple display
138 static const ushort arabicUnicodeMapping[256][2] = {
139     // base of shaped forms, and number-1 of them ( 0 for non shaping,
140     // 1 for right binding and 3 for dual binding
141
142     // These are just the glyphs available in Unicode,
143     // some characters are in R class, but have no glyphs in Unicode.
144
145     { 0x0600, 0 }, // 0x0600
146     { 0x0601, 0 }, // 0x0601
147     { 0x0602, 0 }, // 0x0602
148     { 0x0603, 0 }, // 0x0603
149     { 0x0604, 0 }, // 0x0604
150     { 0x0605, 0 }, // 0x0605
151     { 0x0606, 0 }, // 0x0606
152     { 0x0607, 0 }, // 0x0607
153     { 0x0608, 0 }, // 0x0608
154     { 0x0609, 0 }, // 0x0609
155     { 0x060A, 0 }, // 0x060A
156     { 0x060B, 0 }, // 0x060B
157     { 0x060C, 0 }, // 0x060C
158     { 0x060D, 0 }, // 0x060D
159     { 0x060E, 0 }, // 0x060E
160     { 0x060F, 0 }, // 0x060F
161
162     { 0x0610, 0 }, // 0x0610
163     { 0x0611, 0 }, // 0x0611
164     { 0x0612, 0 }, // 0x0612
165     { 0x0613, 0 }, // 0x0613
166     { 0x0614, 0 }, // 0x0614
167     { 0x0615, 0 }, // 0x0615
168     { 0x0616, 0 }, // 0x0616
169     { 0x0617, 0 }, // 0x0617
170     { 0x0618, 0 }, // 0x0618
171     { 0x0619, 0 }, // 0x0619
172     { 0x061A, 0 }, // 0x061A
173     { 0x061B, 0 }, // 0x061B
174     { 0x061C, 0 }, // 0x061C
175     { 0x061D, 0 }, // 0x061D
176     { 0x061E, 0 }, // 0x061E
177     { 0x061F, 0 }, // 0x061F
178
179     { 0x0620, 0 }, // 0x0620
180     { 0xFE80, 0 }, // 0x0621            HAMZA
181     { 0xFE81, 1 }, // 0x0622    R       ALEF WITH MADDA ABOVE
182     { 0xFE83, 1 }, // 0x0623    R       ALEF WITH HAMZA ABOVE
183     { 0xFE85, 1 }, // 0x0624    R       WAW WITH HAMZA ABOVE
184     { 0xFE87, 1 }, // 0x0625    R       ALEF WITH HAMZA BELOW
185     { 0xFE89, 3 }, // 0x0626    D       YEH WITH HAMZA ABOVE
186     { 0xFE8D, 1 }, // 0x0627    R       ALEF
187     { 0xFE8F, 3 }, // 0x0628    D       BEH
188     { 0xFE93, 1 }, // 0x0629    R       TEH MARBUTA
189     { 0xFE95, 3 }, // 0x062A    D       TEH
190     { 0xFE99, 3 }, // 0x062B    D       THEH
191     { 0xFE9D, 3 }, // 0x062C    D       JEEM
192     { 0xFEA1, 3 }, // 0x062D    D       HAH
193     { 0xFEA5, 3 }, // 0x062E    D       KHAH
194     { 0xFEA9, 1 }, // 0x062F    R       DAL
195
196     { 0xFEAB, 1 }, // 0x0630    R       THAL
197     { 0xFEAD, 1 }, // 0x0631    R       REH
198     { 0xFEAF, 1 }, // 0x0632    R       ZAIN
199     { 0xFEB1, 3 }, // 0x0633    D       SEEN
200     { 0xFEB5, 3 }, // 0x0634    D       SHEEN
201     { 0xFEB9, 3 }, // 0x0635    D       SAD
202     { 0xFEBD, 3 }, // 0x0636    D       DAD
203     { 0xFEC1, 3 }, // 0x0637    D       TAH
204     { 0xFEC5, 3 }, // 0x0638    D       ZAH
205     { 0xFEC9, 3 }, // 0x0639    D       AIN
206     { 0xFECD, 3 }, // 0x063A    D       GHAIN
207     { 0x063B, 0 }, // 0x063B
208     { 0x063C, 0 }, // 0x063C
209     { 0x063D, 0 }, // 0x063D
210     { 0x063E, 0 }, // 0x063E
211     { 0x063F, 0 }, // 0x063F
212
213     { 0x0640, 0 }, // 0x0640    C       TATWEEL // ### Join Causing, only one glyph
214     { 0xFED1, 3 }, // 0x0641    D       FEH
215     { 0xFED5, 3 }, // 0x0642    D       QAF
216     { 0xFED9, 3 }, // 0x0643    D       KAF
217     { 0xFEDD, 3 }, // 0x0644    D       LAM
218     { 0xFEE1, 3 }, // 0x0645    D       MEEM
219     { 0xFEE5, 3 }, // 0x0646    D       NOON
220     { 0xFEE9, 3 }, // 0x0647    D       HEH
221     { 0xFEED, 1 }, // 0x0648    R       WAW
222     { 0x0649, 0 }, // 0x0649            ALEF MAKSURA // ### Dual, glyphs not consecutive, handle in code.
223     { 0xFEF1, 3 }, // 0x064A    D       YEH
224     { 0x064B, 0 }, // 0x064B
225     { 0x064C, 0 }, // 0x064C
226     { 0x064D, 0 }, // 0x064D
227     { 0x064E, 0 }, // 0x064E
228     { 0x064F, 0 }, // 0x064F
229
230     { 0x0650, 0 }, // 0x0650
231     { 0x0651, 0 }, // 0x0651
232     { 0x0652, 0 }, // 0x0652
233     { 0x0653, 0 }, // 0x0653
234     { 0x0654, 0 }, // 0x0654
235     { 0x0655, 0 }, // 0x0655
236     { 0x0656, 0 }, // 0x0656
237     { 0x0657, 0 }, // 0x0657
238     { 0x0658, 0 }, // 0x0658
239     { 0x0659, 0 }, // 0x0659
240     { 0x065A, 0 }, // 0x065A
241     { 0x065B, 0 }, // 0x065B
242     { 0x065C, 0 }, // 0x065C
243     { 0x065D, 0 }, // 0x065D
244     { 0x065E, 0 }, // 0x065E
245     { 0x065F, 0 }, // 0x065F
246
247     { 0x0660, 0 }, // 0x0660
248     { 0x0661, 0 }, // 0x0661
249     { 0x0662, 0 }, // 0x0662
250     { 0x0663, 0 }, // 0x0663
251     { 0x0664, 0 }, // 0x0664
252     { 0x0665, 0 }, // 0x0665
253     { 0x0666, 0 }, // 0x0666
254     { 0x0667, 0 }, // 0x0667
255     { 0x0668, 0 }, // 0x0668
256     { 0x0669, 0 }, // 0x0669
257     { 0x066A, 0 }, // 0x066A
258     { 0x066B, 0 }, // 0x066B
259     { 0x066C, 0 }, // 0x066C
260     { 0x066D, 0 }, // 0x066D
261     { 0x066E, 0 }, // 0x066E
262     { 0x066F, 0 }, // 0x066F
263
264     { 0x0670, 0 }, // 0x0670
265     { 0xFB50, 1 }, // 0x0671    R       ALEF WASLA
266     { 0x0672, 0 }, // 0x0672
267     { 0x0673, 0 }, // 0x0673
268     { 0x0674, 0 }, // 0x0674
269     { 0x0675, 0 }, // 0x0675
270     { 0x0676, 0 }, // 0x0676
271     { 0x0677, 0 }, // 0x0677
272     { 0x0678, 0 }, // 0x0678
273     { 0xFB66, 3 }, // 0x0679    D       TTEH
274     { 0xFB5E, 3 }, // 0x067A    D       TTEHEH
275     { 0xFB52, 3 }, // 0x067B    D       BEEH
276     { 0x067C, 0 }, // 0x067C
277     { 0x067D, 0 }, // 0x067D
278     { 0xFB56, 3 }, // 0x067E    D       PEH
279     { 0xFB62, 3 }, // 0x067F    D       TEHEH
280
281     { 0xFB5A, 3 }, // 0x0680    D       BEHEH
282     { 0x0681, 0 }, // 0x0681
283     { 0x0682, 0 }, // 0x0682
284     { 0xFB76, 3 }, // 0x0683    D       NYEH
285     { 0xFB72, 3 }, // 0x0684    D       DYEH
286     { 0x0685, 0 }, // 0x0685
287     { 0xFB7A, 3 }, // 0x0686    D       TCHEH
288     { 0xFB7E, 3 }, // 0x0687    D       TCHEHEH
289     { 0xFB88, 1 }, // 0x0688    R       DDAL
290     { 0x0689, 0 }, // 0x0689
291     { 0x068A, 0 }, // 0x068A
292     { 0x068B, 0 }, // 0x068B
293     { 0xFB84, 1 }, // 0x068C    R       DAHAL
294     { 0xFB82, 1 }, // 0x068D    R       DDAHAL
295     { 0xFB86, 1 }, // 0x068E    R       DUL
296     { 0x068F, 0 }, // 0x068F
297
298     { 0x0690, 0 }, // 0x0690
299     { 0xFB8C, 1 }, // 0x0691    R       RREH
300     { 0x0692, 0 }, // 0x0692
301     { 0x0693, 0 }, // 0x0693
302     { 0x0694, 0 }, // 0x0694
303     { 0x0695, 0 }, // 0x0695
304     { 0x0696, 0 }, // 0x0696
305     { 0x0697, 0 }, // 0x0697
306     { 0xFB8A, 1 }, // 0x0698    R       JEH
307     { 0x0699, 0 }, // 0x0699
308     { 0x069A, 0 }, // 0x069A
309     { 0x069B, 0 }, // 0x069B
310     { 0x069C, 0 }, // 0x069C
311     { 0x069D, 0 }, // 0x069D
312     { 0x069E, 0 }, // 0x069E
313     { 0x069F, 0 }, // 0x069F
314
315     { 0x06A0, 0 }, // 0x06A0
316     { 0x06A1, 0 }, // 0x06A1
317     { 0x06A2, 0 }, // 0x06A2
318     { 0x06A3, 0 }, // 0x06A3
319     { 0xFB6A, 3 }, // 0x06A4    D       VEH
320     { 0x06A5, 0 }, // 0x06A5
321     { 0xFB6E, 3 }, // 0x06A6    D       PEHEH
322     { 0x06A7, 0 }, // 0x06A7
323     { 0x06A8, 0 }, // 0x06A8
324     { 0xFB8E, 3 }, // 0x06A9    D       KEHEH
325     { 0x06AA, 0 }, // 0x06AA
326     { 0x06AB, 0 }, // 0x06AB
327     { 0x06AC, 0 }, // 0x06AC
328     { 0xFBD3, 3 }, // 0x06AD    D       NG
329     { 0x06AE, 0 }, // 0x06AE
330     { 0xFB92, 3 }, // 0x06AF    D       GAF
331
332     { 0x06B0, 0 }, // 0x06B0
333     { 0xFB9A, 3 }, // 0x06B1    D       NGOEH
334     { 0x06B2, 0 }, // 0x06B2
335     { 0xFB96, 3 }, // 0x06B3    D       GUEH
336     { 0x06B4, 0 }, // 0x06B4
337     { 0x06B5, 0 }, // 0x06B5
338     { 0x06B6, 0 }, // 0x06B6
339     { 0x06B7, 0 }, // 0x06B7
340     { 0x06B8, 0 }, // 0x06B8
341     { 0x06B9, 0 }, // 0x06B9
342     { 0x06BA, 0 }, // 0x06BA
343     { 0xFBA0, 3 }, // 0x06BB    D       RNOON
344     { 0x06BC, 0 }, // 0x06BC
345     { 0x06BD, 0 }, // 0x06BD
346     { 0xFBAA, 3 }, // 0x06BE    D       HEH DOACHASHMEE
347     { 0x06BF, 0 }, // 0x06BF
348
349     { 0xFBA4, 1 }, // 0x06C0    R       HEH WITH YEH ABOVE
350     { 0xFBA6, 3 }, // 0x06C1    D       HEH GOAL
351     { 0x06C2, 0 }, // 0x06C2
352     { 0x06C3, 0 }, // 0x06C3
353     { 0x06C4, 0 }, // 0x06C4
354     { 0xFBE0, 1 }, // 0x06C5    R       KIRGHIZ OE
355     { 0xFBD9, 1 }, // 0x06C6    R       OE
356     { 0xFBD7, 1 }, // 0x06C7    R       U
357     { 0xFBDB, 1 }, // 0x06C8    R       YU
358     { 0xFBE2, 1 }, // 0x06C9    R       KIRGHIZ YU
359     { 0x06CA, 0 }, // 0x06CA
360     { 0xFBDE, 1 }, // 0x06CB    R       VE
361     { 0xFBFC, 3 }, // 0x06CC    D       FARSI YEH
362     { 0x06CD, 0 }, // 0x06CD
363     { 0x06CE, 0 }, // 0x06CE
364     { 0x06CF, 0 }, // 0x06CF
365
366     { 0xFBE4, 3 }, // 0x06D0    D       E
367     { 0x06D1, 0 }, // 0x06D1
368     { 0xFBAE, 1 }, // 0x06D2    R       YEH BARREE
369     { 0xFBB0, 1 }, // 0x06D3    R       YEH BARREE WITH HAMZA ABOVE
370     { 0x06D4, 0 }, // 0x06D4
371     { 0x06D5, 0 }, // 0x06D5
372     { 0x06D6, 0 }, // 0x06D6
373     { 0x06D7, 0 }, // 0x06D7
374     { 0x06D8, 0 }, // 0x06D8
375     { 0x06D9, 0 }, // 0x06D9
376     { 0x06DA, 0 }, // 0x06DA
377     { 0x06DB, 0 }, // 0x06DB
378     { 0x06DC, 0 }, // 0x06DC
379     { 0x06DD, 0 }, // 0x06DD
380     { 0x06DE, 0 }, // 0x06DE
381     { 0x06DF, 0 }, // 0x06DF
382
383     { 0x06E0, 0 }, // 0x06E0
384     { 0x06E1, 0 }, // 0x06E1
385     { 0x06E2, 0 }, // 0x06E2
386     { 0x06E3, 0 }, // 0x06E3
387     { 0x06E4, 0 }, // 0x06E4
388     { 0x06E5, 0 }, // 0x06E5
389     { 0x06E6, 0 }, // 0x06E6
390     { 0x06E7, 0 }, // 0x06E7
391     { 0x06E8, 0 }, // 0x06E8
392     { 0x06E9, 0 }, // 0x06E9
393     { 0x06EA, 0 }, // 0x06EA
394     { 0x06EB, 0 }, // 0x06EB
395     { 0x06EC, 0 }, // 0x06EC
396     { 0x06ED, 0 }, // 0x06ED
397     { 0x06EE, 0 }, // 0x06EE
398     { 0x06EF, 0 }, // 0x06EF
399
400     { 0x06F0, 0 }, // 0x06F0
401     { 0x06F1, 0 }, // 0x06F1
402     { 0x06F2, 0 }, // 0x06F2
403     { 0x06F3, 0 }, // 0x06F3
404     { 0x06F4, 0 }, // 0x06F4
405     { 0x06F5, 0 }, // 0x06F5
406     { 0x06F6, 0 }, // 0x06F6
407     { 0x06F7, 0 }, // 0x06F7
408     { 0x06F8, 0 }, // 0x06F8
409     { 0x06F9, 0 }, // 0x06F9
410     { 0x06FA, 0 }, // 0x06FA
411     { 0x06FB, 0 }, // 0x06FB
412     { 0x06FC, 0 }, // 0x06FC
413     { 0x06FD, 0 }, // 0x06FD
414     { 0x06FE, 0 }, // 0x06FE
415     { 0x06FF, 0 }  // 0x06FF
416 };
417
418 // the arabicUnicodeMapping does not work for U+0649 ALEF MAKSURA, this table does
419 static const ushort alefMaksura[4] = {0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9};
420
421 // this is a bit tricky. Alef always binds to the right, so the second parameter descibing the shape
422 // of the lam can be either initial of medial. So initial maps to the isolated form of the ligature,
423 // medial to the final form
424 static const ushort arabicUnicodeLamAlefMapping[6][4] = {
425     { 0xfffd, 0xfffd, 0xfef5, 0xfef6 }, // 0x622        R       Alef with Madda above
426     { 0xfffd, 0xfffd, 0xfef7, 0xfef8 }, // 0x623        R       Alef with Hamza above
427     { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x624        // Just to fill the table ;-)
428     { 0xfffd, 0xfffd, 0xfef9, 0xfefa }, // 0x625        R       Alef with Hamza below
429     { 0xfffd, 0xfffd, 0xfffd, 0xfffd }, // 0x626        // Just to fill the table ;-)
430     { 0xfffd, 0xfffd, 0xfefb, 0xfefc }  // 0x627        R       Alef
431 };
432
433 static inline int getShape( UniChar cell, int shape)
434 {
435     uint ch = ( cell != 0x49 ) ? arabicUnicodeMapping[cell][0] + shape
436                                : alefMaksura[shape] ;
437     return ch;
438 }
439
440 enum CursiveShape {
441     XIsolated,
442     XFinal,
443     XInitial,
444     XMedial
445 };
446
447 UniChar replacementUniChar = 0xfffd;
448
449 static inline const UniChar *prevChar( const UniChar *str, int stringLength, int pos )
450 {
451     pos--;
452     const UniChar *ch = str + pos;
453     while( pos > -1 ) {
454         if( !_unicodeIsMark(*ch) )
455             return ch;
456         pos--;
457         ch--;
458     }
459     return &replacementUniChar;
460 }
461
462 static inline const UniChar *nextChar( const UniChar *str, int stringLength, int pos)
463 {
464     pos++;
465     int len = stringLength;
466     const UniChar *ch = str + pos;
467     while( pos < len ) {
468         if( !_unicodeIsMark(*ch) )
469             return ch;
470         pos++;
471         ch++;
472     }
473     return &replacementUniChar;
474 }
475
476 static inline bool prevLogicalCharJoins( const UniChar *str, int stringLength, int pos)
477 {
478     return ( _unicodeJoining(*nextChar( str, stringLength, pos )) != JoiningOther );
479 }
480
481 static inline bool nextLogicalCharJoins( const UniChar *str, int stringLength, int pos)
482 {
483     int join = _unicodeJoining(*prevChar( str, stringLength, pos ));
484     return ( join == JoiningDual || join == JoiningCausing );
485 }
486
487 static int glyphVariantLogical( const UniChar *str, int stringLength, int pos)
488 {
489     int joining = _unicodeJoining(str[pos]);
490     switch ( joining ) {
491         case JoiningOther:
492         case JoiningCausing:
493             return XIsolated;
494         case JoiningRight:
495             return ( nextLogicalCharJoins( str, stringLength, pos ) ) ? XFinal : XIsolated;
496         case JoiningDual: {
497             bool right = nextLogicalCharJoins( str, stringLength, pos );
498             bool left = prevLogicalCharJoins( str, stringLength, pos );
499             return ( right ) ? ( left ? XMedial : XFinal ) : ( left ? XInitial : XIsolated );
500         }
501     }
502     return XIsolated;
503 }
504
505 static UniChar *shapeBuffer;
506 static int shapeBufSize = 0;
507
508 #define LTR 0
509 #define RTL 1
510
511 bool hasShapeForNextCharacter (const CharacterShapeIterator *iterator)
512 {
513     if (iterator->currentCharacter - iterator->run->characters >= iterator->run->to)
514         return false;
515     return true;
516 }
517
518 UniChar shapeForNextCharacter (CharacterShapeIterator *iterator)
519 {
520     const WebCoreTextRun *run = iterator->run;
521     int stringLength = run->length;
522     UniChar shapedCharacter = 0;
523     int pos = iterator->currentCharacter - run->characters;
524     
525     if (!hasShapeForNextCharacter(iterator))
526         return 0;
527     
528     UniChar currentCharacter = *iterator->currentCharacter;
529     UniChar r = WK_ROW(currentCharacter);
530     UniChar c = WK_CELL(currentCharacter);
531     if ( r != 0x06 ) {
532         if ( r == 0x20 ) {
533             switch ( c ) {
534                 case 0x0C:
535                 case 0x0D:
536                     goto skip;
537                 default:
538                     break;
539             }
540         }
541         if (_unicodeMirrored(currentCharacter))
542             shapedCharacter = _unicodeMirroredChar(currentCharacter);
543         else
544             shapedCharacter = currentCharacter;
545     } else {
546         int shape = glyphVariantLogical( run->characters, stringLength, pos );
547         ushort map;
548         switch ( c ) {
549             case 0x44: {
550                 const UniChar *pch = nextChar( run->characters, stringLength, pos );
551                 if ( WK_ROW(*pch) == 0x06 ) {
552                     switch ( WK_CELL(*pch) ) {
553                         case 0x22:
554                         case 0x23:
555                         case 0x25:
556                         case 0x27:
557                             map = arabicUnicodeLamAlefMapping[WK_CELL(*pch) - 0x22][shape];
558                             goto next;
559                         default:
560                             break;
561                     }
562                 }
563                 break;
564             }
565             case 0x22: 
566             case 0x23: 
567             case 0x25: 
568             case 0x27: 
569                 if ( *prevChar( run->characters, stringLength, pos ) == 0x0644 ) {
570                     goto skip;
571                 }
572             default:
573                 break;
574         }
575         map = getShape( c, shape );
576     next:
577         shapedCharacter = map;
578     }
579     
580 skip:
581     iterator->currentCharacter++;
582
583     return shapedCharacter;
584 }
585
586 // Assumes input characters are logically ordered.
587 bool initializeCharacterShapeIterator (CharacterShapeIterator *iterator, const WebCoreTextRun *run)
588 {
589     int len = run->to - run->from;
590     int from = run->from;
591     int stringLength = run->length;
592     const UniChar *uc = run->characters;
593     
594     if( len < 0 ) {
595         len = stringLength - from;
596     } else if( len == 0 ) {
597         return false;
598     }
599
600     int i;
601     for (i = from; i < from+len; i++){
602         if (uc[i] >= 0x591 && uc[i] <= 0x700)
603             break;
604     }
605     if (i == from+len)
606         return false;
607     
608     int num = stringLength - from - len;
609     iterator->currentCharacter = uc + from + len;
610     while ( num > 0 && _unicodeCombiningClass(*iterator->currentCharacter) != 0 ) {
611         iterator->currentCharacter++;
612         num--;
613         len++;
614     }
615
616     iterator->currentCharacter = uc + from;
617     while ( len > 0 && _unicodeCombiningClass(*iterator->currentCharacter) != 0 ) {
618         iterator->currentCharacter++;
619         len--;
620         from++;
621     }
622     if ( len == 0 )
623         return false;
624
625     if( !shapeBuffer || len > shapeBufSize ) {
626         if( shapeBuffer )
627             free( (void *) shapeBuffer );
628         shapeBuffer = (UniChar *) malloc( len*sizeof( UniChar ) );
629         shapeBufSize = len;
630     }
631     
632     iterator->currentCharacter = uc + run->from;
633     iterator->run = run;
634     
635     return true;
636 }
637
638 UniChar *shapedString(const WebCoreTextRun *run, int *lengthOut)
639 {
640     int len = run->to - run->from;
641     int from = run->from;
642     int stringLength = run->length;
643     const UniChar *uc = run->characters;
644
645     if( len < 0 ) {
646         len = stringLength - from;
647     } else if( len == 0 ) {
648         return 0;
649     }
650
651     // Early out.  Only shape hebrew and arabic.  Hebrew is included
652     // for shaping mirror characters.
653     int i;
654     for (i = from; i < from+len; i++){
655         if (uc[i] >= 0x591 && uc[i] <= 0x700)
656             break;
657     }
658     if (i == from+len)
659         return 0;
660     
661     int num = stringLength - from - len;
662     const UniChar *ch = uc + from + len;
663     while ( num > 0 && _unicodeCombiningClass(*ch) != 0 ) {
664         ch++;
665         num--;
666         len++;
667     }
668
669     ch = uc + from;
670     while ( len > 0 && _unicodeCombiningClass(*ch) != 0 ) {
671         ch++;
672         len--;
673         from++;
674     }
675     if ( len == 0 )
676         return 0;
677
678     if( !shapeBuffer || len > shapeBufSize ) {
679         if( shapeBuffer )
680             free( (void *) shapeBuffer );
681         shapeBuffer = (UniChar *) malloc( len*sizeof( UniChar ) );
682         shapeBufSize = len;
683     }
684
685     int lenOut = 0;
686     UniChar *data = shapeBuffer;
687
688     for (i = 0; i < len; i++ ) {
689         UniChar r = WK_ROW(*ch);
690         UniChar c = WK_CELL(*ch);
691         if ( r != 0x06 ) {
692             if ( r == 0x20 ) {
693                 switch ( c ) {
694                     case 0x0C:
695                     case 0x0D:
696                         goto skip;
697                     default:
698                         break;
699                 }
700             }
701             if ( _unicodeMirrored(*ch) )
702                 *data = _unicodeMirroredChar(*ch);
703             else
704                 *data = *ch;
705             data++;
706             lenOut++;
707         } else {
708             int pos = i + from;
709             int shape = glyphVariantLogical( uc, stringLength, pos );
710             ushort map;
711             switch ( c ) {
712                 case 0x44: {
713                     const UniChar *pch = nextChar( uc, stringLength, pos );
714                     if ( WK_ROW(*pch) == 0x06 ) {
715                         switch ( WK_CELL(*pch) ) {
716                             case 0x22:
717                             case 0x23:
718                             case 0x25:
719                             case 0x27:
720                                 map = arabicUnicodeLamAlefMapping[WK_CELL(*pch) - 0x22][shape];
721                                 goto next;
722                             default:
723                                 break;
724                         }
725                     }
726                     break;
727                 }
728                 case 0x22: 
729                 case 0x23: 
730                 case 0x25: 
731                 case 0x27: 
732                     if ( *prevChar( uc, stringLength, pos ) == 0x0644 ) {
733                         goto skip;
734                     }
735                 default:
736                     break;
737             }
738             map = getShape( c, shape );
739         next:
740             *data = map;
741             data++;
742             lenOut++;
743         }
744     skip:
745         ch++;
746     }
747
748     *lengthOut = lenOut;
749     return shapeBuffer;
750 }