You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2011/01/11 19:15:18 UTC

svn commit: r1057780 - in /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font: PDFont.java PDSimpleFont.java PDType1CFont.java PDType1Font.java

Author: lehmi
Date: Tue Jan 11 18:15:18 2011
New Revision: 1057780

URL: http://svn.apache.org/viewvc?rev=1057780&view=rev
Log:
PDFBOX-935, PDFBOX-588: fixed the type1 font matrix handling to get the correct font scaling, using the type1c font matrix if embedded to a type 1 font, added font matrix caching

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java?rev=1057780&r1=1057779&r2=1057780&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java Tue Jan 11 18:15:18 2011
@@ -75,6 +75,11 @@ public abstract class PDFont implements 
     private PDFontDescriptor fontDescriptor = null;
 
     /**
+     *  The font matrix
+     */
+    protected PDMatrix fontMatrix = null;
+    
+    /**
      * This is only used if this is a font object and it has an encoding and it is
      * a type0 font with a cmap.
      */
@@ -689,21 +694,22 @@ public abstract class PDFont implements 
      */
     public PDMatrix getFontMatrix()
     {
-        PDMatrix matrix = null;
-        COSArray array = (COSArray)font.getDictionaryObject( COSName.FONT_MATRIX );
-        if( array == null )
-        {
-            array = new COSArray();
-            array.add( new COSFloat( 0.001f ) );
-            array.add( COSInteger.ZERO );
-            array.add( COSInteger.ZERO );
-            array.add( new COSFloat( 0.001f ) );
-            array.add( COSInteger.ZERO );
-            array.add( COSInteger.ZERO );
+        if (fontMatrix == null)
+        {
+            COSArray array = (COSArray)font.getDictionaryObject( COSName.FONT_MATRIX );
+            if( array == null )
+            {
+                array = new COSArray();
+                array.add( new COSFloat( 0.001f ) );
+                array.add( COSInteger.ZERO );
+                array.add( COSInteger.ZERO );
+                array.add( new COSFloat( 0.001f ) );
+                array.add( COSInteger.ZERO );
+                array.add( COSInteger.ZERO );
+            }
+            fontMatrix = new PDMatrix(array);
         }
-        matrix = new PDMatrix(array);
-
-        return matrix;
+        return fontMatrix;
     }
 
     /**

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java?rev=1057780&r1=1057779&r2=1057780&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java Tue Jan 11 18:15:18 2011
@@ -44,7 +44,6 @@ import org.apache.pdfbox.encoding.Encodi
 import org.apache.pdfbox.encoding.conversion.CMapSubstitution;
 
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.util.ResourceLoader;
 
 /**
@@ -249,22 +248,21 @@ public abstract class PDSimpleFont exten
 
     
     /**
-     * This will get the ToUnicode stream.
+     * This will get the ToUnicode object.
      *
-     * @return The ToUnicode stream.
-     * @throws IOException If there is an error getting the stream.
+     * @return The ToUnicode object.
      */
-    public PDStream getToUnicode() throws IOException
+    public COSBase getToUnicode()
     {
-        return PDStream.createFromCOS( font.getDictionaryObject( COSName.TO_UNICODE ) );
+        return font.getDictionaryObject( COSName.TO_UNICODE );
     }
 
     /**
-     * This will set the ToUnicode stream.
+     * This will set the ToUnicode object.
      *
-     * @param unicode The unicode stream.
+     * @param unicode The unicode object.
      */
-    public void setToUnicode( PDStream unicode )
+    public void setToUnicode( COSBase unicode )
     {
         font.setItem( COSName.TO_UNICODE, unicode );
     }
@@ -422,7 +420,7 @@ public abstract class PDSimpleFont exten
     {
         COSName encodingName = null;
         String cmapName = null;
-        COSBase toUnicode = font.getDictionaryObject( COSName.TO_UNICODE );
+        COSBase toUnicode = getToUnicode();
         if( toUnicode != null )
         {
             if ( toUnicode instanceof COSStream )

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1057780&r1=1057779&r2=1057780&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Tue Jan 11 18:15:18 2011
@@ -87,8 +87,6 @@ public class PDType1CFont extends PDSimp
 
     private PDRectangle fontBBox = null;
 
-    private PDMatrix fontMatrix = null;
-
     private static final Log log = LogFactory.getLog(PDType1CFont.class);
 
     private static final byte[] SPACE_BYTES = {(byte)32};
@@ -259,7 +257,7 @@ public class PDType1CFont extends PDSimp
      */
     public PDMatrix getFontMatrix()
     {
-        if( this.fontMatrix == null )
+        if( fontMatrix == null )
         {
             List<Number> numbers = (List<Number>)this.cffFont.getProperty("FontMatrix");
             if( numbers != null && numbers.size() == 6 )
@@ -269,15 +267,14 @@ public class PDType1CFont extends PDSimp
                 {
                     array.add(new COSFloat(number.floatValue()));
                 }
-                this.fontMatrix = new PDMatrix(array);
+                fontMatrix = new PDMatrix(array);
             }
             else
             {
-                this.fontMatrix = super.getFontMatrix();
+                super.getFontMatrix();
             }
         }
-
-        return this.fontMatrix;
+        return fontMatrix;
     }
 
     /**

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1057780&r1=1057779&r2=1057780&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Tue Jan 11 18:15:18 2011
@@ -28,13 +28,16 @@ import java.util.StringTokenizer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fontbox.afm.FontMetric;
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.encoding.AFMEncoding;
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.encoding.EncodingManager;
 import org.apache.pdfbox.encoding.Type1Encoding;
 import org.apache.pdfbox.encoding.WinAnsiEncoding;
+import org.apache.pdfbox.pdmodel.common.PDMatrix;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 
 /**
@@ -269,10 +272,7 @@ public class PDType1Font extends PDSimpl
                 fontEncoding = new AFMEncoding( metric );
             }
         }
-        if (fontEncoding == null)
-        {
-            getEncodingFromFont();
-        }
+        getEncodingFromFont(getEncoding() == null);
         setEncoding(fontEncoding);
     }
     
@@ -280,7 +280,7 @@ public class PDType1Font extends PDSimpl
      * Tries to get the encoding for the type1 font.
      *
      */
-    private void getEncodingFromFont()
+    private void getEncodingFromFont(boolean extractEncoding)
     {
         // This whole section of code needs to be replaced with an actual type1 font parser!!
         // Get the font program from the embedded type font.
@@ -302,45 +302,73 @@ public class PDType1Font extends PDSimpl
                     Type1Encoding encoding = null;
                     while( (line = in.readLine()) != null)
                     {
-                        if (line.startsWith("currentdict end")) {
-                            if (encoding != null)
-                                setEncoding(encoding);
-                            break;
-                        }
-                        if (line.startsWith("/Encoding")) 
+                        if (extractEncoding) 
                         {
-                            if(line.contains("array")) 
-                            {
-                                StringTokenizer st = new StringTokenizer(line);
-                                // ignore the first token
-                                st.nextElement();
-                                int arraySize = Integer.parseInt(st.nextToken());
-                                encoding = new Type1Encoding(arraySize);
+                            if (line.startsWith("currentdict end")) {
+                                if (encoding != null)
+                                    setEncoding(encoding);
+                                break;
                             }
-                            // if there is already an encoding, we don't need to
-                            // assign another one
-                            else if (getEncoding() == null)
+                            if (line.startsWith("/Encoding")) 
                             {
-                                StringTokenizer st = new StringTokenizer(line);
+                                if(line.contains("array")) 
+                                {
+                                    StringTokenizer st = new StringTokenizer(line);
+                                    // ignore the first token
+                                    st.nextElement();
+                                    int arraySize = Integer.parseInt(st.nextToken());
+                                    encoding = new Type1Encoding(arraySize);
+                                }
+                                // if there is already an encoding, we don't need to
+                                // assign another one
+                                else if (getEncoding() == null)
+                                {
+                                    StringTokenizer st = new StringTokenizer(line);
+                                    // ignore the first token
+                                    st.nextElement();
+                                    String type1Encoding = st.nextToken();
+                                    setEncoding(
+                                        EncodingManager.INSTANCE.getEncoding(
+                                                COSName.getPDFName(type1Encoding)));
+                                    break;
+                                }
+                            }
+                            else if (line.startsWith("dup")) {
+                                StringTokenizer st = new StringTokenizer(line.replaceAll("/"," /"));
                                 // ignore the first token
                                 st.nextElement();
-                                String type1Encoding = st.nextToken();
-                                setEncoding(
-                                    EncodingManager.INSTANCE.getEncoding(
-                                            COSName.getPDFName(type1Encoding)));
-                                break;
+                                int index = Integer.parseInt(st.nextToken());
+                                String name = st.nextToken();
+                                if(encoding == null)
+                                    log.warn("Unable to get character encoding.  Encoding defintion found without /Encoding line.");
+                                else
+                                    encoding.addCharacterEncoding(index, name.replace("/", ""));
                             }
                         }
-                        else if (line.startsWith("dup")) {
-                            StringTokenizer st = new StringTokenizer(line.replaceAll("/"," /"));
-                            // ignore the first token
-                            st.nextElement();
-                            int index = Integer.parseInt(st.nextToken());
-                            String name = st.nextToken();
-                            if(encoding == null)
-                                log.warn("Unable to get character encoding.  Encoding defintion found without /Encoding line.");
-                            else
-                                encoding.addCharacterEncoding(index, name.replace("/", ""));
+                        // according to the pdf reference, all font matrices should be same, except for type 3 fonts.
+                        // but obviously there are some type1 fonts with different matrix values, see pdf sample
+                        // attached to PDFBOX-935
+                        if (line.startsWith("/FontMatrix"))
+                        {
+                            String matrixValues = line.substring(line.indexOf("[")+1,line.lastIndexOf("]"));
+                            StringTokenizer st = new StringTokenizer(matrixValues);
+                            COSArray array = new COSArray();
+                            if (st.countTokens() >= 6)
+                            {
+                                try 
+                                {
+                                    for (int i=0;i<6;i++)
+                                    {
+                                        COSFloat floatValue = new COSFloat(Float.parseFloat(st.nextToken()));
+                                        array.add(floatValue);
+                                    }
+                                    fontMatrix = new PDMatrix(array);
+                                }
+                                catch (NumberFormatException exception)
+                                {
+                                    log.error("Can't read the fontmatrix from embedded font file!");
+                                }
+                            }
                         }
                     }
                     in.close();
@@ -353,6 +381,9 @@ public class PDType1Font extends PDSimpl
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public String encode(byte[] c, int offset, int length) throws IOException
     {
@@ -365,4 +396,20 @@ public class PDType1Font extends PDSimpl
             return super.encode(c, offset, length);
         }
     }
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public PDMatrix getFontMatrix()
+    {
+        if (type1CFont != null)
+        {
+            return type1CFont.getFontMatrix();
+        }
+        else
+        {
+            return super.getFontMatrix();
+        }
+    }
 }