aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/render')
-rw-r--r--src/java/org/apache/fop/render/AbstractRenderingContext.java32
-rw-r--r--src/java/org/apache/fop/render/RendererContext.java2
-rw-r--r--src/java/org/apache/fop/render/RenderingContext.java8
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java2
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLGenerator.java19
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java157
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLPainter.java24
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLRenderingContext.java7
8 files changed, 241 insertions, 10 deletions
diff --git a/src/java/org/apache/fop/render/AbstractRenderingContext.java b/src/java/org/apache/fop/render/AbstractRenderingContext.java
index 7bacac58d..365fec871 100644
--- a/src/java/org/apache/fop/render/AbstractRenderingContext.java
+++ b/src/java/org/apache/fop/render/AbstractRenderingContext.java
@@ -19,6 +19,9 @@
package org.apache.fop.render;
+import java.util.Collections;
+import java.util.Map;
+
import org.apache.fop.apps.FOUserAgent;
/**
@@ -27,6 +30,7 @@ import org.apache.fop.apps.FOUserAgent;
public abstract class AbstractRenderingContext implements RenderingContext {
private FOUserAgent userAgent;
+ private Map hints;
/**
* Main constructor.
@@ -45,5 +49,33 @@ public abstract class AbstractRenderingContext implements RenderingContext {
return userAgent;
}
+ /** {@inheritDoc} */
+ public void putHints(Map hints) {
+ if (hints == null) {
+ return;
+ }
+ if (this.hints == null) {
+ this.hints = new java.util.HashMap();
+ }
+ this.hints.putAll(hints);
+ }
+
+ /** {@inheritDoc} */
+ public Map getHints() {
+ if (this.hints == null) {
+ return Collections.EMPTY_MAP;
+ } else {
+ return Collections.unmodifiableMap(this.hints);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Object getHint(Object key) {
+ if (this.hints == null) {
+ return null;
+ } else {
+ return this.hints.get(key);
+ }
+ }
}
diff --git a/src/java/org/apache/fop/render/RendererContext.java b/src/java/org/apache/fop/render/RendererContext.java
index e52588176..595bdd7c2 100644
--- a/src/java/org/apache/fop/render/RendererContext.java
+++ b/src/java/org/apache/fop/render/RendererContext.java
@@ -29,7 +29,7 @@ import org.apache.fop.apps.FOUserAgent;
* so that external handlers can get information to be able to render to the
* render target.
*/
-public class RendererContext implements RenderingContext {
+public class RendererContext {
private String mime;
private AbstractRenderer renderer;
diff --git a/src/java/org/apache/fop/render/RenderingContext.java b/src/java/org/apache/fop/render/RenderingContext.java
index a6f958328..5122841b7 100644
--- a/src/java/org/apache/fop/render/RenderingContext.java
+++ b/src/java/org/apache/fop/render/RenderingContext.java
@@ -19,6 +19,8 @@
package org.apache.fop.render;
+import java.util.Map;
+
import org.apache.fop.apps.FOUserAgent;
/**
@@ -40,4 +42,10 @@ public interface RenderingContext {
*/
FOUserAgent getUserAgent();
+ void putHints(Map hints);
+
+ Map getHints();
+
+ Object getHint(Object key);
+
}
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
index 8380e69cc..105a2a426 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
@@ -127,6 +127,7 @@ public abstract class AbstractIFPainter implements IFPainter {
//Load and convert the image to a supported format
RenderingContext context = createRenderingContext();
Map hints = createDefaultImageProcessingHints(sessionContext);
+ context.putHints(hints);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, imageHandlerRegistry.getSupportedFlavors(context),
hints, sessionContext);
@@ -179,6 +180,7 @@ public abstract class AbstractIFPainter implements IFPainter {
ImageHandlerRegistry imageHandlerRegistry = getFopFactory().getImageHandlerRegistry();
Image effImage;
+ context.putHints(additionalHints);
if (convert) {
Map hints = createDefaultImageProcessingHints(getUserAgent().getImageSessionContext());
if (additionalHints != null) {
diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
index 36d1fe079..67dcce1fb 100644
--- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java
+++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
@@ -22,12 +22,10 @@ package org.apache.fop.render.pcl;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
-import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ByteLookupTable;
-import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
@@ -767,11 +765,20 @@ public class PCLGenerator {
*/
public void paintBitmap(RenderedImage img, Dimension targetDim, boolean sourceTransparency)
throws IOException {
- double targetResolution = img.getWidth() / UnitConv.mpt2in(targetDim.width);
+ double targetHResolution = img.getWidth() / UnitConv.mpt2in(targetDim.width);
+ double targetVResolution = img.getHeight() / UnitConv.mpt2in(targetDim.height);
+ double targetResolution = Math.max(targetHResolution, targetVResolution);
int resolution = (int)Math.round(targetResolution);
int effResolution = calculatePCLResolution(resolution, true);
Dimension orgDim = new Dimension(img.getWidth(), img.getHeight());
- Dimension effDim = getAdjustedDimension(orgDim, targetResolution, effResolution);
+ Dimension effDim;
+ if (targetResolution == effResolution) {
+ effDim = orgDim; //avoid scaling side-effects
+ } else {
+ effDim = new Dimension(
+ (int)Math.ceil(UnitConv.mpt2px(targetDim.width, effResolution)),
+ (int)Math.ceil(UnitConv.mpt2px(targetDim.height, effResolution)));
+ }
boolean scaled = !orgDim.equals(effDim);
//ImageWriterUtil.saveAsPNG(img, new java.io.File("D:/text-0-org.png"));
@@ -791,6 +798,7 @@ public class PCLGenerator {
BufferedImage src = null;
if (img instanceof BufferedImage && !scaled) {
if (!isGrayscaleImage(img) || img.getColorModel().hasAlpha()) {
+ /* Disabled as this doesn't work reliably, use the fallback below
src = new BufferedImage(effDim.width, effDim.height,
BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = src.createGraphics();
@@ -802,6 +810,7 @@ public class PCLGenerator {
ColorConvertOp op = new ColorConvertOp(
ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter((BufferedImage)img, src);
+ */
} else {
src = (BufferedImage)img;
}
@@ -1018,7 +1027,7 @@ public class PCLGenerator {
}
public void endLine() throws IOException {
- if (zeroRow) {
+ if (zeroRow && PCLGenerator.this.currentSourceTransparency) {
writeCommand("*b1Y");
} else if (rlewidth < bytewidth) {
writeCommand("*b1m" + rlewidth + "W");
diff --git a/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java
new file mode 100644
index 000000000..c24dfd7dc
--- /dev/null
+++ b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.pcl;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.image.loader.Image;
+import org.apache.xmlgraphics.image.loader.ImageException;
+import org.apache.xmlgraphics.image.loader.ImageFlavor;
+import org.apache.xmlgraphics.image.loader.ImageManager;
+import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
+import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
+import org.apache.xmlgraphics.java2d.GraphicContext;
+import org.apache.xmlgraphics.util.UnitConv;
+
+import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.render.ImageHandler;
+import org.apache.fop.render.RenderingContext;
+
+/**
+ * Image handler implementation that paints Graphics2D images in PCL. Since PCL is limited in its
+ * vector graphics capabilities, there's a fallback built in that switches to bitmap painting
+ * if an advanced feature is encountered.
+ */
+public class PCLImageHandlerGraphics2D implements ImageHandler {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(PCLImageHandlerGraphics2D.class);
+
+ /** {@inheritDoc} */
+ public int getPriority() {
+ return 400;
+ }
+
+ /** {@inheritDoc} */
+ public Class getSupportedImageClass() {
+ return ImageGraphics2D.class;
+ }
+
+ /** {@inheritDoc} */
+ public ImageFlavor[] getSupportedImageFlavors() {
+ return new ImageFlavor[] {
+ ImageFlavor.GRAPHICS2D
+ };
+ }
+
+ /** {@inheritDoc} */
+ public void handleImage(RenderingContext context, Image image, Rectangle pos)
+ throws IOException {
+ PCLRenderingContext pclContext = (PCLRenderingContext)context;
+ ImageGraphics2D imageG2D = (ImageGraphics2D)image;
+ Dimension imageDim = imageG2D.getSize().getDimensionMpt();
+ PCLGenerator gen = pclContext.getPCLGenerator();
+
+ Point2D transPoint = pclContext.transformedPoint(pos.x, pos.y);
+ gen.setCursorPos(transPoint.getX(), transPoint.getY());
+
+ boolean painted = false;
+ ByteArrayOutputStream baout = new ByteArrayOutputStream();
+ PCLGenerator tempGen = new PCLGenerator(baout, gen.getMaximumBitmapResolution());
+ try {
+ GraphicContext ctx = (GraphicContext)pclContext.getGraphicContext().clone();
+
+ AffineTransform prepareHPGL2 = new AffineTransform();
+ prepareHPGL2.scale(0.001, 0.001);
+ ctx.setTransform(prepareHPGL2);
+
+ PCLGraphics2D graphics = new PCLGraphics2D(tempGen);
+ graphics.setGraphicContext(ctx);
+ graphics.setClippingDisabled(false /*pclContext.isClippingDisabled()*/);
+ Rectangle2D area = new Rectangle2D.Double(
+ 0.0, 0.0, imageDim.getWidth(), imageDim.getHeight());
+ imageG2D.getGraphics2DImagePainter().paint(graphics, area);
+
+ //If we arrive here, the graphic is natively paintable, so write the graphic
+ gen.writeCommand("*c" + gen.formatDouble4(pos.width / 100f) + "x"
+ + gen.formatDouble4(pos.height / 100f) + "Y");
+ gen.writeCommand("*c0T");
+ gen.enterHPGL2Mode(false);
+ gen.writeText("\nIN;");
+ gen.writeText("SP1;");
+ //One Plotter unit is 0.025mm!
+ double scale = imageDim.getWidth() / UnitConv.mm2pt(imageDim.getWidth() * 0.025);
+ gen.writeText("SC0," + gen.formatDouble4(scale)
+ + ",0,-" + gen.formatDouble4(scale) + ",2;");
+ gen.writeText("IR0,100,0,100;");
+ gen.writeText("PU;PA0,0;\n");
+ baout.writeTo(gen.getOutputStream()); //Buffer is written to output stream
+ gen.writeText("\n");
+
+ gen.enterPCLMode(false);
+ painted = true;
+ } catch (UnsupportedOperationException uoe) {
+ log.debug(
+ "Cannot paint graphic natively. Falling back to bitmap painting. Reason: "
+ + uoe.getMessage());
+ }
+
+ if (!painted) {
+ //Fallback solution: Paint to a BufferedImage
+ FOUserAgent ua = context.getUserAgent();
+ ImageManager imageManager = ua.getFactory().getImageManager();
+ ImageRendered imgRend;
+ try {
+ imgRend = (ImageRendered)imageManager.convertImage(
+ imageG2D, new ImageFlavor[] {ImageFlavor.RENDERED_IMAGE}/*, hints*/);
+ } catch (ImageException e) {
+ throw new IOException(
+ "Image conversion error while converting the image to a bitmap"
+ + " as a fallback measure: " + e.getMessage());
+ }
+
+ gen.paintBitmap(imgRend.getRenderedImage(), new Dimension(pos.width, pos.height),
+ pclContext.isSourceTransparencyEnabled());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean isCompatible(RenderingContext targetContext, Image image) {
+ boolean supported = (image == null || image instanceof ImageGraphics2D)
+ && targetContext instanceof PCLRenderingContext;
+ if (supported) {
+ Object hint = targetContext.getHint(PCLConstants.CONV_MODE);
+ if ("bitmap".equals(hint)) {
+ return false;
+ }
+ }
+ return supported;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/pcl/PCLPainter.java b/src/java/org/apache/fop/render/pcl/PCLPainter.java
index 7ad6ea931..b709c28f3 100644
--- a/src/java/org/apache/fop/render/pcl/PCLPainter.java
+++ b/src/java/org/apache/fop/render/pcl/PCLPainter.java
@@ -110,6 +110,10 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
}
}
+ private boolean isSpeedOptimized() {
+ return getPCLUtil().getRenderingMode() == PCLRenderingMode.SPEED;
+ }
+
//----------------------------------------------------------------------------------------------
/** {@inheritDoc} */
@@ -161,6 +165,10 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
return PCLPainter.this.transformedPoint(x, y);
}
+ public GraphicContext getGraphicContext() {
+ return PCLPainter.this.graphicContext;
+ }
+
};
return pdfContext;
}
@@ -203,7 +211,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
public void drawBorderRect(final Rectangle rect,
final BorderProps before, final BorderProps after,
final BorderProps start, final BorderProps end) throws IFException {
- if (getPCLUtil().getRenderingMode() == PCLRenderingMode.SPEED) {
+ if (isSpeedOptimized()) {
super.drawBorderRect(rect, before, after, start, end);
return;
}
@@ -239,7 +247,7 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
public void drawLine(final Point start, final Point end,
final int width, final Color color, final RuleStyle style)
throws IFException {
- if (getPCLUtil().getRenderingMode() == PCLRenderingMode.SPEED) {
+ if (isSpeedOptimized()) {
super.drawLine(start, end, width, color, style);
return;
}
@@ -278,8 +286,16 @@ public class PCLPainter extends AbstractIFPainter implements PCLConstants {
ImageGraphics2D img = new ImageGraphics2D(info, painter);
Map hints = new java.util.HashMap();
- hints.put(ImageProcessingHints.BITMAP_TYPE_INTENT,
- ImageProcessingHints.BITMAP_TYPE_INTENT_GRAY);
+ if (isSpeedOptimized()) {
+ //Gray text may not be painted in this case! We don't get dithering in Sun JREs.
+ //But this approach is about twice as fast as the grayscale image.
+ hints.put(ImageProcessingHints.BITMAP_TYPE_INTENT,
+ ImageProcessingHints.BITMAP_TYPE_INTENT_MONO);
+ } else {
+ hints.put(ImageProcessingHints.BITMAP_TYPE_INTENT,
+ ImageProcessingHints.BITMAP_TYPE_INTENT_GRAY);
+ }
+ hints.put(PCLConstants.CONV_MODE, "bitmap");
PCLRenderingContext context = (PCLRenderingContext)createRenderingContext();
context.setSourceTransparencyEnabled(true);
try {
diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderingContext.java b/src/java/org/apache/fop/render/pcl/PCLRenderingContext.java
index 4c41cbf58..9212770fc 100644
--- a/src/java/org/apache/fop/render/pcl/PCLRenderingContext.java
+++ b/src/java/org/apache/fop/render/pcl/PCLRenderingContext.java
@@ -21,6 +21,7 @@ package org.apache.fop.render.pcl;
import java.awt.geom.Point2D;
+import org.apache.xmlgraphics.java2d.GraphicContext;
import org.apache.xmlgraphics.util.MimeConstants;
import org.apache.fop.apps.FOUserAgent;
@@ -93,4 +94,10 @@ public abstract class PCLRenderingContext extends AbstractRenderingContext {
*/
public abstract Point2D transformedPoint(int x, int y);
+ /**
+ * Returns the current {@code GraphicContext} instance.
+ * @return the graphic context
+ */
+ public abstract GraphicContext getGraphicContext();
+
}