You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/08/28 22:55:22 UTC

svn commit: r1621203 - in /pdfbox/branches/no-awt: fontbox/src/main/java/org/apache/fontbox/cff/ fontbox/src/main/java/org/apache/fontbox/ttf/ fontbox/src/main/java/org/apache/fontbox/type1/ fontbox/src/main/java/org/apache/fontbox/util/ pdfbox/src/mai...

Author: jahewson
Date: Thu Aug 28 20:55:21 2014
New Revision: 1621203

URL: http://svn.apache.org/r1621203
Log:
PDFBOX-2262: Refactor text positioning

Modified:
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Matrix.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFTextStreamEngine.java

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java Thu Aug 28 20:55:21 2014
@@ -92,9 +92,7 @@ public abstract class CFFFont
     public BoundingBox getFontBBox()
     {
         List<Number> numbers = (List<Number>)topDict.get("FontBBox");
-        BoundingBox bbox = new BoundingBox(numbers.get(0).floatValue(), numbers.get(1).floatValue(),
-                                           numbers.get(2).floatValue(), numbers.get(3).floatValue());
-        return bbox;
+        return new BoundingBox(numbers);
     }
 
     /**

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java Thu Aug 28 20:55:21 2014
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.fontbox.encoding.Encoding;
+import org.apache.fontbox.util.BoundingBox;
 
 /**
  * A TrueType font file.
@@ -476,6 +477,17 @@ public class TrueTypeFont implements Typ
     }
 
     @Override
+    public BoundingBox getFontBBox() throws IOException
+    {
+        short xMin = getHeader().getXMin();
+        short xMax = getHeader().getXMax();
+        short yMin = getHeader().getYMin();
+        short yMax = getHeader().getYMax();
+        float scale = 1000f / getUnitsPerEm();
+        return new BoundingBox(xMin * scale, yMin * scale, xMax * scale, yMax * scale);
+    }
+
+    @Override
     public String toString()
     {
         try

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java Thu Aug 28 20:55:21 2014
@@ -1,8 +1,10 @@
 package org.apache.fontbox.ttf;
 
 import org.apache.fontbox.encoding.Encoding;
+import org.apache.fontbox.util.BoundingBox;
 
 import java.awt.geom.GeneralPath;
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 
 /**
@@ -43,5 +45,10 @@ public interface Type1Equivalent
     /**
      * Returns the PostScript Encoding vector for the font.
      */
-    public Encoding getEncoding();
+    public Encoding getEncoding() throws IOException;
+
+    /**
+     * Returns the font's bounding box in PostScript units.
+     */
+    public abstract BoundingBox getFontBBox() throws IOException;
 }

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java Thu Aug 28 20:55:21 2014
@@ -22,6 +22,7 @@ import org.apache.fontbox.cff.Type1CharS
 import org.apache.fontbox.encoding.Encoding;
 import org.apache.fontbox.pfb.PfbParser;
 import org.apache.fontbox.ttf.Type1Equivalent;
+import org.apache.fontbox.util.BoundingBox;
 
 import java.awt.geom.GeneralPath;
 import java.io.IOException;
@@ -233,9 +234,9 @@ public final class Type1Font implements 
      * 
      * @return the font bounding box
      */
-    public List<Number> getFontBBox()
+    public BoundingBox getFontBBox()
     {
-        return Collections.unmodifiableList(fontBBox);
+        return new BoundingBox(fontBBox);
     }
 
     /**

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/util/BoundingBox.java Thu Aug 28 20:55:21 2014
@@ -17,6 +17,8 @@
 package org.apache.fontbox.util;
 
 
+import java.util.List;
+
 /**
  * This is an implementation of a bounding box.  This was originally written for the
  * AMF parser.
@@ -52,6 +54,20 @@ public class BoundingBox
         upperRightX = maxX;
         upperRightY = maxY;
     }
+
+    /**
+     * Constructor.
+     *
+     * @param numbers list of four numbers
+     */
+    public BoundingBox(List<Number> numbers)
+    {
+        lowerLeftX = numbers.get(0).floatValue();
+        lowerLeftY = numbers.get(1).floatValue();
+        upperRightX = numbers.get(2).floatValue();
+        upperRightY = numbers.get(3).floatValue();
+    }
+
     /**
      * Getter for property lowerLeftX.
      *

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java Thu Aug 28 20:55:21 2014
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
@@ -148,6 +149,11 @@ public abstract class PDCIDFont implemen
     }
 
     /**
+     * Returns the font's bounding box.
+     */
+    public abstract BoundingBox getBoundingBox() throws IOException;
+
+    /**
      * This will get the default width. The default value for the default width is 1000.
      *
      * @return The default width for the glyphs in this font.

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java Thu Aug 28 20:55:21 2014
@@ -18,6 +18,7 @@ package org.apache.pdfbox.pdmodel.font;
 
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
@@ -28,6 +29,7 @@ import org.apache.fontbox.cff.CFFFont;
 import org.apache.fontbox.cff.CFFParser;
 import org.apache.fontbox.cff.CFFType1Font;
 import org.apache.fontbox.cff.Type2CharString;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.io.IOUtils;
 import org.apache.pdfbox.pdmodel.common.PDStream;
@@ -134,6 +136,18 @@ public class PDCIDFontType0 extends PDCI
         return fontMatrix;
     }
 
+    @Override
+    public BoundingBox getBoundingBox()
+    {
+        if (cidFont != null)
+        {
+            return cidFont.getFontBBox();
+        } else
+        {
+            return t1Font.getFontBBox();
+        }
+    }
+
     /**
      * Returns the embedded CFF CIDFont.
      */

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java Thu Aug 28 20:55:21 2014
@@ -26,6 +26,7 @@ import org.apache.fontbox.ttf.CmapSubtab
 import org.apache.fontbox.ttf.CmapTable;
 import org.apache.fontbox.ttf.TTFParser;
 import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
@@ -121,6 +122,12 @@ public class PDCIDFontType2 extends PDCI
         return fontMatrix;
     }
 
+    @Override
+    public BoundingBox getBoundingBox() throws IOException
+    {
+        return ttf.getFontBBox();
+    }
+
     private int[] readCIDToGIDMap()
     {
         int[] cid2gid = null;

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java Thu Aug 28 20:55:21 2014
@@ -24,6 +24,7 @@ import java.util.List;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
@@ -33,7 +34,6 @@ import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.io.IOUtils;
 import org.apache.pdfbox.pdmodel.common.COSArrayList;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.util.Matrix;
 
 /**
@@ -157,7 +157,7 @@ public abstract class PDFont implements 
     }
 
     /**
-     * Returns the width of the given character.
+     * Returns the width of the given character, in glyph space.
      *
      * @param code character code
      */
@@ -207,47 +207,12 @@ public abstract class PDFont implements 
     public abstract boolean isEmbedded();
 
     /**
-     * This will get the font height for a character.
+     * Returns the height of the given character, in glyph space. This can be expensive to
+     * calculate. Results are only approximate.
      * 
      * @param code character code
-     * @return The height is in 1000 unit of text space, ie 333 or 777
      */
-    // todo: this is not the glyph height at all! this method is *supposed* to get the y-advance
-    public float getHeight(int code) throws IOException
-    {
-        // maybe there is already a precalculated value
-        PDFontDescriptor desc = getFontDescriptor();
-        if (desc != null)
-        {
-            // the following values are all more or less accurate at least all are average
-            // values. Maybe we'll find another way to get those value for every single glyph
-            // in the future if needed
-            PDRectangle fontBBox = desc.getFontBoundingBox();
-            float retval = 0;
-            if (fontBBox != null)
-            {
-                retval = fontBBox.getHeight() / 2;
-            }
-            if (retval == 0)
-            {
-                retval = desc.getCapHeight();
-            }
-            if (retval == 0)
-            {
-                retval = desc.getAscent();
-            }
-            if (retval == 0)
-            {
-                retval = desc.getXHeight();
-                if (retval > 0)
-                {
-                    retval -= desc.getDescent();
-                }
-            }
-            return retval;
-        }
-        return 0;
-    }
+    public abstract float getHeight(int code) throws IOException;
 
     /**
      * Returns the width of the given Unicode string.
@@ -430,6 +395,11 @@ public abstract class PDFont implements 
     }
 
     /**
+     * Returns the font's bounding box.
+     */
+    public abstract BoundingBox getBoundingBox() throws IOException;
+
+    /**
      * The widths of the characters. This will be null for the standard 14 fonts.
      *
      * @return The widths of the characters.

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java Thu Aug 28 20:55:21 2014
@@ -27,8 +27,10 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fontbox.ttf.CmapSubtable;
 import org.apache.fontbox.ttf.CmapTable;
+import org.apache.fontbox.ttf.GlyphData;
 import org.apache.fontbox.ttf.TTFParser;
 import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.encoding.GlyphList;
@@ -136,6 +138,7 @@ public class PDTrueTypeFont extends PDSi
     @Override
     protected Encoding readEncodingFromFont() throws IOException
     {
+        // TTF fonts don't have PostScript Encoding vectors
         return null;
     }
 
@@ -156,6 +159,12 @@ public class PDTrueTypeFont extends PDSi
         return in.read();
     }
 
+    @Override
+    public BoundingBox getBoundingBox() throws IOException
+    {
+        return ttf.getFontBBox();
+    }
+
     /**
      * Returns the embedded or substituted TrueType font.
      */
@@ -178,6 +187,18 @@ public class PDTrueTypeFont extends PDSi
     }
 
     @Override
+    public float getHeight(int code) throws IOException
+    {
+        int gid = codeToGID(code);
+        GlyphData glyph = ttf.getGlyph().getGlyphs()[gid];
+        if (glyph != null)
+        {
+            return glyph.getBoundingBox().getHeight();
+        }
+        return 0;
+    }
+
+    @Override
     public boolean isEmbedded()
     {
         return isEmbedded;

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java Thu Aug 28 20:55:21 2014
@@ -22,6 +22,7 @@ import java.io.InputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
@@ -226,6 +227,12 @@ public class PDType0Font extends PDFont
     }
 
     @Override
+    public BoundingBox getBoundingBox() throws IOException
+    {
+        return descendantFont.getBoundingBox();
+    }
+
+    @Override
     public int readCode(InputStream in) throws IOException
     {
         return cMap.readCode(in);

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Thu Aug 28 20:55:21 2014
@@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFac
 import org.apache.fontbox.cff.CFFParser;
 import org.apache.fontbox.cff.CFFType1Font;
 import org.apache.fontbox.ttf.Type1Equivalent;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.encoding.GlyphList;
@@ -131,6 +132,12 @@ public class PDType1CFont extends PDSimp
     }
 
     @Override
+    public BoundingBox getBoundingBox() throws IOException
+    {
+        return type1Equivalent.getFontBBox();
+    }
+
+    @Override
     public boolean hasGlyph(String name) throws IOException
     {
         return type1Equivalent.hasGlyph(name);

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Thu Aug 28 20:55:21 2014
@@ -29,6 +29,7 @@ import org.apache.fontbox.afm.AFMParser;
 import org.apache.fontbox.afm.FontMetrics;
 import org.apache.fontbox.ttf.Type1Equivalent;
 import org.apache.fontbox.type1.Type1Font;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
@@ -272,12 +273,15 @@ public class PDType1Font extends PDSimpl
     @Override
     public float getHeight(int code) throws IOException
     {
+        String name = getEncoding().getName(code);
         if (afm != null)
         {
-            String characterName = getEncoding().getName(code);
-            return afm.getCharacterHeight(characterName); // todo: isn't this the y-advance, not the height?
+            return afm.getCharacterHeight(name); // todo: isn't this the y-advance, not the height?
+        }
+        else
+        {
+            return (float)type1Equivalent.getPath(name).getBounds().getHeight();
         }
-        return super.getHeight(code);
     }
 
     @Override
@@ -367,6 +371,12 @@ public class PDType1Font extends PDSimpl
     }
 
     @Override
+    public BoundingBox getBoundingBox() throws IOException
+    {
+        return type1Equivalent.getFontBBox();
+    }
+
+    @Override
     public boolean hasGlyph(String name) throws IOException
     {
         return type1Equivalent.hasGlyph(name);

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java Thu Aug 28 20:55:21 2014
@@ -21,6 +21,7 @@ import java.io.InputStream;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.util.BoundingBox;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
@@ -111,6 +112,42 @@ public class PDType3Font extends PDSimpl
     }
 
     @Override
+    public float getHeight(int code) throws IOException
+    {
+        PDFontDescriptor desc = getFontDescriptor();
+        if (desc != null)
+        {
+            // the following values are all more or less accurate at least all are average
+            // values. Maybe we'll find another way to get those value for every single glyph
+            // in the future if needed
+            PDRectangle fontBBox = desc.getFontBoundingBox();
+            float retval = 0;
+            if (fontBBox != null)
+            {
+                retval = fontBBox.getHeight() / 2;
+            }
+            if (retval == 0)
+            {
+                retval = desc.getCapHeight();
+            }
+            if (retval == 0)
+            {
+                retval = desc.getAscent();
+            }
+            if (retval == 0)
+            {
+                retval = desc.getXHeight();
+                if (retval > 0)
+                {
+                    retval -= desc.getDescent();
+                }
+            }
+            return retval;
+        }
+        return 0;
+    }
+
+    @Override
     public int readCode(InputStream in) throws IOException
     {
         return in.read();
@@ -156,9 +193,8 @@ public class PDType3Font extends PDSimpl
      * This will get the fonts bounding box.
      *
      * @return The fonts bounding box.
-     * @throws IOException If there is an error getting the bounding box.
      */
-    public PDRectangle getBoundingBox() throws IOException
+    public PDRectangle getFontBBox()
     {
         COSArray rect = (COSArray) dict.getDictionaryObject(COSName.FONT_BBOX);
         PDRectangle retval = null;
@@ -168,6 +204,14 @@ public class PDType3Font extends PDSimpl
         }
         return retval;
     }
+
+    @Override
+    public BoundingBox getBoundingBox()
+    {
+        PDRectangle rect = getFontBBox();
+        return new BoundingBox(rect.getLowerLeftX(), rect.getLowerLeftY(),
+                               rect.getWidth(), rect.getHeight());
+    }
     
     /**
      * Returns the dictionary containing all streams to be used to render the glyphs.

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java Thu Aug 28 20:55:21 2014
@@ -271,13 +271,12 @@ public class PageDrawer extends PDFGraph
     }
 
     @Override
-    protected void processGlyph(Matrix textMatrix, Point2D.Float end, float maxHeight,
-                                float widthText, int code, String unicode, PDFont font,
-                                float fontSize) throws IOException
+    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
+                                String unicode, PDFont font) throws IOException
     {
         try
         {
-            AffineTransform at = textMatrix.createAffineTransform();
+            AffineTransform at = textRenderingMatrix.createAffineTransform();
             Matrix fontMatrix = font.getFontMatrix();
 
             // use different methods to draw the string

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Matrix.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Matrix.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Matrix.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Matrix.java Thu Aug 28 20:55:21 2014
@@ -21,6 +21,7 @@ import org.apache.pdfbox.cos.COSFloat;
 import org.apache.pdfbox.cos.COSNumber;
 
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
 
 /**
  * This class will be used for matrix manipulation.
@@ -74,6 +75,7 @@ public class Matrix implements Cloneable
         single[4] = d;
         single[6] = e;
         single[7] = f;
+        single[8] = 1;
     }
 
     /**
@@ -180,6 +182,16 @@ public class Matrix implements Cloneable
     }
 
     /**
+     * Concatenates (premultiplies) the given matrix to this matrix.
+     *
+     * @param matrix The matrix to concatenate.
+     */
+    public void concatenate(Matrix matrix)
+    {
+        matrix.multiply(this, this);
+    }
+
+    /**
      * This will take the current matrix and multipy it with a matrix that is passed in.
      *
      * @param b The matrix to multiply by.
@@ -273,6 +285,39 @@ public class Matrix implements Cloneable
     }
 
     /**
+     * Transforms the given point by this matrix.
+     *
+     * @param point point to transform
+     */
+    public void transform(Point2D point) {
+        double x = point.getX();
+        double y = point.getY();
+        double a = single[0];
+        double b = single[1];
+        double c = single[3];
+        double d = single[4];
+        double e = single[6];
+        double f = single[7];
+        point.setLocation(x * a + y * c + e, x * b + y * d + f);
+    }
+
+    /**
+     * Transforms the given point by this matrix.
+     *
+     * @param x x-coordinate
+     * @param y y-coordinate
+     */
+    public Point2D transform(double x, double y) {
+        double a = single[0];
+        double b = single[1];
+        double c = single[3];
+        double d = single[4];
+        double e = single[6];
+        double f = single[7];
+        return new Point2D.Double(x * a + y * c + e, x * b + y * d + f);
+    }
+
+    /**
      * Create a new matrix with just the scaling operators.
      *
      * @return A new matrix with just the scaling operators.
@@ -337,6 +382,19 @@ public class Matrix implements Cloneable
     }
 
     /**
+     * Produces a copy of the first matrix, with the second matrix concatenated.
+     *
+     * @param a The matrix to copy.
+     * @param b The matrix to concatenate.
+     */
+    public static Matrix concatenate(Matrix a, Matrix b)
+    {
+        Matrix copy = a.clone();
+        copy.concatenate(b);
+        return copy;
+    }
+
+    /**
      * Clones this object.
      * @return cloned matrix as an object.
      */

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java Thu Aug 28 20:55:21 2014
@@ -16,6 +16,7 @@
  */
 package org.apache.pdfbox.util;
 
+import java.awt.Point;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Point2D;
 import java.io.ByteArrayInputStream;
@@ -48,6 +49,7 @@ import org.apache.pdfbox.pdmodel.graphic
 import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
 import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
 import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.state.PDTextState;
 import org.apache.pdfbox.util.operator.Operator;
 import org.apache.pdfbox.util.operator.OperatorProcessor;
 
@@ -358,123 +360,78 @@ public class PDFStreamEngine
      */
     protected void processText(byte[] string) throws IOException
     {
-        // Note on variable names: there are three different units being used in this code.
-        // Character sizes are given in glyph units, text locations are initially given in text
-        // units, and we want to save the data in display units. The variable names should end with
-        // Text or Disp to represent if the values are in text or disp units (no glyph units are
-        // saved).
-
         PDGraphicsState state = getGraphicsState();
-
-        final float fontSizeText = state.getTextState().getFontSize();
-        final float horizontalScalingText = state.getTextState().getHorizontalScaling() / 100f;
-        final float riseText = state.getTextState().getRise();
-        final float wordSpacingText = state.getTextState().getWordSpacing();
-        final float characterSpacingText = state.getTextState().getCharacterSpacing();
+        PDTextState textState = state.getTextState();
 
         // get the current font
-        PDFont font = state.getTextState().getFont();
+        PDFont font = textState.getFont();
         if (font == null)
         {
             LOG.warn("No current font, will use default");
             font = PDFontFactory.createDefaultFont();
         }
 
-        // all fonts have the width/height of a character in thousandths of a unit of text space
-        float fontMatrixXScaling = 1 / 1000f;
-        float fontMatrixYScaling = 1 / 1000f;
-
-        // except Type 3 fonts, those provide the width of a character in glyph space units
-        if (font instanceof PDType3Font)
-        {
-            Matrix fontMatrix = font.getFontMatrix();
-            fontMatrixXScaling = fontMatrix.getValue(0, 0);
-            fontMatrixYScaling = fontMatrix.getValue(1, 1);
-        }
-
-        Matrix textStateParameters = new Matrix();
-        textStateParameters.setValue(0, 0, fontSizeText * horizontalScalingText);
-        textStateParameters.setValue(1, 1, fontSizeText);
-        textStateParameters.setValue(2, 1, riseText);
-
-        Matrix ctm = state.getCurrentTransformationMatrix();
-        Matrix textXctm = new Matrix();
-        Matrix textMatrixEnd = new Matrix();
-        Matrix td = new Matrix();
-        Matrix tempMatrix = new Matrix();
+        float fontSize = textState.getFontSize();
+        float horizontalScaling = textState.getHorizontalScaling() / 100f;
+        float characterSpacing = textState.getCharacterSpacing();
+
+        // put the text state parameters into matrix form
+        Matrix parameters = new Matrix(
+                fontSize * horizontalScaling, 0, // 0
+                0, fontSize,                     // 0
+                0, textState.getRise());         // 1
 
+        // read the stream until it is empty
         InputStream in = new ByteArrayInputStream(string);
         while (in.available() > 0)
         {
+            // decode a character
             int before = in.available();
             int code = font.readCode(in);
             int codeLength = before - in.available();
             String unicode = font.toUnicode(code);
 
-            // TODO: handle horizontal displacement
-            // get the width and height of this character in text units
-            float charHorizontalDisplacementText = font.getWidth(code);
-            float charVerticalDisplacementText = font.getHeight(code); // todo: NOPE we want y-advance not BBox
-
-            // multiply the width/height with the scaling factor
-            charHorizontalDisplacementText = charHorizontalDisplacementText * fontMatrixXScaling;
-            charVerticalDisplacementText = charVerticalDisplacementText * fontMatrixYScaling;
-
             // Word spacing shall be applied to every occurrence of the single-byte character code
             // 32 in a string when using a simple font or a composite font that defines code 32 as
             // a single-byte code.
-            float spacingText = 0;
+            float wordSpacing = 0;
             if (codeLength == 1)
             {
                 if (code == 32)
                 {
-                    spacingText += wordSpacingText;
+                    wordSpacing += textState.getWordSpacing();
                 }
             }
 
-            textMatrix.multiply(ctm, textXctm);
-            // Convert textMatrix to display units
-            // We need to instantiate a new Matrix instance here as it is passed to the TextPosition
-            // constructor below
-            Matrix textMatrixStart = textStateParameters.multiply(textXctm);
-
-            // TODO: tx should be set for horizontal text and ty for vertical text
-            // which seems to be specified in the font (not the direction in the matrix).
-            float tx = charHorizontalDisplacementText * fontSizeText * horizontalScalingText;
-            float ty = 0;
-            // reset the matrix instead of creating a new one
-            td.reset();
-            td.setValue(2, 0, tx);
-            td.setValue(2, 1, ty);
-
-            // The text matrix gets updated after each glyph is placed. The updated
-            // version will have the X and Y coordinates for the next glyph.
-            // textMatrixEnd contains the coordinates of the end of the last glyph without
-            // taking characterSpacingText and spacintText into account, otherwise it'll be
-            // impossible to detect new words within text extraction
-            textStateParameters.multiply(td, tempMatrix);
-            tempMatrix.multiply(textXctm, textMatrixEnd);
-            final float endXPosition = textMatrixEnd.getXPosition();
-            final float endYPosition = textMatrixEnd.getYPosition();
-
-            // add some spacing to the text matrix (see comment above)
-            tx = (charHorizontalDisplacementText * fontSizeText + characterSpacingText +
-                    spacingText) * horizontalScalingText;
-            td.setValue(2, 0, tx);
-            td.multiply(textMatrix, textMatrix);
-
-            // determine the width of this character
-            // TODO: Note that if we handled vertical text, we should be using Y here
-            float startXPosition = textMatrixStart.getXPosition();
-            float widthText = endXPosition - startXPosition;
+            // get glyph's horizontal and vertical displacements (glyph space -> text space)
+            float w0, w1;
+            if (font instanceof PDType3Font)
+            {
+                // Type 3 fonts specify a custom matrix
+                Point2D adv = font.getFontMatrix().transform(font.getWidth(code), font.getHeight(code));
+                w0 = (float)adv.getX();
+                w1 = (float)adv.getY();
+            }
+            else
+            {
+                // all other fonts use 1:1000 for widths, even those with a FontMatrix, see FOP-2252
+                w0 = font.getWidth(code) / 1000f;
+                w1 = 0; // todo: support vertical writing mode
+            }
 
-            float totalVerticalDisplacementDisp = charVerticalDisplacementText * fontSizeText *
-                    textXctm.getYScale();
+            // text rendering matrix (text space -> device space)
+            Matrix ctm = state.getCurrentTransformationMatrix();
+            Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
 
             // process the decoded glyph
-            processGlyph(textMatrixStart, new Point2D.Float(endXPosition, endYPosition),
-                    totalVerticalDisplacementDisp, widthText, code, unicode,
-                    font, fontSizeText);
+            processGlyph(textRenderingMatrix, w0, w1, code, unicode, font);
+
+            // calculate the combined displacements
+            float tx = (w0 * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
+            float ty = 0; // todo: support vertical writing mode
+
+            // update the text matrix
+            textMatrix.concatenate(Matrix.getTranslatingInstance(tx, ty));
         }
     }
 
@@ -482,19 +439,16 @@ public class PDFStreamEngine
      * Called when a glyph is to be processed.This method is intended for overriding in subclasses,
      * the default implementation does nothing.
      *
-     * @param textMatrix the text matrix at the start of the glyph
-     * @param end the end position of the glyph in text space
-     * @param maxHeight the height of the glyph in device space
-     * @param widthText the width of the glyph in text space
-     * @param unicode the Unicode text for this glyph, or null. May be meaningless.
+     * @param textRenderingMatrix the current text rendering matrix, T<sub>rm</sub>
+     * @param dx the x-advance of the glyph in text space
+     * @param dy the y-advance of the glyph in text space
      * @param code internal PDF character code for the glyph
+     * @param unicode the Unicode text for this glyph, or null if the PDF does provide it
      * @param font the current font
-     * @param fontSize font size in text space
      * @throws IOException if the glyph cannot be processed
      */
-    protected void processGlyph(Matrix textMatrix, Point2D.Float end, float maxHeight,
-                                float widthText, int code, String unicode, PDFont font,
-                                float fontSize) throws IOException
+    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
+                                String unicode, PDFont font) throws IOException
     {
         // overridden in subclasses
     }

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFTextStreamEngine.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFTextStreamEngine.java?rev=1621203&r1=1621202&r2=1621203&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFTextStreamEngine.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/PDFTextStreamEngine.java Thu Aug 28 20:55:21 2014
@@ -24,6 +24,7 @@ import org.apache.pdfbox.pdmodel.common.
 import org.apache.pdfbox.pdmodel.font.PDFont;
 import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
 import org.apache.pdfbox.pdmodel.font.PDType3Font;
+import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
 import org.apache.pdfbox.text.TextPosition;
 
 import java.awt.geom.Point2D;
@@ -81,10 +82,46 @@ public class PDFTextStreamEngine extends
      * This method was originally written by Ben Litchfield for PDFStreamEngine.
      */
     @Override
-    protected final void processGlyph(Matrix textMatrix, Point2D.Float end, float maxHeight,
-                                      float widthText, int code, String unicode, PDFont font,
-                                      float fontSize) throws IOException
+    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
+                                String unicode, PDFont font) throws IOException
     {
+        //
+        // legacy calculations which were previously in PDFStreamEngine
+        //
+
+        PDGraphicsState state = getGraphicsState();
+        Matrix ctm = state.getCurrentTransformationMatrix();
+        float fontSize = state.getTextState().getFontSize();
+        float horizontalScaling = state.getTextState().getHorizontalScaling() / 100f;
+        Matrix textMatrix = getTextMatrix();
+
+        // 1/2 the bbox is used as the height todo: why?
+        float glyphHeight = font.getBoundingBox().getHeight() / 2;
+
+        // transform from glyph space -> text space
+        float height = (float)font.getFontMatrix().transform(0, glyphHeight).getY();
+
+        // (modified) combined displacement, this is calculated *without* taking the character
+        // spacing and word spacing into account, due to legacy code in TextStripper
+        float tx = dx * fontSize * horizontalScaling;
+        float ty = 0; // todo: support vertical writing mode
+
+        // (modified) combined displacement matrix
+        Matrix td = Matrix.getTranslatingInstance(tx, ty);
+
+        // (modified) text rendering matrix
+        Matrix nextTextRenderingMatrix = td.multiply(textMatrix).multiply(ctm); // text space -> device space
+        float nextX = nextTextRenderingMatrix.getXPosition();
+        float nextY = nextTextRenderingMatrix.getYPosition();
+
+        // (modified) width and height calculations
+        float dxDisplay = nextX - textRenderingMatrix.getXPosition();
+        float dyDisplay = height * textRenderingMatrix.getYScale();
+
+        //
+        // start of the original method
+        //
+
         // Note on variable names. There are three different units being used in this code.
         // Character sizes are given in glyph units, text locations are initially given in text
         // units, and we want to save the data in display units. The variable names should end with
@@ -93,7 +130,7 @@ public class PDFTextStreamEngine extends
 
         float fontSizeText = getGraphicsState().getTextState().getFontSize();
         float horizontalScalingText = getGraphicsState().getTextState().getHorizontalScaling()/100f;
-        Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
+        //Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
 
         float glyphSpaceToTextSpaceFactor = 1 / 1000f;
         if (font instanceof PDType3Font)
@@ -126,8 +163,8 @@ public class PDFTextStreamEngine extends
         }
 
         // the space width has to be transformed into display units
-        float spaceWidthDisp = spaceWidthText * fontSizeText * horizontalScalingText *
-                textMatrix.getXScale()  * ctm.getXScale();
+        float spaceWidthDisplay = spaceWidthText * fontSizeText * horizontalScalingText *
+                textRenderingMatrix.getXScale()  * ctm.getXScale();
 
         // when there is no Unicode mapping available, Acrobat simply coerces the character code
         // into Unicode, so we do the same. Subclasses of PDFStreamEngine don't necessarily want
@@ -148,9 +185,10 @@ public class PDFTextStreamEngine extends
         }
 
         processTextPosition(new TextPosition(pageRotation, pageSize.getWidth(),
-                pageSize.getHeight(), textMatrix, end.x, end.y, maxHeight, widthText,
-                spaceWidthDisp, unicode, new int[] { code } , font, fontSize,
-                (int)(fontSize * textMatrix.getXScale())));
+                pageSize.getHeight(), textRenderingMatrix, nextX, nextY,
+                dyDisplay, dxDisplay,
+                spaceWidthDisplay, unicode, new int[] { code } , font, fontSize,
+                (int)(fontSize * textRenderingMatrix.getXScale())));
     }
 
     /**