diff options
author | Jeremias Maerki <jeremias@apache.org> | 2008-02-18 15:02:39 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2008-02-18 15:02:39 +0000 |
commit | 76ebc1fa40782c2e6e8e91e51a5440cbc15198f2 (patch) | |
tree | 3ffe455f4d7965af42a94faa7914b7e7b611ffa6 | |
parent | 263b70846b06d2a119d5d253633e5678a9f908bb (diff) | |
download | xmlgraphics-fop-76ebc1fa40782c2e6e8e91e51a5440cbc15198f2.tar.gz xmlgraphics-fop-76ebc1fa40782c2e6e8e91e51a5440cbc15198f2.zip |
fop-rgb-icc() function did not make the round-trip which caused an error in the color_1.xml test case (intermediate format tests). Added a unit test to test the parsing and round-trip.
Documented the cmyk() function.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@628775 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | src/documentation/content/xdocs/trunk/extensions.xml | 18 | ||||
-rw-r--r-- | src/java/org/apache/fop/fo/expr/ICCColorFunction.java | 22 | ||||
-rw-r--r-- | src/java/org/apache/fop/util/ColorUtil.java | 28 | ||||
-rw-r--r-- | test/java/org/apache/fop/UtilityCodeTestSuite.java | 4 | ||||
-rw-r--r-- | test/java/org/apache/fop/traits/TraitColorTestCase.java | 79 | ||||
-rw-r--r-- | test/java/org/apache/fop/util/ColorUtilTestCase.java | 173 | ||||
-rw-r--r-- | test/layoutengine/standard-testcases/color_1.xml | 7 |
7 files changed, 233 insertions, 98 deletions
diff --git a/src/documentation/content/xdocs/trunk/extensions.xml b/src/documentation/content/xdocs/trunk/extensions.xml index fb3db86fe..483866e61 100644 --- a/src/documentation/content/xdocs/trunk/extensions.xml +++ b/src/documentation/content/xdocs/trunk/extensions.xml @@ -210,6 +210,24 @@ to following pages. Here is an example of FO code creating such a table-header:< supported for PDF, PS and Java2D-based renderers. </note> </section> + <section id="color-functions"> + <title>Color functions</title> + <p> + XSL-FO supports specifying color using the rgb(), rgb-icc() and system-color() functions. + Apache FOP provides additional color functions for special use cases. Please note that + using these functions compromises the interoperability of an FO document. + </p> + <section id="color-function-cmyk"> + <title>cmyk()</title> + <p><code>color cmyk(numeric, numeric, numeric, numeric)</code></p> + <p> + This function will construct a color in device-specific CMYK color space. The numbers + must be between 0.0 and 1.0. For output formats that don't support device-specific + color space the CMYK value is converted to an sRGB value. + </p> + </section> + </section> + </section> </body> </document> diff --git a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java index 5bd9d145d..9444639a5 100644 --- a/src/java/org/apache/fop/fo/expr/ICCColorFunction.java +++ b/src/java/org/apache/fop/fo/expr/ICCColorFunction.java @@ -71,19 +71,31 @@ class ICCColorFunction extends FunctionBase { } String src = cp.getSrc(); + float red = 0, green = 0, blue = 0; + red = args[0].getNumber().floatValue(); + green = args[1].getNumber().floatValue(); + blue = args[2].getNumber().floatValue(); + /* Verify rgb replacement arguments */ + if ((red < 0 || red > 255) + || (green < 0 || green > 255) + || (blue < 0 || blue > 255)) { + throw new PropertyException("Color values out of range. " + + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + } + // rgb-icc is replaced with fop-rgb-icc which has an extra fifth argument containing the // color profile src attribute as it is defined in the color-profile declarations element. StringBuffer sb = new StringBuffer(); sb.append("fop-rgb-icc("); - for (int ix = 0; ix < args.length; ix++) { + sb.append(red / 255f); + sb.append(',').append(green / 255f); + sb.append(',').append(blue / 255f); + for (int ix = 3; ix < args.length; ix++) { if (ix == 3) { sb.append(',').append(colorProfileName); sb.append(',').append(src); } else { - if (ix > 0) { - sb.append(','); - } - sb.append(args[ix]); + sb.append(',').append(args[ix]); } } sb.append(")"); diff --git a/src/java/org/apache/fop/util/ColorUtil.java b/src/java/org/apache/fop/util/ColorUtil.java index bb014b2af..fbfc68c36 100644 --- a/src/java/org/apache/fop/util/ColorUtil.java +++ b/src/java/org/apache/fop/util/ColorUtil.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fo.expr.PropertyException; @@ -73,8 +74,8 @@ public final class ColorUtil { * <li>system-color(colorname)</li> * <li>transparent</li> * <li>colorname</li> - * <li>fop-rgb-icc</li> - * <li>cmyk</li> + * <li>fop-rgb-icc(r,g,b,cs,cs-src,[num]+) (r/g/b: 0..1, num: 0..1)</li> + * <li>cmyk(c,m,y,k) (0..1)</li> * </ul> * * @param foUserAgent FOUserAgent object @@ -278,7 +279,7 @@ public final class ColorUtil { //multiply by 0x11 = 17 = 255/15 red = Integer.parseInt(value.substring(1, 2), 16) * 0x11; green = Integer.parseInt(value.substring(2, 3), 16) * 0x11; - blue = Integer.parseInt(value.substring(3, 4), 16) *0X11; + blue = Integer.parseInt(value.substring(3, 4), 16) * 0X11; } else if ((len == 7) || (len == 9)) { red = Integer.parseInt(value.substring(1, 3), 16); green = Integer.parseInt(value.substring(3, 5), 16); @@ -323,6 +324,12 @@ public final class ColorUtil { if (iccProfileSrc == null || "".equals(iccProfileSrc)) { throw new PropertyException("ICC profile source missing"); } + if (iccProfileSrc.startsWith("\"") || iccProfileSrc.startsWith("'")) { + iccProfileSrc = iccProfileSrc.substring(1); + } + if (iccProfileSrc.endsWith("\"") || iccProfileSrc.endsWith("'")) { + iccProfileSrc = iccProfileSrc.substring(0, iccProfileSrc.length() - 1); + } /* ICC profile arguments */ float[] iccComponents = new float[args.length - 5]; for (int ix = 4; ++ix < args.length;) { @@ -336,25 +343,26 @@ public final class ColorUtil { float red = 0, green = 0, blue = 0; red = Float.parseFloat(args[0].trim()); green = Float.parseFloat(args[1].trim()); - blue = Float.parseFloat(args[2].trim());; + blue = Float.parseFloat(args[2].trim()); /* Verify rgb replacement arguments */ - if ((red < 0 || red > 255) - || (green < 0 || green > 255) - || (blue < 0 || blue > 255)) { + if ((red < 0 || red > 1) + || (green < 0 || green > 1) + || (blue < 0 || blue > 1)) { throw new PropertyException("Color values out of range. " - + "Arguments to rgb-icc() must be [0..255] or [0%..100%]"); + + "Fallback RGB arguments to fop-rgb-icc() must be [0..1]"); } if (colorSpace != null) { // ColorSpace available - create ColorExt (keeps track of replacement rgb // values for possible later colorTOsRGBString call - parsedColor = ColorExt.createFromFoRgbIcc(red/255, green/255, blue/255, + parsedColor = ColorExt.createFromFoRgbIcc(red, green, blue, iccProfileName, iccProfileSrc, colorSpace, iccComponents); } else { // ICC profile could not be loaded - use rgb replacement values */ log.warn("Color profile '" + iccProfileSrc + "' not found. Using rgb replacement values."); - parsedColor = new Color((int)red, (int)green, (int)blue); + parsedColor = new Color(Math.round(red * 255), + Math.round(green * 255), Math.round(blue * 255)); } } catch (PropertyException pe) { //simply re-throw diff --git a/test/java/org/apache/fop/UtilityCodeTestSuite.java b/test/java/org/apache/fop/UtilityCodeTestSuite.java index 19d7d0266..86a3469ce 100644 --- a/test/java/org/apache/fop/UtilityCodeTestSuite.java +++ b/test/java/org/apache/fop/UtilityCodeTestSuite.java @@ -24,10 +24,10 @@ import junit.framework.TestSuite; import org.apache.fop.pdf.PDFObjectTestCase; import org.apache.fop.traits.BorderPropsTestCase; -import org.apache.fop.traits.TraitColorTestCase; import org.apache.fop.util.DataURIResolverTestCase; import org.apache.fop.util.ElementListUtilsTestCase; import org.apache.fop.util.PDFNumberTestCase; +import org.apache.fop.util.ColorUtilTestCase; import org.apache.fop.util.UnitConvTestCase; /** @@ -46,7 +46,7 @@ public class UtilityCodeTestSuite { suite.addTest(new TestSuite(PDFNumberTestCase.class)); suite.addTest(new TestSuite(PDFObjectTestCase.class)); suite.addTest(new TestSuite(UnitConvTestCase.class)); - suite.addTest(new TestSuite(TraitColorTestCase.class)); + suite.addTest(new TestSuite(ColorUtilTestCase.class)); suite.addTest(new TestSuite(BorderPropsTestCase.class)); suite.addTest(new TestSuite(ElementListUtilsTestCase.class)); suite.addTest(new TestSuite(DataURIResolverTestCase.class)); diff --git a/test/java/org/apache/fop/traits/TraitColorTestCase.java b/test/java/org/apache/fop/traits/TraitColorTestCase.java deleted file mode 100644 index 90f73dcc3..000000000 --- a/test/java/org/apache/fop/traits/TraitColorTestCase.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.traits; - -import java.awt.Color; - -import junit.framework.TestCase; - -import org.apache.fop.util.ColorUtil; - -/** - * Tests the Trait.Color class. - * TODO: This actually tests the ColorUtil class now. - */ -public class TraitColorTestCase extends TestCase { - - /** - * Test serialization to String. - * @throws Exception if an error occurs - */ - public void testSerialization() throws Exception { - Color col = new Color(1.0f, 1.0f, 0.5f, 1.0f); - String s = ColorUtil.colorToString(col); - - //This is what the old color spit out. Now it is 80 due to rounding - //assertEquals("#ffff7f", s); - assertEquals("#ffff80", s); - - col = new Color(1.0f, 0.0f, 0.0f, 0.8f); - s = ColorUtil.colorToString(col); - assertEquals("#ff0000cc", s); - } - - /** - * Test deserialization from String. - * @throws Exception if an error occurs - */ - public void testDeserialization() throws Exception { - Color col = ColorUtil.parseColorString(null, "#ffff7f"); - assertEquals(255, col.getRed()); - assertEquals(255, col.getGreen()); - assertEquals(127, col.getBlue()); - assertEquals(255, col.getAlpha()); - - col = ColorUtil.parseColorString(null, "#ff0000cc"); - assertEquals(255, col.getRed()); - assertEquals(0, col.getGreen()); - assertEquals(0, col.getBlue()); - assertEquals(204, col.getAlpha()); - } - - /** - * Test equals(). - * @throws Exception if an error occurs - */ - public void testEquals() throws Exception { - Color col1 = ColorUtil.parseColorString(null, "#ff0000cc"); - Color col2 = ColorUtil.parseColorString(null, "#ff0000cc"); - assertEquals(col1, col2); - } - -} diff --git a/test/java/org/apache/fop/util/ColorUtilTestCase.java b/test/java/org/apache/fop/util/ColorUtilTestCase.java new file mode 100644 index 000000000..bdeca4379 --- /dev/null +++ b/test/java/org/apache/fop/util/ColorUtilTestCase.java @@ -0,0 +1,173 @@ +/* + * 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 junit.framework.TestCase; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; + +/** + * Tests the ColorUtil class. + */ +public class ColorUtilTestCase extends TestCase { + + /** + * Test serialization to String. + * @throws Exception if an error occurs + */ + public void testSerialization() throws Exception { + Color col = new Color(1.0f, 1.0f, 0.5f, 1.0f); + String s = ColorUtil.colorToString(col); + + //This is what the old color spit out. Now it is 80 due to rounding + //assertEquals("#ffff7f", s); + assertEquals("#ffff80", s); + + col = new Color(1.0f, 0.0f, 0.0f, 0.8f); + s = ColorUtil.colorToString(col); + assertEquals("#ff0000cc", s); + } + + /** + * Test deserialization from String. + * @throws Exception if an error occurs + */ + public void testDeserialization() throws Exception { + Color col = ColorUtil.parseColorString(null, "#ffff7f"); + assertEquals(255, col.getRed()); + assertEquals(255, col.getGreen()); + assertEquals(127, col.getBlue()); + assertEquals(255, col.getAlpha()); + + col = ColorUtil.parseColorString(null, "#ff0000cc"); + assertEquals(255, col.getRed()); + assertEquals(0, col.getGreen()); + assertEquals(0, col.getBlue()); + assertEquals(204, col.getAlpha()); + } + + /** + * Test equals(). + * @throws Exception if an error occurs + */ + public void testEquals() throws Exception { + Color col1 = ColorUtil.parseColorString(null, "#ff0000cc"); + Color col2 = ColorUtil.parseColorString(null, "#ff0000cc"); + assertEquals(col1, col2); + } + + /** + * Tests the rgb() function. + * @throws Exception if an error occurs + */ + public void testRGB() throws Exception { + FopFactory fopFactory = FopFactory.newInstance(); + FOUserAgent ua = fopFactory.newFOUserAgent(); + Color colActual; + + colActual = ColorUtil.parseColorString(ua, "rgb(255, 40, 0)"); + assertEquals(255, colActual.getRed()); + assertEquals(40, colActual.getGreen()); + assertEquals(0, colActual.getBlue()); + assertEquals(255, colActual.getAlpha()); + assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colActual.getColorSpace()); + } + + /** + * Tests the fop-rgb-icc() function. + * @throws Exception if an error occurs + */ + public void testRGBICC() throws Exception { + FopFactory fopFactory = FopFactory.newInstance(); + ColorSpace cs = fopFactory.getColorSpace(null, + "src/java/org/apache/fop/pdf/sRGB Color Space Profile.icm"); + assertNotNull(cs); + + + FOUserAgent ua = fopFactory.newFOUserAgent(); + ColorExt colActual; + + //fop-rgb-icc() is used instead of rgb-icc() inside FOP! + String colSpec = "fop-rgb-icc(1.0,0.0,0.0,sRGBAlt," + + "\"src/java/org/apache/fop/pdf/sRGB Color Space Profile.icm\",1.0,0.0,0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(ua, colSpec); + //assertEquals(255, colActual.getRed()); //253 is returned + //assertEquals(24, colActual.getGreen()); //24 is returned + //I don't understand the difference. Maybe Java's sRGB and HP's sRGB are somehow not + //equivalent. This is only going to be a problem if anyone actually makes use of the + //RGB fallback in any renderer. + //TODO Anyone know what's going on here? + assertEquals(0, colActual.getBlue()); + assertEquals(cs, colActual.getColorSpace()); + float[] comps = colActual.getOriginalColorComponents(); + assertEquals(3, comps.length); + assertEquals(1f, comps[0], 0); + assertEquals(0f, comps[1], 0); + assertEquals(0f, comps[2], 0); + + assertEquals(colSpec, ColorUtil.colorToString(colActual)); + + colSpec = "fop-rgb-icc(1.0,0.5,0.0,blah," + + "\"invalid.icm\",1.0,0.5,0.0,0.15)"; + Color colFallback = ColorUtil.parseColorString(ua, colSpec); + assertEquals(new Color(1.0f, 0.5f, 0.0f), colFallback); + } + + /** + * Tests the cmyk() function. + * @throws Exception if an error occurs + */ + public void testCMYK() throws Exception { + ColorExt colActual; + String colSpec; + + colSpec = "cmyk(0.0, 0.0, 1.0, 0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(null, colSpec); + assertEquals(255, colActual.getRed()); + assertEquals(255, colActual.getGreen()); + assertEquals(0, colActual.getBlue()); + assertEquals(CMYKColorSpace.getInstance(), colActual.getColorSpace()); + float[] comps = colActual.getOriginalColorComponents(); + assertEquals(4, comps.length); + assertEquals(0f, comps[0], 0); + assertEquals(0f, comps[1], 0); + assertEquals(1f, comps[2], 0); + assertEquals(0f, comps[3], 0); + assertEquals("cmyk(0.0,0.0,1.0,0.0)", ColorUtil.colorToString(colActual)); + + colSpec = "cmyk(0.0274, 0.2196, 0.3216, 0.0)"; + colActual = (ColorExt)ColorUtil.parseColorString(null, colSpec); + assertEquals(248, colActual.getRed()); + assertEquals(199, colActual.getGreen()); + assertEquals(172, colActual.getBlue()); + assertEquals(CMYKColorSpace.getInstance(), colActual.getColorSpace()); + comps = colActual.getOriginalColorComponents(); + assertEquals(0.0274f, comps[0], 0.001); + assertEquals(0.2196f, comps[1], 0.001); + assertEquals(0.3216f, comps[2], 0.001); + assertEquals(0f, comps[3], 0); + assertEquals("cmyk(0.0274,0.2196,0.3216,0.0)", ColorUtil.colorToString(colActual)); + } + +} diff --git a/test/layoutengine/standard-testcases/color_1.xml b/test/layoutengine/standard-testcases/color_1.xml index 55ab47b01..0eb08f8b1 100644 --- a/test/layoutengine/standard-testcases/color_1.xml +++ b/test/layoutengine/standard-testcases/color_1.xml @@ -26,7 +26,7 @@ <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" font-family="Gladiator"> <fo:layout-master-set> <fo:simple-page-master master-name="normal" page-width="5in" page-height="5in"> - <fo:region-body background-color="rgb-icc(100%,0%,0%,sRGB,1,0.5,0)" /> + <fo:region-body background-color="rgb-icc(100%,80%,80%,sRGB,1,0.8,0.8)" /> </fo:simple-page-master> </fo:layout-master-set> <fo:declarations> @@ -41,6 +41,9 @@ <fo:block color="rgb-icc(100%,50%,0%, sRGB, 1, 0.5, 0)">color "rgb-icc(100%,50%,0%, sRGB, 1, 0.5, 0)"</fo:block> <fo:block color="rgb-icc(0%,100%,0%, unknown, 1, 0.5, 0)">color "rgb-icc(0%,100%,0%, unknown, 1, 0.5, 0)"</fo:block> <fo:block color="cmyk(0%,0%,20%,40%)">color "cmyk(0%,0%,20%,40%)" (Khaki)</fo:block> + <!-- NYI + <fo:block color="rgb-icc(153, 153, 102, #CMYK, 0, 0, 0.2, 0.4)">color "rgb-icc(153, 153, 102, #CMYK, 0, 0, 0.2, 0.4)" (Khaki)</fo:block> + --> </fo:flow> </fo:page-sequence> </fo:root> @@ -49,7 +52,7 @@ <!-- Check page --> <!-- Special case? rgb-icc() used before fo:declarations Revert to sRGB fallback for now --> - <eval expected="color=#ff0000" xpath="//regionViewport[1]/@background" /> + <eval expected="color=#ffcccc" xpath="//regionViewport[1]/@background" /> <eval expected="#ff0000" xpath="//block[1]//text/@color"/> <eval expected="#ff8000" xpath="//block[2]//text/@color"/> <eval expected="#ff8000" xpath="//block[3]//text/@color"/> |