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.text.DecimalFormat;
   21   import java.text.DecimalFormatSymbols;
   22   import java.text.NumberFormat;
   23   import java.util.Collection;
   24   import java.util.Locale;
   25   
   26   /**
   27    * This class represents a formatter for a given Type1 font.  
   28    * @author Villu Ruusmann
   29    * @version $Revision: 1.0 $
   30    */
   31   public class Type1FontFormatter
   32   {
   33   
   34       private Type1FontFormatter()
   35       {
   36       }
   37   
   38       /**
   39        * Read and convert a given CFFFont.
   40        * @param font the given CFFFont
   41        * @return the Type1 font
   42        * @throws IOException if an error occurs during reading the given font
   43        */
   44       public static byte[] format(CFFFont font) throws IOException
   45       {
   46           DataOutput output = new DataOutput();
   47           printFont(font, output);
   48           return output.getBytes();
   49       }
   50   
   51       private static void printFont(CFFFont font, DataOutput output)
   52               throws IOException
   53       {
   54           output.println("%!FontType1-1.0 " + font.getName() + " "
   55                   + font.getProperty("version"));
   56   
   57           printFontDictionary(font, output);
   58   
   59           for (int i = 0; i < 8; i++)
   60           {
   61               StringBuilder sb = new StringBuilder();
   62   
   63               for (int j = 0; j < 64; j++)
   64               {
   65                   sb.append("0");
   66               }
   67   
   68               output.println(sb.toString());
   69           }
   70   
   71           output.println("cleartomark");
   72       }
   73   
   74       private static void printFontDictionary(CFFFont font, DataOutput output)
   75               throws IOException
   76       {
   77           output.println("10 dict begin");
   78           output.println("/FontInfo 10 dict dup begin");
   79           output.println("/version (" + font.getProperty("version")
   80                   + ") readonly def");
   81           output.println("/Notice (" + font.getProperty("Notice")
   82                   + ") readonly def");
   83           output.println("/FullName (" + font.getProperty("FullName")
   84                   + ") readonly def");
   85           output.println("/FamilyName (" + font.getProperty("FamilyName")
   86                   + ") readonly def");
   87           output.println("/Weight (" + font.getProperty("Weight")
   88                   + ") readonly def");
   89           output.println("/ItalicAngle " + font.getProperty("ItalicAngle")
   90                   + " def");
   91           output.println("/isFixedPitch " + font.getProperty("isFixedPitch")
   92                   + " def");
   93           output.println("/UnderlinePosition "
   94                   + font.getProperty("UnderlinePosition") + " def");
   95           output.println("/UnderlineThickness "
   96                   + font.getProperty("UnderlineThickness") + " def");
   97           output.println("end readonly def");
   98           output.println("/FontName /" + font.getName() + " def");
   99           output.println("/PaintType " + font.getProperty("PaintType") + " def");
  100           output.println("/FontType 1 def");
  101           NumberFormat matrixFormat = new DecimalFormat("0.########", new DecimalFormatSymbols(Locale.US));
  102           output.println("/FontMatrix "
  103                   + formatArray(font.getProperty("FontMatrix"), matrixFormat, false)
  104                   + " readonly def");
  105           output.println("/FontBBox "
  106                   + formatArray(font.getProperty("FontBBox"), false)
  107                   + " readonly def");
  108           output.println("/StrokeWidth " + font.getProperty("StrokeWidth")
  109                   + " def");
  110   
  111           Collection<CFFFont.Mapping> mappings = font.getMappings();
  112   
  113           output.println("/Encoding 256 array");
  114           output.println("0 1 255 {1 index exch /.notdef put} for");
  115   
  116           for (CFFFont.Mapping mapping : mappings)
  117           {
  118               output.println("dup " + mapping.getCode() + " /"
  119                       + mapping.getName() + " put");
  120           }
  121   
  122           output.println("readonly def");
  123           output.println("currentdict end");
  124   
  125           DataOutput eexecOutput = new DataOutput();
  126   
  127           printEexecFontDictionary(font, eexecOutput);
  128   
  129           output.println("currentfile eexec");
  130   
  131           byte[] eexecBytes = Type1FontUtil.eexecEncrypt(eexecOutput.getBytes());
  132   
  133           String hexString = Type1FontUtil.hexEncode(eexecBytes);
  134           for (int i = 0; i < hexString.length();)
  135           {
  136               String hexLine = hexString.substring(i, Math.min(i + 72, hexString
  137                       .length()));
  138   
  139               output.println(hexLine);
  140   
  141               i += hexLine.length();
  142           }
  143       }
  144   
  145       private static void printEexecFontDictionary(CFFFont font, DataOutput output)
  146               throws IOException
  147       {
  148           output.println("dup /Private 15 dict dup begin");
  149           output
  150                   .println("/RD {string currentfile exch readstring pop} executeonly def");
  151           output.println("/ND {noaccess def} executeonly def");
  152           output.println("/NP {noaccess put} executeonly def");
  153           output.println("/BlueValues "
  154                   + formatArray(font.getProperty("BlueValues"), true) + " ND");
  155           output.println("/OtherBlues "
  156                   + formatArray(font.getProperty("OtherBlues"), true) + " ND");
  157           output.println("/BlueScale " + font.getProperty("BlueScale") + " def");
  158           output.println("/BlueShift " + font.getProperty("BlueShift") + " def");
  159           output.println("/BlueFuzz " + font.getProperty("BlueFuzz") + " def");
  160           output.println("/StdHW " + formatArray(font.getProperty("StdHW"), true)
  161                   + " ND");
  162           output.println("/StdVW " + formatArray(font.getProperty("StdVW"), true)
  163                   + " ND");
  164           output.println("/ForceBold " + font.getProperty("ForceBold") + " def");
  165           output.println("/MinFeature {16 16} def");
  166           output.println("/password 5839 def");
  167   
  168           Collection<CFFFont.Mapping> mappings = font.getMappings();
  169   
  170           output.println("2 index /CharStrings " + mappings.size()
  171                   + " dict dup begin");
  172   
  173           Type1CharStringFormatter formatter = new Type1CharStringFormatter();
  174   
  175           for (CFFFont.Mapping mapping : mappings)
  176           {
  177               byte[] type1Bytes = formatter.format(mapping.toType1Sequence());
  178   
  179               byte[] charstringBytes = Type1FontUtil.charstringEncrypt(
  180                       type1Bytes, 4);
  181   
  182               output.print("/" + mapping.getName() + " " + charstringBytes.length
  183                       + " RD ");
  184               output.write(charstringBytes);
  185               output.print(" ND");
  186   
  187               output.println();
  188           }
  189   
  190           output.println("end");
  191           output.println("end");
  192   
  193           output.println("readonly put");
  194           output.println("noaccess put");
  195           output.println("dup /FontName get exch definefont pop");
  196           output.println("mark currentfile closefile");
  197       }
  198   
  199       private static String formatArray(Object object, boolean executable)
  200       {
  201           return formatArray(object, null, executable);
  202       }
  203   
  204       private static String formatArray(Object object, NumberFormat format, boolean executable)
  205       {
  206           StringBuffer sb = new StringBuffer();
  207   
  208           sb.append(executable ? "{" : "[");
  209   
  210           if (object instanceof Collection)
  211           {
  212               String sep = "";
  213   
  214               Collection<?> elements = (Collection<?>) object;
  215               for (Object element : elements)
  216               {
  217                   sb.append(sep).append(formatElement(element, format));
  218   
  219                   sep = " ";
  220               }
  221           } 
  222           else if (object instanceof Number)
  223           {
  224               sb.append(formatElement(object, format));
  225           }
  226   
  227           sb.append(executable ? "}" : "]");
  228   
  229           return sb.toString();
  230       }
  231   
  232       private static String formatElement(Object object, NumberFormat format)
  233       {
  234           if(format != null)
  235           {
  236               if (object instanceof Double || object instanceof Float)
  237               {
  238                   Number number = (Number)object;
  239                   return format.format(number.doubleValue());
  240               }
  241               else if (object instanceof Long || object instanceof Integer)
  242               {
  243                   Number number = (Number)object;
  244                   return format.format(number.longValue());
  245               }
  246           }
  247           return String.valueOf(object);
  248       }
  249   }

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