]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added support for the rgb-named-color() function that is found in the current XSL...
authorJeremias Maerki <jeremias@apache.org>
Tue, 29 Jun 2010 14:30:53 +0000 (14:30 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 29 Jun 2010 14:30:53 +0000 (14:30 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Color@958992 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fo/expr/NamedColorFunction.java [new file with mode: 0644]
src/java/org/apache/fop/fo/expr/PropertyParser.java
src/java/org/apache/fop/util/ColorUtil.java

diff --git a/src/java/org/apache/fop/fo/expr/NamedColorFunction.java b/src/java/org/apache/fop/fo/expr/NamedColorFunction.java
new file mode 100644 (file)
index 0000000..2bceec8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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;
+        }
+    }
+}
index 87f64065170443460c1463a53985bafa933628e6..91218deece4f966ea924a05b088079e1e3785c9a 100644 (file)
@@ -69,6 +69,7 @@ public final class PropertyParser extends PropertyTokenizer {
         FUNCTION_TABLE.put("label-end", new LabelEndFunction());
         FUNCTION_TABLE.put("body-start", new BodyStartFunction());
         FUNCTION_TABLE.put("rgb-icc", new ICCColorFunction());
+        FUNCTION_TABLE.put("rgb-named-color", new NamedColorFunction());
         FUNCTION_TABLE.put("cmyk", new CMYKcolorFunction()); //non-standard!!!
 
         /**
index 5b72027759754946f7d46f0e01078aee428b9daa..983b3c42124bcb9fe3ecba98fdbd09cc3d743b75 100644 (file)
@@ -21,6 +21,8 @@ package org.apache.fop.util;
 
 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;
 
@@ -32,6 +34,8 @@ import org.apache.xmlgraphics.java2d.color.ColorSpaces;
 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;
@@ -124,6 +128,8 @@ public final class ColorUtil {
                 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);
             }
@@ -366,12 +372,7 @@ 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);
-                    }
+                    iccProfileSrc = unescapeString(iccProfileSrc);
                 }
                 /* ICC profile arguments */
                 int componentStart = 4;
@@ -417,6 +418,116 @@ public final class ColorUtil {
         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.
      *