AFP Renderer does not respect image color settings for svg Submitted by: Peter Hancock <peter.hancock.at.gmail.com> git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@897221 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D(); | AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D(); | ||||
g2d.setGraphicsObject(graphicsObj); | g2d.setGraphicsObject(graphicsObj); | ||||
//set color converter (i.e. an rgb to grayscale converter) | |||||
graphicsObj.setColorConverter(g2d.getPaintingState().getColorConverter()); | |||||
// paint to graphics object | // paint to graphics object | ||||
Graphics2DImagePainter painter = graphicsObjectInfo.getPainter(); | Graphics2DImagePainter painter = graphicsObjectInfo.getPainter(); | ||||
Rectangle2D area = graphicsObjectInfo.getArea(); | Rectangle2D area = graphicsObjectInfo.getArea(); |
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.xmlgraphics.java2d.ColorConverter; | |||||
import org.apache.xmlgraphics.java2d.DefaultColorConverter; | |||||
import org.apache.xmlgraphics.java2d.GrayScaleColorConverter; | |||||
import org.apache.fop.afp.fonts.AFPPageFonts; | import org.apache.fop.afp.fonts.AFPPageFonts; | ||||
import org.apache.fop.util.AbstractPaintingState; | import org.apache.fop.util.AbstractPaintingState; | ||||
/** | /** | ||||
* This keeps information about the current painting state when writing to an AFP datastream. | |||||
* This keeps information about the current painting state when writing to an | |||||
* AFP datastream. | |||||
*/ | */ | ||||
public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState | |||||
implements Cloneable { | |||||
public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState implements | |||||
Cloneable { | |||||
private static final long serialVersionUID = 8206711712452344473L; | private static final long serialVersionUID = 8206711712452344473L; | ||||
/** color image support */ | /** color image support */ | ||||
private boolean colorImages = false; | private boolean colorImages = false; | ||||
/** true if certain image formats may be embedded unchanged in their native format. */ | |||||
/** color image handler */ | |||||
private ColorConverter colorConverter = GrayScaleColorConverter.getInstance(); | |||||
/** | |||||
* true if certain image formats may be embedded unchanged in their native | |||||
* format. | |||||
*/ | |||||
private boolean nativeImagesSupported = false; | private boolean nativeImagesSupported = false; | ||||
/** true if CMYK images (requires IOCA FS45 suppport on the target platform) may be generated */ | |||||
/** | |||||
* true if CMYK images (requires IOCA FS45 suppport on the target platform) | |||||
* may be generated | |||||
*/ | |||||
private boolean cmykImagesSupported; | private boolean cmykImagesSupported; | ||||
/** default value for image depth */ | /** default value for image depth */ | ||||
/** the current page */ | /** the current page */ | ||||
private transient AFPPagePaintingState pagePaintingState = new AFPPagePaintingState(); | private transient AFPPagePaintingState pagePaintingState = new AFPPagePaintingState(); | ||||
// /** reference orientation */ | |||||
// private int orientation = 0; | |||||
// /** reference orientation */ | |||||
// private int orientation = 0; | |||||
/** a unit converter */ | /** a unit converter */ | ||||
private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this); | private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this); | ||||
/** | /** | ||||
* Sets the rotation to be used for portrait pages, valid values are 0 | * Sets the rotation to be used for portrait pages, valid values are 0 | ||||
* (default), 90, 180, 270. | * (default), 90, 180, 270. | ||||
* The rotation in degrees. | * The rotation in degrees. | ||||
*/ | */ | ||||
public void setPortraitRotation(int rotation) { | public void setPortraitRotation(int rotation) { | ||||
if (rotation == 0 || rotation == 90 || rotation == 180 | |||||
|| rotation == 270) { | |||||
if (rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270) { | |||||
portraitRotation = rotation; | portraitRotation = rotation; | ||||
} else { | } else { | ||||
throw new IllegalArgumentException( | |||||
"The portrait rotation must be one" | |||||
+ " of the values 0, 90, 180, 270"); | |||||
throw new IllegalArgumentException("The portrait rotation must be one" | |||||
+ " of the values 0, 90, 180, 270"); | |||||
} | } | ||||
} | } | ||||
* The rotation in degrees. | * The rotation in degrees. | ||||
*/ | */ | ||||
public void setLandscapeRotation(int rotation) { | public void setLandscapeRotation(int rotation) { | ||||
if (rotation == 0 || rotation == 90 || rotation == 180 | |||||
|| rotation == 270) { | |||||
if (rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270) { | |||||
landscapeRotation = rotation; | landscapeRotation = rotation; | ||||
} else { | } else { | ||||
throw new IllegalArgumentException( | |||||
"The landscape rotation must be one" | |||||
+ " of the values 0, 90, 180, 270"); | |||||
throw new IllegalArgumentException("The landscape rotation must be one" | |||||
+ " of the values 0, 90, 180, 270"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Sets whether images are color or not | |||||
* Sets whether images are color or not and instantiates a ColorHandler | |||||
* | * | ||||
* @param colorImages | * @param colorImages | ||||
* color image output | * color image output | ||||
*/ | */ | ||||
public void setColorImages(boolean colorImages) { | public void setColorImages(boolean colorImages) { | ||||
this.colorImages = colorImages; | this.colorImages = colorImages; | ||||
if (colorImages) { | |||||
this.colorConverter = DefaultColorConverter.getInstance(); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
return this.colorImages; | return this.colorImages; | ||||
} | } | ||||
/** | |||||
* Used to convert color in respect of the colorImages flag | |||||
* | |||||
* @return the color converter | |||||
*/ | |||||
public ColorConverter getColorConverter() { | |||||
return this.colorConverter; | |||||
} | |||||
/** | /** | ||||
* Sets whether images are natively supported or not in the AFP environment | * Sets whether images are natively supported or not in the AFP environment | ||||
* | * | ||||
* @param nativeImagesSupported true if images are natively supported in this AFP environment | |||||
* @param nativeImagesSupported | |||||
* true if images are natively supported in this AFP environment | |||||
*/ | */ | ||||
public void setNativeImagesSupported(boolean nativeImagesSupported) { | public void setNativeImagesSupported(boolean nativeImagesSupported) { | ||||
this.nativeImagesSupported = nativeImagesSupported; | this.nativeImagesSupported = nativeImagesSupported; | ||||
} | } | ||||
/** | /** | ||||
* Controls whether CMYK images (IOCA FS45) are enabled. By default, support is disabled | |||||
* for wider compatibility. When disabled, any CMYK image is converted to the selected | |||||
* color format. | |||||
* @param value true to enabled CMYK images | |||||
* Controls whether CMYK images (IOCA FS45) are enabled. By default, support | |||||
* is disabled for wider compatibility. When disabled, any CMYK image is | |||||
* converted to the selected color format. | |||||
* | |||||
* @param value | |||||
* true to enabled CMYK images | |||||
*/ | */ | ||||
public void setCMYKImagesSupported(boolean value) { | public void setCMYKImagesSupported(boolean value) { | ||||
this.cmykImagesSupported = value; | this.cmykImagesSupported = value; | ||||
/** | /** | ||||
* Indicates whether CMYK images (IOCA FS45) are enabled. | * Indicates whether CMYK images (IOCA FS45) are enabled. | ||||
* | |||||
* @return true if IOCA FS45 is enabled | * @return true if IOCA FS45 is enabled | ||||
*/ | */ | ||||
public boolean isCMYKImagesSupported() { | public boolean isCMYKImagesSupported() { | ||||
/** | /** | ||||
* Sets the page width | * Sets the page width | ||||
* | * | ||||
* @param pageWidth the page width | |||||
* @param pageWidth | |||||
* the page width | |||||
*/ | */ | ||||
public void setPageWidth(int pageWidth) { | public void setPageWidth(int pageWidth) { | ||||
pagePaintingState.setWidth(pageWidth); | pagePaintingState.setWidth(pageWidth); | ||||
/** | /** | ||||
* Sets the page height | * Sets the page height | ||||
* | * | ||||
* @param pageHeight the page height | |||||
* @param pageHeight | |||||
* the page height | |||||
*/ | */ | ||||
public void setPageHeight(int pageHeight) { | public void setPageHeight(int pageHeight) { | ||||
pagePaintingState.setHeight(pageHeight); | pagePaintingState.setHeight(pageHeight); | ||||
/** | /** | ||||
* Sets the uri of the current image | * Sets the uri of the current image | ||||
* | * | ||||
* @param uri the uri of the current image | |||||
* @param uri | |||||
* the uri of the current image | |||||
*/ | */ | ||||
public void setImageUri(String uri) { | public void setImageUri(String uri) { | ||||
((AFPData)getData()).imageUri = uri; | |||||
((AFPData) getData()).imageUri = uri; | |||||
} | } | ||||
/** | /** | ||||
* @return the uri of the current image | * @return the uri of the current image | ||||
*/ | */ | ||||
public String getImageUri() { | public String getImageUri() { | ||||
return ((AFPData)getData()).imageUri; | |||||
return ((AFPData) getData()).imageUri; | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
/** | /** | ||||
* Returns a point on the current page, taking the current painting state into account. | |||||
* Returns a point on the current page, taking the current painting state | |||||
* into account. | |||||
* | * | ||||
* @param x the X-coordinate | |||||
* @param y the Y-coordinate | |||||
* @param x | |||||
* the X-coordinate | |||||
* @param y | |||||
* the Y-coordinate | |||||
* @return a point on the current page | * @return a point on the current page | ||||
*/ | */ | ||||
public Point getPoint(int x, int y) { | public Point getPoint(int x, int y) { | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public Object clone() { | public Object clone() { | ||||
AFPPaintingState paintingState = (AFPPaintingState)super.clone(); | |||||
paintingState.pagePaintingState = (AFPPagePaintingState)this.pagePaintingState.clone(); | |||||
AFPPaintingState paintingState = (AFPPaintingState) super.clone(); | |||||
paintingState.pagePaintingState = (AFPPagePaintingState) this.pagePaintingState.clone(); | |||||
paintingState.portraitRotation = this.portraitRotation; | paintingState.portraitRotation = this.portraitRotation; | ||||
paintingState.landscapeRotation = this.landscapeRotation; | paintingState.landscapeRotation = this.landscapeRotation; | ||||
paintingState.bitsPerPixel = this.bitsPerPixel; | paintingState.bitsPerPixel = this.bitsPerPixel; | ||||
paintingState.colorImages = this.colorImages; | paintingState.colorImages = this.colorImages; | ||||
paintingState.colorConverter = this.colorConverter; | |||||
paintingState.resolution = this.resolution; | paintingState.resolution = this.resolution; | ||||
return paintingState; | return paintingState; | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
return "AFPPaintingState{" + "portraitRotation=" + portraitRotation | return "AFPPaintingState{" + "portraitRotation=" + portraitRotation | ||||
+ ", landscapeRotation=" + landscapeRotation | |||||
+ ", colorImages=" + colorImages | |||||
+ ", bitsPerPixel=" + bitsPerPixel | |||||
+ ", resolution=" + resolution | |||||
+ ", pageState=" + pagePaintingState | |||||
+ super.toString() | |||||
+ "}"; | |||||
+ ", landscapeRotation=" + landscapeRotation + ", colorImages=" + colorImages | |||||
+ ", bitsPerPixel=" + bitsPerPixel + ", resolution=" + resolution + ", pageState=" | |||||
+ pagePaintingState + super.toString() + "}"; | |||||
} | } | ||||
/** | /** | ||||
/** | /** | ||||
* Sets the page width | * Sets the page width | ||||
* | * | ||||
* @param width the page width | |||||
* @param width | |||||
* the page width | |||||
*/ | */ | ||||
protected void setWidth(int width) { | protected void setWidth(int width) { | ||||
this.width = width; | this.width = width; | ||||
/** | /** | ||||
* Sets the page height | * Sets the page height | ||||
* | * | ||||
* @param height the page height | |||||
* @param height | |||||
* the page height | |||||
*/ | */ | ||||
protected void setHeight(int height) { | protected void setHeight(int height) { | ||||
this.height = height; | this.height = height; | ||||
/** | /** | ||||
* Sets the current page fonts | * Sets the current page fonts | ||||
* | * | ||||
* @param fonts the current page fonts | |||||
* @param fonts | |||||
* the current page fonts | |||||
*/ | */ | ||||
protected void setFonts(AFPPageFonts fonts) { | protected void setFonts(AFPPageFonts fonts) { | ||||
this.fonts = fonts; | this.fonts = fonts; | ||||
/** | /** | ||||
* Sets the current page orientation | * Sets the current page orientation | ||||
* | * | ||||
* @param orientation the current page orientation | |||||
* @param orientation | |||||
* the current page orientation | |||||
*/ | */ | ||||
protected void setOrientation(int orientation) { | protected void setOrientation(int orientation) { | ||||
this.orientation = orientation; | this.orientation = orientation; | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
return "AFPPagePaintingState{width=" + width | |||||
+ ", height=" + height | |||||
+ ", orientation=" + orientation | |||||
+ ", fonts=" + fonts | |||||
+ ", fontCount=" + fontCount | |||||
+ "}"; | |||||
return "AFPPagePaintingState{width=" + width + ", height=" + height + ", orientation=" | |||||
+ orientation + ", fonts=" + fonts + ", fontCount=" + fontCount + "}"; | |||||
} | } | ||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public Object clone() { | public Object clone() { | ||||
AFPData obj = (AFPData)super.clone(); | |||||
AFPData obj = (AFPData) super.clone(); | |||||
obj.filled = this.filled; | obj.filled = this.filled; | ||||
obj.imageUri = this.imageUri; | obj.imageUri = this.imageUri; | ||||
return obj; | return obj; | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
public String toString() { | public String toString() { | ||||
return "AFPData{" + super.toString() | |||||
+ ", filled=" + filled | |||||
+ ", imageUri=" + imageUri | |||||
+ "}"; | |||||
return "AFPData{" + super.toString() + ", filled=" + filled + ", imageUri=" + imageUri | |||||
+ "}"; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ |
*/ | */ | ||||
public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { | public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { | ||||
/* | |||||
* GOCA Color space support: | |||||
* X'01' RGB | |||||
* X'04' CMYK | |||||
* X'06' Highlight color space | |||||
* X'08' CIELAB | |||||
* X'40' Standard OCA color space | |||||
*/ | |||||
private static final byte RGB = 0x01, CMYK = 0x04; | |||||
private final Color color; | private final Color color; | ||||
private final float[] colorComponents; | private final float[] colorComponents; | ||||
/** | /** | ||||
* Main constructor | * Main constructor | ||||
* | * | ||||
* @param color the color to set | |||||
* @param color | |||||
* the color to set | |||||
*/ | */ | ||||
public GraphicsSetProcessColor(Color color) { | public GraphicsSetProcessColor(Color color) { | ||||
this.color = color; | this.color = color; | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
byte getOrderCode() { | byte getOrderCode() { | ||||
return (byte)0xB2; | |||||
return (byte) 0xB2; | |||||
} | } | ||||
/** {@inheritDoc} */ | /** {@inheritDoc} */ | ||||
byte colspace; | byte colspace; | ||||
int colSpaceType = color.getColorSpace().getType(); | int colSpaceType = color.getColorSpace().getType(); | ||||
if (colSpaceType == ColorSpace.TYPE_CMYK) { | if (colSpaceType == ColorSpace.TYPE_CMYK) { | ||||
colspace = 0x04; | |||||
colspace = CMYK; | |||||
} else if (colSpaceType == ColorSpace.TYPE_RGB) { | } else if (colSpaceType == ColorSpace.TYPE_RGB) { | ||||
colspace = 0x01; | |||||
colspace = RGB; | |||||
} else { | } else { | ||||
log.error("unsupported colorspace " + colSpaceType); | log.error("unsupported colorspace " + colSpaceType); | ||||
colspace = 0x01; | |||||
colspace = RGB; | |||||
} | } | ||||
// COLSIZE(S) | // COLSIZE(S) | ||||
byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; | byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; | ||||
for (int i = 0; i < colorComponents.length; i++) { | for (int i = 0; i < colorComponents.length; i++) { | ||||
colsizes[i] = (byte)8; | |||||
colsizes[i] = (byte) 8; | |||||
} | } | ||||
int len = getDataLength(); | int len = getDataLength(); | ||||
byte[] data = new byte[len]; | byte[] data = new byte[len]; | ||||
data[0] = getOrderCode(); // GSPCOL order code | data[0] = getOrderCode(); // GSPCOL order code | ||||
data[1] = (byte)(len - 2); // LEN | |||||
data[1] = (byte) (len - 2); // LEN | |||||
data[2] = 0x00; // reserved; must be zero | data[2] = 0x00; // reserved; must be zero | ||||
data[3] = colspace; // COLSPCE | data[3] = colspace; // COLSPCE | ||||
data[4] = 0x00; // reserved; must be zero | data[4] = 0x00; // reserved; must be zero | ||||
// COLVALUE(S) | // COLVALUE(S) | ||||
for (int i = 0; i < colorComponents.length; i++) { | for (int i = 0; i < colorComponents.length; i++) { | ||||
data[i + 12] = (byte)(colorComponents[i] * 255); | |||||
data[i + 12] = (byte) (colorComponents[i] * 255); | |||||
} | } | ||||
os.write(data); | os.write(data); |
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.List; | import java.util.List; | ||||
import org.apache.xmlgraphics.java2d.ColorConverter; | |||||
import org.apache.fop.afp.AFPDataObjectInfo; | import org.apache.fop.afp.AFPDataObjectInfo; | ||||
import org.apache.fop.afp.AFPObjectAreaInfo; | import org.apache.fop.afp.AFPObjectAreaInfo; | ||||
import org.apache.fop.afp.Completable; | import org.apache.fop.afp.Completable; | ||||
/** the graphics state */ | /** the graphics state */ | ||||
private final GraphicsState graphicsState = new GraphicsState(); | private final GraphicsState graphicsState = new GraphicsState(); | ||||
/** color converter */ | |||||
private ColorConverter colorConverter = null; | |||||
/** | /** | ||||
* Default constructor | * Default constructor | ||||
* | * | ||||
*/ | */ | ||||
public void setColor(Color color) { | public void setColor(Color color) { | ||||
if (!color.equals(graphicsState.color)) { | if (!color.equals(graphicsState.color)) { | ||||
addObject(new GraphicsSetProcessColor(color)); | |||||
addObject(new GraphicsSetProcessColor(colorConverter.convert(color))); | |||||
graphicsState.color = color; | graphicsState.color = color; | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Sets the color converter | |||||
* | |||||
* @param colorConverter ColorConverter to filter the color | |||||
* when creating a GraphicsSetProcessColor. | |||||
*/ | |||||
public void setColorConverter(ColorConverter colorConverter) { | |||||
this.colorConverter = colorConverter; | |||||
} | |||||
/** | /** | ||||
* Sets the current position | * Sets the current position | ||||
* | * |
import java.awt.color.ColorSpace; | import java.awt.color.ColorSpace; | ||||
import java.awt.color.ICC_ColorSpace; | import java.awt.color.ICC_ColorSpace; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.List; | |||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.List; | |||||
import org.apache.fop.util.CMYKColorSpace; | |||||
import org.apache.fop.util.ColorExt; | |||||
import org.apache.xmlgraphics.java2d.CMYKColorSpace; | |||||
import org.apache.xmlgraphics.java2d.ColorExt; | |||||
/** | /** | ||||
* PDF Color object. | * PDF Color object. |
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; | import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; | ||||
import org.apache.xmlgraphics.image.loader.impl.ImageRendered; | import org.apache.xmlgraphics.image.loader.impl.ImageRendered; | ||||
import org.apache.xmlgraphics.java2d.AbstractGraphics2D; | import org.apache.xmlgraphics.java2d.AbstractGraphics2D; | ||||
import org.apache.xmlgraphics.java2d.ColorExt; | |||||
import org.apache.xmlgraphics.java2d.GraphicContext; | import org.apache.xmlgraphics.java2d.GraphicContext; | ||||
import org.apache.fop.fonts.Font; | import org.apache.fop.fonts.Font; | ||||
import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter; | import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter; | ||||
import org.apache.fop.render.pdf.ImageRawJPEGAdapter; | import org.apache.fop.render.pdf.ImageRawJPEGAdapter; | ||||
import org.apache.fop.render.pdf.ImageRenderedAdapter; | import org.apache.fop.render.pdf.ImageRenderedAdapter; | ||||
import org.apache.fop.util.ColorExt; | |||||
/** | /** | ||||
* PDF Graphics 2D. | * PDF Graphics 2D. |
/* | |||||
* 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.util; | |||||
import java.awt.color.ColorSpace; | |||||
/** | |||||
* This class represents an uncalibrated CMYK color space. It is used by | |||||
* the JpegImage class. | |||||
*/ | |||||
public class CMYKColorSpace extends ColorSpace { | |||||
private static CMYKColorSpace instance; | |||||
/** | |||||
* @see java.awt.color.ColorSpace#ColorSpace(int, int) | |||||
*/ | |||||
protected CMYKColorSpace(int type, int numcomponents) { | |||||
super(type, numcomponents); | |||||
} | |||||
/** | |||||
* Returns an instance of an uncalibrated CMYK color space. | |||||
* @return CMYKColorSpace the requested color space object | |||||
*/ | |||||
public static CMYKColorSpace getInstance() { | |||||
if (instance == null) { | |||||
instance = new CMYKColorSpace(TYPE_CMYK, 4); | |||||
} | |||||
return instance; | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public float[] toRGB(float[] colorvalue) { | |||||
return new float [] { | |||||
(1 - colorvalue[0]) * (1 - colorvalue[3]), | |||||
(1 - colorvalue[1]) * (1 - colorvalue[3]), | |||||
(1 - colorvalue[2]) * (1 - colorvalue[3])}; | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public float[] fromRGB(float[] rgbvalue) { | |||||
throw new UnsupportedOperationException("NYI"); | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public float[] toCIEXYZ(float[] colorvalue) { | |||||
throw new UnsupportedOperationException("NYI"); | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public float[] fromCIEXYZ(float[] colorvalue) { | |||||
throw new UnsupportedOperationException("NYI"); | |||||
} | |||||
} |
/* | |||||
* 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.util; | |||||
import java.awt.Color; | |||||
import java.awt.color.ColorSpace; | |||||
import java.util.Arrays; | |||||
/** | |||||
* Color helper class. | |||||
* <p> | |||||
* This class extends java.awt.Color class keeping track of the original color | |||||
* property values specified by the fo user in a rgb-icc call. | |||||
*/ | |||||
public final class ColorExt extends Color { | |||||
// | |||||
private static final long serialVersionUID = 1L; | |||||
// Values of fop-rgb-icc arguments | |||||
private float rgbReplacementRed; | |||||
private float rgbReplacementGreen; | |||||
private float rgbReplacementBlue; | |||||
private String iccProfileName; | |||||
private String iccProfileSrc; | |||||
private ColorSpace colorSpace; | |||||
private float[] colorValues; | |||||
/* | |||||
* Helper for createFromFoRgbIcc | |||||
*/ | |||||
private ColorExt(ColorSpace colorSpace, float[] colorValues, float opacity) { | |||||
super(colorSpace, colorValues, opacity); | |||||
} | |||||
/* | |||||
* Helper for createFromSvgIccColor | |||||
*/ | |||||
private ColorExt(float red, float green, float blue, float opacity) { | |||||
super(red, green, blue, opacity); | |||||
} | |||||
/** | |||||
* Create ColorExt object backup up FO's rgb-icc color function | |||||
* | |||||
* @param redReplacement | |||||
* Red part of RGB replacement color that will be used when ICC | |||||
* profile can not be loaded | |||||
* @param greenReplacement | |||||
* Green part of RGB replacement color that will be used when ICC | |||||
* profile can not be loaded | |||||
* @param blueReplacement | |||||
* Blue part of RGB replacement color that will be used when ICC | |||||
* profile can not be loaded | |||||
* @param profileName | |||||
* Name of ICC profile | |||||
* @param profileSrc | |||||
* Source of ICC profile | |||||
* @param colorSpace | |||||
* ICC ColorSpace for the ICC profile | |||||
* @param iccValues | |||||
* color values | |||||
* @return the requested color object | |||||
*/ | |||||
public static ColorExt createFromFoRgbIcc(float redReplacement, | |||||
float greenReplacement, float blueReplacement, String profileName, | |||||
String profileSrc, ColorSpace colorSpace, float[] iccValues) { | |||||
ColorExt ce = new ColorExt(colorSpace, iccValues, 1.0f); | |||||
ce.rgbReplacementRed = redReplacement; | |||||
ce.rgbReplacementGreen = greenReplacement; | |||||
ce.rgbReplacementBlue = blueReplacement; | |||||
ce.iccProfileName = profileName; | |||||
ce.iccProfileSrc = profileSrc; | |||||
ce.colorSpace = colorSpace; | |||||
ce.colorValues = iccValues; | |||||
return ce; | |||||
} | |||||
/** | |||||
* Create ColorExt object backing up SVG's icc-color function. | |||||
* | |||||
* @param red | |||||
* Red value resulting from the conversion from the user provided | |||||
* (icc) color values to the batik (rgb) color space | |||||
* @param green | |||||
* Green value resulting from the conversion from the user | |||||
* provided (icc) color values to the batik (rgb) color space | |||||
* @param blue | |||||
* Blue value resulting from the conversion from the user | |||||
* provided (icc) color values to the batik (rgb) color space | |||||
* @param opacity | |||||
* Opacity | |||||
* @param profileName | |||||
* ICC profile name | |||||
* @param profileHref | |||||
* the URI to the color profile | |||||
* @param profileCS | |||||
* ICC ColorSpace profile | |||||
* @param colorValues | |||||
* ICC color values | |||||
* @return the requested color object | |||||
*/ | |||||
public static ColorExt createFromSvgIccColor(float red, float green, | |||||
float blue, float opacity, String profileName, String profileHref, | |||||
ColorSpace profileCS, float[] colorValues) { | |||||
//TODO this method is not referenced by FOP, can it be deleted? | |||||
ColorExt ce = new ColorExt(red, green, blue, opacity); | |||||
ce.rgbReplacementRed = -1; | |||||
ce.rgbReplacementGreen = -1; | |||||
ce.rgbReplacementBlue = -1; | |||||
ce.iccProfileName = profileName; | |||||
ce.iccProfileSrc = profileHref; | |||||
ce.colorSpace = profileCS; | |||||
ce.colorValues = colorValues; | |||||
return ce; | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public int hashCode() { | |||||
//implementation from the superclass should be good enough for our purposes | |||||
return super.hashCode(); | |||||
} | |||||
/** {@inheritDoc} */ | |||||
public boolean equals(Object obj) { | |||||
if (this == obj) { | |||||
return true; | |||||
} | |||||
if (!super.equals(obj)) { | |||||
return false; | |||||
} | |||||
if (getClass() != obj.getClass()) { | |||||
return false; | |||||
} | |||||
ColorExt other = (ColorExt)obj; | |||||
//TODO maybe use super.getColorComponents() instead | |||||
if (!Arrays.equals(colorValues, other.colorValues)) { | |||||
return false; | |||||
} | |||||
if (iccProfileName == null) { | |||||
if (other.iccProfileName != null) { | |||||
return false; | |||||
} | |||||
} else if (!iccProfileName.equals(other.iccProfileName)) { | |||||
return false; | |||||
} | |||||
if (iccProfileSrc == null) { | |||||
if (other.iccProfileSrc != null) { | |||||
return false; | |||||
} | |||||
} else if (!iccProfileSrc.equals(other.iccProfileSrc)) { | |||||
return false; | |||||
} | |||||
if (Float.floatToIntBits(rgbReplacementBlue) | |||||
!= Float.floatToIntBits(other.rgbReplacementBlue)) { | |||||
return false; | |||||
} | |||||
if (Float.floatToIntBits(rgbReplacementGreen) | |||||
!= Float.floatToIntBits(other.rgbReplacementGreen)) { | |||||
return false; | |||||
} | |||||
if (Float.floatToIntBits(rgbReplacementRed) | |||||
!= Float.floatToIntBits(other.rgbReplacementRed)) { | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
/** | |||||
* Get ICC profile name | |||||
* | |||||
* @return ICC profile name | |||||
*/ | |||||
public String getIccProfileName() { | |||||
return this.iccProfileName; | |||||
} | |||||
/** | |||||
* Get ICC profile source | |||||
* | |||||
* @return ICC profile source | |||||
*/ | |||||
public String getIccProfileSrc() { | |||||
return this.iccProfileSrc; | |||||
} | |||||
/** | |||||
* @return the original ColorSpace | |||||
*/ | |||||
public ColorSpace getOrigColorSpace() { | |||||
//TODO this method is probably unnecessary due to super.cs and getColorSpace() | |||||
return this.colorSpace; | |||||
} | |||||
/** | |||||
* Returns the original color values. | |||||
* @return the original color values | |||||
*/ | |||||
public float[] getOriginalColorComponents() { | |||||
//TODO this method is probably unnecessary due to super.fvalue and getColorComponents() | |||||
float[] copy = new float[this.colorValues.length]; | |||||
System.arraycopy(this.colorValues, 0, copy, 0, copy.length); | |||||
return copy; | |||||
} | |||||
/** | |||||
* Create string representation of fop-rgb-icc function call to map this | |||||
* ColorExt settings | |||||
* @return the string representing the internal fop-rgb-icc() function call | |||||
*/ | |||||
public String toFunctionCall() { | |||||
StringBuffer sb = new StringBuffer(40); | |||||
sb.append("fop-rgb-icc("); | |||||
sb.append(this.rgbReplacementRed + ","); | |||||
sb.append(this.rgbReplacementGreen + ","); | |||||
sb.append(this.rgbReplacementBlue + ","); | |||||
sb.append(this.iccProfileName + ","); | |||||
if (this.iccProfileSrc != null) { | |||||
sb.append("\"" + this.iccProfileSrc + "\""); | |||||
} | |||||
float[] colorComponents = this.getColorComponents(null); | |||||
for (int ix = 0; ix < colorComponents.length; ix++) { | |||||
sb.append(","); | |||||
sb.append(colorComponents[ix]); | |||||
} | |||||
sb.append(")"); | |||||
return sb.toString(); | |||||
} | |||||
} |
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||||
import org.apache.xmlgraphics.java2d.CMYKColorSpace; | |||||
import org.apache.xmlgraphics.java2d.ColorExt; | |||||
import org.apache.fop.apps.FOUserAgent; | import org.apache.fop.apps.FOUserAgent; | ||||
import org.apache.fop.fo.expr.PropertyException; | import org.apache.fop.fo.expr.PropertyException; | ||||
* @return the modified color | * @return the modified color | ||||
*/ | */ | ||||
public static Color lightenColor(Color col, float factor) { | public static Color lightenColor(Color col, float factor) { | ||||
// TODO: This function converts the color into the sRGB namespace. | |||||
// This should be avoided if possible. | |||||
float[] cols = new float[4]; | |||||
cols = col.getRGBComponents(cols); | |||||
if (factor > 0) { | |||||
cols[0] += (1.0 - cols[0]) * factor; | |||||
cols[1] += (1.0 - cols[1]) * factor; | |||||
cols[2] += (1.0 - cols[2]) * factor; | |||||
} else { | |||||
cols[0] -= cols[0] * -factor; | |||||
cols[1] -= cols[1] * -factor; | |||||
cols[2] -= cols[2] * -factor; | |||||
} | |||||
return new Color(cols[0], cols[1], cols[2], cols[3]); | |||||
return org.apache.xmlgraphics.java2d.ColorUtil.lightenColor(col, factor); | |||||
} | } | ||||
/** | /** | ||||
* @return true if it is a gray value | * @return true if it is a gray value | ||||
*/ | */ | ||||
public static boolean isGray(Color col) { | public static boolean isGray(Color col) { | ||||
return (col.getRed() == col.getBlue() && col.getRed() == col.getGreen()); | |||||
return org.apache.xmlgraphics.java2d.ColorUtil.isGray(col); | |||||
} | } | ||||
/** | /** | ||||
* @return the CMYK color | * @return the CMYK color | ||||
*/ | */ | ||||
public static Color toCMYKGrayColor(float black) { | public static Color toCMYKGrayColor(float black) { | ||||
float[] cmyk = new float[] {0f, 0f, 0f, 1.0f - black}; | |||||
CMYKColorSpace cmykCs = CMYKColorSpace.getInstance(); | |||||
float[] rgb = cmykCs.toRGB(cmyk); | |||||
return ColorExt.createFromFoRgbIcc(rgb[0], rgb[1], rgb[2], | |||||
CMYK_PSEUDO_PROFILE, null, cmykCs, cmyk); | |||||
return org.apache.xmlgraphics.java2d.ColorUtil.toCMYKGrayColor(black); | |||||
} | } | ||||
} | } |
documents. Example: the fix of marks layering will be such a case when it's done. | documents. Example: the fix of marks layering will be such a case when it's done. | ||||
--> | --> | ||||
<release version="FOP Trunk" date="TBD"> | <release version="FOP Trunk" date="TBD"> | ||||
<action context="Renderers" dev="CB" type="fix" fixes-bug="48376" due-to="Venkat Reddy"> | |||||
<action context="Renderers" dev="CB" type="fix" fixes-bug="48237" due-to="Peter Hancock"> | |||||
Bugfix: AFP Renderer: Respect image color settings for svg | |||||
</action> | |||||
<action context="Renderers" dev="CB" type="fix" fixes-bug="48376" due-to="Venkat Reddy"> | |||||
Bugfix: AFP Renderer: Page Overlays not generated when using Intermediate Format | Bugfix: AFP Renderer: Page Overlays not generated when using Intermediate Format | ||||
</action> | </action> | ||||
<action context="Renderers" dev="CB" type="fix" fixes-bug="48456"> | <action context="Renderers" dev="CB" type="fix" fixes-bug="48456"> |
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.xmlgraphics.java2d.CMYKColorSpace; | |||||
import org.apache.xmlgraphics.java2d.ColorExt; | |||||
import org.apache.fop.fo.Constants; | import org.apache.fop.fo.Constants; | ||||
import org.apache.fop.util.CMYKColorSpace; | |||||
import org.apache.fop.util.ColorExt; | |||||
import org.apache.fop.util.ColorUtil; | import org.apache.fop.util.ColorUtil; | ||||
/** | /** |
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.xmlgraphics.java2d.CMYKColorSpace; | |||||
import org.apache.xmlgraphics.java2d.ColorExt; | |||||
import org.apache.fop.apps.FOUserAgent; | import org.apache.fop.apps.FOUserAgent; | ||||
import org.apache.fop.apps.FopFactory; | import org.apache.fop.apps.FopFactory; | ||||