KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfEncodings


1 /*
2  * Copyright 2002 Paulo Soares
3  *
4  * The contents of this file are subject to the Mozilla Public License Version 1.1
5  * (the "License"); you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the License.
11  *
12  * The Original Code is 'iText, a free JAVA-PDF library'.
13  *
14  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
15  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
16  * All Rights Reserved.
17  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
18  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
19  *
20  * Contributor(s): all the names of the contributors are added in the source code
21  * where applicable.
22  *
23  * Alternatively, the contents of this file may be used under the terms of the
24  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
25  * provisions of LGPL are applicable instead of those above. If you wish to
26  * allow use of your version of this file only under the terms of the LGPL
27  * License and not to allow others to use your version of this file under
28  * the MPL, indicate your decision by deleting the provisions above and
29  * replace them with the notice and other provisions required by the LGPL.
30  * If you do not delete the provisions above, a recipient may use your version
31  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
32  *
33  * This library is free software; you can redistribute it and/or modify it
34  * under the terms of the MPL as stated above or under the terms of the GNU
35  * Library General Public License as published by the Free Software Foundation;
36  * either version 2 of the License, or any later version.
37  *
38  * This library is distributed in the hope that it will be useful, but WITHOUT
39  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
41  * details.
42  *
43  * If you didn't download this code from the following link, you should check if
44  * you aren't using an obsolete version:
45  * http://www.lowagie.com/iText/
46  */

47
48 package com.lowagie.text.pdf;
49 import java.io.BufferedReader JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.io.InputStreamReader JavaDoc;
53 import java.io.UnsupportedEncodingException JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.StringTokenizer JavaDoc;
57
58 import com.lowagie.text.ExceptionConverter;
59 /** Supports fast encodings for winansi and PDFDocEncoding.
60  * Supports conversions from CJK encodings to CID.
61  * Supports custom encodings.
62  * @author Paulo Soares (psoares@consiste.pt)
63  */

64 public class PdfEncodings {
65     protected static final int CIDNONE = 0;
66     protected static final int CIDRANGE = 1;
67     protected static final int CIDCHAR = 2;
68
69     static final char winansiByteToChar[] = {
70         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
71         16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
72         32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
73         48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
74         64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
75         80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
76         96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
77         112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
78         8364, 65533, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 65533, 381, 65533,
79         65533, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 65533, 382, 376,
80         160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
81         176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
82         192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
83         208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
84         224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
85         240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
86         
87     static final char pdfEncodingByteToChar[] = {
88         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
89         16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
90         32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
91         48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
92         64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
93         80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
94         96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
95         112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
96         0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018,
97         0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 65533,
98         0x20ac, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
99         176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
100         192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
101         208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
102         224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
103         240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255};
104         
105     static final IntHashtable winansi = new IntHashtable();
106     
107     static final IntHashtable pdfEncoding = new IntHashtable();
108     
109     static final HashMap JavaDoc extraEncodings = new HashMap JavaDoc();
110     
111     static {
112         for (int k = 128; k < 160; ++k) {
113             char c = winansiByteToChar[k];
114             if (c != 65533)
115                 winansi.put(c, k);
116         }
117
118         for (int k = 128; k < 161; ++k) {
119             char c = pdfEncodingByteToChar[k];
120             if (c != 65533)
121                 pdfEncoding.put(c, k);
122         }
123         
124         addExtraEncoding("Wingdings", new WingdingsConversion());
125         addExtraEncoding("Symbol", new SymbolConversion(true));
126         addExtraEncoding("ZapfDingbats", new SymbolConversion(false));
127         addExtraEncoding("SymbolTT", new SymbolTTConversion());
128         addExtraEncoding("Cp437", new Cp437Conversion());
129     }
130
131     /** Converts a <CODE>String</CODE> to a </CODE>byte</CODE> array according
132      * to the font's encoding.
133      * @return an array of <CODE>byte</CODE> representing the conversion according to the font's encoding
134      * @param encoding the encoding
135      * @param text the <CODE>String</CODE> to be converted
136      */

137     public static final byte[] convertToBytes(String JavaDoc text, String JavaDoc encoding) {
138         if (text == null)
139             return new byte[0];
140         if (encoding == null || encoding.length() == 0) {
141             int len = text.length();
142             byte b[] = new byte[len];
143             for (int k = 0; k < len; ++k)
144                 b[k] = (byte)text.charAt(k);
145             return b;
146         }
147         ExtraEncoding extra = null;
148         synchronized (extraEncodings) {
149             extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
150         }
151         if (extra != null) {
152             byte b[] = extra.charToByte(text, encoding);
153             if (b != null)
154                 return b;
155         }
156         IntHashtable hash = null;
157         if (encoding.equals(BaseFont.WINANSI))
158             hash = winansi;
159         else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
160             hash = pdfEncoding;
161         if (hash != null) {
162             char cc[] = text.toCharArray();
163             int len = cc.length;
164             int ptr = 0;
165             byte b[] = new byte[len];
166             int c = 0;
167             for (int k = 0; k < len; ++k) {
168                 char char1 = cc[k];
169                 if (char1 < 128 || (char1 >= 160 && char1 <= 255))
170                     c = char1;
171                 else
172                     c = hash.get(char1);
173                 if (c != 0)
174                     b[ptr++] = (byte)c;
175             }
176             if (ptr == len)
177                 return b;
178             byte b2[] = new byte[ptr];
179             System.arraycopy(b, 0, b2, 0, ptr);
180             return b2;
181         }
182         if (encoding.equals(PdfObject.TEXT_UNICODE)) {
183             // workaround for jdk 1.2.2 bug
184
char cc[] = text.toCharArray();
185             int len = cc.length;
186             byte b[] = new byte[cc.length * 2 + 2];
187             b[0] = -2;
188             b[1] = -1;
189             int bptr = 2;
190             for (int k = 0; k < len; ++k) {
191                 char c = cc[k];
192                 b[bptr++] = (byte)(c >> 8);
193                 b[bptr++] = (byte)(c & 0xff);
194             }
195             return b;
196         }
197         try {
198             return text.getBytes(encoding);
199         }
200         catch (UnsupportedEncodingException JavaDoc e) {
201             throw new ExceptionConverter(e);
202         }
203     }
204     
205     /** Converts a </CODE>byte</CODE> array to a <CODE>String</CODE> according
206      * to the some encoding.
207      * @param bytes the bytes to convert
208      * @param encoding the encoding
209      * @return the converted <CODE>String</CODE>
210      */

211     public static final String JavaDoc convertToString(byte bytes[], String JavaDoc encoding) {
212         if (bytes == null)
213             return PdfObject.NOTHING;
214         if (encoding == null || encoding.length() == 0) {
215             char c[] = new char[bytes.length];
216             for (int k = 0; k < bytes.length; ++k)
217                 c[k] = (char)(bytes[k] & 0xff);
218             return new String JavaDoc(c);
219         }
220         ExtraEncoding extra = null;
221         synchronized (extraEncodings) {
222             extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
223         }
224         if (extra != null) {
225             String JavaDoc text = extra.byteToChar(bytes, encoding);
226             if (text != null)
227                 return text;
228         }
229         char ch[] = null;
230         if (encoding.equals(BaseFont.WINANSI))
231             ch = winansiByteToChar;
232         else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
233             ch = pdfEncodingByteToChar;
234         if (ch != null) {
235             int len = bytes.length;
236             char c[] = new char[len];
237             for (int k = 0; k < len; ++k) {
238                 c[k] = ch[bytes[k] & 0xff];
239             }
240             return new String JavaDoc(c);
241         }
242         try {
243             return new String JavaDoc(bytes, encoding);
244         }
245         catch (UnsupportedEncodingException JavaDoc e) {
246             throw new ExceptionConverter(e);
247         }
248     }
249     
250     /** Checks is <CODE>text</CODE> only has PdfDocEncoding characters.
251      * @param text the <CODE>String</CODE> to test
252      * @return <CODE>true</CODE> if only PdfDocEncoding characters are present
253      */

254     public static boolean isPdfDocEncoding(String JavaDoc text) {
255         if (text == null)
256             return true;
257         int len = text.length();
258         for (int k = 0; k < len; ++k) {
259             char char1 = text.charAt(k);
260             if (char1 < 128 || (char1 >= 160 && char1 <= 255))
261                 continue;
262             if (!pdfEncoding.containsKey(char1))
263                 return false;
264         }
265         return true;
266     }
267     
268     static final HashMap JavaDoc cmaps = new HashMap JavaDoc();
269     /** Assumes that '\\n' and '\\r\\n' are the newline sequences. It may not work for
270      * all CJK encodings. To be used with loadCmap().
271      */

272     public static final byte CRLF_CID_NEWLINE[][] = new byte[][]{{(byte)'\n'}, {(byte)'\r', (byte)'\n'}};
273
274     /** Clears the CJK cmaps from the cache. If <CODE>name</CODE> is the
275      * empty string then all the cache is cleared. Calling this method
276      * has no consequences other than the need to reload the cmap
277      * if needed.
278      * @param name the name of the cmap to clear or all the cmaps if the empty string
279      */

280     public static void clearCmap(String JavaDoc name) {
281         synchronized (cmaps) {
282             if (name.length() == 0)
283                 cmaps.clear();
284             else
285                 cmaps.remove(name);
286         }
287     }
288     
289     /** Loads a CJK cmap to the cache with the option of associating
290      * sequences to the newline.
291      * @param name the CJK cmap name
292      * @param newline the sequences to be replaced bi a newline in the resulting CID. See <CODE>CRLF_CID_NEWLINE</CODE>
293      */

294     public static void loadCmap(String JavaDoc name, byte newline[][]) {
295         try {
296             char planes[][] = null;
297             synchronized (cmaps) {
298                 planes = (char[][])cmaps.get(name);
299             }
300             if (planes == null) {
301                 planes = readCmap(name, newline);
302                 synchronized (cmaps) {
303                     cmaps.put(name, planes);
304                 }
305             }
306         }
307         catch (IOException JavaDoc e) {
308             throw new ExceptionConverter(e);
309         }
310     }
311     
312     /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
313      * to a CID string. This is needed to reach some CJK characters
314      * that don't exist in 16 bit Unicode.</p>
315      * The font to use this result must use the encoding "Identity-H"
316      * or "Identity-V".</p>
317      * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
318      * @param name the CJK encoding name
319      * @param seq the <CODE>byte</CODE> array to be decoded
320      * @return the CID string
321      */

322     public static String JavaDoc convertCmap(String JavaDoc name, byte seq[]) {
323         return convertCmap(name, seq, 0, seq.length);
324     }
325     
326     /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
327      * to a CID string. This is needed to reach some CJK characters
328      * that don't exist in 16 bit Unicode.</p>
329      * The font to use this result must use the encoding "Identity-H"
330      * or "Identity-V".</p>
331      * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
332      * @param name the CJK encoding name
333      * @param start the start offset in the data
334      * @param length the number of bytes to convert
335      * @param seq the <CODE>byte</CODE> array to be decoded
336      * @return the CID string
337      */

338     public static String JavaDoc convertCmap(String JavaDoc name, byte seq[], int start, int length) {
339         try {
340             char planes[][] = null;
341             synchronized (cmaps) {
342                 planes = (char[][])cmaps.get(name);
343             }
344             if (planes == null) {
345                 planes = readCmap(name, (byte[][])null);
346                 synchronized (cmaps) {
347                     cmaps.put(name, planes);
348                 }
349             }
350             return decodeSequence(seq, start, length, planes);
351         }
352         catch (IOException JavaDoc e) {
353             throw new ExceptionConverter(e);
354         }
355     }
356     
357     static String JavaDoc decodeSequence(byte seq[], int start, int length, char planes[][]) {
358         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
359         int end = start + length;
360         int currentPlane = 0;
361         for (int k = start; k < end; ++k) {
362             int one = (int)seq[k] & 0xff;
363             char plane[] = planes[currentPlane];
364             int cid = plane[one];
365             if ((cid & 0x8000) == 0) {
366                 buf.append((char)cid);
367                 currentPlane = 0;
368             }
369             else
370                 currentPlane = cid & 0x7fff;
371         }
372         return buf.toString();
373     }
374
375     static char[][] readCmap(String JavaDoc name, byte newline[][]) throws IOException JavaDoc {
376         ArrayList JavaDoc planes = new ArrayList JavaDoc();
377         planes.add(new char[256]);
378         readCmap(name, planes);
379         if (newline != null) {
380             for (int k = 0; k < newline.length; ++k)
381                 encodeSequence(newline[k].length, newline[k], BaseFont.CID_NEWLINE, planes);
382         }
383         char ret[][] = new char[planes.size()][];
384         return (char[][])planes.toArray(ret);
385     }
386     
387     static void readCmap(String JavaDoc name, ArrayList JavaDoc planes) throws IOException JavaDoc {
388         String JavaDoc fullName = BaseFont.RESOURCE_PATH + "cmaps/" + name;
389         InputStream JavaDoc in = BaseFont.getResourceStream(fullName);
390         if (in == null)
391             throw new IOException JavaDoc("The Cmap " + name + " was not found.");
392         encodeStream(in, planes);
393         in.close();
394     }
395     
396     static void encodeStream(InputStream JavaDoc in, ArrayList JavaDoc planes) throws IOException JavaDoc {
397         BufferedReader JavaDoc rd = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(in, "iso-8859-1"));
398         String JavaDoc line = null;
399         int state = CIDNONE;
400         byte seqs[] = new byte[7];
401         while ((line = rd.readLine()) != null) {
402             if (line.length() < 6)
403                 continue;
404             switch (state) {
405                 case CIDNONE: {
406                     if (line.indexOf("begincidrange") >= 0)
407                         state = CIDRANGE;
408                     else if (line.indexOf("begincidchar") >= 0)
409                         state = CIDCHAR;
410                     else if (line.indexOf("usecmap") >= 0) {
411                         StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(line);
412                         String JavaDoc t = tk.nextToken();
413                         readCmap(t.substring(1), planes);
414                     }
415                     break;
416                 }
417                 case CIDRANGE: {
418                     if (line.indexOf("endcidrange") >= 0) {
419                         state = CIDNONE;
420                         break;
421                     }
422                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(line);
423                     String JavaDoc t = tk.nextToken();
424                     int size = t.length() / 2 - 1;
425                     long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
426                     t = tk.nextToken();
427                     long end = Long.parseLong(t.substring(1, t.length() - 1), 16);
428                     t = tk.nextToken();
429                     int cid = Integer.parseInt(t);
430                     for (long k = start; k <= end; ++k) {
431                         breakLong(k, size, seqs);
432                         encodeSequence(size, seqs, (char)cid, planes);
433                         ++cid;
434                     }
435                     break;
436                 }
437                 case CIDCHAR: {
438                     if (line.indexOf("endcidchar") >= 0) {
439                         state = CIDNONE;
440                         break;
441                     }
442                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(line);
443                     String JavaDoc t = tk.nextToken();
444                     int size = t.length() / 2 - 1;
445                     long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
446                     t = tk.nextToken();
447                     int cid = Integer.parseInt(t);
448                     breakLong(start, size, seqs);
449                     encodeSequence(size, seqs, (char)cid, planes);
450                     break;
451                 }
452             }
453         }
454     }
455     
456     static void breakLong(long n, int size, byte seqs[]) {
457         for (int k = 0; k < size; ++k) {
458             seqs[k] = (byte)(n >> ((size - 1 - k) * 8));
459         }
460     }
461
462     static void encodeSequence(int size, byte seqs[], char cid, ArrayList JavaDoc planes) {
463         --size;
464         int nextPlane = 0;
465         for (int idx = 0; idx < size; ++idx) {
466             char plane[] = (char[])planes.get(nextPlane);
467             int one = (int)seqs[idx] & 0xff;
468             char c = plane[one];
469             if (c != 0 && (c & 0x8000) == 0)
470                 throw new RuntimeException JavaDoc("Inconsistent mapping.");
471             if (c == 0) {
472                 planes.add(new char[256]);
473                 c = (char)((planes.size() - 1) | 0x8000);
474                 plane[one] = c;
475             }
476             nextPlane = c & 0x7fff;
477         }
478         char plane[] = (char[])planes.get(nextPlane);
479         int one = (int)seqs[size] & 0xff;
480         char c = plane[one];
481         if ((c & 0x8000) != 0)
482             throw new RuntimeException JavaDoc("Inconsistent mapping.");
483         plane[one] = cid;
484     }
485
486     /** Adds an extra encoding.
487      * @param name the name of the encoding. The encoding recognition is case insensitive
488      * @param enc the conversion class
489      */

490     public static void addExtraEncoding(String JavaDoc name, ExtraEncoding enc) {
491         synchronized (extraEncodings) {
492             extraEncodings.put(name.toLowerCase(), enc);
493         }
494     }
495
496     private static class WingdingsConversion implements ExtraEncoding {
497         
498         public byte[] charToByte(String JavaDoc text, String JavaDoc encoding) {
499             char cc[] = text.toCharArray();
500             byte b[] = new byte[cc.length];
501             int ptr = 0;
502             int len = cc.length;
503             for (int k = 0; k < len; ++k) {
504                 char c = cc[k];
505                 if (c == ' ')
506                     b[ptr++] = (byte)c;
507                 else if (c >= '\u2701' && c <= '\u27BE') {
508                     byte v = table[c - 0x2700];
509                     if (v != 0)
510                         b[ptr++] = v;
511                 }
512             }
513             if (ptr == len)
514                 return b;
515             byte b2[] = new byte[ptr];
516             System.arraycopy(b, 0, b2, 0, ptr);
517             return b2;
518         }
519         
520         public String JavaDoc byteToChar(byte[] b, String JavaDoc encoding) {
521             return null;
522         }
523
524         private final static byte table[] = {
525             0, 35, 34, 0, 0, 0, 41, 62, 81, 42,
526             0, 0, 65, 63, 0, 0, 0, 0, 0, -4,
527             0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
528             86, 0, 88, 89, 0, 0, 0, 0, 0, 0,
529             0, 0, -75, 0, 0, 0, 0, 0, -74, 0,
530             0, 0, -83, -81, -84, 0, 0, 0, 0, 0,
531             0, 0, 0, 124, 123, 0, 0, 0, 84, 0,
532             0, 0, 0, 0, 0, 0, 0, -90, 0, 0,
533             0, 113, 114, 0, 0, 0, 117, 0, 0, 0,
534             0, 0, 0, 125, 126, 0, 0, 0, 0, 0,
535             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
536             0, 0, 0, 0, 0, 0, 0, 0, -116, -115,
537             -114, -113, -112, -111, -110, -109, -108, -107, -127, -126,
538             -125, -124, -123, -122, -121, -120, -119, -118, -116, -115,
539             -114, -113, -112, -111, -110, -109, -108, -107, -24, 0,
540             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
541             0, -24, -40, 0, 0, -60, -58, 0, 0, -16,
542             0, 0, 0, 0, 0, 0, 0, 0, 0, -36,
543             0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
544             0
545         };
546     }
547
548     private static class Cp437Conversion implements ExtraEncoding {
549         private static IntHashtable c2b = new IntHashtable();
550         
551         public byte[] charToByte(String JavaDoc text, String JavaDoc encoding) {
552             char cc[] = text.toCharArray();
553             byte b[] = new byte[cc.length];
554             int ptr = 0;
555             int len = cc.length;
556             for (int k = 0; k < len; ++k) {
557                 char c = cc[k];
558                 if (c < ' ')
559                     continue;
560                 if (c < 128)
561                     b[ptr++] = (byte)c;
562                 else {
563                     byte v = (byte)c2b.get(c);
564                     if (v != 0)
565                         b[ptr++] = v;
566                 }
567             }
568             if (ptr == len)
569                 return b;
570             byte b2[] = new byte[ptr];
571             System.arraycopy(b, 0, b2, 0, ptr);
572             return b2;
573         }
574         
575         public String JavaDoc byteToChar(byte[] b, String JavaDoc encoding) {
576             int len = b.length;
577             char cc[] = new char[len];
578             int ptr = 0;
579             for (int k = 0; k < len; ++k) {
580                 int c = b[k] & 0xff;
581                 if (c < ' ')
582                     continue;
583                 if (c < 128)
584                     cc[ptr++] = (char)c;
585                 else {
586                     char v = table[c - 128];
587                     cc[ptr++] = v;
588                 }
589             }
590             return new String JavaDoc(cc, 0, ptr);
591         }
592         
593         private final static char table[] = {
594             '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
595             '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
596             '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
597             '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
598             '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
599             '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
600             '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
601             '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0'
602         };
603         
604         static {
605             for (int k = 0; k < table.length; ++k)
606                 c2b.put(table[k], k + 128);
607         }
608     }
609     
610     private static class SymbolConversion implements ExtraEncoding {
611         
612         private static final IntHashtable t1 = new IntHashtable();
613         private static final IntHashtable t2 = new IntHashtable();
614         private IntHashtable translation;
615         
616         SymbolConversion(boolean symbol) {
617             if (symbol)
618                 translation = t1;
619             else
620                 translation = t2;
621         }
622         
623         public byte[] charToByte(String JavaDoc text, String JavaDoc encoding) {
624             char cc[] = text.toCharArray();
625             byte b[] = new byte[cc.length];
626             int ptr = 0;
627             int len = cc.length;
628             for (int k = 0; k < len; ++k) {
629                 char c = cc[k];
630                 byte v = (byte)translation.get((int)c);
631                 if (v != 0)
632                     b[ptr++] = v;
633             }
634             if (ptr == len)
635                 return b;
636             byte b2[] = new byte[ptr];
637             System.arraycopy(b, 0, b2, 0, ptr);
638             return b2;
639         }
640         
641         public String JavaDoc byteToChar(byte[] b, String JavaDoc encoding) {
642             return null;
643         }
644
645         private final static char table1[] = {
646             ' ','!','\u2200','#','\u2203','%','&','\u220b','(',')','*','+',',','-','.','/',
647             '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
648             '\u2245','\u0391','\u0392','\u03a7','\u0394','\u0395','\u03a6','\u0393','\u0397','\u0399','\u03d1','\u039a','\u039b','\u039c','\u039d','\u039f',
649             '\u03a0','\u0398','\u03a1','\u03a3','\u03a4','\u03a5','\u03c2','\u03a9','\u039e','\u03a8','\u0396','[','\u2234',']','\u22a5','_',
650             '\u0305','\u03b1','\u03b2','\u03c7','\u03b4','\u03b5','\u03d5','\u03b3','\u03b7','\u03b9','\u03c6','\u03ba','\u03bb','\u03bc','\u03bd','\u03bf',
651             '\u03c0','\u03b8','\u03c1','\u03c3','\u03c4','\u03c5','\u03d6','\u03c9','\u03be','\u03c8','\u03b6','{','|','}','~','\0',
652             '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
653             '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
654             '\u20ac','\u03d2','\u2032','\u2264','\u2044','\u221e','\u0192','\u2663','\u2666','\u2665','\u2660','\u2194','\u2190','\u2191','\u2192','\u2193',
655             '\u00b0','\u00b1','\u2033','\u2265','\u00d7','\u221d','\u2202','\u2022','\u00f7','\u2260','\u2261','\u2248','\u2026','\u2502','\u2500','\u21b5',
656             '\u2135','\u2111','\u211c','\u2118','\u2297','\u2295','\u2205','\u2229','\u222a','\u2283','\u2287','\u2284','\u2282','\u2286','\u2208','\u2209',
657             '\u2220','\u2207','\u00ae','\u00a9','\u2122','\u220f','\u221a','\u2022','\u00ac','\u2227','\u2228','\u21d4','\u21d0','\u21d1','\u21d2','\u21d3',
658             '\u25ca','\u2329','\0','\0','\0','\u2211','\u239b','\u239c','\u239d','\u23a1','\u23a2','\u23a3','\u23a7','\u23a8','\u23a9','\u23aa',
659             '\0','\u232a','\u222b','\u2320','\u23ae','\u2321','\u239e','\u239f','\u23a0','\u23a4','\u23a5','\u23a6','\u23ab','\u23ac','\u23ad','\0'
660         };
661
662         private final static char table2[] = {
663             '\u0020','\u2701','\u2702','\u2703','\u2704','\u260e','\u2706','\u2707','\u2708','\u2709','\u261b','\u261e','\u270C','\u270D','\u270E','\u270F',
664             '\u2710','\u2711','\u2712','\u2713','\u2714','\u2715','\u2716','\u2717','\u2718','\u2719','\u271A','\u271B','\u271C','\u271D','\u271E','\u271F',
665             '\u2720','\u2721','\u2722','\u2723','\u2724','\u2725','\u2726','\u2727','\u2605','\u2729','\u272A','\u272B','\u272C','\u272D','\u272E','\u272F',
666             '\u2730','\u2731','\u2732','\u2733','\u2734','\u2735','\u2736','\u2737','\u2738','\u2739','\u273A','\u273B','\u273C','\u273D','\u273E','\u273F',
667             '\u2740','\u2741','\u2742','\u2743','\u2744','\u2745','\u2746','\u2747','\u2748','\u2749','\u274A','\u274B','\u25cf','\u274D','\u25a0','\u274F',
668             '\u2750','\u2751','\u2752','\u25b2','\u25bc','\u25c6','\u2756','\u25d7','\u2758','\u2759','\u275A','\u275B','\u275C','\u275D','\u275E','\u0000',
669             '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
670             '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
671             '\u0000','\u2761','\u2762','\u2763','\u2764','\u2765','\u2766','\u2767','\u2663','\u2666','\u2665','\u2660','\u2460','\u2461','\u2462','\u2463',
672             '\u2464','\u2465','\u2466','\u2467','\u2468','\u2469','\u2776','\u2777','\u2778','\u2779','\u277A','\u277B','\u277C','\u277D','\u277E','\u277F',
673             '\u2780','\u2781','\u2782','\u2783','\u2784','\u2785','\u2786','\u2787','\u2788','\u2789','\u278A','\u278B','\u278C','\u278D','\u278E','\u278F',
674             '\u2790','\u2791','\u2792','\u2793','\u2794','\u2192','\u2194','\u2195','\u2798','\u2799','\u279A','\u279B','\u279C','\u279D','\u279E','\u279F',
675             '\u27A0','\u27A1','\u27A2','\u27A3','\u27A4','\u27A5','\u27A6','\u27A7','\u27A8','\u27A9','\u27AA','\u27AB','\u27AC','\u27AD','\u27AE','\u27AF',
676             '\u0000','\u27B1','\u27B2','\u27B3','\u27B4','\u27B5','\u27B6','\u27B7','\u27B8','\u27B9','\u27BA','\u27BB','\u27BC','\u27BD','\u27BE','\u0000'
677         };
678
679         static {
680             for (int k = 0; k < table1.length; ++k) {
681                 int v = (int)table1[k];
682                 if (v != 0)
683                     t1.put(v, k + 32);
684             }
685             for (int k = 0; k < table2.length; ++k) {
686                 int v = (int)table2[k];
687                 if (v != 0)
688                     t2.put(v, k + 32);
689             }
690         }
691     }
692     
693     private static class SymbolTTConversion implements ExtraEncoding {
694         
695         public byte[] charToByte(String JavaDoc text, String JavaDoc encoding) {
696             char ch[] = text.toCharArray();
697             byte b[] = new byte[ch.length];
698             int ptr = 0;
699             int len = ch.length;
700             for (int k = 0; k < len; ++k) {
701                 char c = ch[k];
702                 if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
703                     b[ptr++] = (byte)c;
704             }
705             if (ptr == len)
706                 return b;
707             byte b2[] = new byte[ptr];
708             System.arraycopy(b, 0, b2, 0, ptr);
709             return b2;
710         }
711         
712         public String JavaDoc byteToChar(byte[] b, String JavaDoc encoding) {
713             return null;
714         }
715         
716     }
717 }
718
Popular Tags