pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jahew...@apache.org
Subject svn commit: r1621383 - in /pdfbox/branches/no-awt: fontbox/src/main/java/org/apache/fontbox/cmap/ pdfbox/src/main/java/org/apache/pdfbox/cos/ pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ pdfbox/src/main/java/org/apache/pdfbox/rendering/ pdfbox/...
Date Fri, 29 Aug 2014 20:40:03 GMT
Author: jahewson
Date: Fri Aug 29 20:40:02 2014
New Revision: 1621383

URL: http://svn.apache.org/r1621383
Log:
PDFBOX-2262/PDFBOX-2294: Implement vertical text rendering

Added:
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Vector.java
Modified:
    pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.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/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/PDSimpleFont.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/rendering/PageDrawer.java
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/CIDType0Glyph2D.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
    pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/operator/text/ShowTextGlyph.java

Modified: pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java?rev=1621383&r1=1621382&r2=1621383&view=diff
==============================================================================
--- pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java (original)
+++ pdfbox/branches/no-awt/fontbox/src/main/java/org/apache/fontbox/cmap/CMap.java Fri Aug
29 20:40:02 2014
@@ -286,6 +286,8 @@ public class CMap
     {
         this.codespaceRanges.addAll(cmap.codespaceRanges);
         this.charToUnicode.putAll(cmap.charToUnicode);
+        this.codeToCid.putAll(cmap.codeToCid);
+        this.codeToCidRanges.addAll(cmap.codeToCidRanges);
     }
     
     /**

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1621383&r1=1621382&r2=1621383&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Fri Aug
29 20:40:02 2014
@@ -179,6 +179,7 @@ public final class COSName extends COSBa
     public static final COSName DUPLEX = new COSName("Duplex");
     public static final COSName DV = new COSName("DV");
     public static final COSName DW = new COSName("DW");
+    public static final COSName DW2 = new COSName("DW2");
     // E
     public static final COSName E = new COSName("E");
     public static final COSName EARLY_CHANGE = new COSName("EarlyChange");
@@ -464,6 +465,7 @@ public final class COSName extends COSBa
     public static final COSName VIEWER_PREFERENCES = new COSName("ViewerPreferences");
     // W
     public static final COSName W = new COSName("W");
+    public static final COSName W2 = new COSName("W2");
     public static final COSName WHITE_POINT = new COSName("WhitePoint");
     public static final COSName WIDTH = new COSName("Width");
     public static final COSName WIDTHS = new COSName("Widths");

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -28,6 +28,7 @@ import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
 import org.apache.pdfbox.util.Matrix;
+import org.apache.pdfbox.util.Vector;
 
 /**
  * A CIDFont. A CIDFont is a PDF object that contains information about a CIDFont program.
Although
@@ -42,6 +43,10 @@ public abstract class PDCIDFont implemen
     private Map<Integer, Float> widths;
     private float defaultWidth;
 
+    private Map<Integer, Float> verticalDisplacementY = new HashMap<Integer, Float>();
// w1y
+    private Map<Integer, Vector> positionVectors = new HashMap<Integer, Vector>();
    // v
+    private float[] dw2;
+
     protected final COSDictionary dict;
     private PDFontDescriptor fontDescriptor;
 
@@ -55,44 +60,96 @@ public abstract class PDCIDFont implemen
         this.dict = fontDictionary;
         this.parent = parent;
         readWidths();
+        readVerticalDisplacements();
     }
 
     private void readWidths()
     {
-        if (widths == null)
+        widths = new HashMap<Integer, Float>();
+        COSArray widths = (COSArray) dict.getDictionaryObject(COSName.W);
+        if (widths != null)
         {
-            widths = new HashMap<Integer, Float>();
-            COSArray widths = (COSArray) dict.getDictionaryObject(COSName.W);
-            if (widths != null)
+            int size = widths.size();
+            int counter = 0;
+            while (counter < size)
             {
-                int size = widths.size();
-                int counter = 0;
-                while (counter < size)
+                COSNumber firstCode = (COSNumber) widths.getObject(counter++);
+                COSBase next = widths.getObject(counter++);
+                if (next instanceof COSArray)
                 {
-                    COSNumber firstCode = (COSNumber) widths.getObject(counter++);
-                    COSBase next = widths.getObject(counter++);
-                    if (next instanceof COSArray)
+                    COSArray array = (COSArray) next;
+                    int startRange = firstCode.intValue();
+                    int arraySize = array.size();
+                    for (int i = 0; i < arraySize; i++)
                     {
-                        COSArray array = (COSArray) next;
-                        int startRange = firstCode.intValue();
-                        int arraySize = array.size();
-                        for (int i = 0; i < arraySize; i++)
-                        {
-                            COSNumber width = (COSNumber) array.get(i);
-                            this.widths.put(startRange + i, width.floatValue());
-                        }
+                        COSNumber width = (COSNumber) array.get(i);
+                        this.widths.put(startRange + i, width.floatValue());
                     }
-                    else
+                }
+                else
+                {
+                    COSNumber secondCode = (COSNumber) next;
+                    COSNumber rangeWidth = (COSNumber) widths.getObject(counter++);
+                    int startRange = firstCode.intValue();
+                    int endRange = secondCode.intValue();
+                    float width = rangeWidth.floatValue();
+                    for (int i = startRange; i <= endRange; i++)
                     {
-                        COSNumber secondCode = (COSNumber) next;
-                        COSNumber rangeWidth = (COSNumber) widths.getObject(counter++);
-                        int startRange = firstCode.intValue();
-                        int endRange = secondCode.intValue();
-                        float width = rangeWidth.floatValue();
-                        for (int i = startRange; i <= endRange; i++)
-                        {
-                            this.widths.put(i, width);
-                        }
+                        this.widths.put(i, width);
+                    }
+                }
+            }
+        }
+
+    }
+
+    private void readVerticalDisplacements()
+    {
+        // default position vector and vertical displacement vector
+        COSArray cosDW2 = (COSArray) dict.getDictionaryObject(COSName.DW2);
+        if (cosDW2 != null)
+        {
+            dw2 = new float[2];
+            dw2[0] = ((COSNumber)cosDW2.get(0)).floatValue();
+            dw2[1] = ((COSNumber)cosDW2.get(1)).floatValue();
+        }
+        else
+        {
+            dw2 = new float[] { 880, -1000 };
+        }
+
+        // vertical metrics for individual CIDs.
+        COSArray w2 = (COSArray) dict.getDictionaryObject(COSName.W2);
+        if (w2 != null)
+        {
+            for (int i = 0; i < w2.size(); i++)
+            {
+                COSNumber c = (COSNumber)w2.get(i);
+                COSBase next = w2.get(++i);
+                if (next instanceof COSArray)
+                {
+                    COSArray array = (COSArray)next;
+                    for (int j = 0; j < array.size(); j++)
+                    {
+                        int cid = c.intValue() + j;
+                        COSNumber w1y = (COSNumber) array.get(j);
+                        COSNumber v1x = (COSNumber) array.get(++j);
+                        COSNumber v1y = (COSNumber) array.get(++j);
+                        verticalDisplacementY.put(cid, w1y.floatValue());
+                        positionVectors.put(cid, new Vector(v1x.floatValue(), v1y.floatValue()));
+                    }
+                }
+                else
+                {
+                    int first = c.intValue();
+                    int last = ((COSNumber) next).intValue();
+                    COSNumber w1y = (COSNumber) w2.get(++i);
+                    COSNumber v1x = (COSNumber) w2.get(++i);
+                    COSNumber v1y = (COSNumber) w2.get(++i);
+                    for (int cid = first; cid <= last; cid++)
+                    {
+                        verticalDisplacementY.put(cid, w1y.floatValue());
+                        positionVectors.put(cid, new Vector(v1x.floatValue(), v1y.floatValue()));
                     }
                 }
             }
@@ -176,6 +233,74 @@ public abstract class PDCIDFont implemen
     }
 
     /**
+     * Returns the default position vector (v).
+     *
+     * @param cid CID
+     */
+    private Vector getDefaultPositionVector(int cid)
+    {
+        float w0;
+        if (widths.containsKey(cid))
+        {
+            Float w = widths.get(cid);
+            if (w != null)
+            {
+                w0 = w;
+            }
+            else
+            {
+                w0 = getDefaultWidth();
+            }
+        }
+        else
+        {
+            w0 = getDefaultWidth();
+        }
+
+        return new Vector(w0 / 2, dw2[0]);
+    }
+
+    /**
+     * Returns the position vector (v) for the given character code.
+     *
+     * @param code character code
+     * @return position vector (v)
+     */
+    public Vector getPositionVector(int code)
+    {
+        int cid = codeToCID(code);
+        Vector v = positionVectors.get(cid);
+        if (v != null)
+        {
+            return v;
+        }
+        else
+        {
+            return getDefaultPositionVector(cid);
+        }
+    }
+
+    /**
+     * Returns the y-component of the vertical displacement vector (w1).
+     *
+     * @param code character code
+     * @return w1y
+     */
+    public float getVerticalDisplacementVectorY(int code)
+    {
+        int cid = codeToCID(code);
+        Float w1y = verticalDisplacementY.get(cid);
+        if (w1y != null)
+        {
+            return w1y;
+        }
+        else
+        {
+            return dw2[1];
+        }
+    }
+
+    /**
      * This will get the font height for a character.
      *
      * @param code character code
@@ -195,7 +320,7 @@ public abstract class PDCIDFont implemen
         // font widths with the widths given in the font dictionary
 
         int cid = codeToCID(code);
-        if (cid < widths.size())
+        if (widths.containsKey(cid))
         {
             Float w = widths.get(cid);
             if (w != null)

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -169,8 +169,7 @@ public class PDCIDFontType2 extends PDCI
             return cMap.toUnicode(code).codePointAt(0); // actually: code -> CID
         }
 
-        // CID CMap is not used for TTF, even if present, see see PDFBOX-1422
-        return code;
+        return cMap.toCID(code);
     }
 
     /**
@@ -181,18 +180,6 @@ public class PDCIDFontType2 extends PDCI
      */
     public int codeToGID(int code) throws IOException
     {
-        int cid = codeToCID(code);
-        return cidToGID(cid);
-    }
-
-    /**
-     * Returns the GID for the given CID.
-     * 
-     * @param cid the given CID (for TTF this is the same as the character code)
-     * @return the mapped GID
-     */
-    public int cidToGID(int cid) throws IOException
-    {
         if (!isEmbedded)
         {
             // The conforming reader shall select glyphs by translating characters from the
@@ -205,6 +192,7 @@ public class PDCIDFontType2 extends PDCI
 
             if (cid2gid != null || hasIdentityCid2Gid)
             {
+                int cid = codeToCID(code);
                 // strange but true, Acrobat allows non-embedded GIDs, test with PDFBOX-2060
                 if (hasIdentityCid2Gid)
                 {
@@ -215,7 +203,7 @@ public class PDCIDFontType2 extends PDCI
                     return cid2gid[cid];
                 }
             }
-            if (!parent.isSymbolic())
+            else if (!parent.isSymbolic())
             {
                 // this nonsymbolic behaviour isn't well documented, test with PDFBOX-1422
 
@@ -234,7 +222,7 @@ public class PDCIDFontType2 extends PDCI
                 // Any undefined entries in the table shall be filled using StandardEncoding
                 if (name == null)
                 {
-                    name = StandardEncoding.INSTANCE.getName(cid); // code = CID for TTF
+                    name = StandardEncoding.INSTANCE.getName(code);
                 }
 
                 // map to a Unicode value using the Adobe Glyph List
@@ -242,6 +230,7 @@ public class PDCIDFontType2 extends PDCI
             }
             else
             {
+                int cid = codeToCID(code);
                 unicode = parent.toUnicode(cid); // code = CID for TTF
             }
 
@@ -261,6 +250,7 @@ public class PDCIDFontType2 extends PDCI
             // a CIDToGIDMap entry that maps CIDs to the glyph indices for the appropriate
glyph
             // descriptions in that font program.
 
+            int cid = codeToCID(code);
             if (cid2gid != null)
             {
                 // use CIDToGIDMap
@@ -326,8 +316,7 @@ public class PDCIDFontType2 extends PDCI
     @Override
     protected float getWidthFromFont(int code) throws IOException
     {
-        int cid = codeToCID(code);
-        int gid = cidToGID(cid);
+        int gid = codeToGID(code);
         int width = ttf.getAdvanceWidth(gid);
         int unitsPerEM = ttf.getUnitsPerEm();
         if (unitsPerEM != 1000)

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -157,7 +157,7 @@ public abstract class PDFont implements 
     }
 
     /**
-     * Returns the width of the given character, in glyph space.
+     * Returns the advance width of the given character, in glyph space.
      *
      * @param code character code
      */
@@ -469,6 +469,11 @@ public abstract class PDFont implements 
     }
 
     /**
+     * Returns true if the font uses vertical writing mode.
+     */
+    public abstract boolean isVertical();
+
+    /**
      * Calling this will release all cached information.
      */
     public void clear()

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java?rev=1621383&r1=1621382&r2=1621383&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
(original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
Fri Aug 29 20:40:02 2014
@@ -236,6 +236,12 @@ public abstract class PDSimpleFont exten
         return null;
     }
 
+    @Override
+    public boolean isVertical()
+    {
+        return false;
+    }
+
     /**
      * Returns true if this font is one of the "standard 14" fonts.
      */

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -27,6 +27,8 @@ import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.encoding.GlyphList;
+import org.apache.pdfbox.encoding.StandardEncoding;
 import org.apache.pdfbox.util.Matrix;
 
 /**
@@ -62,6 +64,12 @@ public class PDType0Font extends PDFont
         readEncoding();
         fetchCMapUCS2();
         descendantFont = PDFontFactory.createDescendantFont(descendantFontDictionary, this);
+
+        // warn if there may be text extraction issues
+        if (!isSymbolic())
+        {
+            LOG.warn("Nonsymbolic Type 0 font: " + getName());
+        }
     }
 
     /**
@@ -173,6 +181,12 @@ public class PDType0Font extends PDFont
     }
 
     @Override
+    public boolean isVertical()
+    {
+        return cMap.getWMode() == 1;
+    }
+
+    @Override
     public float getHeight(int code) throws IOException
     {
         return descendantFont.getHeight(code);
@@ -212,10 +226,18 @@ public class PDType0Font extends PDFont
             return unicode;
         }
 
-        // if the font is composite and uses a predefined cmap (excluding Identity-H/V) then
-        // or if its decendant font uses Adobe-GB1/CNS1/Japan1/Korea1
-        if (isCMapPredefined && cMapUCS2 != null)
+        if (!isSymbolic())
         {
+            // this nonsymbolic behaviour isn't well documented, test with PDFBOX-1422,
+            // also see PDCIDFontType2#cidToGID()
+            String name = StandardEncoding.INSTANCE.getName(code);
+            return GlyphList.toUnicode(name);
+        }
+        else if (isCMapPredefined && cMapUCS2 != null)
+        {
+            // if the font is composite and uses a predefined cmap (excluding Identity-H/V)
then
+            // or if its decendant font uses Adobe-GB1/CNS1/Japan1/Korea1
+
             // e) Map the CID according to the CMap from step d), producing a Unicode value
             return cMapUCS2.toUnicode(code);
         }

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -249,7 +249,7 @@ public class PageDrawer extends PDFGraph
     }
 
     @Override
-    protected void processText(byte[] string) throws IOException
+    protected void showText(byte[] string, float adjustment) throws IOException
     {
         PDGraphicsState state = getGraphicsState();
         RenderingMode renderingMode = state.getTextState().getRenderingMode();
@@ -260,7 +260,7 @@ public class PageDrawer extends PDFGraph
             textClippingArea = new Area();
         }
 
-        super.processText(string);
+        super.showText(string, adjustment);
 
         // apply the buffered clip as one area
         if (renderingMode.isClip())
@@ -271,8 +271,8 @@ public class PageDrawer extends PDFGraph
     }
 
     @Override
-    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
-                                String unicode, PDFont font) throws IOException
+    protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode,
+                             float dx, float dy) throws IOException
     {
         try
         {

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/CIDType0Glyph2D.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/CIDType0Glyph2D.java?rev=1621383&r1=1621382&r2=1621383&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/CIDType0Glyph2D.java
(original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/rendering/font/CIDType0Glyph2D.java
Fri Aug 29 20:40:02 2014
@@ -53,9 +53,9 @@ public class CIDType0Glyph2D implements 
     public GeneralPath getPathForCharacterCode(int code)
     {
         int cid = font.getParent().codeToCID(code);
-        if (cache.containsKey(cid))
+        if (cache.containsKey(code))
         {
-            return cache.get(cid);
+            return cache.get(code);
         }
 
         // don't draw CID 0
@@ -63,7 +63,7 @@ public class CIDType0Glyph2D implements 
         {
             LOG.warn("No glyph for " + code + " (CID 0000) in font " + fontName);
             GeneralPath path = new GeneralPath();
-            cache.put(cid, path);
+            cache.put(code, path);
             return path;
         }
 
@@ -78,7 +78,7 @@ public class CIDType0Glyph2D implements 
             }
 
             GeneralPath path = charString.getPath();
-            cache.put(cid, path);
+            cache.put(code, path);
             return path;
         }
         catch (IOException e)

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=1621383&r1=1621382&r2=1621383&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 Fri Aug
29 20:40:02 2014
@@ -192,6 +192,17 @@ public class Matrix implements Cloneable
     }
 
     /**
+     * Translates this matrix by the given vector.
+     *
+     * @param vector 2D vector
+     */
+    public void translate(Vector vector)
+    {
+        Matrix m = Matrix.getTranslatingInstance(vector.getX(), vector.getY());
+        concatenate(m);
+    }
+
+    /**
      * This will take the current matrix and multipy it with a matrix that is passed in.
      *
      * @param b The matrix to multiply by.

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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -16,7 +16,6 @@
  */
 package org.apache.pdfbox.util;
 
-import java.awt.Point;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Point2D;
 import java.io.ByteArrayInputStream;
@@ -44,6 +43,7 @@ import org.apache.pdfbox.pdmodel.PDResou
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.font.PDFont;
 import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
 import org.apache.pdfbox.pdmodel.font.PDType3Font;
 import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
 import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
@@ -313,7 +313,7 @@ public class PDFStreamEngine
      */
     public void showText(byte[] string) throws IOException
     {
-        processText(string);
+        showText(string, 0);
     }
 
     /**
@@ -325,40 +325,21 @@ public class PDFStreamEngine
      */
     public void showAdjustedText(List<byte[]> strings, List<Float> adjustments)
throws IOException
     {
-        float fontsize = getGraphicsState().getTextState().getFontSize();
-        float horizontalScaling = getGraphicsState().getTextState().getHorizontalScaling()
/ 100;
         for (int i = 0, len = strings.size(); i < len; i++)
         {
-            float adjustment = adjustments.get(i);
-            Matrix adjMatrix = new Matrix();
-            adjustment =- (adjustment / 1000) * horizontalScaling * fontsize;
-            // TODO vertical writing mode
-            adjMatrix.setValue( 2, 0, adjustment );
-            showAdjustedTextRun(strings.get(i), adjMatrix);
+            showText(strings.get(i), adjustments.get(i));
         }
     }
 
     /**
-     * Called when a single run of text with a spacing adjustment is to be shown.
-     *
-     * @param string the encoded text
-     * @param adjustment spacing adjustment to apply before showing the string
-     * @throws IOException if there was an error showing the text
-     */
-    protected void showAdjustedTextRun(byte[] string, Matrix adjustment) throws IOException
-    {
-        setTextMatrix(adjustment.multiply(getTextMatrix(), adjustment));
-        processText(string);
-    }
-
-    /**
      * Process text from the PDF Stream. You should override this method if you want to
      * perform an action when encoded text is being processed.
-     * 
+     *
      * @param string the encoded text
+     * @param adjustment a position adjustment from a TJ array to be applied after the glyph
      * @throws IOException if there is an error processing the string
      */
-    protected void processText(byte[] string) throws IOException
+    protected void showText(byte[] string, float adjustment) throws IOException
     {
         PDGraphicsState state = getGraphicsState();
         PDTextState textState = state.getTextState();
@@ -373,7 +354,7 @@ public class PDFStreamEngine
 
         float fontSize = textState.getFontSize();
         float horizontalScaling = textState.getHorizontalScaling() / 100f;
-        float characterSpacing = textState.getCharacterSpacing();
+        float charSpacing = textState.getCharacterSpacing();
 
         // put the text state parameters into matrix form
         Matrix parameters = new Matrix(
@@ -403,32 +384,66 @@ public class PDFStreamEngine
                 }
             }
 
+            // text rendering matrix (text space -> device space)
+            Matrix ctm = state.getCurrentTransformationMatrix();
+            Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
+
             // get glyph's horizontal and vertical displacements (glyph space -> text
space)
+            // todo: it would be nice to encapsulate the code below
             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));
+                Matrix fontMatrix = font.getFontMatrix();
+                Point2D adv = fontMatrix.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
-            }
+                if (font.isVertical())
+                {
+                    PDType0Font type0 = (PDType0Font)font;
 
-            // text rendering matrix (text space -> device space)
-            Matrix ctm = state.getCurrentTransformationMatrix();
-            Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
+                    // position vector (position of vertical origin relative to horizontal
origin)
+                    Vector v = type0.getDescendantFont().getPositionVector(code);
+                    textRenderingMatrix.translate(v.scale(-1 / 1000f));
+
+                    // displacement vector
+                    w0 = 0;
+                    w1 = type0.getDescendantFont().getVerticalDisplacementVectorY(code) /
1000;
+                }
+                else
+                {
+                    // displacement vector
+                    w0 = font.getWidth(code) / 1000f;
+                    w1 = 0;
+                }
+            }
 
             // process the decoded glyph
-            processGlyph(textRenderingMatrix, w0, w1, code, unicode, font);
+            showGlyph(textRenderingMatrix, font, code, unicode, w0, w1);
+
+            // TJ adjustment after final glyph
+            float tj = 0;
+            if (in.available() == 0)
+            {
+                tj = adjustment;
+            }
 
             // calculate the combined displacements
-            float tx = (w0 * fontSize + characterSpacing + wordSpacing) * horizontalScaling;
-            float ty = 0; // todo: support vertical writing mode
+            float tx, ty;
+            if (font.isVertical())
+            {
+                tx = 0;
+                ty = (w1 - tj / 1000) * fontSize + charSpacing + wordSpacing;
+            }
+            else
+            {
+                tx = ((w0 - tj / 1000) * fontSize + charSpacing + wordSpacing) * horizontalScaling;
+                ty = 0;
+            }
 
             // update the text matrix
             textMatrix.concatenate(Matrix.getTranslatingInstance(tx, ty));
@@ -440,15 +455,15 @@ public class PDFStreamEngine
      * the default implementation does nothing.
      *
      * @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 font the current font
      * @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 dx the x-advance of the glyph in text space
+     * @param dy the y-advance of the glyph in text space
      * @throws IOException if the glyph cannot be processed
      */
-    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
-                                String unicode, PDFont font) throws IOException
+    protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode,
+                             float dx, float dy) 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=1621383&r1=1621382&r2=1621383&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
Fri Aug 29 20:40:02 2014
@@ -27,7 +27,6 @@ import org.apache.pdfbox.pdmodel.font.PD
 import org.apache.pdfbox.pdmodel.graphics.state.PDGraphicsState;
 import org.apache.pdfbox.text.TextPosition;
 
-import java.awt.geom.Point2D;
 import java.io.IOException;
 import java.util.Properties;
 
@@ -82,8 +81,8 @@ public class PDFTextStreamEngine extends
      * This method was originally written by Ben Litchfield for PDFStreamEngine.
      */
     @Override
-    protected void processGlyph(Matrix textRenderingMatrix, float dx, float dy, int code,
-                                String unicode, PDFont font) throws IOException
+    protected void showGlyph(Matrix textRenderingMatrix, PDFont font, int code, String unicode,
+                             float dx, float dy) throws IOException
     {
         //
         // legacy calculations which were previously in PDFStreamEngine

Added: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Vector.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Vector.java?rev=1621383&view=auto
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Vector.java (added)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/Vector.java Fri Aug
29 20:40:02 2014
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.util;
+
+/**
+ * A 2D vector.
+ *
+ * @author John Hewson
+ */
+public final class Vector
+{
+    private final float x, y;
+
+    public Vector(float x, float y)
+    {
+        this.x = x;
+        this.y = y;
+    }
+
+    /**
+     * Returns the x magnitude.
+     */
+    public float getX()
+    {
+        return x;
+    }
+
+    /**
+     * Returns the y magnitude.
+     */
+    public float getY()
+    {
+        return y;
+    }
+
+    /**
+     * Returns a new vector scaled by both x and y.
+     *
+     * @param sxy x and y scale
+     */
+    public Vector scale(float sxy)
+    {
+        return new Vector(x * sxy, y * sxy);
+    }
+
+    @Override
+    public String toString()
+    {
+        return "(" + x + ", " + y + ")";
+    }
+}

Modified: pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/operator/text/ShowTextGlyph.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/operator/text/ShowTextGlyph.java?rev=1621383&r1=1621382&r2=1621383&view=diff
==============================================================================
--- pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/operator/text/ShowTextGlyph.java
(original)
+++ pdfbox/branches/no-awt/pdfbox/src/main/java/org/apache/pdfbox/util/operator/text/ShowTextGlyph.java
Fri Aug 29 20:40:02 2014
@@ -41,24 +41,24 @@ public class ShowTextGlyph extends Opera
 
         List<Float> adjustments = new ArrayList<Float>();
         List<byte[]> strings = new ArrayList<byte[]>();
-        boolean lastWasAdjustment = false;
+        boolean lastWasString = false;
 
         for(int i = 0, len = array.size(); i < len; i++)
         {
             COSBase next = array.get(i);
-            if(next instanceof COSNumber)
+            if (next instanceof COSNumber)
             {
                 adjustments.add(((COSNumber)next).floatValue());
-                lastWasAdjustment = true;
+                lastWasString = false;
             }
             else if(next instanceof COSString)
             {
-                if (!lastWasAdjustment)
+                if (lastWasString)
                 {
-                    adjustments.add(0f);
+                    adjustments.add(0f); // adjustment for previous string
                 }
                 strings.add(((COSString)next).getBytes());
-                lastWasAdjustment = false;
+                lastWasString = true;
             }
             else
             {
@@ -66,6 +66,12 @@ public class ShowTextGlyph extends Opera
             }
         }
 
+        // adjustment for final string
+        if (lastWasString)
+        {
+            adjustments.add(0f);
+        }
+
         context.showAdjustedText(strings, adjustments);
     }
 }



Mime
View raw message