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

svn commit: r1616831 - in /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading: CoonsTriangle.java GouraudShadingContext.java Type4ShadingContext.java Type5ShadingContext.java Vertex.java

Author: tilman
Date: Fri Aug  8 17:07:17 2014
New Revision: 1616831

URL: http://svn.apache.org/r1616831
Log:
PDFBOX-1915: use the hash maps of types 6 and 7 for types 4 and 5, as done by Shaola Ren in GSoC2014

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/CoonsTriangle.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/GouraudShadingContext.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type4ShadingContext.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type5ShadingContext.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Vertex.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/CoonsTriangle.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/CoonsTriangle.java?rev=1616831&r1=1616830&r2=1616831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/CoonsTriangle.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/CoonsTriangle.java Fri Aug  8 17:07:17 2014
@@ -29,8 +29,8 @@ import java.util.HashSet;
  */
 class CoonsTriangle
 {
-    private final Point2D[] corner; // vertexes coordinates of a triangle
-    private final float[][] color;
+    protected final Point2D[] corner; // vertexes coordinates of a triangle
+    protected final float[][] color;
     private final double area; // area of the triangle
     
     /*

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/GouraudShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/GouraudShadingContext.java?rev=1616831&r1=1616830&r2=1616831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/GouraudShadingContext.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/GouraudShadingContext.java Fri Aug  8 17:07:17 2014
@@ -31,16 +31,19 @@ import java.awt.image.Raster;
 import java.awt.image.WritableRaster;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import javax.imageio.stream.ImageInputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.pdmodel.common.PDRange;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
 import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
 import org.apache.pdfbox.util.Matrix;
 
 /**
- * Shades Gouraud triangles for  Type4ShadingContext and Type5ShadingContext.
+ * Shades Gouraud triangles for Type4ShadingContext and Type5ShadingContext.
  * @author Andreas Lehmkühler
  * @author Tilman Hausherr
  * @author Shaola Ren
@@ -57,7 +60,7 @@ abstract class GouraudShadingContext imp
     protected int numberOfColorComponents;
 
     /** triangle list. */
-    protected ArrayList<GouraudTriangle> triangleList;
+    protected ArrayList<CoonsTriangle> triangleList;
 
     /** bits per coordinate. */
     protected int bitsPerCoordinate;
@@ -67,11 +70,14 @@ abstract class GouraudShadingContext imp
 
     /** background values.*/
     protected float[] background;
+    protected int rgbBackground;
 
     private final boolean hasFunction;
-    private final PDShading gouraudShadingType;
+    protected final PDShading gouraudShadingType;
     private PDRectangle bboxRect;
     private float[] bboxTab = new float[4];
+    
+    protected HashMap<Point, Integer> pixelTable;
 
     /**
      * Constructor creates an instance to be used for fill operations.
@@ -80,7 +86,6 @@ abstract class GouraudShadingContext imp
      * @param xform transformation for user to device space
      * @param ctm current transformation matrix
      * @param pageHeight height of the current page
-     * @param dBounds device bounds
      * @throws IOException if something went wrong
      */
     protected GouraudShadingContext(PDShading shading, ColorModel colorModel, AffineTransform xform,
@@ -88,15 +93,13 @@ abstract class GouraudShadingContext imp
     {
         gouraudShadingType = shading;
         deviceBounds = dBounds;
-        triangleList = new ArrayList<GouraudTriangle>();
+        triangleList = new ArrayList<CoonsTriangle>();
         hasFunction = shading.getFunction() != null;
-        LOG.debug("hasFunction: " + hasFunction);
 
         shadingColorSpace = shading.getColorSpace();
         LOG.debug("colorSpace: " + shadingColorSpace);
-
         numberOfColorComponents = hasFunction ? 1 : shadingColorSpace.getNumberOfComponents();
-        
+
         bboxRect = shading.getBBox();
         if (bboxRect != null)
         {
@@ -119,16 +122,17 @@ abstract class GouraudShadingContext imp
         {
             bboxRect = null;
         }
-        
-        LOG.debug("numberOfColorComponents: " + numberOfColorComponents);
-
-        LOG.debug("BBox: " + shading.getBBox());
-        LOG.debug("Background: " + shading.getBackground());
 
         // create the output color model using RGB+alpha as color space
         ColorSpace outputCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
         outputColorModel = new ComponentColorModel(outputCS, true, false, Transparency.TRANSLUCENT,
                 DataBuffer.TYPE_BYTE);
+        COSArray bg = shading.getBackground();
+        if (bg != null)
+        {
+            background = bg.toFloatArray();
+            rgbBackground = convertToRGB(background);
+        }
     }
 
     /**
@@ -143,8 +147,9 @@ abstract class GouraudShadingContext imp
      * @return a new vertex with the flag and the interpolated values
      * @throws IOException if something went wrong
      */
-    protected Vertex readVertex(ImageInputStream input, byte flag, long maxSrcCoord, long maxSrcColor,
-                                PDRange rangeX, PDRange rangeY, PDRange[] colRangeTab) throws IOException
+    protected Vertex readVertex(ImageInputStream input, long maxSrcCoord, long maxSrcColor,
+                                PDRange rangeX, PDRange rangeY, PDRange[] colRangeTab, Matrix ctm, 
+                                AffineTransform xform) throws IOException
     {
         float[] colorComponentTab = new float[numberOfColorComponents];
         long x = input.readBits(bitsPerCoordinate);
@@ -152,14 +157,17 @@ abstract class GouraudShadingContext imp
         double dstX = interpolate(x, maxSrcCoord, rangeX.getMin(), rangeX.getMax());
         double dstY = interpolate(y, maxSrcCoord, rangeY.getMin(), rangeY.getMax());
         LOG.debug("coord: " + String.format("[%06X,%06X] -> [%f,%f]", x, y, dstX, dstY));
+        Point2D tmp = new Point2D.Double(dstX, dstY);
+        transformPoint(tmp, ctm, xform);
+        
         for (int n = 0; n < numberOfColorComponents; ++n)
         {
             int color = (int) input.readBits(bitsPerColorComponent);
-            colorComponentTab[n] = interpolate(color, maxSrcColor, colRangeTab[n].getMin(), colRangeTab[n].getMax());
-            LOG.debug("color[" + n + "]: " + color + "/" + String.format("%02X", color)
-                    + " -> color[" + n + "]: " + colorComponentTab[n]);
+            colorComponentTab[n] = (float) interpolate(color, maxSrcColor, colRangeTab[n].getMin(), colRangeTab[n].getMax());
+            LOG.debug("color[" + n + "]: " + color + "/" + String.format("%02x", color)
+                    + "-> color[" + n + "]: " + colorComponentTab[n]);
         }
-        return new Vertex(flag, new Point2D.Double(dstX, dstY), colorComponentTab);
+        return new Vertex(tmp, colorComponentTab);
     }
     
     // this method is used to arrange the array to denote the left upper corner and right lower corner of the BBox
@@ -174,33 +182,97 @@ abstract class GouraudShadingContext imp
             array[i] = array[j];
             array[j] = tmp;
         }
-    }    
+    }
 
-    /**
-     * Transforms vertices from shading to user space (if applicable) and from user to device space.
-     * @param vertexList list of vertices
-     * @param xform transformation for user to device space
-     * @param ctm current transformation matrix
-     */
-    protected void transformVertices(ArrayList<Vertex> vertexList, Matrix ctm, AffineTransform xform)
+    // transform a point from source space to device space
+    private void transformPoint(Point2D p, Matrix ctm, AffineTransform xform)
     {
-        for (Vertex v : vertexList)
+        if (ctm != null)
         {
-            LOG.debug(v);
-
-            // this segment "inspired" by RadialShadingContext
-            if (ctm != null)
+            ctm.createAffineTransform().transform(p, p);
+        }
+        xform.transform(p, p);
+    }
+    
+    protected HashMap<Point, Integer> calcPixelTable()
+    {
+        HashMap<Point, Integer> map = new HashMap<Point, Integer>();
+        for (CoonsTriangle tri : triangleList)
+        {
+            int degree = tri.getDeg();
+            if (degree == 2)
             {
-                // transform from shading to user space
-                ctm.createAffineTransform().transform(v.point, v.point);
+                Line line = tri.getLine();
+                HashSet<Point> linePoints = line.linePoints;
+                for (Point p : linePoints)
+                {
+                    float[] values = line.getColor(p);
+                    map.put(p, convertToRGB(values));
+                }
+            }
+            else
+            {
+                int[] boundary = tri.getBoundary();
+                boundary[0] = Math.max(boundary[0], deviceBounds.x);
+                boundary[1] = Math.min(boundary[1], deviceBounds.x + deviceBounds.width);
+                boundary[2] = Math.max(boundary[2], deviceBounds.y);
+                boundary[3] = Math.min(boundary[3], deviceBounds.y + deviceBounds.height);
+                for (int x = boundary[0]; x <= boundary[1]; x++)
+                {
+                    for (int y = boundary[2]; y <= boundary[3]; y++)
+                    {
+                        Point p = new Point(x, y);
+                        if (tri.contains(p))
+                        {
+                            float[] values = tri.getColor(p);
+                            map.put(p, convertToRGB(values));
+                        }
+                    }
+                }
             }
-            // transform from user to device space
-            xform.transform(v.point, v.point);
-
-            LOG.debug(v);
         }
+        return map;
     }
+    
+    // convert color to RGB color values
+    private int convertToRGB(float[] values)
+    {
+        float[] nValues = null;
+        float[] rgbValues = null;
+        int normRGBValues = 0;
+        if (hasFunction)
+        {
+            try
+            {
+                nValues = gouraudShadingType.evalFunction(values);
+            }
+            catch (IOException exception)
+            {
+                LOG.error("error while processing a function", exception);
+            }
+        }
 
+        try
+        {
+            if (nValues == null)
+            {
+                rgbValues = shadingColorSpace.toRGB(values);
+            }
+            else
+            {
+                rgbValues = shadingColorSpace.toRGB(nValues);
+            }
+            normRGBValues = (int) (rgbValues[0] * 255);
+            normRGBValues |= (((int) (rgbValues[1] * 255)) << 8);
+            normRGBValues |= (((int) (rgbValues[2] * 255)) << 16);
+        }
+        catch (IOException exception)
+        {
+            LOG.error("error processing color space", exception);
+        }
+        return normRGBValues;
+    }
+    
     @Override
     public void dispose()
     {
@@ -255,66 +327,29 @@ abstract class GouraudShadingContext imp
                             continue;
                         }
                     }
-                    Point2D p = new Point(x + col, y + row);
-                    GouraudTriangle triangle = null;
-                    for (GouraudTriangle tryTriangle : triangleList)
+                    Point p = new Point(currentX, currentY);
+                    int value;
+                    if (pixelTable.containsKey(p))
                     {
-                        if (tryTriangle.contains(p))
-                        {
-                            triangle = tryTriangle;
-                            break;
-                        }
-                    }
-                    float[] values;
-                    if (triangle != null)
-                    {
-                        double[] weights = triangle.getWeights(p);
-                        values = new float[numberOfColorComponents];
-                        for (int i = 0; i < numberOfColorComponents; ++i)
-                        {
-                            values[i] = (float) (triangle.colorA[i] * weights[0]
-                                    + triangle.colorB[i] * weights[1]
-                                    + triangle.colorC[i] * weights[2]);
-                        }
+                        value = pixelTable.get(p);
                     }
                     else
                     {
                         if (background != null)
                         {
-                            values = background;
+                            value = rgbBackground;
                         }
                         else
                         {
                             continue;
                         }
                     }
-
-                    if (hasFunction)
-                    {
-                        try
-                        {
-                            values = gouraudShadingType.evalFunction(values);
-                        }
-                        catch (IOException exception)
-                        {
-                            LOG.error("error while processing a function", exception);
-                        }
-                    }
-
-                    // convert from shading color space to to RGB
-                    try
-                    {
-                        values = shadingColorSpace.toRGB(values);
-                    }
-                    catch (IOException exception)
-                    {
-                        LOG.error("error processing color space", exception);
-                    }
-
                     int index = (row * w + col) * 4;
-                    data[index] = (int) (values[0] * 255);
-                    data[index + 1] = (int) (values[1] * 255);
-                    data[index + 2] = (int) (values[2] * 255);
+                    data[index] = value & 255;
+                    value >>= 8;
+                    data[index + 1] = value & 255;
+                    value >>= 8;
+                    data[index + 2] = value & 255;
                     data[index + 3] = 255;
                 }
             }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type4ShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type4ShadingContext.java?rev=1616831&r1=1616830&r2=1616831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type4ShadingContext.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type4ShadingContext.java Fri Aug  8 17:07:17 2014
@@ -27,9 +27,7 @@ import javax.imageio.stream.ImageInputSt
 import javax.imageio.stream.MemoryCacheImageInputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
-import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.pdmodel.common.PDRange;
 import org.apache.pdfbox.util.Matrix;
@@ -37,213 +35,156 @@ import org.apache.pdfbox.util.Matrix;
 /**
  * AWT PaintContext for Gouraud Triangle Mesh (Type 4) shading.
  * @author Tilman Hausherr
+ * @author Shaola Ren
  */
 class Type4ShadingContext extends GouraudShadingContext
 {
     private static final Log LOG = LogFactory.getLog(Type4ShadingContext.class);
-
-    private int bitsPerFlag;
+    private final int bitsPerFlag;
 
     /**
      * Constructor creates an instance to be used for fill operations.
-     *
      * @param shading the shading type to be used
      * @param cm the color model to be used
      * @param xform transformation for user to device space
      * @param ctm current transformation matrix
      * @param pageHeight height of the current page
-     * @param dBounds device bounds
-     * @throws IOException if something went wrong
      */
-    Type4ShadingContext(PDShadingType4 shading, ColorModel cm, AffineTransform xform,
-            Matrix ctm, int pageHeight, Rectangle dBounds) throws IOException
+    public Type4ShadingContext(PDShadingType4 shading, ColorModel cm, AffineTransform xform,
+                               Matrix ctm, int pageHeight, Rectangle dBounds) throws IOException
     {
         super(shading, cm, xform, ctm, pageHeight, dBounds);
-
-        ArrayList<Vertex> vertexList = new ArrayList<Vertex>();
-
         LOG.debug("Type4ShadingContext");
 
         bitsPerColorComponent = shading.getBitsPerComponent();
         LOG.debug("bitsPerColorComponent: " + bitsPerColorComponent);
         bitsPerCoordinate = shading.getBitsPerCoordinate();
-        long maxSrcCoord = (long) (Math.pow(2, bitsPerCoordinate) - 1);
-        long maxSrcColor = (long) (Math.pow(2, bitsPerColorComponent) - 1);
-        LOG.debug("maxSrcCoord: " + maxSrcCoord);
-        LOG.debug("maxSrcColor: " + maxSrcColor);
-
-        COSDictionary cosDictionary = shading.getCOSDictionary();
-        COSStream cosStream = (COSStream) cosDictionary;
-
-        //The Decode key specifies how
-        //to decode coordinate and color component data into the ranges of values
-        //appropriate for each. The ranges are specified as [xmin xmax ymin ymax c1,min,
-        //c1,max,..., cn, min, cn,max].
-        //
-        // see p344
-        COSArray decode = (COSArray) cosDictionary.getDictionaryObject(COSName.DECODE);
-        LOG.debug("decode: " + decode);
-        PDRange rangeX = shading.getDecodeForParameter(0);
-        PDRange rangeY = shading.getDecodeForParameter(1);
-        LOG.debug("rangeX: " + rangeX.getMin() + ", " + rangeX.getMax());
-        LOG.debug("rangeY: " + rangeY.getMin() + ", " + rangeY.getMax());
-
-        PDRange[] colRangeTab = new PDRange[numberOfColorComponents];
-        for (int i = 0; i < numberOfColorComponents; ++i)
-        {
-            colRangeTab[i] = shading.getDecodeForParameter(2 + i);
-        }
-
-        LOG.debug("bitsPerCoordinate: " + bitsPerCoordinate);
+        LOG.debug(Math.pow(2, bitsPerCoordinate) - 1);
         bitsPerFlag = shading.getBitsPerFlag();
         LOG.debug("bitsPerFlag: " + bitsPerFlag); //TODO handle cases where bitperflag isn't 8
-        LOG.debug("Stream size: " + cosStream.getInt(COSName.LENGTH));
-
-        // get background values if available
-        COSArray bg = shading.getBackground();
-        if (bg != null)
+        triangleList = getTriangleList(xform,ctm);
+        pixelTable = calcPixelTable();
+    }
+    
+    private ArrayList<CoonsTriangle> getTriangleList(AffineTransform xform,Matrix ctm) throws IOException
+    {
+        PDShadingType4 FreeTriangleShadingType = (PDShadingType4) gouraudShadingType;
+        COSDictionary cosDictionary = FreeTriangleShadingType.getCOSDictionary();
+        PDRange rangeX = FreeTriangleShadingType.getDecodeForParameter(0);
+        PDRange rangeY = FreeTriangleShadingType.getDecodeForParameter(1);
+        PDRange[] colRange = new PDRange[numberOfColorComponents];
+        for (int i = 0; i < numberOfColorComponents; ++i)
         {
-            background = bg.toFloatArray();
+            colRange[i] = FreeTriangleShadingType.getDecodeForParameter(2 + i);
         }
-
-        //TODO missing: BBox, AntiAlias (p. 305 in 1.7 spec)
-        // p318:
-        //  reading in sequence from higher-order to lower-order bit positions
+        ArrayList<CoonsTriangle> list = new ArrayList<CoonsTriangle>();
+        long maxSrcCoord = (long) Math.pow(2, bitsPerCoordinate) - 1;
+        long maxSrcColor = (long) Math.pow(2, bitsPerColorComponent) - 1;
+        COSStream cosStream = (COSStream) cosDictionary;
+        
         ImageInputStream mciis = new MemoryCacheImageInputStream(cosStream.getUnfilteredStream());
-        while (true)
+        byte flag = (byte) 0;
+        
+        try
+        {
+            flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
+        }
+        catch (EOFException ex)
+        {
+            LOG.error(ex);
+        }
+        
+        while(true)
         {
+            Vertex p0, p1, p2;
+            Point2D[] ps;
+            float[][] cs;
+            int lastIndex;
             try
             {
-                byte flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
-                LOG.debug("flag: " + flag);
-                switch (flag)
+                switch(flag)
                 {
                     case 0:
-                        Vertex v1 = readVertex(mciis, flag, maxSrcCoord, maxSrcColor, rangeX, rangeY, colRangeTab);
-                        Vertex v2 = readVertex(mciis, (byte) mciis.readBits(bitsPerFlag), maxSrcCoord, maxSrcColor,
-                                rangeX, rangeY, colRangeTab);
-                        Vertex v3 = readVertex(mciis, (byte) mciis.readBits(bitsPerFlag), maxSrcCoord, maxSrcColor,
-                                rangeX, rangeY, colRangeTab);
-
-                        // add them after they're read, so that they are never added if there is a premature EOF
-                        vertexList.add(v1);
-                        vertexList.add(v2);
-                        vertexList.add(v3);
+                        p0 = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                        flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
+                        if (flag != 0)
+                        {
+                            LOG.error("bad triangle: " + flag);
+                        }
+                        p1 = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                        mciis.readBits(bitsPerFlag);
+                        if (flag != 0)
+                        {
+                            LOG.error("bad triangle: " + flag);
+                        }
+                        p2 = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                        ps = new Point2D[]
+                                {
+                                    p0.point, p1.point, p2.point
+                                };
+                        cs = new float[][]
+                                {
+                                    p0.color, p1.color, p2.color
+                                };
+                        list.add(new CoonsTriangle(ps, cs));
+                        flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
                         break;
                     case 1:
+                        lastIndex = list.size() - 1;
+                        if (lastIndex < 0)
+                        {
+                            LOG.error("broken data stream: " + list.size());
+                        }
+                        else
+                        {
+                            CoonsTriangle preTri = list.get(lastIndex);
+                            p2 = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                            ps = new Point2D[]
+                                {
+                                    preTri.corner[1], preTri.corner[2], p2.point
+                                };
+                            cs = new float[][]
+                                {
+                                    preTri.color[1], preTri.color[2], p2.color
+                                };
+                            list.add(new CoonsTriangle(ps, cs));
+                            flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
+                        }
+                        break;
                     case 2:
-                        vertexList.add(readVertex(mciis, flag, maxSrcCoord, maxSrcColor, rangeX, rangeY, colRangeTab));
+                        lastIndex = list.size() - 1;
+                        if (lastIndex < 0)
+                        {
+                            LOG.error("broken data stream: " + list.size());
+                        }
+                        else
+                        {
+                            CoonsTriangle preTri = list.get(lastIndex);
+                            p2 = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                            ps = new Point2D[]
+                                {
+                                    preTri.corner[0], preTri.corner[2], p2.point
+                                };
+                            cs = new float[][]
+                                {
+                                    preTri.color[0], preTri.color[2], p2.color
+                                };
+                            list.add(new CoonsTriangle(ps, cs));
+                            flag = (byte) (mciis.readBits(bitsPerFlag) & 3);
+                        }
                         break;
                     default:
                         LOG.warn("bad flag: " + flag);
-                        break;
+                        break; 
                 }
             }
             catch (EOFException ex)
             {
-                LOG.debug("EOF");
-                if (vertexList.size() < 3)
-                {
-                    LOG.warn("Incomplete mesh is ignored");
-                    vertexList.clear();
-                }
-                else if (vertexList.size() > 1 && vertexList.get(0).flag != 0)
-                {
-                    LOG.warn("Mesh with incorrect start flag " + vertexList.get(0).flag + " is ignored");
-                    vertexList.clear();
-                }
-                // check that there are 3 entries if there is a 0 flag
-                int vi = 0;
-                while (vi < vertexList.size())
-                {
-                    if (vertexList.get(vi).flag == 0)
-                    {
-                        if (vi + 2 >= vertexList.size())
-                        {
-                            LOG.warn("Mesh with incomplete triangle");
-                            // remove rest
-                            while (vertexList.size() >= vi + 1)
-                            {
-                                vertexList.remove(vi);
-                            }
-                            break;
-                        }
-                        vi += 3;
-                    }
-                    else
-                    {
-                        ++vi;
-                    }
-                }
                 break;
             }
         }
         mciis.close();
-        transformVertices(vertexList, ctm, xform);
-        createTriangleList(vertexList);
-    }
-
-    // create GouraudTriangle list from vertices, see p.316 of pdf spec 1.7.
-    private void createTriangleList(ArrayList<Vertex> vertexList)
-    {
-        Point2D a = null, b = null, c = null;
-        float[] aColor = null, bColor = null, cColor = null;
-        int vi = 0;
-        while (vi < vertexList.size())
-        {
-            Vertex v = vertexList.get(vi);
-            switch (v.flag)
-            {
-                case 0:
-                    a = v.point;
-                    aColor = v.color;
-                    ++vi;
-
-                    v = vertexList.get(vi);
-                    b = v.point;
-                    bColor = v.color;
-                    ++vi;
-
-                    v = vertexList.get(vi);
-                    c = v.point;
-                    cColor = v.color;
-                    break;
-
-                case 1:
-                    a = b;
-                    aColor = bColor;
-
-                    b = c;
-                    bColor = cColor;
-
-                    v = vertexList.get(vi);
-                    c = v.point;
-                    cColor = v.color;
-                    break;
-
-                case 2:
-                    b = c;
-                    bColor = cColor;
-
-                    v = vertexList.get(vi);
-                    c = v.point;
-                    cColor = v.color;
-                    break;
-
-                default:
-                    break;
-            }
-            ++vi;
-            GouraudTriangle g = new GouraudTriangle(a, aColor, b, bColor, c, cColor);
-            if (!g.isEmpty())
-            {
-                triangleList.add(g);
-            }
-            else
-            {
-                LOG.debug("triangle is empty!");
-            }
-        }
+        return list;
     }
 
     @Override

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type5ShadingContext.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type5ShadingContext.java?rev=1616831&r1=1616830&r2=1616831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type5ShadingContext.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Type5ShadingContext.java Fri Aug  8 17:07:17 2014
@@ -18,6 +18,7 @@ package org.apache.pdfbox.pdmodel.graphi
 
 import java.awt.Rectangle;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
 import java.awt.image.ColorModel;
 import java.io.EOFException;
 import java.io.IOException;
@@ -26,9 +27,7 @@ import javax.imageio.stream.ImageInputSt
 import javax.imageio.stream.MemoryCacheImageInputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSDictionary;
-import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.pdmodel.common.PDRange;
 import org.apache.pdfbox.util.Matrix;
@@ -36,6 +35,7 @@ import org.apache.pdfbox.util.Matrix;
 /**
  * AWT PaintContext for Gouraud Triangle Lattice (Type 5) shading.
  * @author Tilman Hausherr
+ * @author Shaola Ren
  */
 class Type5ShadingContext extends GouraudShadingContext
 {
@@ -48,10 +48,9 @@ class Type5ShadingContext extends Gourau
      * @param xform transformation for user to device space
      * @param ctm current transformation matrix
      * @param pageHeight height of the current page
-     * @param dBounds device bounds
      * @throws IOException if something went wrong
      */
-    Type5ShadingContext(PDShadingType5 shading, ColorModel cm, AffineTransform xform,
+    public Type5ShadingContext(PDShadingType5 shading, ColorModel cm, AffineTransform xform,
                                Matrix ctm, int pageHeight, Rectangle dBounds) throws IOException
     {
         super(shading, cm, xform, ctm, pageHeight, dBounds);
@@ -62,109 +61,83 @@ class Type5ShadingContext extends Gourau
         LOG.debug("bitsPerColorComponent: " + bitsPerColorComponent);
         bitsPerCoordinate = shading.getBitsPerCoordinate();
         LOG.debug(Math.pow(2, bitsPerCoordinate) - 1);
+        triangleList = getTriangleList(xform,ctm);
+        pixelTable = calcPixelTable();
+    }
+    
+    private ArrayList<CoonsTriangle> getTriangleList(AffineTransform xform, Matrix ctm) throws IOException
+    {
+        ArrayList<CoonsTriangle> list = new ArrayList<CoonsTriangle>();
+        PDShadingType5 LatticeTriangleShadingType = (PDShadingType5) gouraudShadingType;
+        COSDictionary cosDictionary = LatticeTriangleShadingType.getCOSDictionary();
+        PDRange rangeX = LatticeTriangleShadingType.getDecodeForParameter(0);
+        PDRange rangeY = LatticeTriangleShadingType.getDecodeForParameter(1);
+        int numPerRow = LatticeTriangleShadingType.getVerticesPerRow();
+        PDRange[] colRange = new PDRange[numberOfColorComponents];
+        for (int i = 0; i < numberOfColorComponents; ++i)
+        {
+            colRange[i] = LatticeTriangleShadingType.getDecodeForParameter(2 + i);
+        }
+        ArrayList<Vertex> vlist = new ArrayList<Vertex>(); 
         long maxSrcCoord = (long) Math.pow(2, bitsPerCoordinate) - 1;
         long maxSrcColor = (long) Math.pow(2, bitsPerColorComponent) - 1;
-        LOG.debug("maxSrcCoord: " + maxSrcCoord);
-        LOG.debug("maxSrcColor: " + maxSrcColor);
-
-        COSDictionary cosDictionary = shading.getCOSDictionary();
         COSStream cosStream = (COSStream) cosDictionary;
-
-        //The Decode key specifies how
-        //to decode coordinate and color component data into the ranges of values
-        //appropriate for each. The ranges are specified as [xmin xmax ymin ymax c1,min,
-        //c1,max,..., cn, min, cn,max].
-        //
-        // see p344
-        COSArray decode = (COSArray) cosDictionary.getDictionaryObject(COSName.DECODE);
-        LOG.debug("decode: " + decode);
-        PDRange rangeX = shading.getDecodeForParameter(0);
-        PDRange rangeY = shading.getDecodeForParameter(1);
-        LOG.debug("rangeX: " + rangeX.getMin() + ", " + rangeX.getMax());
-        LOG.debug("rangeY: " + rangeY.getMin() + ", " + rangeY.getMax());
-
-        PDRange[] colRangeTab = new PDRange[numberOfColorComponents];
-        for (int i = 0; i < numberOfColorComponents; ++i)
+        
+        ImageInputStream mciis = new MemoryCacheImageInputStream(cosStream.getUnfilteredStream());
+        while(true)
         {
-            colRangeTab[i] = shading.getDecodeForParameter(2 + i);
+            Vertex p;
+            try
+            {
+                p = readVertex(mciis, maxSrcCoord, maxSrcColor,rangeX, rangeY, colRange, ctm, xform);
+                vlist.add(p);
+            }
+            catch(EOFException ex)
+            {
+                break;
+            }
         }
-
-        LOG.debug("bitsPerCoordinate: " + bitsPerCoordinate);
-
-        // get background values if available
-        COSArray bg = shading.getBackground();
-        if (bg != null)
+        int sz = vlist.size(), rowNum = sz / numPerRow;
+        Vertex[][] latticeArray = new Vertex[rowNum][numPerRow];
+        if (rowNum < 2)
         {
-            background = bg.toFloatArray();
+            return triangleList;
         }
-
-        //TODO missing: BBox, AntiAlias (p. 305 in 1.7 spec)
-        
-        // p318:
-        //  reading in sequence from higher-order to lower-order bit positions
-        ImageInputStream mciis = new MemoryCacheImageInputStream(cosStream.getUnfilteredStream());
-
-        int verticesPerRow = shading.getVerticesPerRow(); //TODO check >=2
-        LOG.debug("verticesPerRow" + verticesPerRow);
-
-        try
+        for (int i = 0; i < rowNum; i++)
         {
-            ArrayList<Vertex> prevVertexRow = new ArrayList<Vertex>();
-            while (true)
+            for (int j = 0; j < numPerRow; j++)
             {
-                // read a vertex row
-                ArrayList<Vertex> vertexList = new ArrayList<Vertex>();
-                for (int row = 0; row < verticesPerRow; ++row)
-                {
-                    vertexList.add(readVertex(mciis, (byte) 0, maxSrcCoord, maxSrcColor, rangeX, rangeY, colRangeTab));
-                }
-                transformVertices(vertexList, ctm, xform);
-
-                // create the triangles from two rows
-                if (!prevVertexRow.isEmpty())
-                {
-                    for (int vj = 0; vj < vertexList.size() - 1; ++vj)
-                    {
-                        // p.192,194 pdf spec 1.7
-                        Vertex vij = prevVertexRow.get(vj); // v i,j
-                        Vertex vijplus1 = prevVertexRow.get(vj + 1); // v i,j+1
-                        Vertex viplus1j = vertexList.get(vj); // v i+1,j
-                        Vertex viplus1jplus1 = vertexList.get(vj + 1); // v i+1,j+1
-                        GouraudTriangle g = new GouraudTriangle(vij.point, vij.color,
-                                vijplus1.point, vijplus1.color,
-                                viplus1j.point, viplus1j.color);
-                        if (!g.isEmpty())
-                        {
-                            triangleList.add(g);
-                        }
-                        else
-                        {
-                            LOG.debug("triangle is empty!");
-                        }
-                        g = new GouraudTriangle(vijplus1.point, vijplus1.color,
-                                viplus1j.point, viplus1j.color,
-                                viplus1jplus1.point, viplus1jplus1.color);
-                        if (!g.isEmpty())
-                        {
-                            triangleList.add(g);
-                        }
-                        else
-                        {
-                            LOG.debug("triangle is empty!");
-                        }
-                    }
-                }
-                prevVertexRow = vertexList;
+                latticeArray[i][j] = vlist.get(i * numPerRow + j);
             }
         }
-        catch (EOFException ex)
+        
+        for (int i = 0; i < rowNum - 1; i++)
         {
-            LOG.debug("EOF");
+            for (int j = 0; j < numPerRow - 1; j++)
+            {
+                Point2D[] ps = new Point2D[]
+                                {
+                                    latticeArray[i][j].point, latticeArray[i][j + 1].point, latticeArray[i + 1][j].point
+                                };
+                float[][] cs = new float[][]
+                                {
+                                    latticeArray[i][j].color, latticeArray[i][j + 1].color, latticeArray[i + 1][j].color
+                                };
+                list.add(new CoonsTriangle(ps, cs));
+                ps = new Point2D[]
+                                {
+                                    latticeArray[i][j + 1].point, latticeArray[i + 1][j].point, latticeArray[i + 1][j + 1].point
+                                };
+                cs = new float[][]
+                                {
+                                    latticeArray[i][j + 1].color, latticeArray[i + 1][j].color, latticeArray[i + 1][j + 1].color
+                                };
+                list.add(new CoonsTriangle(ps, cs));
+            }
         }
-
-        mciis.close();
+        return list;
     }
-
+    
     @Override
     public void dispose()
     {

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Vertex.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Vertex.java?rev=1616831&r1=1616830&r2=1616831&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Vertex.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/shading/Vertex.java Fri Aug  8 17:07:17 2014
@@ -25,15 +25,13 @@ import java.awt.geom.Point2D;
  */
 class Vertex
 {
-    public byte flag; // used only with type 4 shading
     public Point2D point;
     public float[] color;
-
-    Vertex(byte flag, Point2D point, float[] color)
+    
+    public Vertex(Point2D p, float[] c)
     {
-        this.flag = flag;
-        this.point = point;
-        this.color = color.clone();
+        point = p;
+        color = c.clone();
     }
 
     @Override
@@ -48,6 +46,6 @@ class Vertex
             }
             colorStr += String.format("%3.2f", f);
         }
-        return "Vertex{" + flag + ": " + point + ", colors=[" + colorStr + "] }";
+        return "Vertex{" + " " + point + ", colors=[" + colorStr + "] }";
     }
 }