Save This Page
Home » pdfbox-1.1.0-src » org.apache.fontbox.cff » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.fontbox.cff;
   18   
   19   import java.io.IOException;
   20   import java.util.ArrayList;
   21   import java.util.List;
   22   
   23   /**
   24    * This class represents a converter for a mapping into a Type2-sequence.
   25    * @author Villu Ruusmann
   26    * @version $Revision: 1.0 $
   27    */
   28   public class Type2CharStringParser
   29   {
   30   
   31       private DataInput input = null;
   32       private int hstemCount = 0;
   33       private int vstemCount = 0;
   34       private List<Object> sequence = null;
   35   
   36       /**
   37        * The given byte array will be parsed and converted to a Type2 sequence.
   38        * @param bytes the given mapping as byte array
   39        * @return the Type2 sequence
   40        * @throws IOException if an error occurs during reading
   41        */
   42       public List<Object> parse(byte[] bytes) throws IOException
   43       {
   44           input = new DataInput(bytes);
   45   
   46           hstemCount = 0;
   47           vstemCount = 0;
   48   
   49           sequence = new ArrayList<Object>();
   50   
   51           while (input.hasRemaining())
   52           {
   53               int b0 = input.readUnsignedByte();
   54   
   55               if (b0 >= 0 && b0 <= 27)
   56               {
   57                   sequence.add(readCommand(b0));
   58               } 
   59               else if (b0 == 28)
   60               {
   61                   sequence.add(readNumber(b0));
   62               } 
   63               else if (b0 >= 29 && b0 <= 31)
   64               {
   65                   sequence.add(readCommand(b0));
   66               } 
   67               else if (b0 >= 32 && b0 <= 255)
   68               {
   69                   sequence.add(readNumber(b0));
   70               }
   71               else
   72               {
   73                   throw new IllegalArgumentException();
   74               }
   75           }
   76   
   77           return sequence;
   78       }
   79   
   80       private CharStringCommand readCommand(int b0) throws IOException
   81       {
   82   
   83           if (b0 == 1 || b0 == 18)
   84           {
   85               hstemCount += peekNumbers().size() / 2;
   86           } 
   87           else if (b0 == 3 || b0 == 19 || b0 == 20 || b0 == 23)
   88           {
   89               vstemCount += peekNumbers().size() / 2;
   90           } // End if
   91   
   92           if (b0 == 12)
   93           {
   94               int b1 = input.readUnsignedByte();
   95   
   96               return new CharStringCommand(b0, b1);
   97           } 
   98           else if (b0 == 19 || b0 == 20)
   99           {
  100               int[] value = new int[1 + getMaskLength()];
  101               value[0] = b0;
  102   
  103               for (int i = 1; i < value.length; i++)
  104               {
  105                   value[i] = input.readUnsignedByte();
  106               }
  107   
  108               return new CharStringCommand(value);
  109           }
  110   
  111           return new CharStringCommand(b0);
  112       }
  113   
  114       private Integer readNumber(int b0) throws IOException
  115       {
  116   
  117           if (b0 == 28)
  118           {
  119               int b1 = input.readUnsignedByte();
  120               int b2 = input.readUnsignedByte();
  121   
  122               return Integer.valueOf((short) (b1 << 8 | b2));
  123           } 
  124           else if (b0 >= 32 && b0 <= 246)
  125           {
  126               return Integer.valueOf(b0 - 139);
  127           } 
  128           else if (b0 >= 247 && b0 <= 250)
  129           {
  130               int b1 = input.readUnsignedByte();
  131   
  132               return Integer.valueOf((b0 - 247) * 256 + b1 + 108);
  133           } 
  134           else if (b0 >= 251 && b0 <= 254)
  135           {
  136               int b1 = input.readUnsignedByte();
  137   
  138               return Integer.valueOf(-(b0 - 251) * 256 - b1 - 108);
  139           } 
  140           else if (b0 == 255)
  141           {
  142               int b1 = input.readUnsignedByte();
  143               int b2 = input.readUnsignedByte();
  144               int b3 = input.readUnsignedByte();
  145               int b4 = input.readUnsignedByte();
  146   
  147               // The lower bytes are representing the digits after 
  148               // the decimal point and aren't needed in this context
  149               return Integer.valueOf((short)(b1 << 8 | b2));
  150           } 
  151           else
  152           {
  153               throw new IllegalArgumentException();
  154           }
  155       }
  156   
  157       private int getMaskLength()
  158       {
  159           int length = 1;
  160   
  161           int hintCount = hstemCount + vstemCount;
  162           while ((hintCount -= 8) > 0)
  163           {
  164               length++;
  165           }
  166   
  167           return length;
  168       }
  169   
  170       private List<Number> peekNumbers()
  171       {
  172           List<Number> numbers = new ArrayList<Number>();
  173   
  174           for (int i = sequence.size() - 1; i > -1; i--)
  175           {
  176               Object object = sequence.get(i);
  177   
  178               if (object instanceof Number)
  179               {
  180                   Number number = (Number) object;
  181   
  182                   numbers.add(0, number);
  183   
  184                   continue;
  185               }
  186   
  187               return numbers;
  188           }
  189   
  190           return numbers;
  191       }
  192   }

Save This Page
Home » pdfbox-1.1.0-src » org.apache.fontbox.cff » [javadoc | source]