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/intermediate/IFParser.java2
-rw-r--r--src/java/org/apache/fop/render/pcl/Java2DRendererOption.java3
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java2
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLGenerator.java398
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java2
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLImageHandlerRenderedImage.java2
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLPainter.java14
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLRendererConfig.java11
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java4
-rw-r--r--src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java19
-rw-r--r--src/java/org/apache/fop/render/ps/Gradient.java85
11 files changed, 493 insertions, 49 deletions
diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 235e051f9..8d562e465 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -523,7 +523,7 @@ public class IFParser implements IFConstants {
establishForeignAttributes(foreignAttributes);
documentHandler.startPage(index, name, pageMasterName,
new Dimension(width, height));
- documentHandler.getContext().setPageNumber(Integer.parseInt(name));
+ documentHandler.getContext().setPageNumber(index + 1);
resetForeignAttributes();
}
diff --git a/src/java/org/apache/fop/render/pcl/Java2DRendererOption.java b/src/java/org/apache/fop/render/pcl/Java2DRendererOption.java
index cb23f7191..9ec0b779b 100644
--- a/src/java/org/apache/fop/render/pcl/Java2DRendererOption.java
+++ b/src/java/org/apache/fop/render/pcl/Java2DRendererOption.java
@@ -27,7 +27,8 @@ public enum Java2DRendererOption implements RendererConfigOption {
RENDERING_MODE("rendering", PCLRenderingMode.class),
TEXT_RENDERING("text-rendering", Boolean.class),
- DISABLE_PJL("disable-pjl", Boolean.class);
+ DISABLE_PJL("disable-pjl", Boolean.class),
+ MODE_COLOR("color", Boolean.class);
private final String name;
diff --git a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
index 1991295bd..66655a721 100644
--- a/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
+++ b/src/java/org/apache/fop/render/pcl/PCLDocumentHandler.java
@@ -274,7 +274,7 @@ public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
try {
Rectangle printArea = this.currentPageDefinition.getLogicalPageRect();
gen.setCursorPos(0, 0);
- gen.paintBitmap(this.currentImage, printArea.getSize(), true);
+ gen.paintBitmap(this.currentImage, printArea.getSize(), true, pclUtil);
} catch (IOException ioe) {
throw new IFException("I/O error while encoding page image", ioe);
} finally {
diff --git a/src/java/org/apache/fop/render/pcl/PCLGenerator.java b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
index 67d37fbb5..589779ad9 100644
--- a/src/java/org/apache/fop/render/pcl/PCLGenerator.java
+++ b/src/java/org/apache/fop/render/pcl/PCLGenerator.java
@@ -21,12 +21,19 @@ package org.apache.fop.render.pcl;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DirectColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
+import java.awt.image.SinglePixelPackedSampleModel;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -380,7 +387,7 @@ public class PCLGenerator {
* @param col the fill color
* @throws IOException In case of an I/O error
*/
- protected void fillRect(int w, int h, Color col) throws IOException {
+ protected void fillRect(int w, int h, Color col, boolean colorEnabled) throws IOException {
if ((w == 0) || (h == 0)) {
return;
}
@@ -399,12 +406,19 @@ public class PCLGenerator {
writeCommand("*c" + lineshade + "G");
writeCommand("*c2P"); //Shaded fill
} else {
- defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4);
+ if (colorEnabled) {
+ selectColor(col);
+ writeCommand("*c" + formatDouble4(w / 100.0) + "h"
+ + formatDouble4(h / 100.0) + "V");
+ writeCommand("*c0P"); //Solid fill
+ } else {
+ defineGrayscalePattern(col, 32, DitherUtil.DITHER_MATRIX_4X4);
- writeCommand("*c" + formatDouble4(w / 100.0) + "h"
- + formatDouble4(h / 100.0) + "V");
- writeCommand("*c32G");
- writeCommand("*c4P"); //User-defined pattern
+ writeCommand("*c" + formatDouble4(w / 100.0) + "h"
+ + formatDouble4(h / 100.0) + "V");
+ writeCommand("*c32G");
+ writeCommand("*c4P"); //User-defined pattern
+ }
}
// Reset pattern transparency mode.
setPatternTransparencyMode(true);
@@ -530,6 +544,13 @@ public class PCLGenerator {
}
}
+ public void selectColor(Color col) throws IOException {
+ writeCommand("*v6W");
+ writeBytes(new byte[]{0, 1, 1, 8, 8, 8});
+ writeCommand(String.format("*v%da%db%dc0I", col.getRed(), col.getGreen(), col.getBlue()));
+ writeCommand("*v0S");
+ }
+
/**
* Select the current pattern
* @param patternID the pattern ID (<ESC>*c#G command)
@@ -696,13 +717,15 @@ public class PCLGenerator {
* @param sourceTransparency true if the background should not be erased
* @throws IOException In case of an I/O error
*/
- public void paintBitmap(RenderedImage img, Dimension targetDim, boolean sourceTransparency)
- throws IOException {
+ public void paintBitmap(RenderedImage img, Dimension targetDim, boolean sourceTransparency,
+ PCLRenderingUtil pclUtil) throws IOException {
+ final boolean printerSupportsColor = pclUtil.isColorEnabled();
+ boolean monochrome = isMonochromeImage(img);
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);
+ int effResolution = calculatePCLResolution(resolution, !(printerSupportsColor && !monochrome));
Dimension orgDim = new Dimension(img.getWidth(), img.getHeight());
Dimension effDim;
if (targetResolution == effResolution) {
@@ -713,27 +736,30 @@ public class PCLGenerator {
(int)Math.ceil(UnitConv.mpt2px(targetDim.height, effResolution)));
}
boolean scaled = !orgDim.equals(effDim);
-
- boolean monochrome = isMonochromeImage(img);
if (!monochrome) {
- //Transparency mask disabled. Doesn't work reliably
- /*
- final boolean transparencyDisabled = true;
- RenderedImage mask = (transparencyDisabled ? null : getMask(img, effDim));
- if (mask != null) {
- pushCursorPos();
- selectCurrentPattern(0, 1); //Solid white
- setTransparencyMode(true, true);
- paintMonochromeBitmap(mask, effResolution);
- popCursorPos();
- }
- */
+ if (printerSupportsColor) {
+ selectCurrentPattern(0, 0); //Solid black
+ renderImageAsColor(img, effResolution);
+ } else {
+ //Transparency mask disabled. Doesn't work reliably
+ /*
+ final boolean transparencyDisabled = true;
+ RenderedImage mask = (transparencyDisabled ? null : getMask(img, effDim));
+ if (mask != null) {
+ pushCursorPos();
+ selectCurrentPattern(0, 1); //Solid white
+ setTransparencyMode(true, true);
+ paintMonochromeBitmap(mask, effResolution);
+ popCursorPos();
+ }
+ */
- RenderedImage red = BitmapImageUtil.convertToMonochrome(
- img, effDim, this.ditheringQuality);
- selectCurrentPattern(0, 0); //Solid black
- setTransparencyMode(sourceTransparency /*|| mask != null*/, true);
- paintMonochromeBitmap(red, effResolution);
+ RenderedImage red = BitmapImageUtil.convertToMonochrome(
+ img, effDim, this.ditheringQuality);
+ selectCurrentPattern(0, 0); //Solid black
+ setTransparencyMode(sourceTransparency /*|| mask != null*/, true);
+ paintMonochromeBitmap(red, effResolution);
+ }
} else {
RenderedImage effImg = img;
if (scaled) {
@@ -755,6 +781,90 @@ public class PCLGenerator {
return (int)greyVal;
}
+ private void renderImageAsColor(RenderedImage imgOrg, int dpi) throws IOException {
+ BufferedImage img = new BufferedImage(imgOrg.getWidth(), imgOrg.getHeight(), BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, imgOrg.getWidth(), imgOrg.getHeight());
+ g.drawImage((Image) imgOrg, 0, 0, null);
+
+ if (!isValidPCLResolution(dpi)) {
+ throw new IllegalArgumentException("Invalid PCL resolution: " + dpi);
+ }
+ int w = img.getWidth();
+ ColorModel cm = img.getColorModel();
+ if (cm instanceof DirectColorModel) {
+ writeCommand("*v6W"); // ImagingMode
+ out.write(new byte[]{0, 3, 0, 8, 8, 8});
+ } else {
+ IndexColorModel icm = (IndexColorModel)cm;
+ writeCommand("*v6W"); // ImagingMode
+ out.write(new byte[]{0, 1, (byte)icm.getMapSize(), 8, 8, 8});
+
+ byte[] reds = new byte[256];
+ byte[] greens = new byte[256];
+ byte[] blues = new byte[256];
+
+ icm.getReds(reds);
+ icm.getGreens(greens);
+ icm.getBlues(blues);
+ for (int i = 0; i < icm.getMapSize(); i++) {
+ writeCommand("*v" + (reds[i] & 0xFF) + "A"); //ColorComponentOne
+ writeCommand("*v" + (greens[i] & 0xFF) + "B"); //ColorComponentTwo
+ writeCommand("*v" + (blues[i] & 0xFF) + "C"); //ColorComponentThree
+ writeCommand("*v" + i + "I"); //AssignColorIndex
+ }
+ }
+ setRasterGraphicsResolution(dpi);
+ writeCommand("*r0f" + img.getHeight() + "t" + (w) + "S");
+ writeCommand("*r1A");
+
+ Raster raster = img.getData();
+
+ ColorEncoder encoder = new ColorEncoder(img);
+ // Transfer graphics data
+ if (cm.getTransferType() == DataBuffer.TYPE_BYTE) {
+ DataBufferByte dataBuffer = (DataBufferByte)raster.getDataBuffer();
+ if (img.getSampleModel() instanceof MultiPixelPackedSampleModel && dataBuffer.getNumBanks() == 1) {
+ byte[] buf = dataBuffer.getData();
+ MultiPixelPackedSampleModel sampleModel = (MultiPixelPackedSampleModel)img.getSampleModel();
+ int scanlineStride = sampleModel.getScanlineStride();
+ int idx = 0;
+ for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
+ for (int x = 0; x < scanlineStride; x++) {
+ encoder.add8Bits(buf[idx]);
+ idx++;
+ }
+ encoder.endLine();
+ }
+ } else {
+ throw new IOException("Unsupported image");
+ }
+ } else if (cm.getTransferType() == DataBuffer.TYPE_INT) {
+ DataBufferInt dataBuffer = (DataBufferInt)raster.getDataBuffer();
+ if (img.getSampleModel() instanceof SinglePixelPackedSampleModel && dataBuffer.getNumBanks() == 1) {
+ int[] buf = dataBuffer.getData();
+ SinglePixelPackedSampleModel sampleModel = (SinglePixelPackedSampleModel)img.getSampleModel();
+ int scanlineStride = sampleModel.getScanlineStride();
+ int idx = 0;
+ for (int y = 0, maxy = img.getHeight(); y < maxy; y++) {
+ for (int x = 0; x < scanlineStride; x++) {
+ encoder.add8Bits((byte)(buf[idx] >> 16));
+ encoder.add8Bits((byte)(buf[idx] >> 8));
+ encoder.add8Bits((byte)(buf[idx] >> 0));
+ idx++;
+ }
+ encoder.endLine();
+ }
+ } else {
+ throw new IOException("Unsupported image");
+ }
+ } else {
+ throw new IOException("Unsupported image");
+ }
+ // End raster graphics
+ writeCommand("*rB");
+ }
/**
* Paint a bitmap at the current cursor position. The bitmap must be a monochrome
* (1-bit) bitmap image.
@@ -921,4 +1031,236 @@ public class PCLGenerator {
}
+ private class ColorEncoder {
+ private int imgw;
+ private int bytewidth;
+ private byte ib; //current image bits
+
+ private int currentIndex;
+ private int len;
+ private int shiftBit = 0x80;
+ private int whiteLines;
+ final byte[] zeros;
+ final byte[] buff1;
+ final byte[] buff2;
+ final byte[] encodedRun;
+ final byte[] encodedTagged;
+ final byte[] encodedDelta;
+ byte[] seed;
+ byte[] current;
+ int compression;
+ int seedLen;
+
+ public ColorEncoder(RenderedImage img) {
+ imgw = img.getWidth();
+ bytewidth = imgw * 3 + 1;
+
+ zeros = new byte[bytewidth];
+ buff1 = new byte[bytewidth];
+ buff2 = new byte[bytewidth];
+ encodedRun = new byte[bytewidth];
+ encodedTagged = new byte[bytewidth];
+ encodedDelta = new byte[bytewidth];
+
+ seed = buff1;
+ current = buff2;
+
+ seedLen = 0;
+ compression = (-1);
+ System.arraycopy(zeros, 0, seed, 0, zeros.length);
+
+ }
+
+ private int runCompression(byte[] buff, int len) {
+ int bytes = 0;
+
+ try {
+ for (int i = 0; i < len;) {
+ int sameCount;
+ byte seed = current[i++];
+
+ for (sameCount = 1; i < len && current[i] == seed; i++) {
+ sameCount++;
+ }
+
+ for (; sameCount > 256; sameCount -= 256) {
+ buff[bytes++] = (byte)255;
+ buff[bytes++] = seed;
+ }
+ if (sameCount > 0) {
+ buff[bytes++] = (byte)(sameCount - 1);
+ buff[bytes++] = seed;
+ }
+
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return len + 1;
+ }
+ return bytes;
+ }
+
+ private int deltaCompression(byte[] seed, byte[] buff, int len) {
+ int bytes = 0;
+
+ try {
+ for (int i = 0; i < len;) {
+ int sameCount;
+ int diffCount;
+
+ for (sameCount = 0; i < len && current[i] == seed[i]; i++) {
+ sameCount++;
+ }
+ for (diffCount = 0; i < len && current[i] != seed[i]; i++) {
+ diffCount++;
+ }
+
+ for (; diffCount != 0;) {
+ int diffToWrite = (diffCount > 8) ? 8 : diffCount;
+ int sameToWrite = (sameCount > 31) ? 31 : sameCount;
+
+ buff[bytes++] = (byte)(((diffToWrite - 1) << 5) | sameToWrite);
+ sameCount -= sameToWrite;
+ if (sameToWrite == 31) {
+ for (; sameCount >= 255; sameCount -= 255) {
+ buff[bytes++] = (byte)255;
+ }
+ buff[bytes++] = (byte)sameCount;
+ sameCount = 0;
+ }
+
+ System.arraycopy(current, i - diffCount, buff, bytes, diffToWrite);
+ bytes += diffToWrite;
+
+ diffCount -= diffToWrite;
+ }
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return len + 1;
+ }
+ return bytes;
+ }
+
+ private int tiffCompression(byte[] encodedTagged, int len) {
+ int literalCount = 0;
+ int bytes = 0;
+
+ try {
+ for (int from = 0; from < len;) {
+ int repeatLength;
+ int repeatValue = current[from];
+
+ for (repeatLength = 1; repeatLength < 128
+ && from + repeatLength < len
+ && current[from + repeatLength] == repeatValue;) {
+ repeatLength++;
+ }
+
+ if (literalCount == 128 || (repeatLength > 2 && literalCount > 0)) {
+ encodedTagged[bytes++] = (byte)(literalCount - 1);
+ System.arraycopy(current, from - literalCount, encodedTagged, bytes, literalCount);
+ bytes += literalCount;
+ literalCount = 0;
+ }
+ if (repeatLength > 2) {
+ encodedTagged[bytes++] = (byte)(1 - repeatLength);
+ encodedTagged[bytes++] = current[from];
+ from += repeatLength;
+ } else {
+ literalCount++;
+ from++;
+ }
+ }
+ if (literalCount > 0) {
+ encodedTagged[bytes++] = (byte)(literalCount - 1);
+ System.arraycopy(current, (3 * len) - literalCount, encodedTagged, bytes, literalCount);
+ bytes += literalCount;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return len + 1;
+ }
+ return bytes;
+ }
+
+ public void addBit(boolean bit) {
+ //Set image bit for black
+ if (bit) {
+ ib |= shiftBit;
+ }
+ shiftBit >>= 1;
+ if (shiftBit == 0) {
+ add8Bits(ib);
+ shiftBit = 0x80;
+ ib = 0;
+ }
+ }
+
+ public void add8Bits(byte b) {
+ current[currentIndex++] = b;
+ if (b != 0) {
+ len = currentIndex;
+ }
+ }
+
+ public void endLine() throws IOException {
+ if (len == 0) {
+ whiteLines++;
+ } else {
+ if (whiteLines > 0) {
+ writeCommand("*b" + whiteLines + "Y");
+ whiteLines = 0;
+ }
+
+ int unencodedCount = len;
+ int runCount = runCompression(encodedRun, len);
+ int tiffCount = tiffCompression(encodedTagged, len);
+ int deltaCount = deltaCompression(seed, encodedDelta, Math.max(len, seedLen));
+
+ int bestCount = Math.min(unencodedCount, Math.min(runCount, Math.min(tiffCount, deltaCount)));
+ int bestCompression;
+
+ if (bestCount == unencodedCount) {
+ bestCompression = 0;
+ } else if (bestCount == runCount) {
+ bestCompression = 1;
+ } else if (bestCount == tiffCount) {
+ bestCompression = 2;
+ } else {
+ bestCompression = 3;
+ }
+
+ if (compression != bestCompression) {
+ compression = bestCompression;
+ writeCommand("*b" + compression + "M");
+ }
+
+ if (bestCompression == 0) {
+ writeCommand("*b" + unencodedCount + "W");
+ out.write(current, 0, unencodedCount);
+ } else if (bestCompression == 1) {
+ writeCommand("*b" + runCount + "W");
+ out.write(encodedRun, 0, runCount);
+ } else if (bestCompression == 2) {
+ writeCommand("*b" + tiffCount + "W");
+ out.write(encodedTagged, 0, tiffCount);
+ } else if (bestCompression == 3) {
+ writeCommand("*b" + deltaCount + "W");
+ out.write(encodedDelta, 0, deltaCount);
+ }
+
+ if (current == buff1) {
+ seed = buff1;
+ current = buff2;
+ } else {
+ seed = buff2;
+ current = buff1;
+ }
+ seedLen = len;
+ }
+ shiftBit = 0x80;
+ ib = 0;
+ len = 0;
+ currentIndex = 0;
+ }
+ }
+
}
diff --git a/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java
index 014bc47a1..66336955e 100644
--- a/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java
+++ b/src/java/org/apache/fop/render/pcl/PCLImageHandlerGraphics2D.java
@@ -139,7 +139,7 @@ public class PCLImageHandlerGraphics2D implements ImageHandler {
}
gen.paintBitmap(imgRend.getRenderedImage(), new Dimension(pos.width, pos.height),
- pclContext.isSourceTransparencyEnabled());
+ pclContext.isSourceTransparencyEnabled(), pclContext.getPCLUtil());
}
}
diff --git a/src/java/org/apache/fop/render/pcl/PCLImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/pcl/PCLImageHandlerRenderedImage.java
index ebfb1829a..aabb9c5ac 100644
--- a/src/java/org/apache/fop/render/pcl/PCLImageHandlerRenderedImage.java
+++ b/src/java/org/apache/fop/render/pcl/PCLImageHandlerRenderedImage.java
@@ -66,7 +66,7 @@ public class PCLImageHandlerRenderedImage implements ImageHandler {
Point2D transPoint = pclContext.transformedPoint(pos.x, pos.y);
gen.setCursorPos(transPoint.getX(), transPoint.getY());
gen.paintBitmap(ri, new Dimension(pos.width, pos.height),
- pclContext.isSourceTransparencyEnabled());
+ pclContext.isSourceTransparencyEnabled(), pclContext.getPCLUtil());
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/pcl/PCLPainter.java b/src/java/org/apache/fop/render/pcl/PCLPainter.java
index 69465a7fd..65e996d08 100644
--- a/src/java/org/apache/fop/render/pcl/PCLPainter.java
+++ b/src/java/org/apache/fop/render/pcl/PCLPainter.java
@@ -211,7 +211,7 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
}
try {
setCursorPos(rect.x, rect.y);
- gen.fillRect(rect.width, rect.height, fillColor);
+ gen.fillRect(rect.width, rect.height, fillColor, getPCLUtil().isColorEnabled());
} catch (IOException ioe) {
throw new IFException("I/O error in fillRect()", ioe);
}
@@ -410,7 +410,11 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
Color textColor = state.getTextColor();
if (textColor != null) {
gen.setTransparencyMode(true, false);
- gen.selectGrayscale(textColor);
+ if (getDocumentHandler().getPCLUtil().isColorEnabled()) {
+ gen.selectColor(textColor);
+ } else {
+ gen.selectGrayscale(textColor);
+ }
}
gen.setTransparencyMode(true, true);
@@ -492,7 +496,11 @@ public class PCLPainter extends AbstractIFPainter<PCLDocumentHandler> implements
Color textColor = state.getTextColor();
if (textColor != null) {
gen.setTransparencyMode(true, false);
- gen.selectGrayscale(textColor);
+ if (getDocumentHandler().getPCLUtil().isColorEnabled()) {
+ gen.selectColor(textColor);
+ } else {
+ gen.selectGrayscale(textColor);
+ }
}
if (x != -1 && y != -1) {
diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfig.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfig.java
index 29fccc2c8..05e72b00e 100644
--- a/src/java/org/apache/fop/render/pcl/PCLRendererConfig.java
+++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfig.java
@@ -32,6 +32,7 @@ import org.apache.fop.fonts.DefaultFontConfig.DefaultFontConfigParser;
import org.apache.fop.render.RendererConfig;
import static org.apache.fop.render.pcl.Java2DRendererOption.DISABLE_PJL;
+import static org.apache.fop.render.pcl.Java2DRendererOption.MODE_COLOR;
import static org.apache.fop.render.pcl.Java2DRendererOption.RENDERING_MODE;
import static org.apache.fop.render.pcl.Java2DRendererOption.TEXT_RENDERING;
@@ -65,6 +66,10 @@ public final class PCLRendererConfig implements RendererConfig {
return getParam(DISABLE_PJL, Boolean.class);
}
+ public Boolean isColorEnabled() {
+ return getParam(MODE_COLOR, Boolean.class);
+ }
+
private <T> T getParam(Java2DRendererOption option, Class<T> type) {
assert option.getType().equals(type);
return type.cast(params.get(option));
@@ -90,6 +95,12 @@ public final class PCLRendererConfig implements RendererConfig {
private void configure(Configuration cfg, PCLRendererConfig config) throws FOPException {
if (cfg != null) {
+ Configuration imagesCfg = cfg.getChild("images");
+ String imageMode = imagesCfg.getAttribute("mode", null);
+ if ("color".equalsIgnoreCase(imageMode)) {
+ config.setParam(MODE_COLOR, true);
+ }
+
String rendering = cfg.getChild(RENDERING_MODE.getName()).getValue(null);
if (rendering != null) {
try {
diff --git a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
index 33376655f..7a92b7408 100644
--- a/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
@@ -67,7 +67,9 @@ public class PCLRendererConfigurator extends PrintRendererConfigurator {
if (config.isTextRendering() != null) {
pclUtil.setAllTextAsBitmaps(config.isTextRendering());
}
-
+ if (config.isColorEnabled() != null) {
+ pclUtil.setColorEnabled(config.isColorEnabled());
+ }
}
@Override
diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java b/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
index 32693764f..674605bde 100644
--- a/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
+++ b/src/java/org/apache/fop/render/pcl/PCLRenderingUtil.java
@@ -50,12 +50,7 @@ public class PCLRenderingUtil {
/** Controls the dithering quality when rendering gray or color images. */
private float ditheringQuality = 0.5f;
- /**
- * Controls whether an RGB canvas is used when converting Java2D graphics to bitmaps.
- * This can be used to work around problems with Apache Batik, for example, but setting
- * this to true will increase memory consumption.
- */
- private boolean useColorCanvas;
+ private boolean useColor;
/**
* Controls whether the generation of PJL commands gets disabled.
@@ -142,12 +137,12 @@ public class PCLRenderingUtil {
return this.allTextAsBitmaps;
}
- /**
- * Indicates whether a color canvas is used when creating bitmap images.
- * @return true if a color canvas is used.
- */
- public boolean isColorCanvasEnabled() {
- return this.useColorCanvas;
+ public void setColorEnabled(boolean useColor) {
+ this.useColor = useColor;
+ }
+
+ public boolean isColorEnabled() {
+ return useColor;
}
/**
diff --git a/src/java/org/apache/fop/render/ps/Gradient.java b/src/java/org/apache/fop/render/ps/Gradient.java
new file mode 100644
index 000000000..558f3b952
--- /dev/null
+++ b/src/java/org/apache/fop/render/ps/Gradient.java
@@ -0,0 +1,85 @@
+/*
+ * 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.ps;
+
+import java.util.List;
+
+import org.apache.fop.render.gradient.Function;
+import org.apache.fop.render.gradient.Function.SubFunctionRenderer;
+import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
+import org.apache.fop.render.gradient.Pattern;
+import org.apache.fop.render.gradient.Shading;
+
+/**
+ * Helper class to draw gradients in PostScript.
+ */
+public final class Gradient {
+
+ private Gradient() { }
+
+ public static String outputPattern(Pattern pattern, DoubleFormatter doubleFormatter) {
+ StringBuilder p = new StringBuilder(64);
+ p.append("/Pattern setcolorspace\n");
+ p.append("<< \n/Type /Pattern \n");
+
+ p.append("/PatternType " + pattern.getPatternType() + " \n");
+
+ if (pattern.getShading() != null) {
+ p.append("/Shading ");
+ outputShading(p, pattern.getShading(), doubleFormatter);
+ p.append(" \n");
+ }
+ p.append(">> \n");
+ List<Double> matrix = pattern.getMatrix();
+ if (matrix == null) {
+ p.append("matrix ");
+ } else {
+ p.append("[ ");
+ for (double m : pattern.getMatrix()) {
+ p.append(doubleFormatter.formatDouble(m));
+ p.append(" ");
+ }
+ p.append("] ");
+ }
+ p.append("makepattern setcolor\n");
+
+ return p.toString();
+ }
+
+ private static void outputShading(StringBuilder out, Shading shading, final DoubleFormatter doubleFormatter) {
+ final Function function = shading.getFunction();
+ Shading.FunctionRenderer functionRenderer = new Shading.FunctionRenderer() {
+
+ public void outputFunction(StringBuilder out) {
+ SubFunctionRenderer subFunctionRenderer = new Function.SubFunctionRenderer() {
+
+ public void outputFunction(StringBuilder out, int functionIndex) {
+ Function subFunction = function.getFunctions().get(functionIndex);
+ assert subFunction.getFunctions().isEmpty();
+ subFunction.output(out, doubleFormatter, null);
+ }
+ };
+ function.output(out, doubleFormatter, subFunctionRenderer);
+ }
+ };
+ shading.output(out, doubleFormatter, functionRenderer);
+ }
+
+}