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/30 20:38:08 UTC
svn commit: r1621508 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics:
color/PDPattern.java pattern/TilingPaint.java
Author: tilman
Date: Sat Aug 30 18:38:08 2014
New Revision: 1621508
URL: http://svn.apache.org/r1621508
Log:
PDFBOX-1094, PDFBOX-1422: fix tiling and shading patterns
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/TilingPaint.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java?rev=1621508&r1=1621507&r2=1621508&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/color/PDPattern.java Sat Aug 30 18:38:08 2014
@@ -24,6 +24,7 @@ import org.apache.pdfbox.pdmodel.graphic
import org.apache.pdfbox.pdmodel.graphics.pattern.TilingPaint;
import org.apache.pdfbox.pdmodel.graphics.shading.PDShading;
import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.pdfbox.util.Matrix;
import java.awt.Paint;
import java.awt.geom.AffineTransform;
@@ -34,7 +35,6 @@ import java.io.IOException;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.pdfbox.util.Matrix;
/**
* A Pattern color space is either a Tiling pattern or a Shading pattern.
@@ -106,22 +106,39 @@ public final class PDPattern extends PDS
@Override
public Paint toPaint(PDFRenderer renderer, PDColor color,
- Matrix subStreamMatrix, AffineTransform xform,
+ Matrix substreamMatrix, AffineTransform xform,
int pageHeight) throws IOException
{
PDAbstractPattern pattern = getPattern(color);
if (pattern instanceof PDTilingPattern)
{
- PDTilingPattern tilingPattern = (PDTilingPattern)pattern;
+ PDTilingPattern tilingPattern = (PDTilingPattern) pattern;
+
+ Matrix patternMatrix = tilingPattern.getMatrix();
+ Matrix substreamMatrixClone = substreamMatrix.clone();
+ substreamMatrixClone.setValue(2, 0, 0);
+ substreamMatrixClone.setValue(2, 1, 0);
+ Matrix matrix;
+ if (patternMatrix == null)
+ {
+ matrix = substreamMatrixClone;
+ }
+ else
+ {
+ matrix = patternMatrix.multiply(substreamMatrixClone);
+ }
+
if (tilingPattern.getPaintType() == PDTilingPattern.PAINT_COLORED)
{
// colored tiling pattern
- return new TilingPaint(renderer, tilingPattern, subStreamMatrix, xform);
+ return new TilingPaint(renderer, tilingPattern,
+ matrix, xform);
}
else
{
// uncolored tiling pattern
- return new TilingPaint(renderer, tilingPattern, underlyingColorSpace, color, subStreamMatrix, xform);
+ return new TilingPaint(renderer, tilingPattern, underlyingColorSpace, color,
+ matrix, xform);
}
}
else
@@ -133,7 +150,12 @@ public final class PDPattern extends PDS
LOG.error("shadingPattern ist null, will be filled with transparency");
return new Color(0,0,0,0);
}
- return shading.toPaint(shadingPattern.getMatrix());
+ Matrix patternMatrix = shadingPattern.getMatrix();
+ if (patternMatrix == null)
+ {
+ return shading.toPaint(substreamMatrix);
+ }
+ return shading.toPaint(patternMatrix.multiply(substreamMatrix));
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/TilingPaint.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/TilingPaint.java?rev=1621508&r1=1621507&r2=1621508&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/TilingPaint.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/graphics/pattern/TilingPaint.java Sat Aug 30 18:38:08 2014
@@ -29,17 +29,19 @@ import java.awt.image.ComponentColorMode
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import java.io.IOException;
-
-import org.apache.pdfbox.rendering.PDFRenderer;
-import org.apache.pdfbox.rendering.PageDrawer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.pdfbox.rendering.PageDrawer;
import org.apache.pdfbox.rendering.TilingPatternDrawer;
import org.apache.pdfbox.util.Matrix;
/**
- * AWT Paint for a tiling pattern, which consists of a small repeating graphical figure.
+ * AWT Paint for a tiling pattern, which consists of a small repeating graphical
+ * figure.
*
* @author Andreas Lehmkühler
* @author John Hewson
@@ -47,116 +49,128 @@ import org.apache.pdfbox.util.Matrix;
public class TilingPaint extends TexturePaint
{
/**
+ * Logger instance.
+ */
+ private static final Log LOG = LogFactory.getLog(TilingPaint.class);
+
+ /**
* Creates a new colored tiling Paint.
+ *
* @param pattern tiling pattern dictionary
*/
- public TilingPaint(PDFRenderer renderer, PDTilingPattern pattern,
- Matrix matrix, AffineTransform xform) throws IOException
+ public TilingPaint(PDFRenderer renderer, PDTilingPattern pattern, Matrix matrix, AffineTransform xform) throws IOException
{
- super(getImage(renderer, pattern, null ,null), getTransformedRect(pattern));
+ super(getImage(renderer, pattern, null, null, matrix, xform), getTransformedRect(pattern, matrix));
}
/**
* Creates a new uncolored tiling Paint.
+ *
* @param pattern tiling pattern dictionary
* @param colorSpace color space for this tiling
* @param color color for this tiling
*/
public TilingPaint(PDFRenderer renderer, PDTilingPattern pattern, PDColorSpace colorSpace,
- PDColor color, Matrix matrix, AffineTransform xform) throws IOException
+ PDColor color, Matrix matrix, AffineTransform xform) throws IOException
{
- super(getImage(renderer, pattern, colorSpace, color), getTransformedRect(pattern));
+ super(getImage(renderer, pattern, colorSpace, color, matrix, xform), getTransformedRect(pattern, matrix));
}
// gets rect in parent content stream coordinates
- private static Rectangle2D getTransformedRect(PDTilingPattern pattern)
+ private static Rectangle2D getTransformedRect(PDTilingPattern pattern, Matrix matrix)
{
float x = pattern.getBBox().getLowerLeftX();
float y = pattern.getBBox().getLowerLeftY();
float width = pattern.getBBox().getWidth();
float height = pattern.getBBox().getHeight();
- // xStep and yStep
- if (pattern.getXStep() != 0)
+ // xStep and yStep, but ignore 32767 steps
+ if (pattern.getXStep() != 0 && pattern.getXStep() != Short.MAX_VALUE)
{
width = pattern.getXStep();
}
- if (pattern.getYStep() != 0)
+ if (pattern.getYStep() != 0 && pattern.getYStep() != Short.MAX_VALUE)
{
height = pattern.getYStep();
}
Rectangle2D rectangle;
- if (pattern.getMatrix() == null)
- {
- rectangle = new Rectangle2D.Float(x, y, width, height);
- }
- else
- {
- AffineTransform at = pattern.getMatrix().createAffineTransform();
- Point2D p1 = new Point2D.Float(x,y);
- Point2D p2 = new Point2D.Float(x+width,y+height);
- at.transform(p1, p1);
- at.transform(p2, p2);
- // at.createTransformedShape(rect).getBounds2D() gets empty rectangle
- // when negative numbers, so we do it the hard way
- rectangle = new Rectangle2D.Float(
- (float) Math.min(p1.getX(), p2.getX()),
- (float) Math.min(p1.getY(), p2.getY()),
- (float) Math.abs(p2.getX() - p1.getX()),
- (float) Math.abs(p2.getY() - p1.getY()));
- }
+ AffineTransform at = matrix.createAffineTransform();
+ Point2D p1 = new Point2D.Float(x, y);
+ Point2D p2 = new Point2D.Float(x + width, y + height);
+ at.transform(p1, p1);
+ at.transform(p2, p2);
+ // at.createTransformedShape(rect).getBounds2D() gets empty rectangle
+ // when negative numbers, so we do it the hard way
+ rectangle = new Rectangle2D.Float(
+ (float) Math.min(p1.getX(), p2.getX()),
+ (float) Math.min(p1.getY(), p2.getY()),
+ (float) Math.abs(p2.getX() - p1.getX()),
+ (float) Math.abs(p2.getY() - p1.getY()));
return rectangle;
}
+ // get lower left coord of bbox
+ private static Point2D getTransformedPoint(PDTilingPattern pattern, Matrix matrix)
+ {
+ float x = pattern.getBBox().getLowerLeftX();
+ float y = pattern.getBBox().getLowerLeftY();
+ float width = pattern.getBBox().getWidth();
+ float height = pattern.getBBox().getHeight();
+
+ AffineTransform at = matrix.createAffineTransform();
+ Point2D p1 = new Point2D.Float(x, y);
+ Point2D p2 = new Point2D.Float(x + width, y + height);
+ at.transform(p1, p1);
+ at.transform(p2, p2);
+ return new Point2D.Float(
+ (float) Math.min(p1.getX(), p2.getX()),
+ (float) Math.min(p1.getY(), p2.getY()));
+ }
+
// gets image in parent stream coordinates
private static BufferedImage getImage(PDFRenderer renderer, PDTilingPattern pattern,
- PDColorSpace colorSpace, PDColor color) throws IOException
+ PDColorSpace colorSpace, PDColor color, Matrix matrix, AffineTransform xform) throws IOException
{
ColorSpace outputCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorModel cm = new ComponentColorModel(outputCS, true, false,
Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
- Rectangle2D rect = getTransformedRect(pattern);
+ Rectangle2D rect = getTransformedRect(pattern, matrix);
int width = Math.round((float) rect.getWidth());
int height = Math.round((float) rect.getHeight());
- if (width < 1)
+
+ int rasterWidth = (int) (width * Math.abs(xform.getScaleX()));
+ int rasterHeight = (int) (height * Math.abs(xform.getScaleY()));
+ if (rasterWidth < 1)
{
- width = 1;
+ rasterWidth = 1;
}
- if (height < 1)
+ if (rasterHeight < 1)
{
- height = 1;
- }
+ rasterHeight = 1;
+ }
// create raster
- WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
+ WritableRaster raster = cm.createCompatibleWritableRaster(rasterWidth, rasterHeight);
BufferedImage image = new BufferedImage(cm, raster, false, null);
- // TODO the pattern matrix needs to map onto the parent stream's initial space, not the CTM
- // so the transformation below is not correct, because TilingPaint needs more
- // information to perform the transformation correctly, see PDF 32000, p174.
-
- // matrix
- Matrix matrix;
- if (pattern.getMatrix() == null)
- {
- // identity
- matrix = new Matrix();
- }
- else
- {
- // undo translation
- matrix = pattern.getMatrix().clone();
- matrix.setValue(2, 0, matrix.getValue(2, 0) - (float)rect.getX()); // tx
- matrix.setValue(2, 1, matrix.getValue(2, 1) - (float)rect.getY()); // ty
- }
+ matrix = matrix.clone();
+ Point2D p = getTransformedPoint(pattern, matrix);
+ matrix.setValue(2, 0, matrix.getValue(2, 0) - (float) p.getX()); // tx
+ matrix.setValue(2, 1, matrix.getValue(2, 1) - (float) p.getY()); // ty
// TODO: need to make it easy to use a custom TilingPatternDrawer
PageDrawer drawer = new TilingPatternDrawer(renderer);
PDRectangle pdRect = new PDRectangle(0, 0, width, height);
Graphics2D graphics = image.createGraphics();
+ // transform without the translation
+ AffineTransform at = new AffineTransform(
+ xform.getScaleX(), xform.getShearY(),
+ xform.getShearX(), -xform.getScaleY(),
+ 0, 0);
+ graphics.transform(at);
drawer.drawTilingPattern(graphics, pattern, pdRect, matrix, colorSpace, color);
graphics.dispose();