Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]
    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;
   50   import java.io.IOException;
   51   import java.io.InputStream;
   52   import java.io.InputStreamReader;
   53   import java.io.UnsupportedEncodingException;
   54   import java.util.ArrayList;
   55   import java.util.HashMap;
   56   import java.util.StringTokenizer;
   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 HashMap extraEncodings = new HashMap();
  110       
  111       static {        
  112           for (int k = 128; k < 161; ++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 text, String 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 = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
  148           if (extra != null) {
  149               byte b[] = extra.charToByte(text, encoding);
  150               if (b != null)
  151                   return b;
  152           }
  153           IntHashtable hash = null;
  154           if (encoding.equals(BaseFont.WINANSI))
  155               hash = winansi;
  156           else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
  157               hash = pdfEncoding;
  158           if (hash != null) {
  159               char cc[] = text.toCharArray();
  160               int len = cc.length;
  161               int ptr = 0;
  162               byte b[] = new byte[len];
  163               int c = 0;
  164               for (int k = 0; k < len; ++k) {
  165                   char char1 = cc[k];
  166                   if (char1 < 128 || (char1 > 160 && char1 <= 255))
  167                       c = char1;
  168                   else
  169                       c = hash.get(char1);
  170                   if (c != 0)
  171                       b[ptr++] = (byte)c;
  172               }
  173               if (ptr == len)
  174                   return b;
  175               byte b2[] = new byte[ptr];
  176               System.arraycopy(b, 0, b2, 0, ptr);
  177               return b2;
  178           }
  179           if (encoding.equals(PdfObject.TEXT_UNICODE)) {
  180               // workaround for jdk 1.2.2 bug
  181               char cc[] = text.toCharArray();
  182               int len = cc.length;
  183               byte b[] = new byte[cc.length * 2 + 2];
  184               b[0] = -2;
  185               b[1] = -1;
  186               int bptr = 2;
  187               for (int k = 0; k < len; ++k) {
  188                   char c = cc[k];
  189                   b[bptr++] = (byte)(c >> 8);
  190                   b[bptr++] = (byte)(c & 0xff);
  191               }
  192               return b;
  193           }
  194           try {
  195               return text.getBytes(encoding);
  196           }
  197           catch (UnsupportedEncodingException e) {
  198               throw new ExceptionConverter(e);
  199           }
  200       }
  201       
  202       /** Converts a <CODE>String</CODE> to a </CODE>byte</CODE> array according
  203        * to the font's encoding.
  204        * @return an array of <CODE>byte</CODE> representing the conversion according to the font's encoding
  205        * @param encoding the encoding
  206        * @param char1 the <CODE>char</CODE> to be converted
  207        */
  208       public static final byte[] convertToBytes(char char1, String encoding) {
  209           if (encoding == null || encoding.length() == 0)
  210               return new byte[]{(byte)char1};
  211           ExtraEncoding extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
  212           if (extra != null) {
  213               byte b[] = extra.charToByte(char1, encoding);
  214               if (b != null)
  215                   return b;
  216           }
  217           IntHashtable hash = null;
  218           if (encoding.equals(BaseFont.WINANSI))
  219               hash = winansi;
  220           else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
  221               hash = pdfEncoding;
  222           if (hash != null) {
  223               int c = 0;
  224               if (char1 < 128 || (char1 > 160 && char1 <= 255))
  225                   c = char1;
  226               else
  227                   c = hash.get(char1);
  228               if (c != 0)
  229                   return new byte[]{(byte)c};
  230               else
  231                   return new byte[0];
  232           }
  233           if (encoding.equals(PdfObject.TEXT_UNICODE)) {
  234               // workaround for jdk 1.2.2 bug
  235               byte b[] = new byte[4];
  236               b[0] = -2;
  237               b[1] = -1;
  238               b[2] = (byte)(char1 >> 8);
  239               b[3] = (byte)(char1 & 0xff);
  240               return b;
  241           }
  242           try {
  243               return String.valueOf(char1).getBytes(encoding);
  244           }
  245           catch (UnsupportedEncodingException e) {
  246               throw new ExceptionConverter(e);
  247           }
  248       }
  249       
  250       /** Converts a </CODE>byte</CODE> array to a <CODE>String</CODE> according
  251        * to the some encoding.
  252        * @param bytes the bytes to convert
  253        * @param encoding the encoding
  254        * @return the converted <CODE>String</CODE>
  255        */    
  256       public static final String convertToString(byte bytes[], String encoding) {
  257           if (bytes == null)
  258               return PdfObject.NOTHING;
  259           if (encoding == null || encoding.length() == 0) {
  260               char c[] = new char[bytes.length];
  261               for (int k = 0; k < bytes.length; ++k)
  262                   c[k] = (char)(bytes[k] & 0xff);
  263               return new String(c);
  264           }
  265           ExtraEncoding extra = (ExtraEncoding)extraEncodings.get(encoding.toLowerCase());
  266           if (extra != null) {
  267               String text = extra.byteToChar(bytes, encoding);
  268               if (text != null)
  269                   return text;
  270           }
  271           char ch[] = null;
  272           if (encoding.equals(BaseFont.WINANSI))
  273               ch = winansiByteToChar;
  274           else if (encoding.equals(PdfObject.TEXT_PDFDOCENCODING))
  275               ch = pdfEncodingByteToChar;
  276           if (ch != null) {
  277               int len = bytes.length;
  278               char c[] = new char[len];
  279               for (int k = 0; k < len; ++k) {
  280                   c[k] = ch[bytes[k] & 0xff];
  281               }
  282               return new String(c);
  283           }
  284           try {
  285               return new String(bytes, encoding);
  286           }
  287           catch (UnsupportedEncodingException e) {
  288               throw new ExceptionConverter(e);
  289           }
  290       }
  291       
  292       /** Checks is <CODE>text</CODE> only has PdfDocEncoding characters.
  293        * @param text the <CODE>String</CODE> to test
  294        * @return <CODE>true</CODE> if only PdfDocEncoding characters are present
  295        */    
  296       public static boolean isPdfDocEncoding(String text) {
  297           if (text == null)
  298               return true;
  299           int len = text.length();
  300           for (int k = 0; k < len; ++k) {
  301               char char1 = text.charAt(k);
  302               if (char1 < 128 || (char1 > 160 && char1 <= 255))
  303                   continue;
  304               if (!pdfEncoding.containsKey(char1))
  305                   return false;
  306           }
  307           return true;
  308       }
  309       
  310       static final HashMap cmaps = new HashMap();
  311       /** Assumes that '\\n' and '\\r\\n' are the newline sequences. It may not work for
  312        * all CJK encodings. To be used with loadCmap().
  313        */    
  314       public static final byte CRLF_CID_NEWLINE[][] = new byte[][]{{(byte)'\n'}, {(byte)'\r', (byte)'\n'}};
  315   
  316       /** Clears the CJK cmaps from the cache. If <CODE>name</CODE> is the
  317        * empty string then all the cache is cleared. Calling this method
  318        * has no consequences other than the need to reload the cmap
  319        * if needed.
  320        * @param name the name of the cmap to clear or all the cmaps if the empty string
  321        */    
  322       public static void clearCmap(String name) {
  323           synchronized (cmaps) {
  324               if (name.length() == 0)
  325                   cmaps.clear();
  326               else
  327                   cmaps.remove(name);
  328           }
  329       }
  330       
  331       /** Loads a CJK cmap to the cache with the option of associating
  332        * sequences to the newline.
  333        * @param name the CJK cmap name
  334        * @param newline the sequences to be replaced by a newline in the resulting CID. See <CODE>CRLF_CID_NEWLINE</CODE>
  335        */    
  336       public static void loadCmap(String name, byte newline[][]) {
  337           try {
  338               char planes[][] = null;
  339               synchronized (cmaps) {
  340                   planes = (char[][])cmaps.get(name);
  341               }
  342               if (planes == null) {
  343                   planes = readCmap(name, newline);
  344                   synchronized (cmaps) {
  345                       cmaps.put(name, planes);
  346                   }
  347               }
  348           }
  349           catch (IOException e) {
  350               throw new ExceptionConverter(e);
  351           }        
  352       }
  353       
  354       /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
  355        * to a CID string. This is needed to reach some CJK characters
  356        * that don't exist in 16 bit Unicode.</p>
  357        * The font to use this result must use the encoding "Identity-H"
  358        * or "Identity-V".</p>
  359        * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
  360        * @param name the CJK encoding name
  361        * @param seq the <CODE>byte</CODE> array to be decoded
  362        * @return the CID string
  363        */    
  364       public static String convertCmap(String name, byte seq[]) {
  365           return convertCmap(name, seq, 0, seq.length);
  366       }
  367       
  368       /** Converts a <CODE>byte</CODE> array encoded as <CODE>name</CODE>
  369        * to a CID string. This is needed to reach some CJK characters
  370        * that don't exist in 16 bit Unicode.</p>
  371        * The font to use this result must use the encoding "Identity-H"
  372        * or "Identity-V".</p>
  373        * See ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/.
  374        * @param name the CJK encoding name
  375        * @param start the start offset in the data
  376        * @param length the number of bytes to convert
  377        * @param seq the <CODE>byte</CODE> array to be decoded
  378        * @return the CID string
  379        */    
  380       public static String convertCmap(String name, byte seq[], int start, int length) {
  381           try {
  382               char planes[][] = null;
  383               synchronized (cmaps) {
  384                   planes = (char[][])cmaps.get(name);
  385               }
  386               if (planes == null) {
  387                   planes = readCmap(name, (byte[][])null);
  388                   synchronized (cmaps) {
  389                       cmaps.put(name, planes);
  390                   }
  391               }
  392               return decodeSequence(seq, start, length, planes);
  393           }
  394           catch (IOException e) {
  395               throw new ExceptionConverter(e);
  396           }        
  397       }
  398       
  399       static String decodeSequence(byte seq[], int start, int length, char planes[][]) {
  400           StringBuffer buf = new StringBuffer();
  401           int end = start + length;
  402           int currentPlane = 0;
  403           for (int k = start; k < end; ++k) {
  404               int one = seq[k] & 0xff;
  405               char plane[] = planes[currentPlane];
  406               int cid = plane[one];
  407               if ((cid & 0x8000) == 0) {
  408                   buf.append((char)cid);
  409                   currentPlane = 0;
  410               }
  411               else
  412                   currentPlane = cid & 0x7fff;
  413           }
  414           return buf.toString();
  415       }
  416   
  417       static char[][] readCmap(String name, byte newline[][]) throws IOException {
  418           ArrayList planes = new ArrayList();
  419           planes.add(new char[256]);
  420           readCmap(name, planes);
  421           if (newline != null) {
  422               for (int k = 0; k < newline.length; ++k)
  423                   encodeSequence(newline[k].length, newline[k], BaseFont.CID_NEWLINE, planes);
  424           }
  425           char ret[][] = new char[planes.size()][];
  426           return (char[][])planes.toArray(ret);
  427       }
  428       
  429       static void readCmap(String name, ArrayList planes) throws IOException {
  430           String fullName = BaseFont.RESOURCE_PATH + "cmaps/" + name;
  431           InputStream in = BaseFont.getResourceStream(fullName);
  432           if (in == null)
  433               throw new IOException("The Cmap " + name + " was not found.");
  434           encodeStream(in, planes);
  435           in.close();
  436       }
  437       
  438       static void encodeStream(InputStream in, ArrayList planes) throws IOException {
  439           BufferedReader rd = new BufferedReader(new InputStreamReader(in, "iso-8859-1"));
  440           String line = null;
  441           int state = CIDNONE;
  442           byte seqs[] = new byte[7];
  443           while ((line = rd.readLine()) != null) {
  444               if (line.length() < 6)
  445                   continue;
  446               switch (state) {
  447                   case CIDNONE: {
  448                       if (line.indexOf("begincidrange") >= 0)
  449                           state = CIDRANGE;
  450                       else if (line.indexOf("begincidchar") >= 0)
  451                           state = CIDCHAR;
  452                       else if (line.indexOf("usecmap") >= 0) {
  453                           StringTokenizer tk = new StringTokenizer(line);
  454                           String t = tk.nextToken();
  455                           readCmap(t.substring(1), planes);
  456                       }
  457                       break;
  458                   }
  459                   case CIDRANGE: {
  460                       if (line.indexOf("endcidrange") >= 0) {
  461                           state = CIDNONE;
  462                           break;
  463                       }
  464                       StringTokenizer tk = new StringTokenizer(line);
  465                       String t = tk.nextToken();
  466                       int size = t.length() / 2 - 1;
  467                       long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
  468                       t = tk.nextToken();
  469                       long end = Long.parseLong(t.substring(1, t.length() - 1), 16);
  470                       t = tk.nextToken();
  471                       int cid = Integer.parseInt(t);
  472                       for (long k = start; k <= end; ++k) {
  473                           breakLong(k, size, seqs);
  474                           encodeSequence(size, seqs, (char)cid, planes);
  475                           ++cid;
  476                       }
  477                       break;
  478                   }
  479                   case CIDCHAR: {
  480                       if (line.indexOf("endcidchar") >= 0) {
  481                           state = CIDNONE;
  482                           break;
  483                       }
  484                       StringTokenizer tk = new StringTokenizer(line);
  485                       String t = tk.nextToken();
  486                       int size = t.length() / 2 - 1;
  487                       long start = Long.parseLong(t.substring(1, t.length() - 1), 16);
  488                       t = tk.nextToken();
  489                       int cid = Integer.parseInt(t);
  490                       breakLong(start, size, seqs);
  491                       encodeSequence(size, seqs, (char)cid, planes);
  492                       break;
  493                   }
  494               }
  495           }
  496       }
  497       
  498       static void breakLong(long n, int size, byte seqs[]) {
  499           for (int k = 0; k < size; ++k) {
  500               seqs[k] = (byte)(n >> ((size - 1 - k) * 8));
  501           }
  502       }
  503   
  504       static void encodeSequence(int size, byte seqs[], char cid, ArrayList planes) {
  505           --size;
  506           int nextPlane = 0;
  507           for (int idx = 0; idx < size; ++idx) {
  508               char plane[] = (char[])planes.get(nextPlane);
  509               int one = seqs[idx] & 0xff;
  510               char c = plane[one];
  511               if (c != 0 && (c & 0x8000) == 0)
  512                   throw new RuntimeException("Inconsistent mapping.");
  513               if (c == 0) {
  514                   planes.add(new char[256]);
  515                   c = (char)((planes.size() - 1) | 0x8000);
  516                   plane[one] = c;
  517               }
  518               nextPlane = c & 0x7fff;
  519           }
  520           char plane[] = (char[])planes.get(nextPlane);
  521           int one = seqs[size] & 0xff;
  522           char c = plane[one];
  523           if ((c & 0x8000) != 0)
  524               throw new RuntimeException("Inconsistent mapping.");
  525           plane[one] = cid;
  526       }
  527   
  528       /** Adds an extra encoding.
  529        * @param name the name of the encoding. The encoding recognition is case insensitive
  530        * @param enc the conversion class
  531        */    
  532       public static void addExtraEncoding(String name, ExtraEncoding enc) {
  533           synchronized (extraEncodings) { // This serializes concurrent updates
  534               HashMap newEncodings = (HashMap)extraEncodings.clone();
  535               newEncodings.put(name.toLowerCase(), enc);
  536               extraEncodings = newEncodings;  // This swap does not require synchronization with reader
  537           }
  538       }
  539       
  540       private static class WingdingsConversion implements ExtraEncoding {
  541           
  542           public byte[] charToByte(char char1, String encoding) {
  543               if (char1 == ' ')
  544                   return new byte[]{(byte)char1};
  545               else if (char1 >= '\u2701' && char1 <= '\u27BE') {
  546                   byte v = table[char1 - 0x2700];
  547                   if (v != 0)
  548                       return new byte[]{v};
  549               }
  550               return new byte[0];
  551           }
  552           
  553           public byte[] charToByte(String text, String encoding) {
  554               char cc[] = text.toCharArray();
  555               byte b[] = new byte[cc.length];
  556               int ptr = 0;
  557               int len = cc.length;
  558               for (int k = 0; k < len; ++k) {
  559                   char c = cc[k];
  560                   if (c == ' ')
  561                       b[ptr++] = (byte)c;
  562                   else if (c >= '\u2701' && c <= '\u27BE') {
  563                       byte v = table[c - 0x2700];
  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 byteToChar(byte[] b, String encoding) {
  576               return null;
  577           }
  578   
  579           private final static byte table[] = {
  580               0, 35, 34, 0, 0, 0, 41, 62, 81, 42, 
  581               0, 0, 65, 63, 0, 0, 0, 0, 0, -4, 
  582               0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 
  583               86, 0, 88, 89, 0, 0, 0, 0, 0, 0, 
  584               0, 0, -75, 0, 0, 0, 0, 0, -74, 0, 
  585               0, 0, -83, -81, -84, 0, 0, 0, 0, 0, 
  586               0, 0, 0, 124, 123, 0, 0, 0, 84, 0, 
  587               0, 0, 0, 0, 0, 0, 0, -90, 0, 0, 
  588               0, 113, 114, 0, 0, 0, 117, 0, 0, 0, 
  589               0, 0, 0, 125, 126, 0, 0, 0, 0, 0, 
  590               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  591               0, 0, 0, 0, 0, 0, 0, 0, -116, -115, 
  592               -114, -113, -112, -111, -110, -109, -108, -107, -127, -126, 
  593               -125, -124, -123, -122, -121, -120, -119, -118, -116, -115, 
  594               -114, -113, -112, -111, -110, -109, -108, -107, -24, 0, 
  595               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  596               0, -24, -40, 0, 0, -60, -58, 0, 0, -16, 
  597               0, 0, 0, 0, 0, 0, 0, 0, 0, -36, 
  598               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  599               0
  600           };
  601       }
  602   
  603       private static class Cp437Conversion implements ExtraEncoding {
  604           private static IntHashtable c2b = new IntHashtable();
  605           
  606           public byte[] charToByte(String text, String encoding) {
  607               char cc[] = text.toCharArray();
  608               byte b[] = new byte[cc.length];
  609               int ptr = 0;
  610               int len = cc.length;
  611               for (int k = 0; k < len; ++k) {
  612                   char c = cc[k];
  613                   if (c < 128)
  614                       b[ptr++] = (byte)c;
  615                   else {
  616                       byte v = (byte)c2b.get(c);
  617                       if (v != 0)
  618                           b[ptr++] = v;
  619                   }
  620               }
  621               if (ptr == len)
  622                   return b;
  623               byte b2[] = new byte[ptr];
  624               System.arraycopy(b, 0, b2, 0, ptr);
  625               return b2;
  626           }
  627           
  628           public byte[] charToByte(char char1, String encoding) {
  629               if (char1 < 128)
  630                   return new byte[]{(byte)char1};
  631               else {
  632                   byte v = (byte)c2b.get(char1);
  633                   if (v != 0)
  634                       return new byte[]{v};
  635                   else
  636                       return new byte[0];
  637               }
  638           }
  639           
  640           public String byteToChar(byte[] b, String encoding) {
  641               int len = b.length;
  642               char cc[] = new char[len];
  643               int ptr = 0;
  644               for (int k = 0; k < len; ++k) {
  645                   int c = b[k] & 0xff;
  646                   if (c < ' ')
  647                       continue;
  648                   if (c < 128)
  649                       cc[ptr++] = (char)c;
  650                   else {
  651                       char v = table[c - 128];
  652                       cc[ptr++] = v;
  653                   }
  654               }
  655               return new String(cc, 0, ptr);
  656           }
  657           
  658           private final static char table[] = {
  659               '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5',
  660               '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', '\u00DC', '\u00A2', '\u00A3', '\u00A5', '\u20A7', '\u0192',
  661               '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', '\u00BF', '\u2310', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB',
  662               '\u2591', '\u2592', '\u2593', '\u2502', '\u2524', '\u2561', '\u2562', '\u2556', '\u2555', '\u2563', '\u2551', '\u2557', '\u255D', '\u255C', '\u255B', '\u2510',
  663               '\u2514', '\u2534', '\u252C', '\u251C', '\u2500', '\u253C', '\u255E', '\u255F', '\u255A', '\u2554', '\u2569', '\u2566', '\u2560', '\u2550', '\u256C', '\u2567',
  664               '\u2568', '\u2564', '\u2565', '\u2559', '\u2558', '\u2552', '\u2553', '\u256B', '\u256A', '\u2518', '\u250C', '\u2588', '\u2584', '\u258C', '\u2590', '\u2580',
  665               '\u03B1', '\u00DF', '\u0393', '\u03C0', '\u03A3', '\u03C3', '\u00B5', '\u03C4', '\u03A6', '\u0398', '\u03A9', '\u03B4', '\u221E', '\u03C6', '\u03B5', '\u2229',
  666               '\u2261', '\u00B1', '\u2265', '\u2264', '\u2320', '\u2321', '\u00F7', '\u2248', '\u00B0', '\u2219', '\u00B7', '\u221A', '\u207F', '\u00B2', '\u25A0', '\u00A0'
  667           };
  668           
  669           static {
  670               for (int k = 0; k < table.length; ++k)
  671                   c2b.put(table[k], k + 128);
  672           }
  673       }
  674       
  675       private static class SymbolConversion implements ExtraEncoding {
  676           
  677           private static final IntHashtable t1 = new IntHashtable();
  678           private static final IntHashtable t2 = new IntHashtable();
  679           private IntHashtable translation;
  680           
  681           SymbolConversion(boolean symbol) {
  682               if (symbol)
  683                   translation = t1;
  684               else
  685                   translation = t2;
  686           }
  687           
  688           public byte[] charToByte(String text, String encoding) {
  689               char cc[] = text.toCharArray();
  690               byte b[] = new byte[cc.length];
  691               int ptr = 0;
  692               int len = cc.length;
  693               for (int k = 0; k < len; ++k) {
  694                   char c = cc[k];
  695                   byte v = (byte)translation.get(c);
  696                   if (v != 0)
  697                       b[ptr++] = v;
  698               }
  699               if (ptr == len)
  700                   return b;
  701               byte b2[] = new byte[ptr];
  702               System.arraycopy(b, 0, b2, 0, ptr);
  703               return b2;
  704           }
  705           
  706           public byte[] charToByte(char char1, String encoding) {
  707               byte v = (byte)translation.get(char1);
  708               if (v != 0)
  709                   return new byte[]{v};
  710               else
  711                   return new byte[0];
  712           }
  713           
  714           public String byteToChar(byte[] b, String encoding) {
  715               return null;
  716           }
  717   
  718           private final static char table1[] = {
  719               ' ','!','\u2200','#','\u2203','%','&','\u220b','(',')','*','+',',','-','.','/',
  720               '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
  721               '\u2245','\u0391','\u0392','\u03a7','\u0394','\u0395','\u03a6','\u0393','\u0397','\u0399','\u03d1','\u039a','\u039b','\u039c','\u039d','\u039f',
  722               '\u03a0','\u0398','\u03a1','\u03a3','\u03a4','\u03a5','\u03c2','\u03a9','\u039e','\u03a8','\u0396','[','\u2234',']','\u22a5','_',
  723               '\u0305','\u03b1','\u03b2','\u03c7','\u03b4','\u03b5','\u03d5','\u03b3','\u03b7','\u03b9','\u03c6','\u03ba','\u03bb','\u03bc','\u03bd','\u03bf',
  724               '\u03c0','\u03b8','\u03c1','\u03c3','\u03c4','\u03c5','\u03d6','\u03c9','\u03be','\u03c8','\u03b6','{','|','}','~','\0',
  725               '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
  726               '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
  727               '\u20ac','\u03d2','\u2032','\u2264','\u2044','\u221e','\u0192','\u2663','\u2666','\u2665','\u2660','\u2194','\u2190','\u2191','\u2192','\u2193',
  728               '\u00b0','\u00b1','\u2033','\u2265','\u00d7','\u221d','\u2202','\u2022','\u00f7','\u2260','\u2261','\u2248','\u2026','\u2502','\u2500','\u21b5',
  729               '\u2135','\u2111','\u211c','\u2118','\u2297','\u2295','\u2205','\u2229','\u222a','\u2283','\u2287','\u2284','\u2282','\u2286','\u2208','\u2209',
  730               '\u2220','\u2207','\u00ae','\u00a9','\u2122','\u220f','\u221a','\u2022','\u00ac','\u2227','\u2228','\u21d4','\u21d0','\u21d1','\u21d2','\u21d3',
  731               '\u25ca','\u2329','\0','\0','\0','\u2211','\u239b','\u239c','\u239d','\u23a1','\u23a2','\u23a3','\u23a7','\u23a8','\u23a9','\u23aa',
  732               '\0','\u232a','\u222b','\u2320','\u23ae','\u2321','\u239e','\u239f','\u23a0','\u23a4','\u23a5','\u23a6','\u23ab','\u23ac','\u23ad','\0'
  733           };
  734   
  735           private final static char table2[] = {
  736               '\u0020','\u2701','\u2702','\u2703','\u2704','\u260e','\u2706','\u2707','\u2708','\u2709','\u261b','\u261e','\u270C','\u270D','\u270E','\u270F',
  737               '\u2710','\u2711','\u2712','\u2713','\u2714','\u2715','\u2716','\u2717','\u2718','\u2719','\u271A','\u271B','\u271C','\u271D','\u271E','\u271F',
  738               '\u2720','\u2721','\u2722','\u2723','\u2724','\u2725','\u2726','\u2727','\u2605','\u2729','\u272A','\u272B','\u272C','\u272D','\u272E','\u272F',
  739               '\u2730','\u2731','\u2732','\u2733','\u2734','\u2735','\u2736','\u2737','\u2738','\u2739','\u273A','\u273B','\u273C','\u273D','\u273E','\u273F',
  740               '\u2740','\u2741','\u2742','\u2743','\u2744','\u2745','\u2746','\u2747','\u2748','\u2749','\u274A','\u274B','\u25cf','\u274D','\u25a0','\u274F',
  741               '\u2750','\u2751','\u2752','\u25b2','\u25bc','\u25c6','\u2756','\u25d7','\u2758','\u2759','\u275A','\u275B','\u275C','\u275D','\u275E','\u0000',
  742               '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
  743               '\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0',
  744               '\u0000','\u2761','\u2762','\u2763','\u2764','\u2765','\u2766','\u2767','\u2663','\u2666','\u2665','\u2660','\u2460','\u2461','\u2462','\u2463',
  745               '\u2464','\u2465','\u2466','\u2467','\u2468','\u2469','\u2776','\u2777','\u2778','\u2779','\u277A','\u277B','\u277C','\u277D','\u277E','\u277F',
  746               '\u2780','\u2781','\u2782','\u2783','\u2784','\u2785','\u2786','\u2787','\u2788','\u2789','\u278A','\u278B','\u278C','\u278D','\u278E','\u278F',
  747               '\u2790','\u2791','\u2792','\u2793','\u2794','\u2192','\u2194','\u2195','\u2798','\u2799','\u279A','\u279B','\u279C','\u279D','\u279E','\u279F',
  748               '\u27A0','\u27A1','\u27A2','\u27A3','\u27A4','\u27A5','\u27A6','\u27A7','\u27A8','\u27A9','\u27AA','\u27AB','\u27AC','\u27AD','\u27AE','\u27AF',
  749               '\u0000','\u27B1','\u27B2','\u27B3','\u27B4','\u27B5','\u27B6','\u27B7','\u27B8','\u27B9','\u27BA','\u27BB','\u27BC','\u27BD','\u27BE','\u0000'
  750           };
  751   
  752           static {
  753               for (int k = 0; k < table1.length; ++k) {
  754                   int v = table1[k];
  755                   if (v != 0)
  756                       t1.put(v, k + 32);
  757               }
  758               for (int k = 0; k < table2.length; ++k) {
  759                   int v = table2[k];
  760                   if (v != 0)
  761                       t2.put(v, k + 32);
  762               }
  763           }
  764       }
  765       
  766       private static class SymbolTTConversion implements ExtraEncoding {
  767           
  768           public byte[] charToByte(char char1, String encoding) {
  769               if ((char1 & 0xff00) == 0 || (char1 & 0xff00) == 0xf000)
  770                   return new byte[]{(byte)char1};
  771               else
  772                   return new byte[0];
  773           }
  774           
  775           public byte[] charToByte(String text, String encoding) {
  776               char ch[] = text.toCharArray();
  777               byte b[] = new byte[ch.length];
  778               int ptr = 0;
  779               int len = ch.length;
  780               for (int k = 0; k < len; ++k) {
  781                   char c = ch[k];
  782                   if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000)
  783                       b[ptr++] = (byte)c;
  784               }
  785               if (ptr == len)
  786                   return b;
  787               byte b2[] = new byte[ptr];
  788               System.arraycopy(b, 0, b2, 0, ptr);
  789               return b2;
  790           }
  791           
  792           public String byteToChar(byte[] b, String encoding) {
  793               return null;
  794           }
  795           
  796       }
  797   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » [javadoc | source]