diff options
Diffstat (limited to 'src/java/org/apache/fop/render')
7 files changed, 148 insertions, 67 deletions
diff --git a/src/java/org/apache/fop/render/afp/AFPCustomizable.java b/src/java/org/apache/fop/render/afp/AFPCustomizable.java index ff4fb0100..ed1ea443b 100644 --- a/src/java/org/apache/fop/render/afp/AFPCustomizable.java +++ b/src/java/org/apache/fop/render/afp/AFPCustomizable.java @@ -51,6 +51,12 @@ public interface AFPCustomizable { void setNativeImagesSupported(boolean nativeImages); /** + * Sets the shading mode for painting filled rectangles. + * @param shadingMode the shading mode + */ + void setShadingMode(AFPShadingMode shadingMode); + + /** * Sets the output/device resolution * * @param resolution diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 8d29145cf..febfb9672 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -25,10 +25,13 @@ import java.awt.geom.AffineTransform; import java.io.IOException; import java.util.Map; +import org.apache.fop.afp.AFPDitheredRectanglePainter; import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPRectanglePainter; import org.apache.fop.afp.AFPResourceLevelDefaults; import org.apache.fop.afp.AFPResourceManager; import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.afp.AbstractAFPPainter; import org.apache.fop.afp.DataStream; import org.apache.fop.afp.fonts.AFPFontCollection; import org.apache.fop.afp.fonts.AFPPageFonts; @@ -76,6 +79,9 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler private int location = LOC_ELSEWHERE; + /** the shading mode for filled rectangles */ + private AFPShadingMode shadingMode = AFPShadingMode.COLOR; + /** * Default constructor. */ @@ -125,6 +131,16 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler return this.resourceManager; } + AbstractAFPPainter createRectanglePainter() { + if (AFPShadingMode.DITHERED.equals(this.shadingMode)) { + return new AFPDitheredRectanglePainter( + getPaintingState(), getDataStream(), getResourceManager()); + } else { + return new AFPRectanglePainter( + getPaintingState(), getDataStream()); + } + } + /** {@inheritDoc} */ public void startDocument() throws IFException { super.startDocument(); @@ -309,6 +325,11 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler } /** {@inheritDoc} */ + public void setShadingMode(AFPShadingMode shadingMode) { + this.shadingMode = shadingMode; + } + + /** {@inheritDoc} */ public void setResolution(int resolution) { paintingState.setResolution(resolution); } diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java index a92be9d6e..e591812f9 100644 --- a/src/java/org/apache/fop/render/afp/AFPPainter.java +++ b/src/java/org/apache/fop/render/afp/AFPPainter.java @@ -35,8 +35,8 @@ import org.apache.xmlgraphics.image.loader.ImageSessionContext; import org.apache.fop.afp.AFPBorderPainter; import org.apache.fop.afp.AFPPaintingState; -import org.apache.fop.afp.AFPRectanglePainter; import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.afp.AbstractAFPPainter; import org.apache.fop.afp.BorderPaintingInfo; import org.apache.fop.afp.DataStream; import org.apache.fop.afp.RectanglePaintingInfo; @@ -79,7 +79,7 @@ public class AFPPainter extends AbstractIFPainter { /** the border painter */ private AFPBorderPainterAdapter borderPainter; /** the rectangle painter */ - private AFPRectanglePainter rectanglePainter; + private AbstractAFPPainter rectanglePainter; /** unit converter */ private final AFPUnitConverter unitConv; @@ -94,7 +94,7 @@ public class AFPPainter extends AbstractIFPainter { this.state = IFState.create(); this.borderPainter = new AFPBorderPainterAdapter( new AFPBorderPainter(getPaintingState(), getDataStream())); - this.rectanglePainter = new AFPRectanglePainter(getPaintingState(), getDataStream()); + this.rectanglePainter = documentHandler.createRectanglePainter(); this.unitConv = getPaintingState().getUnitConverter(); } @@ -222,7 +222,11 @@ public class AFPPainter extends AbstractIFPainter { } RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo( toPoint(rect.x), toPoint(rect.y), toPoint(rect.width), toPoint(rect.height)); - rectanglePainter.paint(rectanglePaintInfo); + try { + rectanglePainter.paint(rectanglePaintInfo); + } catch (IOException ioe) { + throw new IFException("IO error while painting rectangle", ioe); + } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index 94fd05dc8..5024fa7b6 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -43,6 +43,7 @@ import org.apache.xmlgraphics.ps.ImageEncodingHelper; import org.apache.fop.afp.AFPBorderPainter; import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPDitheredRectanglePainter; import org.apache.fop.afp.AFPEventProducer; import org.apache.fop.afp.AFPPaintingState; import org.apache.fop.afp.AFPRectanglePainter; @@ -50,6 +51,7 @@ import org.apache.fop.afp.AFPResourceLevelDefaults; import org.apache.fop.afp.AFPResourceManager; import org.apache.fop.afp.AFPTextDataInfo; import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.afp.AbstractAFPPainter; import org.apache.fop.afp.BorderPaintingInfo; import org.apache.fop.afp.DataStream; import org.apache.fop.afp.RectanglePaintingInfo; @@ -167,7 +169,10 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust /** the image handler registry */ private final AFPImageHandlerRegistry imageHandlerRegistry; - private AFPRectanglePainter rectanglePainter; + private AbstractAFPPainter rectanglePainter; + + /** the shading mode for filled rectangles */ + private AFPShadingMode shadingMode = AFPShadingMode.COLOR; /** * Constructor for AFPRenderer. @@ -201,11 +206,21 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust this.dataStream = resourceManager.createDataStream(paintingState, outputStream); this.borderPainter = new AFPBorderPainter(paintingState, dataStream); - this.rectanglePainter = new AFPRectanglePainter(paintingState, dataStream); + this.rectanglePainter = createRectanglePainter(); dataStream.startDocument(); } + AbstractAFPPainter createRectanglePainter() { + if (AFPShadingMode.DITHERED.equals(this.shadingMode)) { + return new AFPDitheredRectanglePainter( + this.paintingState, this.dataStream, this.resourceManager); + } else { + return new AFPRectanglePainter( + this.paintingState, this.dataStream); + } + } + /** {@inheritDoc} */ public void stopRenderer() throws IOException { dataStream.endDocument(); @@ -362,7 +377,12 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust /** {@inheritDoc} */ public void fillRect(float x, float y, float width, float height) { RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo(x, y, width, height); - rectanglePainter.paint(rectanglePaintInfo); + try { + rectanglePainter.paint(rectanglePaintInfo); + } catch (IOException ioe) { + //TODO not ideal, but the AFPRenderer is legacy + throw new RuntimeException("I/O error while painting a filled rectangle", ioe); + } } /** {@inheritDoc} */ @@ -728,6 +748,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust } /** {@inheritDoc} */ + public void setShadingMode(AFPShadingMode shadingMode) { + this.shadingMode = shadingMode; + } + + /** {@inheritDoc} */ public void setResolution(int resolution) { paintingState.setResolution(resolution); } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index fcc1140c7..892018f9b 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -299,6 +299,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false); customizable.setNativeImagesSupported(nativeImageSupport); + // shading (filled rectangles) + Configuration shadingCfg = cfg.getChild("shading"); + AFPShadingMode shadingMode = AFPShadingMode.valueOf( + shadingCfg.getValue(AFPShadingMode.COLOR.getName())); + customizable.setShadingMode(shadingMode); + // renderer resolution Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false); if (rendererResolutionCfg != null) { diff --git a/src/java/org/apache/fop/render/afp/AFPShadingMode.java b/src/java/org/apache/fop/render/afp/AFPShadingMode.java new file mode 100644 index 000000000..b45c33a8e --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPShadingMode.java @@ -0,0 +1,74 @@ +/* + * 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.afp; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +/** Enumeration class for the AFP shading mode. */ +public final class AFPShadingMode implements Serializable { + + private static final long serialVersionUID = 8579867898716480779L; + + /** the color mode (the default) */ + public static final AFPShadingMode COLOR = new AFPShadingMode("COLOR"); + /** the dithered mode */ + public static final AFPShadingMode DITHERED = new AFPShadingMode("DITHERED"); + + private String name; + + /** + * Constructor to add a new named item. + * @param name Name of the item. + */ + private AFPShadingMode(String name) { + this.name = name; + } + + /** @return the name of the enumeration */ + public String getName() { + return this.name; + } + + /** + * Returns the enumeration/singleton object based on its name. + * @param name the name of the enumeration value + * @return the enumeration object + */ + public static AFPShadingMode valueOf(String name) { + if (COLOR.getName().equalsIgnoreCase(name)) { + return COLOR; + } else if (DITHERED.getName().equalsIgnoreCase(name)) { + return DITHERED; + } else { + throw new IllegalArgumentException("Illegal value for enumeration: " + name); + } + } + + private Object readResolve() throws ObjectStreamException { + return valueOf(getName()); + } + + /** {@inheritDoc} */ + public String toString() { + return getClass().getName() + ":" + name; + } + +} diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java index c36d2a66e..2146bb3b8 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java +++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java @@ -48,6 +48,7 @@ import org.apache.xmlgraphics.image.GraphicsUtil; import org.apache.xmlgraphics.util.UnitConv; import org.apache.fop.util.bitmap.BitmapImageUtil; +import org.apache.fop.util.bitmap.DitherUtil; import org.apache.fop.util.bitmap.MonochromeBitmapConverter; /** @@ -65,11 +66,6 @@ public class PCLGenerator { /** A list of all supported resolutions in PCL (values in dpi) */ public static final int[] PCL_RESOLUTIONS = new int[] {75, 100, 150, 200, 300, 600}; - /** Selects a 4x4 Bayer dither matrix (17 grayscales) */ - public static final int DITHER_MATRIX_4X4 = 4; - /** Selects a 8x8 Bayer dither matrix (65 grayscales) */ - public static final int DITHER_MATRIX_8X8 = 8; - private final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US); private final DecimalFormat df2 = new DecimalFormat("0.##", symbols); private final DecimalFormat df4 = new DecimalFormat("0.####", symbols); @@ -390,7 +386,7 @@ public class PCLGenerator { writeCommand("*c" + lineshade + "G"); writeCommand("*c2P"); //Shaded fill } else { - defineGrayscalePattern(col, 32, DITHER_MATRIX_4X4); + defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4); writeCommand("*c" + formatDouble4(w / 100.0) + "h" + formatDouble4(h / 100.0) + "V"); @@ -401,34 +397,6 @@ public class PCLGenerator { setPatternTransparencyMode(true); } - //Bayer dither matrices (4x4 and 8x8 are derived from the 2x2 matrix) - private static final int[] BAYER_D2 = new int[] {0, 2, 3, 1}; - private static final int[] BAYER_D4; - private static final int[] BAYER_D8; - - static { - BAYER_D4 = deriveBayerMatrix(BAYER_D2); - BAYER_D8 = deriveBayerMatrix(BAYER_D4); - } - - private static void setValueInMatrix(int[] dn, int half, int part, int idx, int value) { - int xoff = (part & 1) * half; - int yoff = (part & 2) * half * half; - int matrixIndex = yoff + ((idx / half) * half * 2) + (idx % half) + xoff; - dn[matrixIndex] = value; - } - - private static int[] deriveBayerMatrix(int[] d) { - int[] dn = new int[d.length * 4]; - int half = (int)Math.sqrt(d.length); - for (int part = 0; part < 4; part++) { - for (int i = 0, c = d.length; i < c; i++) { - setValueInMatrix(dn, half, part, i, d[i] * 4 + BAYER_D2[part]); - } - } - return dn; - } - /** * Generates a user-defined pattern for a dithering pattern matching the grayscale value * of the color given. @@ -453,35 +421,12 @@ public class PCLGenerator { byte[] pattern; if (ditherMatrixSize == 8) { - int gray65 = gray255 * 65 / 255; - - pattern = new byte[BAYER_D8.length / 8]; - - for (int i = 0, c = BAYER_D8.length; i < c; i++) { - boolean dot = !(BAYER_D8[i] < gray65 - 1); - if (dot) { - int byteIdx = i / 8; - pattern[byteIdx] |= 1 << (i % 8); - } - } + pattern = DitherUtil.getBayerDither(DitherUtil.DITHER_MATRIX_8X8, gray255, false); } else { - int gray17 = gray255 * 17 / 255; - //Since a 4x4 pattern did not work, the 4x4 pattern is applied 4 times to an //8x8 pattern. Maybe this could be changed to use an 8x8 bayer dither pattern //instead of the 4x4 one. - pattern = new byte[BAYER_D4.length / 8 * 4]; - - for (int i = 0, c = BAYER_D4.length; i < c; i++) { - boolean dot = !(BAYER_D4[i] < gray17 - 1); - if (dot) { - int byteIdx = i / 4; - pattern[byteIdx] |= 1 << (i % 4); - pattern[byteIdx] |= 1 << ((i % 4) + 4); - pattern[byteIdx + 4] |= 1 << (i % 4); - pattern[byteIdx + 4] |= 1 << ((i % 4) + 4); - } - } + pattern = DitherUtil.getBayerDither(DitherUtil.DITHER_MATRIX_4X4, gray255, true); } data.write(pattern); if ((baout.size() % 2) > 0) { @@ -564,7 +509,7 @@ public class PCLGenerator { if (usePCLShades) { selectCurrentPattern(convertToPCLShade(col), 2); } else { - defineGrayscalePattern(col, 32, DITHER_MATRIX_4X4); + defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4); selectCurrentPattern(32, 4); } } |