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 2014/06/22 15:25:35 UTC

svn commit: r1604572 - in /pdfbox/trunk: fontbox/src/main/java/org/apache/fontbox/cff/ fontbox/src/main/java/org/apache/fontbox/util/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/

Author: lehmi
Date: Sun Jun 22 13:25:34 2014
New Revision: 1604572

URL: http://svn.apache.org/r1604572
Log:
PDFBOX-2157: removed the AFMFormatter class, create FontMetric on the fly when parsing the CFF font

Removed:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/AFMFormatter.java
Modified:
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
    pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java?rev=1604572&r1=1604571&r2=1604572&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java Sun Jun 22 13:25:34 2014
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.fontbox.afm.FontMetric;
 import org.apache.fontbox.cff.charset.CFFCharset;
 import org.apache.fontbox.cff.encoding.CFFEncoding;
 import org.apache.fontbox.type1.Type1CharStringReader;
@@ -48,7 +49,8 @@ public class CFFFont implements Type1Cha
     private IndexData globalSubrIndex = null;
     private IndexData localSubrIndex = null;
     private Map<String, Type2CharString> charStringCache = new HashMap<String, Type2CharString>();
-
+    private FontMetric fontMetric = null;
+    
     /**
      * The name of the font.
      * 
@@ -91,6 +93,54 @@ public class CFFFont implements Type1Cha
     }
 
     /**
+     * Returns the string value for the given name from the dictionary.
+     * 
+     * @param name the name of the value
+     * @return the string value of the name if available
+     */
+    public String getPropertyAsString(String name)
+    {
+        Object value = getProperty(name);
+        if (value != null && value instanceof String)
+        {
+            return (String)value;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the float value for the given name from the dictionary.
+     * 
+     * @param name the name of the value
+     * @return the float value of the name if available
+     */
+    public float getPropertyAsFloat(String name, float defaultValue)
+    {
+        Object value = getProperty(name);
+        if (value != null && value instanceof Float)
+        {
+            return (Float)value;
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Returns the boolean value for the given name from the dictionary.
+     * 
+     * @param name the name of the value
+     * @return the boolean value of the name if available
+     */
+    public boolean getPropertyAsBoolean(String name, boolean defaultValue)
+    {
+        Object value = getProperty(name);
+        if (value != null && value instanceof Boolean)
+        {
+            return (Boolean)value;
+        }
+        return defaultValue;
+    }
+
+    /**
      * Adds the given key/value pair to the top dictionary.
      * 
      * @param name the given key
@@ -315,6 +365,26 @@ public class CFFFont implements Type1Cha
     }
 
     /**
+     * Returns the FontMetric of the font.
+     * 
+     * @return the font metrics
+     */
+    public FontMetric getFontMetric()
+    {
+        return fontMetric;
+    }
+
+    /**
+     * Sets the FontMetric of the font.
+     * 
+     * @param metric the given FontMetric 
+     */
+    public void setFontMetric(FontMetric metric)
+    {
+        fontMetric = metric;
+    }
+
+    /**
      * Returns the SID for a given glyph name.
      * @param name glyph name
      * @return SID

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java?rev=1604572&r1=1604571&r2=1604572&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFParser.java Sun Jun 22 13:25:34 2014
@@ -16,9 +16,11 @@
  */
 package org.apache.fontbox.cff;
 
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -26,6 +28,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.fontbox.afm.CharMetric;
+import org.apache.fontbox.afm.FontMetric;
 import org.apache.fontbox.cff.CFFFont.Mapping;
 import org.apache.fontbox.cff.charset.CFFCharset;
 import org.apache.fontbox.cff.charset.CFFExpertCharset;
@@ -34,6 +38,7 @@ import org.apache.fontbox.cff.charset.CF
 import org.apache.fontbox.cff.encoding.CFFEncoding;
 import org.apache.fontbox.cff.encoding.CFFExpertEncoding;
 import org.apache.fontbox.cff.encoding.CFFStandardEncoding;
+import org.apache.fontbox.util.BoundingBox;
 
 /**
  * This class represents a parser for a CFF font. 
@@ -119,6 +124,7 @@ public class CFFParser
         {
             CFFFont font = parseFont(i);
             font.setGlobalSubrIndex(globalSubrIndex);
+            createFontMetrics(font);
             fonts.add(font);
         }
         return fonts;
@@ -567,7 +573,6 @@ public class CFFParser
                 font.setLocalSubrIndex(readIndexData(input));
             }
         }
-
         return font;
     }
 
@@ -1285,4 +1290,75 @@ public class CFFParser
             }
         }
     }
+
+    private void createFontMetrics(CFFFont font) throws IOException
+    {
+        FontMetric fontMetrics = new FontMetric();
+        fontMetrics.setAFMVersion(2.0f);
+        fontMetrics.setFontName( font.getName() );
+        fontMetrics.setFullName( font.getPropertyAsString("FullName") );
+        fontMetrics.setFamilyName( font.getPropertyAsString("FamilyName") );
+        fontMetrics.setWeight( font.getPropertyAsString("Weight") );
+        CFFEncoding encoding = font.getEncoding();
+        if (encoding.isFontSpecific())
+        {
+            fontMetrics.setEncodingScheme("FontSpecific");
+        }
+        fontMetrics.setUnderlinePosition(font.getPropertyAsFloat("UnderlinePosition", -100));
+        fontMetrics.setUnderlineThickness(font.getPropertyAsFloat("UnderlineThickness", 50));
+        fontMetrics.setItalicAngle(font.getPropertyAsFloat("ItalicAngle", 0));
+        fontMetrics.setFixedPitch(font.getPropertyAsBoolean("isFixedPitch",false) );
+        
+        List<CharMetricSortable> metrics = createCharMetrics(font);
+        Collections.sort(metrics);
+        BoundingBox bounds = null;
+        for (CharMetric metric : metrics)
+        {
+            fontMetrics.addCharMetric(metric);
+            if(bounds == null)
+            {
+                bounds = metric.getBoundingBox();
+            }
+            else
+            {
+                BoundingBox.union(bounds, metric.getBoundingBox(), bounds);
+            }
+        }
+        fontMetrics.setFontBBox(bounds);
+        font.setFontMetric(fontMetrics);
+    }
+
+    private List<CharMetricSortable> createCharMetrics(CFFFont font) throws IOException
+    {
+        List<CharMetricSortable> metrics = new ArrayList<CharMetricSortable>();
+        Collection<CFFFont.Mapping> mappings = font.getMappings();
+        for (CFFFont.Mapping mapping : mappings)
+        {
+            CharMetricSortable metric = new CharMetricSortable();
+            metric.setCharacterCode(mapping.getCode());
+            metric.setName(mapping.getName());
+            metric.setWx(mapping.getType1CharString().getWidth());
+            metric.setBBox(mapping.getType1CharString().getBounds());
+            metrics.add(metric);
+        }
+        return metrics;
+    }
+
+    /**
+     * This class represents the metric of one single character. 
+     */
+    private static class CharMetricSortable extends CharMetric implements Comparable<CharMetric>
+    {
+        public int compareTo(CharMetric that)
+        {
+            return getCharacterCode() - that.getCharacterCode();
+        }
+        
+        public void setBBox(Rectangle2D rect)
+        {
+            BoundingBox bBox = new BoundingBox((float)rect.getMinX(), (float)rect.getMinY(), (float)rect.getMaxX(), (float)rect.getMaxY());
+            setBoundingBox(bBox);
+        }
+    }
+
 }

Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java?rev=1604572&r1=1604571&r2=1604572&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java Sun Jun 22 13:25:34 2014
@@ -16,14 +16,12 @@
  */
 package org.apache.fontbox.util;
 
-import java.awt.Point;
 
 /**
  * This is an implementation of a bounding box.  This was originally written for the
  * AMF parser.
  *
  * @author Ben Litchfield (ben@benlitchfield.com)
- * @version $Revision: 1.1 $
  */
 public class BoundingBox
 {
@@ -171,18 +169,6 @@ public class BoundingBox
     }
     
     /**
-     * Checks if a point is inside this rectangle.
-     * 
-     * @param point The point to check
-     * 
-     * @return true If the point is on the edge or inside the rectangle bounds. 
-     */
-    public boolean contains( Point point )
-    {
-        return contains( (float)point.getX(), (float)point.getY() );
-    }
-    
-    /**
      * This will return a string representation of this rectangle.
      *
      * @return This object as a string.
@@ -193,4 +179,33 @@ public class BoundingBox
                      getUpperRightX() + "," + getUpperRightY() +"]";
     }
 
+    /**
+     * Unions the given bounding boxes and puts the result into the 
+     * specified result bounding box.
+     * 
+     * @param bBox1 the first bounding box to be combined with each other
+     * @param bBox2 the second bounding box to be combined with each other
+     * @param result the bounding box that holds the results of the union
+     * 
+     */
+    public static void union(BoundingBox bBox1, BoundingBox bBox2, BoundingBox result)
+    {
+        float x1 = Math.min(bBox1.getLowerLeftX(), bBox2.getLowerLeftX());
+        float y1 = Math.min(bBox1.getLowerLeftY(), bBox2.getLowerLeftY());
+        float x2 = Math.max(bBox1.getUpperRightX(), bBox2.getUpperRightX());
+        float y2 = Math.max(bBox1.getUpperRightY(), bBox2.getUpperRightY());
+        if (x2 < x1)
+        {
+            float temp = x1;
+            x1 = x2;
+            x2 = temp;
+        }
+        if (y2 < y1)
+        {
+            float temp = y1;
+            y1 = y2;
+            y2 = temp;
+        }
+        result = new BoundingBox(x1, y1, x2, y2);
+    }
 }
\ No newline at end of file

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=1604572&r1=1604571&r2=1604572&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 Sun Jun 22 13:25:34 2014
@@ -17,7 +17,6 @@
 
 package org.apache.pdfbox.pdmodel.font;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,12 +29,9 @@ import java.util.Map;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.fontbox.afm.AFMParser;
 import org.apache.fontbox.afm.FontMetric;
-import org.apache.fontbox.cff.AFMFormatter;
 import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFParser;
-import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSFloat;
@@ -251,14 +247,7 @@ public class PDType1CFont extends PDFont
     {
         if (fontMetric == null)
         {
-            try
-            {
-                fontMetric = prepareFontMetric(cffFont);
-            }
-            catch (IOException exception)
-            {
-                LOG.error("An error occured while extracting the font metrics!", exception);
-            }
+            fontMetric = cffFont.getFontMetric();
         }
         return fontMetric;
     }
@@ -361,31 +350,6 @@ public class PDType1CFont extends PDFont
         return null;
     }
 
-    private FontMetric prepareFontMetric(CFFFont font) throws IOException
-    {
-        byte[] afmBytes = AFMFormatter.format(font);
-
-        InputStream is = new ByteArrayInputStream(afmBytes);
-        try
-        {
-            AFMParser afmParser = new AFMParser(is);
-            FontMetric result = afmParser.parse();
-
-            // Replace default FontBBox value with a newly computed one
-            BoundingBox bounds = result.getFontBBox();
-            List<Integer> numbers = Arrays.asList((int) bounds.getLowerLeftX(),
-                    (int) bounds.getLowerLeftY(), (int) bounds.getUpperRightX(),
-                    (int) bounds.getUpperRightY());
-            font.addValueToTopDict("FontBBox", numbers);
-
-            return result;
-        }
-        finally
-        {
-            is.close();
-        }
-    }
-
     /**
      * Returns the raw data of the font as CFFFont.
      *