pdfbox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From msahy...@apache.org
Subject svn commit: r1708713 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
Date Wed, 14 Oct 2015 23:18:17 GMT
Author: msahyoun
Date: Wed Oct 14 23:18:17 2015
New Revision: 1708713

URL: http://svn.apache.org/viewvc?rev=1708713&view=rev
Log:
PDFBOX-3023: respect the font color setting in the DA string

Added:
    pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
  (with props)
Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java?rev=1708713&r1=1708712&r2=1708713&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java
(original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceString.java
Wed Oct 14 23:18:17 2015
@@ -17,15 +17,25 @@
 package org.apache.pdfbox.pdmodel.interactive.form;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+
 import org.apache.pdfbox.contentstream.operator.Operator;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSObject;
 import org.apache.pdfbox.cos.COSString;
 import org.apache.pdfbox.pdfparser.PDFStreamParser;
 import org.apache.pdfbox.pdmodel.PDPageContentStream;
 import org.apache.pdfbox.pdmodel.PDResources;
 import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
+import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceColorSpace;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
 
 /**
@@ -45,9 +55,13 @@ class PDDefaultAppearanceString
      */
     private static final float DEFAULT_FONT_SIZE = 12;
     
-    private final List<Object> tokens;
     private final PDResources defaultResources;
     
+    private COSName fontName;
+    private PDFont font;
+    private float fontSize = DEFAULT_FONT_SIZE;
+    private PDColor fontColor;
+    
     /**
      * Constructor for reading an existing DA string.
      * 
@@ -67,79 +81,192 @@ class PDDefaultAppearanceString
             throw new IllegalArgumentException("/DR is a required entry");
         }
         
-        PDFStreamParser parser = new PDFStreamParser(defaultAppearance.getBytes());
-        parser.parse();
-        tokens = parser.getTokens();
-        
         this.defaultResources = defaultResources;
+        processAppearanceStringOperators(defaultAppearance.getBytes());
     }
     
     /**
-     * Returns the font size.
+     * Processes the operators of the given content stream.
+     *
+     * @param content the content to parse.
+     * @throws IOException if there is an error reading or parsing the content stream.
      */
-    public float getFontSize()
+    private void processAppearanceStringOperators(byte[] content) throws IOException
     {
-        if (!tokens.isEmpty())
+        List<COSBase> arguments = new ArrayList<COSBase>();
+        PDFStreamParser parser = new PDFStreamParser(content);
+        Object token = parser.parseNextToken();
+        while (token != null)
         {
-            // daString looks like "BMC /Helv 3.4 Tf EMC"
-            // use the fontsize of the default existing apperance stream
-            int fontIndex = tokens.indexOf(Operator.getOperator("Tf"));
-            if (fontIndex != -1)
+            if (token instanceof COSObject)
             {
-                return ((COSNumber) tokens.get(fontIndex - 1)).floatValue();
+                arguments.add(((COSObject) token).getObject());
             }
+            else if (token instanceof Operator)
+            {
+                processOperator((Operator) token, arguments);
+                arguments = new ArrayList<COSBase>();
+            }
+            else
+            {
+                arguments.add((COSBase) token);
+            }
+            token = parser.parseNextToken();
         }
-        
-        return DEFAULT_FONT_SIZE;
     }
     
     /**
-     * w in an appearance stream represents the lineWidth.
-     *
-     * @return the linewidth
+     * This is used to handle an operation.
+     * 
+     * @param operator The operation to perform.
+     * @param operands The list of arguments.
+     * @throws IOException If there is an error processing the operation.
      */
-    public float getLineWidth()
+    private void processOperator(Operator operator, List<COSBase> operands) throws
IOException
     {
-        float retval = 0f;
-        if (tokens != null)
+        String name = operator.getName();
+        
+        if ("Tf".equals(name))
         {
-            int btIndex = tokens.indexOf(Operator.getOperator("BT"));
-            int wIndex = tokens.indexOf(Operator.getOperator("w"));
-            // the w should only be used if it is before the first BT.
-            if (wIndex > 0 && (wIndex < btIndex || btIndex == -1))
-            {
-                retval = ((COSNumber) tokens.get(wIndex - 1)).floatValue();
-            }
+            processSetFont(operands);
+        }
+        else if ("rg".equals(name))
+        {
+            processSetFontColor(operands);
         }
-        return retval;
     }
-
+    
     /**
-     * Returns the font.
+     * Process the set font and font size operator.
      * 
-     * @throws IOException If the font could not be found.
+     * @param operands the font name and size
+     * @throws IOException in case there are missing operators or the font is not within
the resources
      */
-    public PDFont getFont() throws IOException
+    private void processSetFont(List<COSBase> operands) throws IOException
     {
-        COSName name = getFontResourceName();
-        PDFont font = defaultResources.getFont(name);
+        if (operands.size() < 2)
+        {
+            throw new IOException("Missing operands for set font operator " + Arrays.toString(operands.toArray()));
+        }
+
+        COSBase base0 = operands.get(0);
+        COSBase base1 = operands.get(1);
+        if (!(base0 instanceof COSName))
+        {
+            return;
+        }
+        if (!(base1 instanceof COSNumber))
+        {
+            return;
+        }
+        COSName fontName = (COSName) base0;
+        
+        PDFont font = defaultResources.getFont(fontName);
+        float fontSize = ((COSNumber) base1).floatValue();
         
         // todo: handle cases where font == null with special mapping logic (see PDFBOX-2661)
         if (font == null)
         {
-            throw new IOException("Could not find font: /" + name.getName());
+            throw new IOException("Could not find font: /" + fontName.getName());
         }
-        
+        setFontName(fontName);
+        setFont(font);
+        setFontSize(fontSize);
+    }
+    
+    /**
+     * Process the font color operator.
+     * 
+     * This is assumed to be an RGB color.
+     * 
+     * @param operands the color components
+     * @throws IOException in case of the color components not matching
+     */
+    private void processSetFontColor(List<COSBase> operands) throws IOException
+    {
+        PDColorSpace colorSpace = PDDeviceRGB.INSTANCE;
+        if (colorSpace instanceof PDDeviceColorSpace &&
+            operands.size() < colorSpace.getNumberOfComponents())
+        {
+            throw new IOException("Missing operands for set non stroking color operator "
+ Arrays.toString(operands.toArray()));
+        }
+        COSArray array = new COSArray();
+        array.addAll(operands);
+        setFontColor(new PDColor(array, colorSpace));
+    }
+
+    /**
+     * Get the font name
+     * 
+     * @return the font name to use for resource lookup
+     */
+    COSName getFontName()
+    {
+        return fontName;
+    }
+
+    /**
+     * Set the font name.
+     * 
+     * @param fontName the font name to use for resource lookup
+     */
+    void setFontName(COSName fontName)
+    {
+        this.fontName = fontName;
+    }
+    
+    /**
+     * Returns the font.
+     */
+    PDFont getFont() throws IOException
+    {
         return font;
     }
+    
+    /**
+     * Set the font.
+     * 
+     * @param font the font to use.
+     */
+    void setFont(PDFont font)
+    {
+        this.font = font;
+    }
+
+    /**
+     * Returns the font size.
+     */
+    public float getFontSize()
+    {
+        return fontSize;
+    }
+    
+    /**
+     * Set the font size.
+     * 
+     * @param fontSize the font size.
+     */
+    void setFontSize(float fontSize)
+    {
+        this.fontSize = fontSize;
+    }
+    
+    /**
+     * Returns the font color
+     */
+    PDColor getFontColor()
+    {
+        return fontColor;
+    }
 
     /**
-     * Returns the name of the font in the Resources.
+     * Set the font color.
+     * 
+     * @param fontColor the fontColor to use.
      */
-    private COSName getFontResourceName()
+    void setFontColor(PDColor fontColor)
     {
-        int setFontOperatorIndex = tokens.indexOf(Operator.getOperator("Tf"));
-        return (COSName) tokens.get(setFontOperatorIndex - 2);
+        this.fontColor = fontColor;
     }
 
     /**
@@ -153,7 +280,11 @@ class PDDefaultAppearanceString
             fontSize = zeroFontSize;
         }
         contents.setFont(getFont(), fontSize);
-        // todo: set more state...
+        
+        if (getFontColor() != null)
+        {
+            contents.setNonStrokingColor(getFontColor());
+        }
     }
 
     /**
@@ -170,9 +301,7 @@ class PDDefaultAppearanceString
             appearanceStream.setResources(streamResources);
         }
         
-        // fonts
-        COSName fontName = getFontResourceName();
-        if (streamResources.getFont(fontName) == null)
+        if (streamResources.getFont(getFontName()) == null)
         {
             streamResources.put(fontName, getFont());
         }

Added: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java?rev=1708713&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
(added)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
Wed Oct 14 23:18:17 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.pdmodel.interactive.form;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB;
+import org.junit.Before;
+import org.junit.Test;
+
+public class PDDefaultAppearanceStringTest
+{
+    // Used to check resources lookup 
+    private PDResources resources;
+    private COSName fontResourceName;
+    
+    @Before
+    public void setUp()
+    {
+        resources = new PDResources();
+        // the resource name is created when the font is added so need
+        // to capture that
+        fontResourceName = resources.add(PDType1Font.HELVETICA);
+    }
+    
+    @Test
+    public void testParseDAString() throws IOException
+    {
+        COSString sampleString = new COSString("/" + fontResourceName.getName() + " 12 Tf
0.019 0.305 0.627 rg 0g");
+
+        PDDefaultAppearanceString defaultAppearanceString = new PDDefaultAppearanceString(sampleString,
resources);
+
+        assertEquals(12, defaultAppearanceString.getFontSize(), 0.001);
+        assertEquals(PDType1Font.HELVETICA, defaultAppearanceString.getFont());
+        assertEquals(PDDeviceRGB.INSTANCE, defaultAppearanceString.getFontColor().getColorSpace());
+        assertEquals(0.019, defaultAppearanceString.getFontColor().getComponents()[0], 0.0001);
+        assertEquals(0.305, defaultAppearanceString.getFontColor().getComponents()[1], 0.0001);
+        assertEquals(0.627, defaultAppearanceString.getFontColor().getComponents()[2], 0.0001);
+    }
+    
+    @Test(expected=IOException.class)
+    public void testFontResourceUnavailable() throws IOException
+    {
+        COSString sampleString = new COSString("/Helvetica 12 Tf 0.019 0.305 0.627 rg 0g");
+        new PDDefaultAppearanceString(sampleString, resources);
+    }
+    
+    @Test(expected=IOException.class)
+    public void testWrongNumberOfColorArguments() throws IOException
+    {
+        COSString sampleString = new COSString("/Helvetica 12 Tf 0.305 0.627 rg 0g");
+        new PDDefaultAppearanceString(sampleString, resources);
+    } 
+}

Propchange: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDDefaultAppearanceStringTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message