1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  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 /* $Id$ */
19 
20 package org.apache.fop.complexscripts.util;
21 
22 import java.util.Arrays;
23 
24 /**
25  * <p>Mirror related utilities.</p>
26  *
27  * <p>This work was originally authored by Glenn Adams (gadams@apache.org).</p>
28  */
29 public final class CharMirror {
30 
CharMirror()31     private CharMirror() {
32     }
33 
34     /**
35      * Mirror characters that are designated as having the bidi mirrorred property.
36      * @param s a string whose characters are to be mirrored
37      * @return the resulting string
38      */
mirror(String s)39     public static String mirror(String s) {
40         StringBuffer sb = new StringBuffer(s);
41         for (int i = 0, n = sb.length(); i < n; ++i) {
42             sb.setCharAt(i, (char) mirror(sb.charAt(i)));
43         }
44         return sb.toString();
45     }
46 
47     /**
48      * Determine if string has a mirrorable character.
49      * @param s a string whose characters are to be tested for mirrorability
50      * @return true if some character can be mirrored
51      */
hasMirrorable(String s)52     public static boolean hasMirrorable(String s) {
53         for (int i = 0, n = s.length(); i < n; ++i) {
54             char c = s.charAt(i);
55             if (Arrays.binarySearch(mirroredCharacters, c) >= 0) {
56                 return true;
57             }
58         }
59         return false;
60     }
61 
62     private static int[] mirroredCharacters = {
63         0x0028,
64         0x0029,
65         0x003C,
66         0x003E,
67         0x005B,
68         0x005D,
69         0x007B,
70         0x007D,
71         0x00AB,
72         0x00BB,
73         0x0F3A,
74         0x0F3B,
75         0x0F3C,
76         0x0F3D,
77         0x169B,
78         0x169C,
79         0x2039,
80         0x203A,
81         0x2045,
82         0x2046,
83         0x207D,
84         0x207E,
85         0x208D,
86         0x208E,
87         0x2208,
88         0x2209,
89         0x220A,
90         0x220B,
91         0x220C,
92         0x220D,
93         0x2215,
94         0x223C,
95         0x223D,
96         0x2243,
97         0x2252,
98         0x2253,
99         0x2254,
100         0x2255,
101         0x2264,
102         0x2265,
103         0x2266,
104         0x2267,
105         0x2268,
106         0x2269,
107         0x226A,
108         0x226B,
109         0x226E,
110         0x226F,
111         0x2270,
112         0x2271,
113         0x2272,
114         0x2273,
115         0x2274,
116         0x2275,
117         0x2276,
118         0x2277,
119         0x2278,
120         0x2279,
121         0x227A,
122         0x227B,
123         0x227C,
124         0x227D,
125         0x227E,
126         0x227F,
127         0x2280,
128         0x2281,
129         0x2282,
130         0x2283,
131         0x2284,
132         0x2285,
133         0x2286,
134         0x2287,
135         0x2288,
136         0x2289,
137         0x228A,
138         0x228B,
139         0x228F,
140         0x2290,
141         0x2291,
142         0x2292,
143         0x2298,
144         0x22A2,
145         0x22A3,
146         0x22A6,
147         0x22A8,
148         0x22A9,
149         0x22AB,
150         0x22B0,
151         0x22B1,
152         0x22B2,
153         0x22B3,
154         0x22B4,
155         0x22B5,
156         0x22B6,
157         0x22B7,
158         0x22C9,
159         0x22CA,
160         0x22CB,
161         0x22CC,
162         0x22CD,
163         0x22D0,
164         0x22D1,
165         0x22D6,
166         0x22D7,
167         0x22D8,
168         0x22D9,
169         0x22DA,
170         0x22DB,
171         0x22DC,
172         0x22DD,
173         0x22DE,
174         0x22DF,
175         0x22E0,
176         0x22E1,
177         0x22E2,
178         0x22E3,
179         0x22E4,
180         0x22E5,
181         0x22E6,
182         0x22E7,
183         0x22E8,
184         0x22E9,
185         0x22EA,
186         0x22EB,
187         0x22EC,
188         0x22ED,
189         0x22F0,
190         0x22F1,
191         0x22F2,
192         0x22F3,
193         0x22F4,
194         0x22F6,
195         0x22F7,
196         0x22FA,
197         0x22FB,
198         0x22FC,
199         0x22FD,
200         0x22FE,
201         0x2308,
202         0x2309,
203         0x230A,
204         0x230B,
205         0x2329,
206         0x232A,
207         0x2768,
208         0x2769,
209         0x276A,
210         0x276B,
211         0x276C,
212         0x276D,
213         0x276E,
214         0x276F,
215         0x2770,
216         0x2771,
217         0x2772,
218         0x2773,
219         0x2774,
220         0x2775,
221         0x27C3,
222         0x27C4,
223         0x27C5,
224         0x27C6,
225         0x27C8,
226         0x27C9,
227         0x27D5,
228         0x27D6,
229         0x27DD,
230         0x27DE,
231         0x27E2,
232         0x27E3,
233         0x27E4,
234         0x27E5,
235         0x27E6,
236         0x27E7,
237         0x27E8,
238         0x27E9,
239         0x27EA,
240         0x27EB,
241         0x27EC,
242         0x27ED,
243         0x27EE,
244         0x27EF,
245         0x2983,
246         0x2984,
247         0x2985,
248         0x2986,
249         0x2987,
250         0x2988,
251         0x2989,
252         0x298A,
253         0x298B,
254         0x298C,
255         0x298D,
256         0x298E,
257         0x298F,
258         0x2990,
259         0x2991,
260         0x2992,
261         0x2993,
262         0x2994,
263         0x2995,
264         0x2996,
265         0x2997,
266         0x2998,
267         0x29B8,
268         0x29C0,
269         0x29C1,
270         0x29C4,
271         0x29C5,
272         0x29CF,
273         0x29D0,
274         0x29D1,
275         0x29D2,
276         0x29D4,
277         0x29D5,
278         0x29D8,
279         0x29D9,
280         0x29DA,
281         0x29DB,
282         0x29F5,
283         0x29F8,
284         0x29F9,
285         0x29FC,
286         0x29FD,
287         0x2A2B,
288         0x2A2C,
289         0x2A2D,
290         0x2A2E,
291         0x2A34,
292         0x2A35,
293         0x2A3C,
294         0x2A3D,
295         0x2A64,
296         0x2A65,
297         0x2A79,
298         0x2A7A,
299         0x2A7D,
300         0x2A7E,
301         0x2A7F,
302         0x2A80,
303         0x2A81,
304         0x2A82,
305         0x2A83,
306         0x2A84,
307         0x2A8B,
308         0x2A8C,
309         0x2A91,
310         0x2A92,
311         0x2A93,
312         0x2A94,
313         0x2A95,
314         0x2A96,
315         0x2A97,
316         0x2A98,
317         0x2A99,
318         0x2A9A,
319         0x2A9B,
320         0x2A9C,
321         0x2AA1,
322         0x2AA2,
323         0x2AA6,
324         0x2AA7,
325         0x2AA8,
326         0x2AA9,
327         0x2AAA,
328         0x2AAB,
329         0x2AAC,
330         0x2AAD,
331         0x2AAF,
332         0x2AB0,
333         0x2AB3,
334         0x2AB4,
335         0x2AC3,
336         0x2AC4,
337         0x2AC5,
338         0x2AC6,
339         0x2ACD,
340         0x2ACE,
341         0x2ACF,
342         0x2AD0,
343         0x2AD1,
344         0x2AD2,
345         0x2AD3,
346         0x2AD4,
347         0x2AD5,
348         0x2AD6,
349         0x2ADE,
350         0x2AE3,
351         0x2E02,
352         0x2E03,
353         0x2E04,
354         0x2E05,
355         0x2E09,
356         0x2E0A,
357         0x2E0C,
358         0x2E0D,
359         0x2E1C,
360         0x2E1D,
361         0x2E20,
362         0x2E21,
363         0x2E22,
364         0x2E23,
365         0x2E24,
366         0x2E25,
367         0x2E26,
368         0x300E,
369         0x300F,
370         0x3010,
371         0x3011,
372         0x3014,
373         0x3015,
374         0x3016,
375         0x3017,
376         0x3018,
377         0x3019,
378         0x301A,
379         0x301B,
380         0xFE59,
381         0xFE5A,
382         0xFF3B,
383         0xFF3D,
384         0xFF5B,
385         0xFF5D,
386         0xFF5F,
387         0xFF60,
388         0xFF62,
389         0xFF63
390     };
391 
392     private static int[] mirroredCharactersMapping = {
393         0x0029,
394         0x0028,
395         0x003E,
396         0x003C,
397         0x005D,
398         0x005B,
399         0x007D,
400         0x007B,
401         0x00BB,
402         0x00AB,
403         0x0F3B,
404         0x0F3A,
405         0x0F3D,
406         0x0F3C,
407         0x169C,
408         0x169B,
409         0x203A,
410         0x2039,
411         0x2046,
412         0x2045,
413         0x207E,
414         0x207D,
415         0x208E,
416         0x208D,
417         0x220B,
418         0x220C,
419         0x220D,
420         0x2208,
421         0x2209,
422         0x220A,
423         0x29F5,
424         0x223D,
425         0x223C,
426         0x22CD,
427         0x2253,
428         0x2252,
429         0x2255,
430         0x2254,
431         0x2265,
432         0x2264,
433         0x2267,
434         0x2266,
435         0x2269,
436         0x2268,
437         0x226B,
438         0x226A,
439         0x226F,
440         0x226E,
441         0x2271,
442         0x2270,
443         0x2273,
444         0x2272,
445         0x2275,
446         0x2274,
447         0x2277,
448         0x2276,
449         0x2279,
450         0x2278,
451         0x227B,
452         0x227A,
453         0x227D,
454         0x227C,
455         0x227F,
456         0x227E,
457         0x2281,
458         0x2280,
459         0x2283,
460         0x2282,
461         0x2285,
462         0x2284,
463         0x2287,
464         0x2286,
465         0x2289,
466         0x2288,
467         0x228B,
468         0x228A,
469         0x2290,
470         0x228F,
471         0x2292,
472         0x2291,
473         0x29B8,
474         0x22A3,
475         0x22A2,
476         0x2ADE,
477         0x2AE4,
478         0x2AE3,
479         0x2AE5,
480         0x22B1,
481         0x22B0,
482         0x22B3,
483         0x22B2,
484         0x22B5,
485         0x22B4,
486         0x22B7,
487         0x22B6,
488         0x22CA,
489         0x22C9,
490         0x22CC,
491         0x22CB,
492         0x2243,
493         0x22D1,
494         0x22D0,
495         0x22D7,
496         0x22D6,
497         0x22D9,
498         0x22D8,
499         0x22DB,
500         0x22DA,
501         0x22DD,
502         0x22DC,
503         0x22DF,
504         0x22DE,
505         0x22E1,
506         0x22E0,
507         0x22E3,
508         0x22E2,
509         0x22E5,
510         0x22E4,
511         0x22E7,
512         0x22E6,
513         0x22E9,
514         0x22E8,
515         0x22EB,
516         0x22EA,
517         0x22ED,
518         0x22EC,
519         0x22F1,
520         0x22F0,
521         0x22FA,
522         0x22FB,
523         0x22FC,
524         0x22FD,
525         0x22FE,
526         0x22F2,
527         0x22F3,
528         0x22F4,
529         0x22F6,
530         0x22F7,
531         0x2309,
532         0x2308,
533         0x230B,
534         0x230A,
535         0x232A,
536         0x2329,
537         0x2769,
538         0x2768,
539         0x276B,
540         0x276A,
541         0x276D,
542         0x276C,
543         0x276F,
544         0x276E,
545         0x2771,
546         0x2770,
547         0x2773,
548         0x2772,
549         0x2775,
550         0x2774,
551         0x27C4,
552         0x27C3,
553         0x27C6,
554         0x27C5,
555         0x27C9,
556         0x27C8,
557         0x27D6,
558         0x27D5,
559         0x27DE,
560         0x27DD,
561         0x27E3,
562         0x27E2,
563         0x27E5,
564         0x27E4,
565         0x27E7,
566         0x27E6,
567         0x27E9,
568         0x27E8,
569         0x27EB,
570         0x27EA,
571         0x27ED,
572         0x27EC,
573         0x27EF,
574         0x27EE,
575         0x2984,
576         0x2983,
577         0x2986,
578         0x2985,
579         0x2988,
580         0x2987,
581         0x298A,
582         0x2989,
583         0x298C,
584         0x298B,
585         0x2990,
586         0x298F,
587         0x298E,
588         0x298D,
589         0x2992,
590         0x2991,
591         0x2994,
592         0x2993,
593         0x2996,
594         0x2995,
595         0x2998,
596         0x2997,
597         0x2298,
598         0x29C1,
599         0x29C0,
600         0x29C5,
601         0x29C4,
602         0x29D0,
603         0x29CF,
604         0x29D2,
605         0x29D1,
606         0x29D5,
607         0x29D4,
608         0x29D9,
609         0x29D8,
610         0x29DB,
611         0x29DA,
612         0x2215,
613         0x29F9,
614         0x29F8,
615         0x29FD,
616         0x29FC,
617         0x2A2C,
618         0x2A2B,
619         0x2A2E,
620         0x2A2D,
621         0x2A35,
622         0x2A34,
623         0x2A3D,
624         0x2A3C,
625         0x2A65,
626         0x2A64,
627         0x2A7A,
628         0x2A79,
629         0x2A7E,
630         0x2A7D,
631         0x2A80,
632         0x2A7F,
633         0x2A82,
634         0x2A81,
635         0x2A84,
636         0x2A83,
637         0x2A8C,
638         0x2A8B,
639         0x2A92,
640         0x2A91,
641         0x2A94,
642         0x2A93,
643         0x2A96,
644         0x2A95,
645         0x2A98,
646         0x2A97,
647         0x2A9A,
648         0x2A99,
649         0x2A9C,
650         0x2A9B,
651         0x2AA2,
652         0x2AA1,
653         0x2AA7,
654         0x2AA6,
655         0x2AA9,
656         0x2AA8,
657         0x2AAB,
658         0x2AAA,
659         0x2AAD,
660         0x2AAC,
661         0x2AB0,
662         0x2AAF,
663         0x2AB4,
664         0x2AB3,
665         0x2AC4,
666         0x2AC3,
667         0x2AC6,
668         0x2AC5,
669         0x2ACE,
670         0x2ACD,
671         0x2AD0,
672         0x2ACF,
673         0x2AD2,
674         0x2AD1,
675         0x2AD4,
676         0x2AD3,
677         0x2AD6,
678         0x2AD5,
679         0x22A6,
680         0x22A9,
681         0x2E03,
682         0x2E02,
683         0x2E05,
684         0x2E04,
685         0x2E0A,
686         0x2E09,
687         0x2E0D,
688         0x2E0C,
689         0x2E1D,
690         0x2E1C,
691         0x2E21,
692         0x2E20,
693         0x2E23,
694         0x2E22,
695         0x2E25,
696         0x2E24,
697         0x2E27,
698         0x300F,
699         0x300E,
700         0x3011,
701         0x3010,
702         0x3015,
703         0x3014,
704         0x3017,
705         0x3016,
706         0x3019,
707         0x3018,
708         0x301B,
709         0x301A,
710         0xFE5A,
711         0xFE59,
712         0xFF3D,
713         0xFF3B,
714         0xFF5D,
715         0xFF5B,
716         0xFF60,
717         0xFF5F,
718         0xFF63,
719         0xFF62
720     };
721 
mirror(int c)722     private static int mirror(int c) {
723         int i = Arrays.binarySearch(mirroredCharacters, c);
724         if (i < 0) {
725             return c;
726         } else {
727             return mirroredCharactersMapping [ i ];
728         }
729     }
730 
731 }
732