Source Code Cross Referenced for BidiLine.java in  » PDF » pdf-itext » com » lowagie » text » pdf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » PDF » pdf itext » com.lowagie.text.pdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *
003:         * Copyright 2002 Paulo Soares
004:         *
005:         * The contents of this file are subject to the Mozilla Public License Version 1.1
006:         * (the "License"); you may not use this file except in compliance with the License.
007:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
008:         *
009:         * Software distributed under the License is distributed on an "AS IS" basis,
010:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011:         * for the specific language governing rights and limitations under the License.
012:         *
013:         * The Original Code is 'iText, a free JAVA-PDF library'.
014:         *
015:         * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
016:         * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
017:         * All Rights Reserved.
018:         * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
019:         * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
020:         *
021:         * Contributor(s): all the names of the contributors are added in the source code
022:         * where applicable.
023:         *
024:         * Alternatively, the contents of this file may be used under the terms of the
025:         * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
026:         * provisions of LGPL are applicable instead of those above.  If you wish to
027:         * allow use of your version of this file only under the terms of the LGPL
028:         * License and not to allow others to use your version of this file under
029:         * the MPL, indicate your decision by deleting the provisions above and
030:         * replace them with the notice and other provisions required by the LGPL.
031:         * If you do not delete the provisions above, a recipient may use your version
032:         * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
033:         *
034:         * This library is free software; you can redistribute it and/or modify it
035:         * under the terms of the MPL as stated above or under the terms of the GNU
036:         * Library General Public License as published by the Free Software Foundation;
037:         * either version 2 of the License, or any later version.
038:         *
039:         * This library is distributed in the hope that it will be useful, but WITHOUT
040:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
041:         * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
042:         * details.
043:         *
044:         * If you didn't download this code from the following link, you should check if
045:         * you aren't using an obsolete version:
046:         * http://www.lowagie.com/iText/
047:         */
048:
049:        package com.lowagie.text.pdf;
050:
051:        import java.util.ArrayList;
052:
053:        import com.lowagie.text.Chunk;
054:
055:        /** Does all the line bidirectional processing with PdfChunk assembly.
056:         *
057:         * @author Paulo Soares (psoares@consiste.pt)
058:         */
059:        public class BidiLine {
060:
061:            protected int runDirection;
062:            protected int pieceSize = 256;
063:            protected char text[] = new char[pieceSize];
064:            protected PdfChunk detailChunks[] = new PdfChunk[pieceSize];
065:            protected int totalTextLength = 0;
066:
067:            protected byte orderLevels[] = new byte[pieceSize];
068:            protected int indexChars[] = new int[pieceSize];
069:
070:            protected ArrayList chunks = new ArrayList();
071:            protected int indexChunk = 0;
072:            protected int indexChunkChar = 0;
073:            protected int currentChar = 0;
074:
075:            protected int storedRunDirection;
076:            protected char storedText[] = new char[0];
077:            protected PdfChunk storedDetailChunks[] = new PdfChunk[0];
078:            protected int storedTotalTextLength = 0;
079:
080:            protected byte storedOrderLevels[] = new byte[0];
081:            protected int storedIndexChars[] = new int[0];
082:
083:            protected int storedIndexChunk = 0;
084:            protected int storedIndexChunkChar = 0;
085:            protected int storedCurrentChar = 0;
086:
087:            protected boolean shortStore;
088:            //    protected ArabicShaping arabic = new ArabicShaping(ArabicShaping.LETTERS_SHAPE | ArabicShaping.LENGTH_GROW_SHRINK | ArabicShaping.TEXT_DIRECTION_LOGICAL);
089:            protected static final IntHashtable mirrorChars = new IntHashtable();
090:            protected int arabicOptions;
091:
092:            /** Creates new BidiLine */
093:            public BidiLine() {
094:            }
095:
096:            public BidiLine(BidiLine org) {
097:                runDirection = org.runDirection;
098:                pieceSize = org.pieceSize;
099:                text = (char[]) org.text.clone();
100:                detailChunks = (PdfChunk[]) org.detailChunks.clone();
101:                totalTextLength = org.totalTextLength;
102:
103:                orderLevels = (byte[]) org.orderLevels.clone();
104:                indexChars = (int[]) org.indexChars.clone();
105:
106:                chunks = new ArrayList(org.chunks);
107:                indexChunk = org.indexChunk;
108:                indexChunkChar = org.indexChunkChar;
109:                currentChar = org.currentChar;
110:
111:                storedRunDirection = org.storedRunDirection;
112:                storedText = (char[]) org.storedText.clone();
113:                storedDetailChunks = (PdfChunk[]) org.storedDetailChunks
114:                        .clone();
115:                storedTotalTextLength = org.storedTotalTextLength;
116:
117:                storedOrderLevels = (byte[]) org.storedOrderLevels.clone();
118:                storedIndexChars = (int[]) org.storedIndexChars.clone();
119:
120:                storedIndexChunk = org.storedIndexChunk;
121:                storedIndexChunkChar = org.storedIndexChunkChar;
122:                storedCurrentChar = org.storedCurrentChar;
123:
124:                shortStore = org.shortStore;
125:                arabicOptions = org.arabicOptions;
126:            }
127:
128:            public boolean isEmpty() {
129:                return (currentChar >= totalTextLength && indexChunk >= chunks
130:                        .size());
131:            }
132:
133:            public void clearChunks() {
134:                chunks.clear();
135:                totalTextLength = 0;
136:                currentChar = 0;
137:            }
138:
139:            public boolean getParagraph(int runDirection) {
140:                this .runDirection = runDirection;
141:                currentChar = 0;
142:                totalTextLength = 0;
143:                boolean hasText = false;
144:                char c;
145:                char uniC;
146:                BaseFont bf;
147:                for (; indexChunk < chunks.size(); ++indexChunk) {
148:                    PdfChunk ck = (PdfChunk) chunks.get(indexChunk);
149:                    bf = ck.font().getFont();
150:                    String s = ck.toString();
151:                    int len = s.length();
152:                    for (; indexChunkChar < len; ++indexChunkChar) {
153:                        c = s.charAt(indexChunkChar);
154:                        uniC = bf.getUnicodeEquivalent(c);
155:                        if (uniC == '\r' || uniC == '\n') {
156:                            // next condition is never true for CID
157:                            if (uniC == '\r' && indexChunkChar + 1 < len
158:                                    && s.charAt(indexChunkChar + 1) == '\n')
159:                                ++indexChunkChar;
160:                            ++indexChunkChar;
161:                            if (indexChunkChar >= len) {
162:                                indexChunkChar = 0;
163:                                ++indexChunk;
164:                            }
165:                            hasText = true;
166:                            if (totalTextLength == 0)
167:                                detailChunks[0] = ck;
168:                            break;
169:                        }
170:                        addPiece(c, ck);
171:                    }
172:                    if (hasText)
173:                        break;
174:                    indexChunkChar = 0;
175:                }
176:                if (totalTextLength == 0)
177:                    return hasText;
178:
179:                // remove trailing WS
180:                totalTextLength = trimRight(0, totalTextLength - 1) + 1;
181:                if (totalTextLength == 0)
182:                    return true;
183:
184:                if (runDirection == PdfWriter.RUN_DIRECTION_LTR
185:                        || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
186:                    if (orderLevels.length < totalTextLength) {
187:                        orderLevels = new byte[pieceSize];
188:                        indexChars = new int[pieceSize];
189:                    }
190:                    ArabicLigaturizer.processNumbers(text, 0, totalTextLength,
191:                            arabicOptions);
192:                    BidiOrder order = new BidiOrder(
193:                            text,
194:                            0,
195:                            totalTextLength,
196:                            (byte) (runDirection == PdfWriter.RUN_DIRECTION_RTL ? 1
197:                                    : 0));
198:                    byte od[] = order.getLevels();
199:                    for (int k = 0; k < totalTextLength; ++k) {
200:                        orderLevels[k] = od[k];
201:                        indexChars[k] = k;
202:                    }
203:                    doArabicShapping();
204:                    mirrorGlyphs();
205:                }
206:                totalTextLength = trimRightEx(0, totalTextLength - 1) + 1;
207:                return true;
208:            }
209:
210:            public void addChunk(PdfChunk chunk) {
211:                chunks.add(chunk);
212:            }
213:
214:            public void addChunks(ArrayList chunks) {
215:                this .chunks.addAll(chunks);
216:            }
217:
218:            public void addPiece(char c, PdfChunk chunk) {
219:                if (totalTextLength >= pieceSize) {
220:                    char tempText[] = text;
221:                    PdfChunk tempDetailChunks[] = detailChunks;
222:                    pieceSize *= 2;
223:                    text = new char[pieceSize];
224:                    detailChunks = new PdfChunk[pieceSize];
225:                    System.arraycopy(tempText, 0, text, 0, totalTextLength);
226:                    System.arraycopy(tempDetailChunks, 0, detailChunks, 0,
227:                            totalTextLength);
228:                }
229:                text[totalTextLength] = c;
230:                detailChunks[totalTextLength++] = chunk;
231:            }
232:
233:            public void save() {
234:                if (indexChunk > 0) {
235:                    if (indexChunk >= chunks.size())
236:                        chunks.clear();
237:                    else {
238:                        for (--indexChunk; indexChunk >= 0; --indexChunk)
239:                            chunks.remove(indexChunk);
240:                    }
241:                    indexChunk = 0;
242:                }
243:                storedRunDirection = runDirection;
244:                storedTotalTextLength = totalTextLength;
245:                storedIndexChunk = indexChunk;
246:                storedIndexChunkChar = indexChunkChar;
247:                storedCurrentChar = currentChar;
248:                shortStore = (currentChar < totalTextLength);
249:                if (!shortStore) {
250:                    // long save
251:                    if (storedText.length < totalTextLength) {
252:                        storedText = new char[totalTextLength];
253:                        storedDetailChunks = new PdfChunk[totalTextLength];
254:                    }
255:                    System.arraycopy(text, 0, storedText, 0, totalTextLength);
256:                    System.arraycopy(detailChunks, 0, storedDetailChunks, 0,
257:                            totalTextLength);
258:                }
259:                if (runDirection == PdfWriter.RUN_DIRECTION_LTR
260:                        || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
261:                    if (storedOrderLevels.length < totalTextLength) {
262:                        storedOrderLevels = new byte[totalTextLength];
263:                        storedIndexChars = new int[totalTextLength];
264:                    }
265:                    System.arraycopy(orderLevels, currentChar,
266:                            storedOrderLevels, currentChar, totalTextLength
267:                                    - currentChar);
268:                    System.arraycopy(indexChars, currentChar, storedIndexChars,
269:                            currentChar, totalTextLength - currentChar);
270:                }
271:            }
272:
273:            public void restore() {
274:                runDirection = storedRunDirection;
275:                totalTextLength = storedTotalTextLength;
276:                indexChunk = storedIndexChunk;
277:                indexChunkChar = storedIndexChunkChar;
278:                currentChar = storedCurrentChar;
279:                if (!shortStore) {
280:                    // long restore
281:                    System.arraycopy(storedText, 0, text, 0, totalTextLength);
282:                    System.arraycopy(storedDetailChunks, 0, detailChunks, 0,
283:                            totalTextLength);
284:                }
285:                if (runDirection == PdfWriter.RUN_DIRECTION_LTR
286:                        || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
287:                    System.arraycopy(storedOrderLevels, currentChar,
288:                            orderLevels, currentChar, totalTextLength
289:                                    - currentChar);
290:                    System.arraycopy(storedIndexChars, currentChar, indexChars,
291:                            currentChar, totalTextLength - currentChar);
292:                }
293:            }
294:
295:            public void mirrorGlyphs() {
296:                for (int k = 0; k < totalTextLength; ++k) {
297:                    if ((orderLevels[k] & 1) == 1) {
298:                        int mirror = mirrorChars.get(text[k]);
299:                        if (mirror != 0)
300:                            text[k] = (char) mirror;
301:                    }
302:                }
303:            }
304:
305:            public void doArabicShapping() {
306:                int src = 0;
307:                int dest = 0;
308:                for (;;) {
309:                    while (src < totalTextLength) {
310:                        char c = text[src];
311:                        if (c >= 0x0600 && c <= 0x06ff)
312:                            break;
313:                        if (src != dest) {
314:                            text[dest] = text[src];
315:                            detailChunks[dest] = detailChunks[src];
316:                            orderLevels[dest] = orderLevels[src];
317:                        }
318:                        ++src;
319:                        ++dest;
320:                    }
321:                    if (src >= totalTextLength) {
322:                        totalTextLength = dest;
323:                        return;
324:                    }
325:                    int startArabicIdx = src;
326:                    ++src;
327:                    while (src < totalTextLength) {
328:                        char c = text[src];
329:                        if (c < 0x0600 || c > 0x06ff)
330:                            break;
331:                        ++src;
332:                    }
333:                    int arabicWordSize = src - startArabicIdx;
334:                    int size = ArabicLigaturizer
335:                            .arabic_shape(text, startArabicIdx, arabicWordSize,
336:                                    text, dest, arabicWordSize, arabicOptions /*PangoArabicShapping.ar_novowel PangoArabicShapping.ar_lig | PangoArabicShapping.ar_composedtashkeel*/);
337:                    if (startArabicIdx != dest) {
338:                        for (int k = 0; k < size; ++k) {
339:                            detailChunks[dest] = detailChunks[startArabicIdx];
340:                            orderLevels[dest++] = orderLevels[startArabicIdx++];
341:                        }
342:                    } else
343:                        dest += size;
344:                }
345:            }
346:
347:            public PdfLine processLine(float width, int alignment,
348:                    int runDirection, int arabicOptions) {
349:                this .arabicOptions = arabicOptions;
350:                save();
351:                boolean isRTL = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
352:                if (currentChar >= totalTextLength) {
353:                    boolean hasText = getParagraph(runDirection);
354:                    if (!hasText)
355:                        return null;
356:                    if (totalTextLength == 0) {
357:                        ArrayList ar = new ArrayList();
358:                        PdfChunk ck = new PdfChunk("", detailChunks[0]);
359:                        ar.add(ck);
360:                        return new PdfLine(0, 0, alignment, true, ar, isRTL);
361:                    }
362:                }
363:                float originalWidth = width;
364:                int lastSplit = -1;
365:                if (currentChar != 0)
366:                    currentChar = trimLeftEx(currentChar, totalTextLength - 1);
367:                int oldCurrentChar = currentChar;
368:                char c = 0;
369:                char uniC = 0;
370:                PdfChunk ck = null;
371:                float charWidth = 0;
372:                PdfChunk lastValidChunk = null;
373:                for (; currentChar < totalTextLength; ++currentChar) {
374:                    c = text[currentChar];
375:                    ck = detailChunks[currentChar];
376:                    uniC = ck.getUnicodeEquivalent(c);
377:                    if (PdfChunk.noPrint(uniC))
378:                        continue;
379:                    charWidth = ck.getCharWidth(c);
380:                    if (ck.isExtSplitCharacter(oldCurrentChar, currentChar,
381:                            totalTextLength, text, detailChunks))
382:                        lastSplit = currentChar;
383:                    if (width - charWidth < 0)
384:                        break;
385:                    width -= charWidth;
386:                    lastValidChunk = ck;
387:                }
388:                if (lastValidChunk == null) {
389:                    // not even a single char fit; must output the first char
390:                    ++currentChar;
391:                    return new PdfLine(0, 0, alignment, false,
392:                            createArrayOfPdfChunks(currentChar - 1,
393:                                    currentChar - 1), isRTL);
394:                }
395:                if (currentChar >= totalTextLength) {
396:                    // there was more line than text
397:                    return new PdfLine(0, width, alignment, true,
398:                            createArrayOfPdfChunks(oldCurrentChar,
399:                                    totalTextLength - 1), isRTL);
400:                }
401:                int newCurrentChar = trimRightEx(oldCurrentChar,
402:                        currentChar - 1);
403:                if (newCurrentChar < oldCurrentChar) {
404:                    // only WS
405:                    return new PdfLine(0, width, alignment, false,
406:                            createArrayOfPdfChunks(oldCurrentChar,
407:                                    currentChar - 1), isRTL);
408:                }
409:                if (newCurrentChar == currentChar - 1) { // middle of word
410:                    HyphenationEvent he = (HyphenationEvent) lastValidChunk
411:                            .getAttribute(Chunk.HYPHENATION);
412:                    if (he != null) {
413:                        int word[] = getWord(oldCurrentChar, newCurrentChar);
414:                        if (word != null) {
415:                            float testWidth = width
416:                                    + getWidth(word[0], currentChar - 1);
417:                            String pre = he.getHyphenatedWordPre(new String(
418:                                    text, word[0], word[1] - word[0]),
419:                                    lastValidChunk.font().getFont(),
420:                                    lastValidChunk.font().size(), testWidth);
421:                            String post = he.getHyphenatedWordPost();
422:                            if (pre.length() > 0) {
423:                                PdfChunk extra = new PdfChunk(pre,
424:                                        lastValidChunk);
425:                                currentChar = word[1] - post.length();
426:                                return new PdfLine(0, testWidth
427:                                        - lastValidChunk.font().width(pre),
428:                                        alignment, false,
429:                                        createArrayOfPdfChunks(oldCurrentChar,
430:                                                word[0] - 1, extra), isRTL);
431:                            }
432:                        }
433:                    }
434:                }
435:                if (lastSplit == -1 || lastSplit >= newCurrentChar) {
436:                    // no split point or split point ahead of end
437:                    return new PdfLine(0, width
438:                            + getWidth(newCurrentChar + 1, currentChar - 1),
439:                            alignment, false, createArrayOfPdfChunks(
440:                                    oldCurrentChar, newCurrentChar), isRTL);
441:                }
442:                // standard split
443:                currentChar = lastSplit + 1;
444:                newCurrentChar = trimRightEx(oldCurrentChar, lastSplit);
445:                if (newCurrentChar < oldCurrentChar) {
446:                    // only WS again
447:                    newCurrentChar = currentChar - 1;
448:                }
449:                return new PdfLine(0, originalWidth
450:                        - getWidth(oldCurrentChar, newCurrentChar), alignment,
451:                        false, createArrayOfPdfChunks(oldCurrentChar,
452:                                newCurrentChar), isRTL);
453:            }
454:
455:            /** Gets the width of a range of characters.
456:             * @param startIdx the first index to calculate
457:             * @param lastIdx the last inclusive index to calculate
458:             * @return the sum of all widths
459:             */
460:            public float getWidth(int startIdx, int lastIdx) {
461:                char c = 0;
462:                char uniC;
463:                PdfChunk ck = null;
464:                float width = 0;
465:                for (; startIdx <= lastIdx; ++startIdx) {
466:                    c = text[startIdx];
467:                    ck = detailChunks[startIdx];
468:                    uniC = ck.getUnicodeEquivalent(c);
469:                    if (PdfChunk.noPrint(uniC))
470:                        continue;
471:                    width += detailChunks[startIdx].getCharWidth(c);
472:                }
473:                return width;
474:            }
475:
476:            public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx) {
477:                return createArrayOfPdfChunks(startIdx, endIdx, null);
478:            }
479:
480:            public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx,
481:                    PdfChunk extraPdfChunk) {
482:                boolean bidi = (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL);
483:                if (bidi)
484:                    reorder(startIdx, endIdx);
485:                ArrayList ar = new ArrayList();
486:                PdfChunk refCk = detailChunks[startIdx];
487:                PdfChunk ck = null;
488:                StringBuffer buf = new StringBuffer();
489:                char c;
490:                int idx = 0;
491:                for (; startIdx <= endIdx; ++startIdx) {
492:                    idx = bidi ? indexChars[startIdx] : startIdx;
493:                    c = text[idx];
494:                    ck = detailChunks[idx];
495:                    if (PdfChunk.noPrint(ck.getUnicodeEquivalent(c)))
496:                        continue;
497:                    if (ck.isImage()) {
498:                        if (buf.length() > 0) {
499:                            ar.add(new PdfChunk(buf.toString(), refCk));
500:                            buf = new StringBuffer();
501:                        }
502:                        ar.add(ck);
503:                    } else if (ck == refCk) {
504:                        buf.append(c);
505:                    } else {
506:                        if (buf.length() > 0) {
507:                            ar.add(new PdfChunk(buf.toString(), refCk));
508:                            buf = new StringBuffer();
509:                        }
510:                        if (!ck.isImage())
511:                            buf.append(c);
512:                        refCk = ck;
513:                    }
514:                }
515:                if (buf.length() > 0) {
516:                    ar.add(new PdfChunk(buf.toString(), refCk));
517:                }
518:                if (extraPdfChunk != null)
519:                    ar.add(extraPdfChunk);
520:                return ar;
521:            }
522:
523:            public int[] getWord(int startIdx, int idx) {
524:                int last = idx;
525:                int first = idx;
526:                // forward
527:                for (; last < totalTextLength; ++last) {
528:                    if (!Character.isLetter(text[last]))
529:                        break;
530:                }
531:                if (last == idx)
532:                    return null;
533:                // backward
534:                for (; first >= startIdx; --first) {
535:                    if (!Character.isLetter(text[first]))
536:                        break;
537:                }
538:                ++first;
539:                return new int[] { first, last };
540:            }
541:
542:            public int trimRight(int startIdx, int endIdx) {
543:                int idx = endIdx;
544:                char c;
545:                for (; idx >= startIdx; --idx) {
546:                    c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
547:                    if (!isWS(c))
548:                        break;
549:                }
550:                return idx;
551:            }
552:
553:            public int trimLeft(int startIdx, int endIdx) {
554:                int idx = startIdx;
555:                char c;
556:                for (; idx <= endIdx; ++idx) {
557:                    c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
558:                    if (!isWS(c))
559:                        break;
560:                }
561:                return idx;
562:            }
563:
564:            public int trimRightEx(int startIdx, int endIdx) {
565:                int idx = endIdx;
566:                char c = 0;
567:                for (; idx >= startIdx; --idx) {
568:                    c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
569:                    if (!isWS(c) && !PdfChunk.noPrint(c))
570:                        break;
571:                }
572:                return idx;
573:            }
574:
575:            public int trimLeftEx(int startIdx, int endIdx) {
576:                int idx = startIdx;
577:                char c = 0;
578:                for (; idx <= endIdx; ++idx) {
579:                    c = detailChunks[idx].getUnicodeEquivalent(text[idx]);
580:                    if (!isWS(c) && !PdfChunk.noPrint(c))
581:                        break;
582:                }
583:                return idx;
584:            }
585:
586:            public void reorder(int start, int end) {
587:                byte maxLevel = orderLevels[start];
588:                byte minLevel = maxLevel;
589:                byte onlyOddLevels = maxLevel;
590:                byte onlyEvenLevels = maxLevel;
591:                for (int k = start + 1; k <= end; ++k) {
592:                    byte b = orderLevels[k];
593:                    if (b > maxLevel)
594:                        maxLevel = b;
595:                    else if (b < minLevel)
596:                        minLevel = b;
597:                    onlyOddLevels &= b;
598:                    onlyEvenLevels |= b;
599:                }
600:                if ((onlyEvenLevels & 1) == 0) // nothing to do
601:                    return;
602:                if ((onlyOddLevels & 1) == 1) { // single inversion
603:                    flip(start, end + 1);
604:                    return;
605:                }
606:                minLevel |= 1;
607:                for (; maxLevel >= minLevel; --maxLevel) {
608:                    int pstart = start;
609:                    for (;;) {
610:                        for (; pstart <= end; ++pstart) {
611:                            if (orderLevels[pstart] >= maxLevel)
612:                                break;
613:                        }
614:                        if (pstart > end)
615:                            break;
616:                        int pend = pstart + 1;
617:                        for (; pend <= end; ++pend) {
618:                            if (orderLevels[pend] < maxLevel)
619:                                break;
620:                        }
621:                        flip(pstart, pend);
622:                        pstart = pend + 1;
623:                    }
624:                }
625:            }
626:
627:            public void flip(int start, int end) {
628:                int mid = (start + end) / 2;
629:                --end;
630:                for (; start < mid; ++start, --end) {
631:                    int temp = indexChars[start];
632:                    indexChars[start] = indexChars[end];
633:                    indexChars[end] = temp;
634:                }
635:            }
636:
637:            public static boolean isWS(char c) {
638:                return (c <= ' ');
639:            }
640:
641:            static {
642:                mirrorChars.put(0x0028, 0x0029); // LEFT PARENTHESIS
643:                mirrorChars.put(0x0029, 0x0028); // RIGHT PARENTHESIS
644:                mirrorChars.put(0x003C, 0x003E); // LESS-THAN SIGN
645:                mirrorChars.put(0x003E, 0x003C); // GREATER-THAN SIGN
646:                mirrorChars.put(0x005B, 0x005D); // LEFT SQUARE BRACKET
647:                mirrorChars.put(0x005D, 0x005B); // RIGHT SQUARE BRACKET
648:                mirrorChars.put(0x007B, 0x007D); // LEFT CURLY BRACKET
649:                mirrorChars.put(0x007D, 0x007B); // RIGHT CURLY BRACKET
650:                mirrorChars.put(0x00AB, 0x00BB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
651:                mirrorChars.put(0x00BB, 0x00AB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
652:                mirrorChars.put(0x2039, 0x203A); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
653:                mirrorChars.put(0x203A, 0x2039); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
654:                mirrorChars.put(0x2045, 0x2046); // LEFT SQUARE BRACKET WITH QUILL
655:                mirrorChars.put(0x2046, 0x2045); // RIGHT SQUARE BRACKET WITH QUILL
656:                mirrorChars.put(0x207D, 0x207E); // SUPERSCRIPT LEFT PARENTHESIS
657:                mirrorChars.put(0x207E, 0x207D); // SUPERSCRIPT RIGHT PARENTHESIS
658:                mirrorChars.put(0x208D, 0x208E); // SUBSCRIPT LEFT PARENTHESIS
659:                mirrorChars.put(0x208E, 0x208D); // SUBSCRIPT RIGHT PARENTHESIS
660:                mirrorChars.put(0x2208, 0x220B); // ELEMENT OF
661:                mirrorChars.put(0x2209, 0x220C); // NOT AN ELEMENT OF
662:                mirrorChars.put(0x220A, 0x220D); // SMALL ELEMENT OF
663:                mirrorChars.put(0x220B, 0x2208); // CONTAINS AS MEMBER
664:                mirrorChars.put(0x220C, 0x2209); // DOES NOT CONTAIN AS MEMBER
665:                mirrorChars.put(0x220D, 0x220A); // SMALL CONTAINS AS MEMBER
666:                mirrorChars.put(0x2215, 0x29F5); // DIVISION SLASH
667:                mirrorChars.put(0x223C, 0x223D); // TILDE OPERATOR
668:                mirrorChars.put(0x223D, 0x223C); // REVERSED TILDE
669:                mirrorChars.put(0x2243, 0x22CD); // ASYMPTOTICALLY EQUAL TO
670:                mirrorChars.put(0x2252, 0x2253); // APPROXIMATELY EQUAL TO OR THE IMAGE OF
671:                mirrorChars.put(0x2253, 0x2252); // IMAGE OF OR APPROXIMATELY EQUAL TO
672:                mirrorChars.put(0x2254, 0x2255); // COLON EQUALS
673:                mirrorChars.put(0x2255, 0x2254); // EQUALS COLON
674:                mirrorChars.put(0x2264, 0x2265); // LESS-THAN OR EQUAL TO
675:                mirrorChars.put(0x2265, 0x2264); // GREATER-THAN OR EQUAL TO
676:                mirrorChars.put(0x2266, 0x2267); // LESS-THAN OVER EQUAL TO
677:                mirrorChars.put(0x2267, 0x2266); // GREATER-THAN OVER EQUAL TO
678:                mirrorChars.put(0x2268, 0x2269); // [BEST FIT] LESS-THAN BUT NOT EQUAL TO
679:                mirrorChars.put(0x2269, 0x2268); // [BEST FIT] GREATER-THAN BUT NOT EQUAL TO
680:                mirrorChars.put(0x226A, 0x226B); // MUCH LESS-THAN
681:                mirrorChars.put(0x226B, 0x226A); // MUCH GREATER-THAN
682:                mirrorChars.put(0x226E, 0x226F); // [BEST FIT] NOT LESS-THAN
683:                mirrorChars.put(0x226F, 0x226E); // [BEST FIT] NOT GREATER-THAN
684:                mirrorChars.put(0x2270, 0x2271); // [BEST FIT] NEITHER LESS-THAN NOR EQUAL TO
685:                mirrorChars.put(0x2271, 0x2270); // [BEST FIT] NEITHER GREATER-THAN NOR EQUAL TO
686:                mirrorChars.put(0x2272, 0x2273); // [BEST FIT] LESS-THAN OR EQUIVALENT TO
687:                mirrorChars.put(0x2273, 0x2272); // [BEST FIT] GREATER-THAN OR EQUIVALENT TO
688:                mirrorChars.put(0x2274, 0x2275); // [BEST FIT] NEITHER LESS-THAN NOR EQUIVALENT TO
689:                mirrorChars.put(0x2275, 0x2274); // [BEST FIT] NEITHER GREATER-THAN NOR EQUIVALENT TO
690:                mirrorChars.put(0x2276, 0x2277); // LESS-THAN OR GREATER-THAN
691:                mirrorChars.put(0x2277, 0x2276); // GREATER-THAN OR LESS-THAN
692:                mirrorChars.put(0x2278, 0x2279); // NEITHER LESS-THAN NOR GREATER-THAN
693:                mirrorChars.put(0x2279, 0x2278); // NEITHER GREATER-THAN NOR LESS-THAN
694:                mirrorChars.put(0x227A, 0x227B); // PRECEDES
695:                mirrorChars.put(0x227B, 0x227A); // SUCCEEDS
696:                mirrorChars.put(0x227C, 0x227D); // PRECEDES OR EQUAL TO
697:                mirrorChars.put(0x227D, 0x227C); // SUCCEEDS OR EQUAL TO
698:                mirrorChars.put(0x227E, 0x227F); // [BEST FIT] PRECEDES OR EQUIVALENT TO
699:                mirrorChars.put(0x227F, 0x227E); // [BEST FIT] SUCCEEDS OR EQUIVALENT TO
700:                mirrorChars.put(0x2280, 0x2281); // [BEST FIT] DOES NOT PRECEDE
701:                mirrorChars.put(0x2281, 0x2280); // [BEST FIT] DOES NOT SUCCEED
702:                mirrorChars.put(0x2282, 0x2283); // SUBSET OF
703:                mirrorChars.put(0x2283, 0x2282); // SUPERSET OF
704:                mirrorChars.put(0x2284, 0x2285); // [BEST FIT] NOT A SUBSET OF
705:                mirrorChars.put(0x2285, 0x2284); // [BEST FIT] NOT A SUPERSET OF
706:                mirrorChars.put(0x2286, 0x2287); // SUBSET OF OR EQUAL TO
707:                mirrorChars.put(0x2287, 0x2286); // SUPERSET OF OR EQUAL TO
708:                mirrorChars.put(0x2288, 0x2289); // [BEST FIT] NEITHER A SUBSET OF NOR EQUAL TO
709:                mirrorChars.put(0x2289, 0x2288); // [BEST FIT] NEITHER A SUPERSET OF NOR EQUAL TO
710:                mirrorChars.put(0x228A, 0x228B); // [BEST FIT] SUBSET OF WITH NOT EQUAL TO
711:                mirrorChars.put(0x228B, 0x228A); // [BEST FIT] SUPERSET OF WITH NOT EQUAL TO
712:                mirrorChars.put(0x228F, 0x2290); // SQUARE IMAGE OF
713:                mirrorChars.put(0x2290, 0x228F); // SQUARE ORIGINAL OF
714:                mirrorChars.put(0x2291, 0x2292); // SQUARE IMAGE OF OR EQUAL TO
715:                mirrorChars.put(0x2292, 0x2291); // SQUARE ORIGINAL OF OR EQUAL TO
716:                mirrorChars.put(0x2298, 0x29B8); // CIRCLED DIVISION SLASH
717:                mirrorChars.put(0x22A2, 0x22A3); // RIGHT TACK
718:                mirrorChars.put(0x22A3, 0x22A2); // LEFT TACK
719:                mirrorChars.put(0x22A6, 0x2ADE); // ASSERTION
720:                mirrorChars.put(0x22A8, 0x2AE4); // TRUE
721:                mirrorChars.put(0x22A9, 0x2AE3); // FORCES
722:                mirrorChars.put(0x22AB, 0x2AE5); // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
723:                mirrorChars.put(0x22B0, 0x22B1); // PRECEDES UNDER RELATION
724:                mirrorChars.put(0x22B1, 0x22B0); // SUCCEEDS UNDER RELATION
725:                mirrorChars.put(0x22B2, 0x22B3); // NORMAL SUBGROUP OF
726:                mirrorChars.put(0x22B3, 0x22B2); // CONTAINS AS NORMAL SUBGROUP
727:                mirrorChars.put(0x22B4, 0x22B5); // NORMAL SUBGROUP OF OR EQUAL TO
728:                mirrorChars.put(0x22B5, 0x22B4); // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
729:                mirrorChars.put(0x22B6, 0x22B7); // ORIGINAL OF
730:                mirrorChars.put(0x22B7, 0x22B6); // IMAGE OF
731:                mirrorChars.put(0x22C9, 0x22CA); // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
732:                mirrorChars.put(0x22CA, 0x22C9); // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
733:                mirrorChars.put(0x22CB, 0x22CC); // LEFT SEMIDIRECT PRODUCT
734:                mirrorChars.put(0x22CC, 0x22CB); // RIGHT SEMIDIRECT PRODUCT
735:                mirrorChars.put(0x22CD, 0x2243); // REVERSED TILDE EQUALS
736:                mirrorChars.put(0x22D0, 0x22D1); // DOUBLE SUBSET
737:                mirrorChars.put(0x22D1, 0x22D0); // DOUBLE SUPERSET
738:                mirrorChars.put(0x22D6, 0x22D7); // LESS-THAN WITH DOT
739:                mirrorChars.put(0x22D7, 0x22D6); // GREATER-THAN WITH DOT
740:                mirrorChars.put(0x22D8, 0x22D9); // VERY MUCH LESS-THAN
741:                mirrorChars.put(0x22D9, 0x22D8); // VERY MUCH GREATER-THAN
742:                mirrorChars.put(0x22DA, 0x22DB); // LESS-THAN EQUAL TO OR GREATER-THAN
743:                mirrorChars.put(0x22DB, 0x22DA); // GREATER-THAN EQUAL TO OR LESS-THAN
744:                mirrorChars.put(0x22DC, 0x22DD); // EQUAL TO OR LESS-THAN
745:                mirrorChars.put(0x22DD, 0x22DC); // EQUAL TO OR GREATER-THAN
746:                mirrorChars.put(0x22DE, 0x22DF); // EQUAL TO OR PRECEDES
747:                mirrorChars.put(0x22DF, 0x22DE); // EQUAL TO OR SUCCEEDS
748:                mirrorChars.put(0x22E0, 0x22E1); // [BEST FIT] DOES NOT PRECEDE OR EQUAL
749:                mirrorChars.put(0x22E1, 0x22E0); // [BEST FIT] DOES NOT SUCCEED OR EQUAL
750:                mirrorChars.put(0x22E2, 0x22E3); // [BEST FIT] NOT SQUARE IMAGE OF OR EQUAL TO
751:                mirrorChars.put(0x22E3, 0x22E2); // [BEST FIT] NOT SQUARE ORIGINAL OF OR EQUAL TO
752:                mirrorChars.put(0x22E4, 0x22E5); // [BEST FIT] SQUARE IMAGE OF OR NOT EQUAL TO
753:                mirrorChars.put(0x22E5, 0x22E4); // [BEST FIT] SQUARE ORIGINAL OF OR NOT EQUAL TO
754:                mirrorChars.put(0x22E6, 0x22E7); // [BEST FIT] LESS-THAN BUT NOT EQUIVALENT TO
755:                mirrorChars.put(0x22E7, 0x22E6); // [BEST FIT] GREATER-THAN BUT NOT EQUIVALENT TO
756:                mirrorChars.put(0x22E8, 0x22E9); // [BEST FIT] PRECEDES BUT NOT EQUIVALENT TO
757:                mirrorChars.put(0x22E9, 0x22E8); // [BEST FIT] SUCCEEDS BUT NOT EQUIVALENT TO
758:                mirrorChars.put(0x22EA, 0x22EB); // [BEST FIT] NOT NORMAL SUBGROUP OF
759:                mirrorChars.put(0x22EB, 0x22EA); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP
760:                mirrorChars.put(0x22EC, 0x22ED); // [BEST FIT] NOT NORMAL SUBGROUP OF OR EQUAL TO
761:                mirrorChars.put(0x22ED, 0x22EC); // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
762:                mirrorChars.put(0x22F0, 0x22F1); // UP RIGHT DIAGONAL ELLIPSIS
763:                mirrorChars.put(0x22F1, 0x22F0); // DOWN RIGHT DIAGONAL ELLIPSIS
764:                mirrorChars.put(0x22F2, 0x22FA); // ELEMENT OF WITH LONG HORIZONTAL STROKE
765:                mirrorChars.put(0x22F3, 0x22FB); // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
766:                mirrorChars.put(0x22F4, 0x22FC); // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
767:                mirrorChars.put(0x22F6, 0x22FD); // ELEMENT OF WITH OVERBAR
768:                mirrorChars.put(0x22F7, 0x22FE); // SMALL ELEMENT OF WITH OVERBAR
769:                mirrorChars.put(0x22FA, 0x22F2); // CONTAINS WITH LONG HORIZONTAL STROKE
770:                mirrorChars.put(0x22FB, 0x22F3); // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
771:                mirrorChars.put(0x22FC, 0x22F4); // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
772:                mirrorChars.put(0x22FD, 0x22F6); // CONTAINS WITH OVERBAR
773:                mirrorChars.put(0x22FE, 0x22F7); // SMALL CONTAINS WITH OVERBAR
774:                mirrorChars.put(0x2308, 0x2309); // LEFT CEILING
775:                mirrorChars.put(0x2309, 0x2308); // RIGHT CEILING
776:                mirrorChars.put(0x230A, 0x230B); // LEFT FLOOR
777:                mirrorChars.put(0x230B, 0x230A); // RIGHT FLOOR
778:                mirrorChars.put(0x2329, 0x232A); // LEFT-POINTING ANGLE BRACKET
779:                mirrorChars.put(0x232A, 0x2329); // RIGHT-POINTING ANGLE BRACKET
780:                mirrorChars.put(0x2768, 0x2769); // MEDIUM LEFT PARENTHESIS ORNAMENT
781:                mirrorChars.put(0x2769, 0x2768); // MEDIUM RIGHT PARENTHESIS ORNAMENT
782:                mirrorChars.put(0x276A, 0x276B); // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
783:                mirrorChars.put(0x276B, 0x276A); // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
784:                mirrorChars.put(0x276C, 0x276D); // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
785:                mirrorChars.put(0x276D, 0x276C); // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
786:                mirrorChars.put(0x276E, 0x276F); // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
787:                mirrorChars.put(0x276F, 0x276E); // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
788:                mirrorChars.put(0x2770, 0x2771); // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
789:                mirrorChars.put(0x2771, 0x2770); // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
790:                mirrorChars.put(0x2772, 0x2773); // LIGHT LEFT TORTOISE SHELL BRACKET
791:                mirrorChars.put(0x2773, 0x2772); // LIGHT RIGHT TORTOISE SHELL BRACKET
792:                mirrorChars.put(0x2774, 0x2775); // MEDIUM LEFT CURLY BRACKET ORNAMENT
793:                mirrorChars.put(0x2775, 0x2774); // MEDIUM RIGHT CURLY BRACKET ORNAMENT
794:                mirrorChars.put(0x27D5, 0x27D6); // LEFT OUTER JOIN
795:                mirrorChars.put(0x27D6, 0x27D5); // RIGHT OUTER JOIN
796:                mirrorChars.put(0x27DD, 0x27DE); // LONG RIGHT TACK
797:                mirrorChars.put(0x27DE, 0x27DD); // LONG LEFT TACK
798:                mirrorChars.put(0x27E2, 0x27E3); // WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
799:                mirrorChars.put(0x27E3, 0x27E2); // WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
800:                mirrorChars.put(0x27E4, 0x27E5); // WHITE SQUARE WITH LEFTWARDS TICK
801:                mirrorChars.put(0x27E5, 0x27E4); // WHITE SQUARE WITH RIGHTWARDS TICK
802:                mirrorChars.put(0x27E6, 0x27E7); // MATHEMATICAL LEFT WHITE SQUARE BRACKET
803:                mirrorChars.put(0x27E7, 0x27E6); // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
804:                mirrorChars.put(0x27E8, 0x27E9); // MATHEMATICAL LEFT ANGLE BRACKET
805:                mirrorChars.put(0x27E9, 0x27E8); // MATHEMATICAL RIGHT ANGLE BRACKET
806:                mirrorChars.put(0x27EA, 0x27EB); // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
807:                mirrorChars.put(0x27EB, 0x27EA); // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
808:                mirrorChars.put(0x2983, 0x2984); // LEFT WHITE CURLY BRACKET
809:                mirrorChars.put(0x2984, 0x2983); // RIGHT WHITE CURLY BRACKET
810:                mirrorChars.put(0x2985, 0x2986); // LEFT WHITE PARENTHESIS
811:                mirrorChars.put(0x2986, 0x2985); // RIGHT WHITE PARENTHESIS
812:                mirrorChars.put(0x2987, 0x2988); // Z NOTATION LEFT IMAGE BRACKET
813:                mirrorChars.put(0x2988, 0x2987); // Z NOTATION RIGHT IMAGE BRACKET
814:                mirrorChars.put(0x2989, 0x298A); // Z NOTATION LEFT BINDING BRACKET
815:                mirrorChars.put(0x298A, 0x2989); // Z NOTATION RIGHT BINDING BRACKET
816:                mirrorChars.put(0x298B, 0x298C); // LEFT SQUARE BRACKET WITH UNDERBAR
817:                mirrorChars.put(0x298C, 0x298B); // RIGHT SQUARE BRACKET WITH UNDERBAR
818:                mirrorChars.put(0x298D, 0x2990); // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
819:                mirrorChars.put(0x298E, 0x298F); // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
820:                mirrorChars.put(0x298F, 0x298E); // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
821:                mirrorChars.put(0x2990, 0x298D); // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
822:                mirrorChars.put(0x2991, 0x2992); // LEFT ANGLE BRACKET WITH DOT
823:                mirrorChars.put(0x2992, 0x2991); // RIGHT ANGLE BRACKET WITH DOT
824:                mirrorChars.put(0x2993, 0x2994); // LEFT ARC LESS-THAN BRACKET
825:                mirrorChars.put(0x2994, 0x2993); // RIGHT ARC GREATER-THAN BRACKET
826:                mirrorChars.put(0x2995, 0x2996); // DOUBLE LEFT ARC GREATER-THAN BRACKET
827:                mirrorChars.put(0x2996, 0x2995); // DOUBLE RIGHT ARC LESS-THAN BRACKET
828:                mirrorChars.put(0x2997, 0x2998); // LEFT BLACK TORTOISE SHELL BRACKET
829:                mirrorChars.put(0x2998, 0x2997); // RIGHT BLACK TORTOISE SHELL BRACKET
830:                mirrorChars.put(0x29B8, 0x2298); // CIRCLED REVERSE SOLIDUS
831:                mirrorChars.put(0x29C0, 0x29C1); // CIRCLED LESS-THAN
832:                mirrorChars.put(0x29C1, 0x29C0); // CIRCLED GREATER-THAN
833:                mirrorChars.put(0x29C4, 0x29C5); // SQUARED RISING DIAGONAL SLASH
834:                mirrorChars.put(0x29C5, 0x29C4); // SQUARED FALLING DIAGONAL SLASH
835:                mirrorChars.put(0x29CF, 0x29D0); // LEFT TRIANGLE BESIDE VERTICAL BAR
836:                mirrorChars.put(0x29D0, 0x29CF); // VERTICAL BAR BESIDE RIGHT TRIANGLE
837:                mirrorChars.put(0x29D1, 0x29D2); // BOWTIE WITH LEFT HALF BLACK
838:                mirrorChars.put(0x29D2, 0x29D1); // BOWTIE WITH RIGHT HALF BLACK
839:                mirrorChars.put(0x29D4, 0x29D5); // TIMES WITH LEFT HALF BLACK
840:                mirrorChars.put(0x29D5, 0x29D4); // TIMES WITH RIGHT HALF BLACK
841:                mirrorChars.put(0x29D8, 0x29D9); // LEFT WIGGLY FENCE
842:                mirrorChars.put(0x29D9, 0x29D8); // RIGHT WIGGLY FENCE
843:                mirrorChars.put(0x29DA, 0x29DB); // LEFT DOUBLE WIGGLY FENCE
844:                mirrorChars.put(0x29DB, 0x29DA); // RIGHT DOUBLE WIGGLY FENCE
845:                mirrorChars.put(0x29F5, 0x2215); // REVERSE SOLIDUS OPERATOR
846:                mirrorChars.put(0x29F8, 0x29F9); // BIG SOLIDUS
847:                mirrorChars.put(0x29F9, 0x29F8); // BIG REVERSE SOLIDUS
848:                mirrorChars.put(0x29FC, 0x29FD); // LEFT-POINTING CURVED ANGLE BRACKET
849:                mirrorChars.put(0x29FD, 0x29FC); // RIGHT-POINTING CURVED ANGLE BRACKET
850:                mirrorChars.put(0x2A2B, 0x2A2C); // MINUS SIGN WITH FALLING DOTS
851:                mirrorChars.put(0x2A2C, 0x2A2B); // MINUS SIGN WITH RISING DOTS
852:                mirrorChars.put(0x2A2D, 0x2A2C); // PLUS SIGN IN LEFT HALF CIRCLE
853:                mirrorChars.put(0x2A2E, 0x2A2D); // PLUS SIGN IN RIGHT HALF CIRCLE
854:                mirrorChars.put(0x2A34, 0x2A35); // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
855:                mirrorChars.put(0x2A35, 0x2A34); // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
856:                mirrorChars.put(0x2A3C, 0x2A3D); // INTERIOR PRODUCT
857:                mirrorChars.put(0x2A3D, 0x2A3C); // RIGHTHAND INTERIOR PRODUCT
858:                mirrorChars.put(0x2A64, 0x2A65); // Z NOTATION DOMAIN ANTIRESTRICTION
859:                mirrorChars.put(0x2A65, 0x2A64); // Z NOTATION RANGE ANTIRESTRICTION
860:                mirrorChars.put(0x2A79, 0x2A7A); // LESS-THAN WITH CIRCLE INSIDE
861:                mirrorChars.put(0x2A7A, 0x2A79); // GREATER-THAN WITH CIRCLE INSIDE
862:                mirrorChars.put(0x2A7D, 0x2A7E); // LESS-THAN OR SLANTED EQUAL TO
863:                mirrorChars.put(0x2A7E, 0x2A7D); // GREATER-THAN OR SLANTED EQUAL TO
864:                mirrorChars.put(0x2A7F, 0x2A80); // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
865:                mirrorChars.put(0x2A80, 0x2A7F); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
866:                mirrorChars.put(0x2A81, 0x2A82); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
867:                mirrorChars.put(0x2A82, 0x2A81); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
868:                mirrorChars.put(0x2A83, 0x2A84); // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
869:                mirrorChars.put(0x2A84, 0x2A83); // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
870:                mirrorChars.put(0x2A8B, 0x2A8C); // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
871:                mirrorChars.put(0x2A8C, 0x2A8B); // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
872:                mirrorChars.put(0x2A91, 0x2A92); // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
873:                mirrorChars.put(0x2A92, 0x2A91); // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
874:                mirrorChars.put(0x2A93, 0x2A94); // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
875:                mirrorChars.put(0x2A94, 0x2A93); // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
876:                mirrorChars.put(0x2A95, 0x2A96); // SLANTED EQUAL TO OR LESS-THAN
877:                mirrorChars.put(0x2A96, 0x2A95); // SLANTED EQUAL TO OR GREATER-THAN
878:                mirrorChars.put(0x2A97, 0x2A98); // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
879:                mirrorChars.put(0x2A98, 0x2A97); // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
880:                mirrorChars.put(0x2A99, 0x2A9A); // DOUBLE-LINE EQUAL TO OR LESS-THAN
881:                mirrorChars.put(0x2A9A, 0x2A99); // DOUBLE-LINE EQUAL TO OR GREATER-THAN
882:                mirrorChars.put(0x2A9B, 0x2A9C); // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
883:                mirrorChars.put(0x2A9C, 0x2A9B); // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
884:                mirrorChars.put(0x2AA1, 0x2AA2); // DOUBLE NESTED LESS-THAN
885:                mirrorChars.put(0x2AA2, 0x2AA1); // DOUBLE NESTED GREATER-THAN
886:                mirrorChars.put(0x2AA6, 0x2AA7); // LESS-THAN CLOSED BY CURVE
887:                mirrorChars.put(0x2AA7, 0x2AA6); // GREATER-THAN CLOSED BY CURVE
888:                mirrorChars.put(0x2AA8, 0x2AA9); // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
889:                mirrorChars.put(0x2AA9, 0x2AA8); // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
890:                mirrorChars.put(0x2AAA, 0x2AAB); // SMALLER THAN
891:                mirrorChars.put(0x2AAB, 0x2AAA); // LARGER THAN
892:                mirrorChars.put(0x2AAC, 0x2AAD); // SMALLER THAN OR EQUAL TO
893:                mirrorChars.put(0x2AAD, 0x2AAC); // LARGER THAN OR EQUAL TO
894:                mirrorChars.put(0x2AAF, 0x2AB0); // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
895:                mirrorChars.put(0x2AB0, 0x2AAF); // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
896:                mirrorChars.put(0x2AB3, 0x2AB4); // PRECEDES ABOVE EQUALS SIGN
897:                mirrorChars.put(0x2AB4, 0x2AB3); // SUCCEEDS ABOVE EQUALS SIGN
898:                mirrorChars.put(0x2ABB, 0x2ABC); // DOUBLE PRECEDES
899:                mirrorChars.put(0x2ABC, 0x2ABB); // DOUBLE SUCCEEDS
900:                mirrorChars.put(0x2ABD, 0x2ABE); // SUBSET WITH DOT
901:                mirrorChars.put(0x2ABE, 0x2ABD); // SUPERSET WITH DOT
902:                mirrorChars.put(0x2ABF, 0x2AC0); // SUBSET WITH PLUS SIGN BELOW
903:                mirrorChars.put(0x2AC0, 0x2ABF); // SUPERSET WITH PLUS SIGN BELOW
904:                mirrorChars.put(0x2AC1, 0x2AC2); // SUBSET WITH MULTIPLICATION SIGN BELOW
905:                mirrorChars.put(0x2AC2, 0x2AC1); // SUPERSET WITH MULTIPLICATION SIGN BELOW
906:                mirrorChars.put(0x2AC3, 0x2AC4); // SUBSET OF OR EQUAL TO WITH DOT ABOVE
907:                mirrorChars.put(0x2AC4, 0x2AC3); // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
908:                mirrorChars.put(0x2AC5, 0x2AC6); // SUBSET OF ABOVE EQUALS SIGN
909:                mirrorChars.put(0x2AC6, 0x2AC5); // SUPERSET OF ABOVE EQUALS SIGN
910:                mirrorChars.put(0x2ACD, 0x2ACE); // SQUARE LEFT OPEN BOX OPERATOR
911:                mirrorChars.put(0x2ACE, 0x2ACD); // SQUARE RIGHT OPEN BOX OPERATOR
912:                mirrorChars.put(0x2ACF, 0x2AD0); // CLOSED SUBSET
913:                mirrorChars.put(0x2AD0, 0x2ACF); // CLOSED SUPERSET
914:                mirrorChars.put(0x2AD1, 0x2AD2); // CLOSED SUBSET OR EQUAL TO
915:                mirrorChars.put(0x2AD2, 0x2AD1); // CLOSED SUPERSET OR EQUAL TO
916:                mirrorChars.put(0x2AD3, 0x2AD4); // SUBSET ABOVE SUPERSET
917:                mirrorChars.put(0x2AD4, 0x2AD3); // SUPERSET ABOVE SUBSET
918:                mirrorChars.put(0x2AD5, 0x2AD6); // SUBSET ABOVE SUBSET
919:                mirrorChars.put(0x2AD6, 0x2AD5); // SUPERSET ABOVE SUPERSET
920:                mirrorChars.put(0x2ADE, 0x22A6); // SHORT LEFT TACK
921:                mirrorChars.put(0x2AE3, 0x22A9); // DOUBLE VERTICAL BAR LEFT TURNSTILE
922:                mirrorChars.put(0x2AE4, 0x22A8); // VERTICAL BAR DOUBLE LEFT TURNSTILE
923:                mirrorChars.put(0x2AE5, 0x22AB); // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
924:                mirrorChars.put(0x2AEC, 0x2AED); // DOUBLE STROKE NOT SIGN
925:                mirrorChars.put(0x2AED, 0x2AEC); // REVERSED DOUBLE STROKE NOT SIGN
926:                mirrorChars.put(0x2AF7, 0x2AF8); // TRIPLE NESTED LESS-THAN
927:                mirrorChars.put(0x2AF8, 0x2AF7); // TRIPLE NESTED GREATER-THAN
928:                mirrorChars.put(0x2AF9, 0x2AFA); // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
929:                mirrorChars.put(0x2AFA, 0x2AF9); // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
930:                mirrorChars.put(0x3008, 0x3009); // LEFT ANGLE BRACKET
931:                mirrorChars.put(0x3009, 0x3008); // RIGHT ANGLE BRACKET
932:                mirrorChars.put(0x300A, 0x300B); // LEFT DOUBLE ANGLE BRACKET
933:                mirrorChars.put(0x300B, 0x300A); // RIGHT DOUBLE ANGLE BRACKET
934:                mirrorChars.put(0x300C, 0x300D); // [BEST FIT] LEFT CORNER BRACKET
935:                mirrorChars.put(0x300D, 0x300C); // [BEST FIT] RIGHT CORNER BRACKET
936:                mirrorChars.put(0x300E, 0x300F); // [BEST FIT] LEFT WHITE CORNER BRACKET
937:                mirrorChars.put(0x300F, 0x300E); // [BEST FIT] RIGHT WHITE CORNER BRACKET
938:                mirrorChars.put(0x3010, 0x3011); // LEFT BLACK LENTICULAR BRACKET
939:                mirrorChars.put(0x3011, 0x3010); // RIGHT BLACK LENTICULAR BRACKET
940:                mirrorChars.put(0x3014, 0x3015); // LEFT TORTOISE SHELL BRACKET
941:                mirrorChars.put(0x3015, 0x3014); // RIGHT TORTOISE SHELL BRACKET
942:                mirrorChars.put(0x3016, 0x3017); // LEFT WHITE LENTICULAR BRACKET
943:                mirrorChars.put(0x3017, 0x3016); // RIGHT WHITE LENTICULAR BRACKET
944:                mirrorChars.put(0x3018, 0x3019); // LEFT WHITE TORTOISE SHELL BRACKET
945:                mirrorChars.put(0x3019, 0x3018); // RIGHT WHITE TORTOISE SHELL BRACKET
946:                mirrorChars.put(0x301A, 0x301B); // LEFT WHITE SQUARE BRACKET
947:                mirrorChars.put(0x301B, 0x301A); // RIGHT WHITE SQUARE BRACKET
948:                mirrorChars.put(0xFF08, 0xFF09); // FULLWIDTH LEFT PARENTHESIS
949:                mirrorChars.put(0xFF09, 0xFF08); // FULLWIDTH RIGHT PARENTHESIS
950:                mirrorChars.put(0xFF1C, 0xFF1E); // FULLWIDTH LESS-THAN SIGN
951:                mirrorChars.put(0xFF1E, 0xFF1C); // FULLWIDTH GREATER-THAN SIGN
952:                mirrorChars.put(0xFF3B, 0xFF3D); // FULLWIDTH LEFT SQUARE BRACKET
953:                mirrorChars.put(0xFF3D, 0xFF3B); // FULLWIDTH RIGHT SQUARE BRACKET
954:                mirrorChars.put(0xFF5B, 0xFF5D); // FULLWIDTH LEFT CURLY BRACKET
955:                mirrorChars.put(0xFF5D, 0xFF5B); // FULLWIDTH RIGHT CURLY BRACKET
956:                mirrorChars.put(0xFF5F, 0xFF60); // FULLWIDTH LEFT WHITE PARENTHESIS
957:                mirrorChars.put(0xFF60, 0xFF5F); // FULLWIDTH RIGHT WHITE PARENTHESIS
958:                mirrorChars.put(0xFF62, 0xFF63); // [BEST FIT] HALFWIDTH LEFT CORNER BRACKET
959:                mirrorChars.put(0xFF63, 0xFF62); // [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET
960:            }
961:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.