ソースを参照

Making conversion hints available to ImageHandler implementations, too.

(Re-)implemented Graphics2D support for PCL. It can be disabled by fox:conversion-mode="bitmap" if necessary.
Fixed a bug with non-uniform image scaling when encoding bitmap images.
Commented some code that did not reliably convert color images to grayscale. The (probably slower) fallback code is used instead.
Some performance improvements for text painting using bitmaps when <rendering>speed<rendering> is selected.
Removed the RenderingContext interface from RendererContext since it's not used.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@711269 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Jeremias Maerki 15年前
コミット
dfeb96c655

+ 1
- 0
src/java/META-INF/services/org.apache.fop.render.ImageHandler ファイルの表示

@@ -6,3 +6,4 @@ org.apache.fop.render.pdf.PDFImageHandlerSVG
org.apache.fop.render.java2d.Java2DImageHandlerRenderedImage
org.apache.fop.render.java2d.Java2DImageHandlerGraphics2D
org.apache.fop.render.pcl.PCLImageHandlerRenderedImage
org.apache.fop.render.pcl.PCLImageHandlerGraphics2D

+ 32
- 0
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);
}
}
}


+ 1
- 1
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;

+ 8
- 0
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);

}

+ 2
- 0
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) {

+ 14
- 5
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");

+ 157
- 0
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;
}

}

+ 20
- 4
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 {

+ 7
- 0
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();

}

読み込み中…
キャンセル
保存