KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > gvt > text > ArabicTextHandler


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.gvt.text;
19
20 import java.text.AttributedCharacterIterator JavaDoc;
21 import java.text.AttributedString JavaDoc;
22 import java.util.HashMap JavaDoc;
23 import java.util.Map JavaDoc;
24
25
26 /**
27  * Handles the processing of arabic text. In particular it determines the
28  * form each arabic char should take. It also contains methods for substituting
29  * plain arabic glyphs with their shaped forms. This is needed when the arabic
30  * text is rendered using an AWT font.
31  *
32  * @author <a HREF="mailto:bella.robinson@cmis.csiro.au">Bella Robinson</a>
33  * @version $Id: ArabicTextHandler.java,v 1.8 2005/03/27 08:58:35 cam Exp $
34  */

35 public class ArabicTextHandler {
36
37     private final static int arabicStart = 0x0600;
38     private final static int arabicEnd = 0x06FF;
39
40     private final static Map JavaDoc charMap = new HashMap JavaDoc(54);
41
42     /**
43      * If the AttributedString contains any arabic chars, assigns an
44      * arabic form attribute, i&#x2e;e&#x2e; initial|medial|terminal|isolated,
45      * to each arabic char.
46      *
47      * @param as The string to attach the arabic form attributes to.
48      * @return An attributed string with arabic form attributes.
49      */

50     public static AttributedString JavaDoc assignArabicForms(AttributedString JavaDoc as) {
51
52         // first check to see if the string contains any arabic chars
53
// if not, then don't need to do anything
54
if (!containsArabic(as)) {
55             return as;
56         }
57
58         // if the string contains any ligatures with transparent chars
59
// eg. AtB where AB form a ligature and t is transparent, then
60
// reorder that part of the string so that it becomes tAB
61
// construct the reordered ACI
62
AttributedCharacterIterator JavaDoc aci = as.getIterator();
63         boolean didSomeReordering = false;
64         int numChars = aci.getEndIndex() - aci.getBeginIndex();
65         int charOrder[] = new int[numChars];
66         for (int i = 0; i < numChars; i++) {
67             charOrder[i] = i + aci.getBeginIndex();
68         }
69         for (int i = 1; i < numChars-1; i++) {
70             char c = aci.setIndex(aci.getBeginIndex() + i);
71             if (arabicCharTransparent(c)) {
72                 char prevChar = aci.setIndex(aci.getBeginIndex() + i-1);
73                 char nextChar = aci.setIndex(aci.getBeginIndex() + i+1);
74                 if (charMap.get("" + prevChar + nextChar) != null) {
75                     // found a ligature, separated by a transparent char
76
didSomeReordering = true;
77                     int temp = charOrder[i];
78                     charOrder[i] = charOrder[i-1];
79                     charOrder[i-1] = temp;
80                 }
81             }
82         }
83         if (didSomeReordering) {
84             // need to reconstruct the reordered attributed string
85
String JavaDoc reorderedString = "";
86             char c;
87             for (int i = 0; i < numChars; i++) {
88                 c = aci.setIndex(charOrder[i]);
89                 reorderedString += c;
90             }
91             AttributedString JavaDoc reorderedAS = new AttributedString JavaDoc(reorderedString);
92             for (int i = 0; i < numChars; i++) {
93                 aci.setIndex(charOrder[i]);
94                 Map JavaDoc attributes = aci.getAttributes();
95                 reorderedAS.addAttributes(attributes, i, i+1);
96             }
97             if (charOrder[0] == (aci.getBeginIndex()+1) && charOrder[1] == aci.getBeginIndex()) {
98                 // have swapped the first 2 chars, may need to move any position attributes
99

100                 aci.first();
101                 Float JavaDoc x = (Float JavaDoc) aci.getAttribute(
102                     GVTAttributedCharacterIterator.TextAttribute.X);
103                 Float JavaDoc y = (Float JavaDoc) aci.getAttribute(
104                     GVTAttributedCharacterIterator.TextAttribute.Y);
105
106                 if (x != null && !x.isNaN()) {
107                     reorderedAS.addAttribute(GVTAttributedCharacterIterator.TextAttribute.X,
108                         new Float JavaDoc(Float.NaN), 1, 2);
109                     reorderedAS.addAttribute(GVTAttributedCharacterIterator.TextAttribute.X, x, 0, 1);
110                 }
111                 if (y != null && !y.isNaN()) {
112                     reorderedAS.addAttribute(GVTAttributedCharacterIterator.TextAttribute.Y,
113                         new Float JavaDoc(Float.NaN), 1, 2);
114                     reorderedAS.addAttribute(GVTAttributedCharacterIterator.TextAttribute.Y, y, 0, 1);
115                 }
116             }
117             as = reorderedAS;
118         }
119
120
121         // first assign none to all arabic letters
122
int c;
123         aci = as.getIterator();
124         for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
125             c = aci.setIndex(i);
126             if (c >= arabicStart && c <= arabicEnd) {
127                 as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM,
128                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_NONE, i, i+1);
129             }
130         }
131         aci.first();
132
133         boolean moreRuns = true;
134         // for each run of arabic chars, assign the appropriate form
135
while (moreRuns) {
136             int start = aci.getRunStart(
137                     GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
138             int end = aci.getRunLimit(
139                     GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
140
141             aci.setIndex(start);
142
143             if (aci.getAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM) != null) {
144
145                 // only modify if the chars in the run are arabic
146

147                 int currentIndex = start;
148                 while (currentIndex < end) {
149
150                     char currentChar= aci.setIndex(currentIndex);
151                     char prevChar = currentChar;
152                     int prevCharIndex = currentIndex-1;
153                     if (currentIndex > start) { // if not at the start
154
prevChar = aci.setIndex(prevCharIndex);
155                     }
156
157                     while (arabicCharTransparent(currentChar) && currentIndex < end) {
158                         currentIndex++;
159                         currentChar = aci.setIndex(currentIndex);
160                     }
161                     if (currentIndex >= end) {
162                         break;
163                     }
164
165                     if (!arabicCharTransparent(currentChar)) { // if current char is not transparent
166

167                         if (prevCharIndex >= start) { // if not at the start
168

169                             // if prev char right AND current char left
170
if (arabicCharShapesRight(prevChar)
171                                 && arabicCharShapesLeft(currentChar)) {
172
173                                 // then single increment the for of the previous char
174
aci.setIndex(prevCharIndex);
175                                 Integer JavaDoc prevForm = (Integer JavaDoc)aci.getAttribute(
176                                     GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
177                                 prevForm = new Integer JavaDoc(prevForm.intValue()+1);
178
179                                 as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM,
180                                                 prevForm, prevCharIndex, prevCharIndex+1);
181
182                                 // and set the form of the current char to INITIAL
183
as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM,
184                                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL,
185                                                 currentIndex, currentIndex+1);
186                              }
187
188                             // if not prev char right OR not current char left
189
// AND current char can be shaped
190
if ((!arabicCharShapesRight(prevChar) ||
191                                  !arabicCharShapesLeft(currentChar))
192                                  && arabicCharShaped(currentChar)) {
193
194                                 // set the form of the current char to ISOLATE
195
as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM,
196                                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_ISOLATED,
197                                                 currentIndex, currentIndex+1);
198                             }
199
200                         // if this is the first arabic char and its shaped, set to ISOLATE
201
} else if (arabicCharShaped(currentChar)) {
202                             // set the form of the current char to ISOLATE
203
as.addAttribute(GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM,
204                                             GVTAttributedCharacterIterator.TextAttribute.ARABIC_ISOLATED,
205                                           currentIndex, currentIndex+1);
206                         }
207                     }
208                     currentIndex++;
209                 }
210             }
211             if (aci.setIndex(end) == AttributedCharacterIterator.DONE) {
212                 moreRuns = false;
213             }
214         }
215         return as;
216     }
217
218     /**
219      * Returns true if the char is a standard arabic char.
220      * (ie. within the range U+0600 - U+6FF)
221      *
222      * @param c The character to test.
223      * @return True if the char is arabic, false otherwise.
224      */

225     public static boolean arabicChar(char c) {
226         if (c >= arabicStart && c <= arabicEnd) {
227             return true;
228         }
229         return false;
230     }
231
232     /**
233      * Returns true if the string contains any arabic characters.
234      *
235      * @param as The string to test.
236      * @return True if at least one char is arabic, false otherwise.
237      */

238     public static boolean containsArabic(AttributedString JavaDoc as) {
239         return containsArabic(as.getIterator());
240     }
241
242     /**
243      * Returns true if the ACI contains any arabic characters.
244      *
245      * @param aci The AttributedCharacterIterator to test.
246      * @return True if at least one char is arabic, false otherwise.
247      */

248     public static boolean containsArabic(AttributedCharacterIterator JavaDoc aci) {
249         char c;
250         for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
251             c = aci.setIndex(i);
252             if (arabicChar(c)) {
253                 return true;
254             }
255         }
256         return false;
257     }
258
259     /**
260      * Returns true if the char is transparent.
261      *
262      * @param c The character to test.
263      * @return True if the character is transparent, false otherwise.
264      */

265     public static boolean arabicCharTransparent(char c) {
266         int charVal = c;
267         if ((charVal >= 0x64B && charVal <= 0x655)
268             || (charVal == 0x0670)
269             || (charVal >= 0x06D6 && charVal <= 0x06E4)
270             || (charVal >= 0x06E7 && charVal <= 0x06E8)
271             || (charVal >= 0x06EA && charVal <= 0x06ED)) {
272             return true;
273         }
274         return false;
275     }
276
277     /**
278      * Returns true if the character shapes to the right. Note that duel
279      * shaping characters also shape to the right and so will return true.
280      *
281      * @param c The character to test.
282      * @return True if the character shapes to the right, false otherwise.
283      */

284     private static boolean arabicCharShapesRight(char c) {
285         int charVal = c;
286         if ((charVal >= 0x622 && charVal <= 0x625)
287          || (charVal == 0x627)
288          || (charVal == 0x629)
289          || (charVal >= 0x062F && charVal <= 0x0632)
290          || (charVal == 0x0648)
291          || (charVal >= 0x0671 && charVal <= 0x0673)
292          || (charVal >= 0x0675 && charVal <= 0x0677)
293          || (charVal >= 0x0688 && charVal <= 0x0699)
294          || (charVal == 0x06C0)
295          || (charVal >= 0x06C2 && charVal <= 0x06CB)
296          || (charVal == 0x06CD)
297          || (charVal == 0x06CF)
298          || (charVal >= 0x06D2 && charVal <= 0x06D3)
299          // check for duel shaping too
300
|| arabicCharShapesDuel(c)) {
301             return true;
302         }
303         return false;
304     }
305
306     /**
307      * Returns true if character has duel shaping.
308      *
309      * @param c The character to test.
310      * @return True if the character is duel shaping, false otherwise.
311      */

312     private static boolean arabicCharShapesDuel(char c) {
313         int charVal = c;
314
315         if ((charVal == 0x626)
316          || (charVal == 0x628)
317          || (charVal >= 0x062A && charVal <= 0x062E)
318          || (charVal >= 0x0633 && charVal <= 0x063A)
319          || (charVal >= 0x0641 && charVal <= 0x0647)
320          || (charVal >= 0x0649 && charVal <= 0x064A)
321          || (charVal >= 0x0678 && charVal <= 0x0687)
322          || (charVal >= 0x069A && charVal <= 0x06BF)
323          || (charVal == 0x6C1)
324          || (charVal == 0x6CC)
325          || (charVal == 0x6CE)
326          || (charVal >= 0x06D0 && charVal <= 0x06D1)
327          || (charVal >= 0x06FA && charVal <= 0x06FC)) {
328             return true;
329         }
330         return false;
331     }
332
333     /**
334      * Returns true if character shapes to the left. Note that duel
335      * shaping characters also shape to the left and so will return true.
336      *
337      * @param c The character to test.
338      * @return True if the character shapes to the left, false otherwise.
339      */

340     private static boolean arabicCharShapesLeft(char c) {
341         return arabicCharShapesDuel(c);
342     }
343
344     /**
345      * Returns true if character is shaped.
346      *
347      * @param c The character to test.
348      * @return True if the character is shaped, false otherwise.
349      */

350     private static boolean arabicCharShaped(char c) {
351         return arabicCharShapesRight(c);
352     }
353
354
355     /**
356      * Will try and find a substitute character of the specified form.
357      *
358      * @param unicode The unicode value of the glyph to try and replace. It
359      * may be ligature and so may contain more than one character.
360      * @param form Indicates the required arabic form.
361      * (isolated = 1, final = 2, initial = 3, medial = 4)
362      *
363      * @return The unicode value of the substutute char, or -1 if no susbtitue
364      * exists.
365      */

366     public static int getSubstituteChar(String JavaDoc unicode, int form) {
367         if (charMap.containsKey(unicode) && form > 0) {
368             int chars[] = (int[])charMap.get(unicode);
369             if (chars[form-1] > 0) {
370                 return chars[form-1];
371             }
372         }
373         return -1;
374     }
375
376     /**
377      * Where possible substitues plain arabic glyphs with their shaped
378      * forms. This is needed when the arabic text is rendered using
379      * an AWT font. Simple arabic ligatures will also be recognised
380      * and replaced by a single character so the length of the
381      * resulting string may be shorter than the number of characters
382      * in the aci.
383      *
384      * @param aci Contains the text to process. Arabic form attributes
385      * should already be assigned to each arabic character.
386      * @return A String containing the shaped versions of the arabic characters
387      */

388     public static String JavaDoc createSubstituteString(AttributedCharacterIterator JavaDoc aci) {
389
390         String JavaDoc substString = "";
391         for (int i = aci.getBeginIndex(); i < aci.getEndIndex(); i++) {
392             char c = aci.setIndex(i);
393             if (arabicChar(c)) {
394                 Integer JavaDoc form = (Integer JavaDoc)aci.getAttribute(
395                     GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
396
397                 // see if the c is the start of a ligature
398
if (charStartsLigature(c) && i < aci.getEndIndex()) {
399                     char nextChar = aci.setIndex(i+1);
400                     Integer JavaDoc nextForm = (Integer JavaDoc)aci.getAttribute(
401                     GVTAttributedCharacterIterator.TextAttribute.ARABIC_FORM);
402                     if (form != null && nextForm != null) {
403                         if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)
404                             && nextForm.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_INITIAL)) {
405                             // look for an isolated ligature
406
int substChar = ArabicTextHandler.getSubstituteChar("" + c + nextChar,
407                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_ISOLATED.intValue());
408                             if (substChar > -1) {
409                                 substString += (char)substChar;
410                                 i++;
411                                 continue;
412                             }
413                         } else if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL)) {
414                             // look for a terminal ligature
415
int substChar = ArabicTextHandler.getSubstituteChar("" + c + nextChar,
416                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_TERMINAL.intValue());
417                             if (substChar > -1) {
418                                 substString += (char)substChar;
419                                 i++;
420                                 continue;
421                             }
422                         } else if (form.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)
423                                 && nextForm.equals(GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL)) {
424                             // look for a medial ligature
425
int substChar = ArabicTextHandler.getSubstituteChar("" + c + nextChar,
426                                 GVTAttributedCharacterIterator.TextAttribute.ARABIC_MEDIAL.intValue());
427                             if (substChar > -1) {
428                                 substString += (char)substChar;
429                                 i++;
430                                 continue;
431                             }
432                         }
433                     }
434                 }
435
436                 // couln't find a matching ligature so just look for a simple substitution
437
if (form != null && form.intValue() > 0) {
438                     int substChar = ArabicTextHandler.getSubstituteChar(""+c, form.intValue());
439                     if (substChar > -1) {
440                         substString += (char)substChar;
441                     } else {
442                         substString += c;
443                     }
444                 } else {
445                     substString += c;
446                 }
447             } else {
448                 substString += c;
449             }
450         }
451         return substString;
452     }
453
454     /**
455      * Returns true if a ligature exists that starts with the
456      * specified character.
457      *
458      * @param c The character to test.
459      * @return True if there is a ligature that starts with c, false otherwise.
460      */

461     public static boolean charStartsLigature(char c) {
462         int charVal = c;
463         if (charVal == 0x064B || charVal == 0x064C || charVal == 0x064D
464          || charVal == 0x064E || charVal == 0x064F || charVal == 0x0650
465          || charVal == 0x0651 || charVal == 0x0652 || charVal == 0x0622
466          || charVal == 0x0623 || charVal == 0x0625 || charVal == 0x0627) {
467             return true;
468         }
469         return false;
470     }
471
472     /**
473      * Returns the number of characters the glyph for the specified character
474      * represents. If the glyph represents a ligature this will be 2, otherwise 1.
475      *
476      * @param c The character to test.
477      * @return The number of characters the glyph for c represents.
478      */

479     public static int getNumChars(char c) {
480         // if c is a ligature returns 2, else returns 1
481
if (isLigature(c)) {
482             // at the moment only support ligatures with two chars
483
return 2;
484         }
485         return 1;
486     }
487
488     /**
489      * Returns true if the glyph for the specified character respresents a ligature.
490      *
491      * @param c The character to test.
492      * @return True if c is a ligature, false otherwise.
493      */

494     public static boolean isLigature(char c) {
495         int charVal = c;
496         if ((charVal >= 0xFE70 && charVal <= 0xFE72)
497             || (charVal == 0xFE74)
498             || (charVal >= 0xFE76 && charVal <= 0xFE7F)
499             || (charVal >= 0xFEF5 && charVal <= 0xFEFC)) {
500             return true;
501         }
502         return false;
503     }
504
505
506     static {
507
508         // constructs the character map that maps arabic characters and
509
// ligature to their various forms
510
// NOTE: the unicode values for ligatures are stored here in
511
// visual order (not logical order)
512

513         int chars1[] = {0xFE70, -1, -1, -1}; // isolated, final, initial, medial
514
charMap.put(new String JavaDoc("" + (char)0x064B + (char)0x0020), chars1);
515
516         int chars2[] = {-1, -1, -1, 0xFE71};
517         charMap.put(new String JavaDoc("" + (char)0x064B + (char)0x0640), chars2);
518
519         int chars3[] = {0xFE72, -1, -1, -1};
520         charMap.put(new String JavaDoc("" + (char)0x064C + (char)0x0020), chars3);
521
522         int chars4[] = {0xFE74, -1, -1, -1};
523         charMap.put(new String JavaDoc("" + (char)0x064D + (char)0x0020), chars4);
524
525         int chars5[] = {0xFE76, -1, -1, -1};
526         charMap.put(new String JavaDoc("" + (char)0x064E + (char)0x0020), chars5);
527
528         int chars6[] = {-1, -1, -1, 0xFE77};
529         charMap.put(new String JavaDoc("" + (char)0x064E + (char)0x0640), chars6);
530
531         int chars7[] = {0xFE78, -1, -1, -1};
532         charMap.put(new String JavaDoc("" + (char)0x064F + (char)0x0020), chars7);
533
534         int chars8[] = {-1, -1, -1, 0xFE79};
535         charMap.put(new String JavaDoc("" + (char)0x064F + (char)0x0640), chars8);
536
537         int chars9[] = {0xFE7A, -1, -1, -1};
538         charMap.put(new String JavaDoc("" + (char)0x0650 + (char)0x0020), chars9);
539
540         int chars10[] = {-1, -1, -1, 0xFE7B};
541         charMap.put(new String JavaDoc("" + (char)0x0650 + (char)0x0640), chars10);
542
543         int chars11[] = {0xFE7C, -1, -1, -1};
544         charMap.put(new String JavaDoc("" + (char)0x0651 + (char)0x0020), chars11);
545
546         int chars12[] = {-1, -1, -1, 0xFE7D};
547         charMap.put(new String JavaDoc("" + (char)0x0651 + (char)0x0640), chars12);
548
549         int chars13[] = {0xFE7E, -1, -1, -1};
550         charMap.put(new String JavaDoc("" + (char)0x0652 + (char)0x0020), chars13);
551
552         int chars14[] = {-1, -1, -1, 0xFE7F};
553         charMap.put(new String JavaDoc("" + (char)0x0652 + (char)0x0640), chars14);
554
555         int chars15[] = {0xFE80, -1, -1, -1};
556         charMap.put(new String JavaDoc("" + (char)0x0621), chars15);
557
558         int chars16[] = {0xFE81, 0xFE82, -1, -1};
559         charMap.put(new String JavaDoc("" + (char)0x0622), chars16);
560
561         int chars17[] = {0xFE83, 0xFE84, -1, -1};
562         charMap.put(new String JavaDoc("" + (char)0x0623), chars17);
563
564         int chars18[] = {0xFE85, 0xFE86, -1, -1};
565         charMap.put(new String JavaDoc("" + (char)0x0624), chars18);
566
567         int chars19[] = {0xFE87, 0xFE88, -1, -1};
568         charMap.put(new String JavaDoc("" + (char)0x0625), chars19);
569
570         int chars20[] = {0xFE89, 0xFE8A, 0xFE8B, 0xFE8C};
571         charMap.put(new String JavaDoc("" + (char)0x0626), chars20);
572
573         int chars21[] = {0xFE8D, 0xFE8E, -1, -1};
574         charMap.put(new String JavaDoc("" + (char)0x0627), chars21);
575
576         int chars22[] = {0xFE8F, 0xFE90, 0xFE91, 0xFE92};
577         charMap.put(new String JavaDoc("" + (char)0x0628), chars22);
578
579         int chars23[] = {0xFE93, 0xFE94, -1, -1};
580         charMap.put(new String JavaDoc("" + (char)0x0629), chars23);
581
582         int chars24[] = {0xFE95, 0xFE96, 0xFE97, 0xFE98};
583         charMap.put(new String JavaDoc("" + (char)0x062A), chars24);
584
585         int chars25[] = {0xFE99, 0xFE9A, 0xFE9B, 0xFE9C};
586         charMap.put(new String JavaDoc("" + (char)0x062B), chars25);
587
588         int chars26[] = {0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0};
589         charMap.put(new String JavaDoc("" + (char)0x062C), chars26);
590
591         int chars27[] = {0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4};
592         charMap.put(new String JavaDoc("" + (char)0x062D), chars27);
593
594         int chars28[] = {0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8};
595         charMap.put(new String JavaDoc("" + (char)0x062E), chars28);
596
597         int chars29[] = {0xFEA9, 0xFEAA, -1, -1};
598         charMap.put(new String JavaDoc("" + (char)0x062F), chars29);
599
600         int chars30[] = {0xFEAB, 0xFEAC, -1, -1};
601         charMap.put(new String JavaDoc("" + (char)0x0630), chars30);
602
603         int chars31[] = {0xFEAD, 0xFEAE, -1, -1};
604         charMap.put(new String JavaDoc("" + (char)0x0631), chars31);
605
606         int chars32[] = {0xFEAF, 0xFEB0, -1, -1};
607         charMap.put(new String JavaDoc("" + (char)0x0632), chars32);
608
609         int chars33[] = {0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4};
610         charMap.put(new String JavaDoc("" + (char)0x0633), chars33);
611
612         int chars34[] = {0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8};
613         charMap.put(new String JavaDoc("" + (char)0x0634), chars34);
614
615         int chars35[] = {0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC};
616         charMap.put(new String JavaDoc("" + (char)0x0635), chars35);
617
618         int chars36[] = {0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0};
619         charMap.put(new String JavaDoc("" + (char)0x0636), chars36);
620
621         int chars37[] = {0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4};
622         charMap.put(new String JavaDoc("" + (char)0x0637), chars37);
623
624         int chars38[] = {0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8};
625         charMap.put(new String JavaDoc("" + (char)0x0638), chars38);
626
627         int chars39[] = {0xFEC9, 0xFECA, 0xFECB, 0xFECC};
628         charMap.put(new String JavaDoc("" + (char)0x0639), chars39);
629
630         int chars40[] = { 0xFECD, 0xFECE, 0xFECF, 0xFED0};
631         charMap.put(new String JavaDoc("" + (char)0x063A), chars40);
632
633         int chars41[] = {0xFED1, 0xFED2, 0xFED3, 0xFED4};
634         charMap.put(new String JavaDoc("" + (char)0x0641), chars41);
635
636         int chars42[] = {0xFED5, 0xFED6, 0xFED7, 0xFED8};
637         charMap.put(new String JavaDoc("" + (char)0x0642), chars42);
638
639         int chars43[] = {0xFED9, 0xFEDA, 0xFEDB, 0xFEDC};
640         charMap.put(new String JavaDoc("" + (char)0x0643), chars43);
641
642         int chars44[] = {0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0};
643         charMap.put(new String JavaDoc("" + (char)0x0644), chars44);
644
645         int chars45[] = {0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4};
646         charMap.put(new String JavaDoc("" + (char)0x0645), chars45);
647
648         int chars46[] = {0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8};
649         charMap.put(new String JavaDoc("" + (char)0x0646), chars46);
650
651         int chars47[] = {0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC};
652         charMap.put(new String JavaDoc("" + (char)0x0647), chars47);
653
654         int chars48[] = {0xFEED, 0xFEEE, -1, -1};
655         charMap.put(new String JavaDoc("" + (char)0x0648), chars48);
656
657         int chars49[] = {0xFEEF, 0xFEF0, -1, -1};
658         charMap.put(new String JavaDoc("" + (char)0x0649), chars49);
659
660         int chars50[] = {0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4};
661         charMap.put(new String JavaDoc("" + (char)0x064A), chars50);
662
663          int chars51[] = {0xFEF5, 0xFEF6, -1, -1};
664         charMap.put(new String JavaDoc("" + (char)0x0622 + (char)0x0644), chars51);
665
666         int chars52[] = {0xFEF7, 0xFEF8, -1, -1};
667         charMap.put(new String JavaDoc("" + (char)0x0623 + (char)0x0644), chars52);
668
669         int chars53[] = {0xFEF9, 0xFEFA, -1, -1};
670         charMap.put(new String JavaDoc("" + (char)0x0625 + (char)0x0644), chars53);
671
672         int chars54[] = {0xFEFB, 0xFEFC, -1, -1};
673         charMap.put(new String JavaDoc("" + (char)0x0627 + (char)0x0644), chars54);
674
675     }
676
677
678 }
679
Popular Tags