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 + "] }";
}
}