Home » pdfbox-1.1.0-src » org.apache.pdfbox.pdmodel.font » [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.pdfbox.pdmodel.font;
   18   
   19   import java.io.BufferedInputStream;
   20   import java.io.FileInputStream;
   21   import java.io.IOException;
   22   import java.io.InputStream;
   23   import java.util.ArrayList;
   24   import java.util.Iterator;
   25   import java.util.List;
   26   
   27   import org.apache.fontbox.afm.AFMParser;
   28   import org.apache.fontbox.afm.CharMetric;
   29   import org.apache.fontbox.afm.FontMetric;
   30   
   31   import org.apache.fontbox.pfb.PfbParser;
   32   
   33   import org.apache.pdfbox.encoding.AFMEncoding;
   34   import org.apache.pdfbox.encoding.DictionaryEncoding;
   35   import org.apache.pdfbox.encoding.Encoding;
   36   import org.apache.pdfbox.pdmodel.PDDocument;
   37   import org.apache.pdfbox.pdmodel.common.PDRectangle;
   38   import org.apache.pdfbox.pdmodel.common.PDStream;
   39   import org.apache.pdfbox.cos.COSArray;
   40   import org.apache.pdfbox.cos.COSDictionary;
   41   import org.apache.pdfbox.cos.COSInteger;
   42   import org.apache.pdfbox.cos.COSName;
   43   
   44   /**
   45    * This is implementation of the Type1 Font
   46    * with a afm and a pfb file.
   47    *
   48    * @author <a href="mailto:m.g.n@gmx.de">Michael Niedermair</a>
   49    * @version $Revision: 1.5 $
   50    */
   51   public class PDType1AfmPfbFont extends PDType1Font
   52   {
   53       /**
   54        * the buffersize.
   55        */
   56       private static final int BUFFERSIZE = 0xffff;
   57   
   58       /**
   59        * The font descriptor.
   60        */
   61       private PDFontDescriptorDictionary fd;
   62   
   63       /**
   64        * The font metric.
   65        */
   66       private FontMetric metric;
   67   
   68       /**
   69        * Create a new object.
   70        * @param doc       The PDF document that will hold the embedded font.
   71        * @param afmname   The font filename.
   72        * @throws IOException If there is an error loading the data.
   73        */
   74       public PDType1AfmPfbFont(final PDDocument doc, final String afmname)
   75           throws IOException
   76       {
   77   
   78           super();
   79           InputStream afmin = new BufferedInputStream(new FileInputStream(afmname), BUFFERSIZE);
   80           String pfbname = afmname.replaceAll(".AFM", "").replaceAll(".afm", "") + ".pfb";
   81           InputStream pfbin = new BufferedInputStream(new FileInputStream(pfbname), BUFFERSIZE);
   82           load(doc, afmin, pfbin);
   83       }
   84   
   85       /**
   86        * Create a new object.
   87        * @param doc       The PDF document that will hold the embedded font.
   88        * @param afm       The afm input.
   89        * @param pfb       The pfb input.
   90        * @throws IOException If there is an error loading the data.
   91        */
   92       public PDType1AfmPfbFont(final PDDocument doc, final InputStream afm, final InputStream pfb)
   93           throws IOException
   94       {
   95           super();
   96           load(doc, afm, pfb);
   97       }
   98   
   99       /**
  100        * This will load a afm and pfb to be embedding into a document.
  101        *
  102        * @param doc   The PDF document that will hold the embedded font.
  103        * @param afm   The afm input.
  104        * @param pfb   The pfb input.
  105        * @throws IOException If there is an error loading the data.
  106        */
  107       private void load(final PDDocument doc, final InputStream afm,
  108               final InputStream pfb) throws IOException
  109       {
  110   
  111           fd = new PDFontDescriptorDictionary();
  112           setFontDescriptor(fd);
  113   
  114           // read the pfb
  115           PfbParser pfbparser = new PfbParser(pfb);
  116           pfb.close();
  117   
  118           PDStream fontStream = new PDStream(doc, pfbparser.getInputStream(),
  119                   false);
  120           fontStream.getStream().setInt("Length", pfbparser.size());
  121           for (int i = 0; i < pfbparser.getLengths().length; i++)
  122           {
  123               fontStream.getStream().setInt("Length" + (i + 1),
  124                       pfbparser.getLengths()[i]);
  125           }
  126           fontStream.addCompression();
  127           fd.setFontFile(fontStream);
  128   
  129           // read the afm
  130           AFMParser parser = new AFMParser(afm);
  131           parser.parse();
  132           metric = parser.getResult();
  133           setEncoding(afmToDictionary(new AFMEncoding(metric)));
  134   
  135           // set the values
  136           setBaseFont(metric.getFontName());
  137           fd.setFontName(metric.getFontName());
  138           fd.setFontFamily(metric.getFamilyName());
  139           fd.setNonSymbolic(true);
  140           fd.setFontBoundingBox(new PDRectangle(metric.getFontBBox()));
  141           fd.setItalicAngle(metric.getItalicAngle());
  142           fd.setAscent(metric.getAscender());
  143           fd.setDescent(metric.getDescender());
  144           fd.setCapHeight(metric.getCapHeight());
  145           fd.setXHeight(metric.getXHeight());
  146           fd.setAverageWidth(metric.getAverageCharacterWidth());
  147           fd.setCharacterSet(metric.getCharacterSet());
  148   
  149           // get firstchar, lastchar
  150           int firstchar = 255;
  151           int lastchar = 0;
  152   
  153           // widths
  154           List listmetric = metric.getCharMetrics();
  155           Encoding encoding = getEncoding();
  156           int maxWidths = 256;
  157           List widths = new ArrayList(maxWidths);
  158           Integer zero = new Integer(250);
  159           Iterator iter = listmetric.iterator();
  160           for( int i=0; i<maxWidths; i++ )
  161           {
  162               widths.add(zero);
  163           }
  164           while (iter.hasNext())
  165           {
  166               CharMetric m = (CharMetric) iter.next();
  167               int n = m.getCharacterCode();
  168               if (n > 0)
  169               {
  170                   firstchar = Math.min(firstchar, n);
  171                   lastchar = Math.max(lastchar, n);
  172                   if (m.getWx() > 0)
  173                   {
  174                       float width = m.getWx();
  175                       widths.set(n,new Float(width));
  176                       // germandbls has 2 character codes !! Don't ask me why .....
  177                       // StandardEncoding = 0373 = 251
  178                       // WinANSIEncoding = 0337 = 223
  179                       if (m.getName().equals("germandbls") && n != 223)
  180                       {
  181                           widths.set(0337,new Float(width));
  182                       }
  183                   }
  184               }
  185               else 
  186               {
  187                   // my AFMPFB-Fonts has no character-codes for german umlauts
  188                   // so that I've to add them here by hand
  189                   if (m.getName().equals("adieresis"))
  190                   {
  191                       widths.set(0344,(Float)widths.get(encoding.getCode(COSName.getPDFName( "a" ))));
  192                   }
  193                   else if (m.getName().equals("odieresis"))
  194                   {
  195                       widths.set(0366,(Float)widths.get(encoding.getCode(COSName.getPDFName( "o" ))));
  196                   }
  197                   else if (m.getName().equals("udieresis"))
  198                   {
  199                       widths.set(0374,(Float)widths.get(encoding.getCode(COSName.getPDFName( "u" ))));
  200                   }
  201                   else if (m.getName().equals("Adieresis"))
  202                   {
  203                       widths.set(0304,(Float)widths.get(encoding.getCode(COSName.getPDFName( "A" ))));
  204                   }
  205                   else if (m.getName().equals("Odieresis"))
  206                   {
  207                       widths.set(0326,(Float)widths.get(encoding.getCode(COSName.getPDFName( "O" ))));
  208                   }
  209                   else if (m.getName().equals("Udieresis"))
  210                   {
  211                       widths.set(0334,(Float)widths.get(encoding.getCode(COSName.getPDFName( "U" ))));
  212                   }
  213               }
  214           }
  215           setFirstChar(0);
  216           setLastChar(255);
  217           setWidths(widths);
  218       }
  219   
  220       /*
  221        *  This will generate a Encoding from the AFM-Encoding, because the AFM-Enconding isn't exported to the pdf
  222        *  and consequently the StandardEncoding is used so that any special character is missing
  223        *  I've copied the code from the pdfbox-forum posted by V0JT4 and made some additions concerning german umlauts
  224        *  see also https://sourceforge.net/forum/message.php?msg_id=4705274
  225        */
  226       private DictionaryEncoding afmToDictionary(AFMEncoding encoding) throws java.io.IOException 
  227       {
  228           COSArray array = new COSArray();
  229           array.add(COSInteger.ZERO);
  230           for (int i = 0; i < 256; i++) 
  231           {
  232               array.add(encoding.getName(i));
  233           }
  234           // my AFMPFB-Fonts has no character-codes for german umlauts
  235           // so that I've to add them here by hand
  236           array.set( 0337+1, COSName.getPDFName("germandbls"));
  237           array.set( 0344+1, COSName.getPDFName("adieresis"));
  238           array.set( 0366+1, COSName.getPDFName("odieresis"));
  239           array.set( 0374+1, COSName.getPDFName("udieresis"));
  240           array.set( 0304+1, COSName.getPDFName("Adieresis"));
  241           array.set( 0326+1, COSName.getPDFName("Odieresis"));
  242           array.set( 0334+1, COSName.getPDFName("Udieresis"));
  243   
  244           COSDictionary dictionary = new COSDictionary();
  245           dictionary.setItem(COSName.NAME, COSName.ENCODING);
  246           dictionary.setItem(COSName.DIFFERENCES, array);
  247           dictionary.setItem(COSName.BASE_ENCODING, COSName.STANDARD_ENCODING);
  248           return new DictionaryEncoding(dictionary);
  249       }
  250   
  251   
  252   
  253       /**
  254        * {@inheritDoc}
  255        */
  256       public PDFontDescriptor getFontDescriptor() throws IOException
  257       {
  258           return fd;
  259       }
  260   
  261   }

Home » pdfbox-1.1.0-src » org.apache.pdfbox.pdmodel.font » [javadoc | source]