--- /dev/null
+/*
+ * 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.fo.expr;
+import org.apache.fop.datatypes.PercentBase;
+import org.apache.fop.datatypes.PercentBaseContext;
+import org.apache.fop.fo.pagination.ColorProfile;
+import org.apache.fop.fo.pagination.Declarations;
+import org.apache.fop.fo.properties.ColorProperty;
+import org.apache.fop.fo.properties.Property;
+
+/**
+ * Implements the rgb-named-color() function.
+ * @since XSL-FO 2.0
+ */
+class NamedColorFunction extends FunctionBase {
+
+ /**
+ * rgb-named-color() takes a 5 arguments.
+ * {@inheritDoc}
+ */
+ public int nbArgs() {
+ return 5;
+ }
+
+ /** {@inheritDoc} */
+ public PercentBase getPercentBase() {
+ return new NamedPercentBase();
+ }
+
+ /** {@inheritDoc} */
+ public Property eval(Property[] args,
+ PropertyInfo pInfo) throws PropertyException {
+ // Map color profile NCNAME to src from declarations/color-profile element
+ String colorProfileName = args[3].getString();
+ String colorName = args[4].getString();
+
+ Declarations decls = pInfo.getFO().getRoot().getDeclarations();
+ ColorProfile cp = null;
+ if (decls != null) {
+ cp = decls.getColorProfile(colorProfileName);
+ }
+ if (cp == null) {
+ PropertyException pe = new PropertyException("The " + colorProfileName
+ + " color profile was not declared");
+ pe.setPropertyInfo(pInfo);
+ throw pe;
+ }
+ String src = (cp != null ? 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("sRGB color values out of range. "
+ + "Arguments to rgb-named-color() must be [0..255] or [0%..100%]");
+ }
+
+ // rgb-named-color is replaced with fop-rgb-named-color which has an extra 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-named-color(");
+ sb.append(red / 255f);
+ sb.append(',').append(green / 255f);
+ sb.append(',').append(blue / 255f);
+ sb.append(',').append(colorProfileName);
+ sb.append(',').append(src);
+ sb.append(", '").append(colorName).append('\'');
+ sb.append(")");
+
+ return ColorProperty.getInstance(pInfo.getUserAgent(), sb.toString());
+ }
+
+ private static final class NamedPercentBase implements PercentBase {
+
+ /** {@inheritDoc} */
+ public int getBaseLength(PercentBaseContext context) throws PropertyException {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ public double getBaseValue() {
+ return 255f;
+ }
+
+ /** {@inheritDoc} */
+ public int getDimension() {
+ return 0;
+ }
+ }
+}
import java.awt.Color;
import java.awt.color.ColorSpace;
+import java.awt.color.ICC_ColorSpace;
+import java.awt.color.ICC_Profile;
import java.util.Collections;
import java.util.Map;
import org.apache.xmlgraphics.java2d.color.DeviceCMYKColorSpace;
import org.apache.xmlgraphics.java2d.color.ICCColor;
import org.apache.xmlgraphics.java2d.color.NamedColorSpace;
+import org.apache.xmlgraphics.java2d.color.profile.NamedColorProfile;
+import org.apache.xmlgraphics.java2d.color.profile.NamedColorProfileParser;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.expr.PropertyException;
parsedColor = parseAsSystemColor(value);
} else if (value.startsWith("fop-rgb-icc")) {
parsedColor = parseAsFopRgbIcc(foUserAgent, value);
+ } else if (value.startsWith("fop-rgb-named-color")) {
+ parsedColor = parseAsFopRgbNamedColor(foUserAgent, value);
} else if (value.startsWith("cmyk")) {
parsedColor = parseAsCMYK(value);
}
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);
- }
+ iccProfileSrc = unescapeString(iccProfileSrc);
}
/* ICC profile arguments */
int componentStart = 4;
return parsedColor;
}
+ /**
+ * Parse a color specified using the fop-rgb-named-color() function.
+ *
+ * @param value the function call
+ * @return a color if possible
+ * @throws PropertyException if the format is wrong.
+ */
+ private static Color parseAsFopRgbNamedColor(FOUserAgent foUserAgent, String value)
+ throws PropertyException {
+ Color parsedColor;
+ int poss = value.indexOf("(");
+ int pose = value.indexOf(")");
+ if (poss != -1 && pose != -1) {
+ String[] args = value.substring(poss + 1, pose).split(",");
+
+ try {
+ if (args.length != 6) {
+ throw new PropertyException("rgb-named() function must have 6 arguments");
+ }
+
+ //Set up fallback sRGB value
+ float red = Float.parseFloat(args[0].trim());
+ float green = Float.parseFloat(args[1].trim());
+ float blue = Float.parseFloat(args[2].trim());
+ /* Verify rgb replacement arguments */
+ if ((red < 0 || red > 1)
+ || (green < 0 || green > 1)
+ || (blue < 0 || blue > 1)) {
+ throw new PropertyException("Color values out of range. "
+ + "Fallback RGB arguments to fop-rgb-named-color() must be [0..1]");
+ }
+ Color sRGB = new ColorExt(red, green, blue, null);
+
+ /* Get and verify ICC profile name */
+ String iccProfileName = args[3].trim();
+ if (iccProfileName == null || "".equals(iccProfileName)) {
+ throw new PropertyException("ICC profile name missing");
+ }
+ ICC_ColorSpace colorSpace = null;
+ String iccProfileSrc = null;
+ if (isPseudoProfile(iccProfileName)) {
+ throw new IllegalArgumentException(
+ "Pseudo-profiles are not allowed with fop-rgb-named-color()");
+ } else {
+ /* Get and verify ICC profile source */
+ iccProfileSrc = args[4].trim();
+ if (iccProfileSrc == null || "".equals(iccProfileSrc)) {
+ throw new PropertyException("ICC profile source missing");
+ }
+ iccProfileSrc = unescapeString(iccProfileSrc);
+ }
+
+ // color name
+ String colorName = unescapeString(args[5].trim());
+
+ /* Ask FOP factory to get ColorSpace for the specified ICC profile source */
+ if (foUserAgent != null && iccProfileSrc != null) {
+ colorSpace = (ICC_ColorSpace)foUserAgent.getFactory().getColorSpace(
+ foUserAgent.getBaseURL(), iccProfileSrc);
+ }
+ if (colorSpace != null) {
+ ICC_Profile profile = colorSpace.getProfile();
+ if (NamedColorProfileParser.isNamedColorProfile(profile)) {
+ NamedColorProfileParser parser = new NamedColorProfileParser();
+ NamedColorProfile ncp = parser.parseProfile(profile);
+ NamedColorSpace ncs = ncp.getNamedColor(colorName);
+ if (ncs != null) {
+ ICCColor iccColor = new ICCColor(ncs,
+ iccProfileName, iccProfileSrc,
+ new float[] {1.0f}, 1.0f);
+ parsedColor = new ColorExt(red, green, blue, new Color[] {iccColor});
+ } else {
+ log.warn("Color '" + colorName
+ + "' does not exist in named color profile: " + iccProfileSrc);
+ parsedColor = sRGB;
+ }
+ } else {
+ log.warn("ICC profile is no named color profile: " + iccProfileSrc);
+ parsedColor = sRGB;
+ }
+ } else {
+ // ICC profile could not be loaded - use rgb replacement values */
+ log.warn("Color profile '" + iccProfileSrc
+ + "' not found. Using sRGB replacement values.");
+ parsedColor = sRGB;
+ }
+ } catch (PropertyException pe) {
+ //simply re-throw
+ throw pe;
+ } catch (Exception e) {
+ //wrap in a PropertyException
+ throw new PropertyException(e);
+ }
+ } else {
+ throw new PropertyException("Unknown color format: " + value
+ + ". Must be fop-rgb-named-color(r,g,b,NCNAME,src,color-name)");
+ }
+ return parsedColor;
+ }
+
+ private static String unescapeString(String iccProfileSrc) {
+ if (iccProfileSrc.startsWith("\"") || iccProfileSrc.startsWith("'")) {
+ iccProfileSrc = iccProfileSrc.substring(1);
+ }
+ if (iccProfileSrc.endsWith("\"") || iccProfileSrc.endsWith("'")) {
+ iccProfileSrc = iccProfileSrc.substring(0, iccProfileSrc.length() - 1);
+ }
+ return iccProfileSrc;
+ }
+
/**
* Parse a color given with the cmyk() function.
*