/*

   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.

 */
package org.apache.batik.bridge;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.color.ICC_Profile;
import java.io.IOException;

import org.apache.batik.css.engine.SVGCSSEngine;
import org.apache.batik.css.engine.value.Value;
import org.apache.batik.css.engine.value.svg.ICCColor;
import org.apache.batik.css.engine.value.svg12.CIELabColor;
import org.apache.batik.css.engine.value.svg12.DeviceColor;
import org.apache.batik.css.engine.value.svg12.ICCNamedColor;
import org.apache.batik.gvt.CompositeShapePainter;
import org.apache.batik.gvt.FillShapePainter;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.Marker;
import org.apache.batik.gvt.MarkerShapePainter;
import org.apache.batik.gvt.ShapeNode;
import org.apache.batik.gvt.ShapePainter;
import org.apache.batik.gvt.StrokeShapePainter;
import org.apache.batik.util.CSSConstants;
import org.apache.batik.util.SVGConstants;

import org.apache.xmlgraphics.java2d.color.CIELabColorSpace;
import org.apache.xmlgraphics.java2d.color.ColorSpaces;
import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives;
import org.apache.xmlgraphics.java2d.color.DeviceCMYKColorSpace;
import org.apache.xmlgraphics.java2d.color.ICCColorSpaceWithIntent;
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.w3c.dom.Element;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.CSSValue;

/**
 * A collection of utility methods to deliver <code>java.awt.Paint</code>,
 * <code>java.awt.Stroke</code> objects that could be used to paint a
 * shape. This class also provides additional methods the deliver SVG
 * Paint using the ShapePainter interface.
 *
 * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
 * @version $Id$
 */
public abstract class PaintServer
    implements SVGConstants, CSSConstants, ErrorConstants {

    /**
     * No instance of this class is required.
     */
    protected PaintServer() {}


    /////////////////////////////////////////////////////////////////////////
    // 'marker-start', 'marker-mid', 'marker-end' delegates to the PaintServer
    /////////////////////////////////////////////////////////////////////////

    /**
     * Returns a <code>ShapePainter</code> defined on the specified
     * element and for the specified shape node.
     *
     * @param e the element with the marker CSS properties
     * @param node the shape node
     * @param ctx the bridge context
     */
    public static ShapePainter convertMarkers(Element e,
                                              ShapeNode node,
                                              BridgeContext ctx) {
        Value v;
        v = CSSUtilities.getComputedStyle(e, SVGCSSEngine.MARKER_START_INDEX);
        Marker startMarker = convertMarker(e, v, ctx);
        v = CSSUtilities.getComputedStyle(e, SVGCSSEngine.MARKER_MID_INDEX);
        Marker midMarker = convertMarker(e, v, ctx);
        v = CSSUtilities.getComputedStyle(e, SVGCSSEngine.MARKER_END_INDEX);
        Marker endMarker = convertMarker(e, v, ctx);

        if (startMarker != null || midMarker != null || endMarker != null) {
            MarkerShapePainter p = new MarkerShapePainter(node.getShape());
            p.setStartMarker(startMarker);
            p.setMiddleMarker(midMarker);
            p.setEndMarker(endMarker);
            return p;
        } else {
            return null;
        }
    }

    /////////////////////////////////////////////////////////////////////////
    // org.apache.batik.gvt.Marker
    /////////////////////////////////////////////////////////////////////////

    /**
     * Returns a <code>Marker</code> defined on the specified element by
     * the specified value, and for the specified shape node.
     *
     * @param e the painted element
     * @param v the CSS value describing the marker to construct
     * @param ctx the bridge context
     */
    public static Marker convertMarker(Element e,
                                       Value v,
                                       BridgeContext ctx) {

        if (v.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
            return null; // 'none'
        } else {
            String uri = v.getStringValue();
            Element markerElement = ctx.getReferencedElement(e, uri);
            Bridge bridge = ctx.getBridge(markerElement);
            if (bridge == null || !(bridge instanceof MarkerBridge)) {
                throw new BridgeException(ctx, e, ERR_CSS_URI_BAD_TARGET,
                                          new Object[] {uri});
            }
            return ((MarkerBridge)bridge).createMarker(ctx, markerElement, e);
        }
    }

    /////////////////////////////////////////////////////////////////////////
    // 'stroke', 'fill' ... converts to ShapePainter
    /////////////////////////////////////////////////////////////////////////

    /**
     * Returns a <code>ShapePainter</code> defined on the specified element and
     * for the specified shape node, and using the specified bridge
     * context.
     *
     * @param e the element interested in a shape painter
     * @param node the shape node
     * @param ctx the bridge context
     */
    public static ShapePainter convertFillAndStroke(Element e,
                                                    ShapeNode node,
                                                    BridgeContext ctx) {
        Shape shape = node.getShape();
        if (shape == null) return null;

        Paint  fillPaint   = convertFillPaint  (e, node, ctx);
        FillShapePainter fp = new FillShapePainter(shape);
        fp.setPaint(fillPaint);

        Stroke stroke      = convertStroke     (e);
        if (stroke == null)
            return fp;

        Paint  strokePaint = convertStrokePaint(e, node, ctx);
        StrokeShapePainter sp = new StrokeShapePainter(shape);
        sp.setStroke(stroke);
        sp.setPaint(strokePaint);

        CompositeShapePainter cp = new CompositeShapePainter(shape);
        cp.addShapePainter(fp);
        cp.addShapePainter(sp);
        return cp;
    }


    public static ShapePainter convertStrokePainter(Element e,
                                                    ShapeNode node,
                                                    BridgeContext ctx) {
        Shape shape = node.getShape();
        if (shape == null) return null;

        Stroke stroke = convertStroke(e);
        if (stroke == null)
            return null;

        Paint  strokePaint = convertStrokePaint(e, node, ctx);
        StrokeShapePainter sp = new StrokeShapePainter(shape);
        sp.setStroke(stroke);
        sp.setPaint(strokePaint);
        return sp;
    }

    /////////////////////////////////////////////////////////////////////////
    // java.awt.Paint
    /////////////////////////////////////////////////////////////////////////

    /**
     * Converts for the specified element, its stroke paint properties
     * to a Paint object.
     *
     * @param strokedElement the element interested in a Paint
     * @param strokedNode the graphics node to stroke
     * @param ctx the bridge context
     */
    public static Paint convertStrokePaint(Element strokedElement,
                                           GraphicsNode strokedNode,
                                           BridgeContext ctx) {
        Value v = CSSUtilities.getComputedStyle
            (strokedElement, SVGCSSEngine.STROKE_OPACITY_INDEX);
        float opacity = convertOpacity(v);
        v = CSSUtilities.getComputedStyle
            (strokedElement, SVGCSSEngine.STROKE_INDEX);

        return convertPaint(strokedElement,
                            strokedNode,
                            v,
                            opacity,
                            ctx);
    }

    /**
     * Converts for the specified element, its fill paint properties
     * to a Paint object.
     *
     * @param filledElement the element interested in a Paint
     * @param filledNode the graphics node to fill
     * @param ctx the bridge context
     */
    public static Paint convertFillPaint(Element filledElement,
                                         GraphicsNode filledNode,
                                         BridgeContext ctx) {
        Value v = CSSUtilities.getComputedStyle
            (filledElement, SVGCSSEngine.FILL_OPACITY_INDEX);
        float opacity = convertOpacity(v);
        v = CSSUtilities.getComputedStyle
            (filledElement, SVGCSSEngine.FILL_INDEX);

        return convertPaint(filledElement,
                            filledNode,
                            v,
                            opacity,
                            ctx);
    }

    /**
     * Converts a Paint definition to a concrete <code>java.awt.Paint</code>
     * instance according to the specified parameters.
     *
     * @param paintedElement the element interested in a Paint
     * @param paintedNode the graphics node to paint (objectBoundingBox)
     * @param paintDef the paint definition
     * @param opacity the opacity to consider for the Paint
     * @param ctx the bridge context
     */
    public static Paint convertPaint(Element paintedElement,
                                        GraphicsNode paintedNode,
                                        Value paintDef,
                                        float opacity,
                                        BridgeContext ctx) {
        if (paintDef.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
            switch (paintDef.getPrimitiveType()) {
            case CSSPrimitiveValue.CSS_IDENT:
                return null; // none

            case CSSPrimitiveValue.CSS_RGBCOLOR:
                return convertColor(paintDef, opacity);

            case CSSPrimitiveValue.CSS_URI:
                return convertURIPaint(paintedElement,
                                       paintedNode,
                                       paintDef,
                                       opacity,
                                       ctx);

            default:
                throw new IllegalArgumentException
                    ("Paint argument is not an appropriate CSS value");
            }
        } else { // List
            Value v = paintDef.item(0);
            switch (v.getPrimitiveType()) {
            case CSSPrimitiveValue.CSS_RGBCOLOR:
                return convertRGBICCColor(paintedElement, v,
                                          paintDef.item(1),
                                          opacity, ctx);

            case CSSPrimitiveValue.CSS_URI: {
                Paint result = silentConvertURIPaint(paintedElement,
                                                     paintedNode,
                                                     v, opacity, ctx);
                if (result != null) return result;

                v = paintDef.item(1);
                switch (v.getPrimitiveType()) {
                case CSSPrimitiveValue.CSS_IDENT:
                    return null; // none

                case CSSPrimitiveValue.CSS_RGBCOLOR:
                    if (paintDef.getLength() == 2) {
                        return convertColor(v, opacity);
                    } else {
                        return convertRGBICCColor(paintedElement, v,
                                                  paintDef.item(2),
                                                  opacity, ctx);
                    }
                default:
                    throw new IllegalArgumentException
                        ("Paint argument is not an appropriate CSS value");
                }
            }
            default:
                // can't be reached
                throw new IllegalArgumentException
                    ("Paint argument is not an appropriate CSS value");
            }
        }
    }

    /**
     * Converts a Paint specified by URI without sending any error.
     * if a problem occured while processing the URI, it just returns
     * null (same effect as 'none')
     *
     * @param paintedElement the element interested in a Paint
     * @param paintedNode the graphics node to paint (objectBoundingBox)
     * @param paintDef the paint definition
     * @param opacity the opacity to consider for the Paint
     * @param ctx the bridge context
     * @return the paint object or null when impossible
     */
    public static Paint silentConvertURIPaint(Element paintedElement,
                                              GraphicsNode paintedNode,
                                              Value paintDef,
                                              float opacity,
                                              BridgeContext ctx) {
        Paint paint = null;
        try {
            paint = convertURIPaint(paintedElement, paintedNode,
                                    paintDef, opacity, ctx);
        } catch (BridgeException ex) {
        }
        return paint;
    }

    /**
     * Converts a Paint specified as a URI.
     *
     * @param paintedElement the element interested in a Paint
     * @param paintedNode the graphics node to paint (objectBoundingBox)
     * @param paintDef the paint definition
     * @param opacity the opacity to consider for the Paint
     * @param ctx the bridge context
     */
    public static Paint convertURIPaint(Element paintedElement,
                                        GraphicsNode paintedNode,
                                        Value paintDef,
                                        float opacity,
                                        BridgeContext ctx) {

        String uri = paintDef.getStringValue();
        Element paintElement = ctx.getReferencedElement(paintedElement, uri);

        Bridge bridge = ctx.getBridge(paintElement);
        if (bridge == null || !(bridge instanceof PaintBridge)) {
            throw new BridgeException
                (ctx, paintedElement, ERR_CSS_URI_BAD_TARGET,
                 new Object[] {uri});
        }
        return ((PaintBridge)bridge).createPaint(ctx,
                                                 paintElement,
                                                 paintedElement,
                                                 paintedNode,
                                                 opacity);
    }

    /**
     * Returns a Color object that corresponds to the input Paint's
     * ICC color value or an RGB color if the related color profile
     * could not be used or loaded for any reason.
     *
     * @param paintedElement the element using the color
     * @param colorDef the color definition
     * @param iccColor the ICC color definition
     * @param opacity the opacity
     * @param ctx the bridge context to use
     */
    public static Color convertRGBICCColor(Element paintedElement,
                                           Value colorDef,
                                           Value iccColor,
                                           float opacity,
                                           BridgeContext ctx) {
        Color color = null;
        if (iccColor != null) {
            if (iccColor instanceof ICCColor) {
                color = convertICCColor(paintedElement, (ICCColor)iccColor, opacity, ctx);
            } else if (iccColor instanceof ICCNamedColor) {
                color = convertICCNamedColor(paintedElement, (ICCNamedColor)iccColor, opacity, ctx);
            } else if (iccColor instanceof CIELabColor) {
                color = convertCIELabColor(paintedElement, (CIELabColor)iccColor, opacity, ctx);
            } else if (iccColor instanceof DeviceColor) {
                color = convertDeviceColor(paintedElement, colorDef, (DeviceColor)iccColor, opacity, ctx);
            }
        }
        if (color == null){
            color = convertColor(colorDef, opacity);
        }
        return color;
    }

    /**
     * Returns a Color object that corresponds to the input Paint's
     * ICC color value or null if the related color profile could not
     * be used or loaded for any reason.
     *
     * @param e the element using the color
     * @param c the ICC color definition
     * @param opacity the opacity
     * @param ctx the bridge context to use
     */
    public static Color convertICCColor(Element e,
                                        ICCColor c,
                                        float opacity,
                                        BridgeContext ctx) {
        // Get ICC Profile's name
        String iccProfileName = c.getColorProfile();
        if (iccProfileName == null){
            return null;
        }
        // Ask the bridge to map the ICC profile name to an  ICC_Profile object
        SVGColorProfileElementBridge profileBridge
            = (SVGColorProfileElementBridge)
            ctx.getBridge(SVG_NAMESPACE_URI, SVG_COLOR_PROFILE_TAG);
        if (profileBridge == null){
            return null; // no bridge for color profile
        }

        ICCColorSpaceWithIntent profileCS
            = profileBridge.createICCColorSpaceWithIntent(ctx, e, iccProfileName);
        if (profileCS == null){
            return null; // no profile
        }

        // Now, convert the colors to an array of floats
        int n = c.getNumberOfColors();
        float[] colorValue = new float[n];
        if (n == 0) {
            return null;
        }
        for (int i = 0; i < n; i++) {
            colorValue[i] = c.getColor(i);
        }

        // Convert values to RGB
        float[] rgb = profileCS.intendedToRGB(colorValue);
        //TODO Preserve original ICC color value!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        return new Color(rgb[0], rgb[1], rgb[2], opacity);
    }

    /**
     * Returns a Color object that corresponds to the input Paint's
     * ICC named color value or null if the related color profile could not
     * be used or loaded for any reason.
     *
     * @param e the element using the color
     * @param c the ICC named color definition
     * @param opacity the opacity
     * @param ctx the bridge context to use
     */
    public static Color convertICCNamedColor(Element e,
                                        ICCNamedColor c,
                                        float opacity,
                                        BridgeContext ctx) {
        // Get ICC Profile's name
        String iccProfileName = c.getColorProfile();
        if (iccProfileName == null){
            return null;
        }
        // Ask the bridge to map the ICC profile name to an  ICC_Profile object
        SVGColorProfileElementBridge profileBridge
            = (SVGColorProfileElementBridge)
            ctx.getBridge(SVG_NAMESPACE_URI, SVG_COLOR_PROFILE_TAG);
        if (profileBridge == null){
            return null; // no bridge for color profile
        }

        ICCColorSpaceWithIntent profileCS
            = profileBridge.createICCColorSpaceWithIntent(ctx, e, iccProfileName);
        if (profileCS == null){
            return null; // no profile
        }
        ICC_Profile iccProfile = profileCS.getProfile();

        String iccProfileSrc = null; //TODO Fill me!

        if (NamedColorProfileParser.isNamedColorProfile(iccProfile)) {
            NamedColorProfileParser parser = new NamedColorProfileParser();
            NamedColorProfile ncp;
            try {
                ncp = parser.parseProfile(iccProfile, iccProfileName, iccProfileSrc);
            } catch (IOException ioe) {
                return null;
            }
            NamedColorSpace ncs = ncp.getNamedColor(c.getColorName());
            if (ncs != null) {
                Color specColor
                    = new ColorWithAlternatives(ncs, new float[] {1.0f}, opacity, null);
                return specColor;
            } else {
                /*
                log.warn("Color '" + colorName
                        + "' does not exist in named color profile: " + iccProfileSrc);
                */
            }
        } else {
            //log.warn("ICC profile is no named color profile: " + iccProfileSrc);
        }

        return null;
    }

    /**
     * Returns a Color object that corresponds to the input Paint's
     * CIE Lab color value.
     *
     * @param e the element using the color
     * @param c the CIE Lab color definition
     * @param opacity the opacity
     * @param ctx the bridge context to use
     */
    public static Color convertCIELabColor(Element e,
                                        CIELabColor c,
                                        float opacity,
                                        BridgeContext ctx) {
        CIELabColorSpace cs = new CIELabColorSpace(c.getWhitePoint());
        float[] lab = c.getColorValues();
        Color specColor = cs.toColor(lab[0], lab[1], lab[2], opacity);
        return specColor;
    }

    /**
     * Returns a Color object that corresponds to the input Paint's
     * device-specific color value.
     *
     * @param e the element using the color
     * @param srgb the sRGB fallback color
     * @param c the device-specific color definition
     * @param opacity the opacity
     * @param ctx the bridge context to use
     */
    public static Color convertDeviceColor(Element e,
                                        Value srgb,
                                        DeviceColor c,
                                        float opacity,
                                        BridgeContext ctx) {
        int r = resolveColorComponent(srgb.getRed());
        int g = resolveColorComponent(srgb.getGreen());
        int b = resolveColorComponent(srgb.getBlue());
        if (c.isNChannel()) {
            return convertColor(srgb, opacity); //NYI
        } else {
            if (c.getNumberOfColors() == 4) {
                DeviceCMYKColorSpace cmykCs = ColorSpaces.getDeviceCMYKColorSpace();
                float[] comps = new float[4];
                for (int i = 0; i < 4; i++) {
                    comps[i] = c.getColor(i);
                }
                Color cmyk = new ColorWithAlternatives(cmykCs, comps, opacity, null);
                Color specColor = new ColorWithAlternatives(r, g, b, Math.round(opacity * 255f),
                        new Color[] {cmyk});
                return specColor;
            } else {
                return convertColor(srgb, opacity); //NYI
            }
        }
    }

    /**
     * Converts the given Value and opacity to a Color object.
     * @param c The CSS color to convert.
     * @param opacity The opacity value (0 &lt;= o &lt;= 1).
     */
    public static Color convertColor(Value c, float opacity) {
        int r = resolveColorComponent(c.getRed());
        int g = resolveColorComponent(c.getGreen());
        int b = resolveColorComponent(c.getBlue());
        return new Color(r, g, b, Math.round(opacity * 255f));
    }

    /////////////////////////////////////////////////////////////////////////
    // java.awt.stroke
    /////////////////////////////////////////////////////////////////////////

    /**
     * Converts a <code>Stroke</code> object defined on the specified element.
     *
     * @param e the element on which the stroke is specified
     */
    public static Stroke convertStroke(Element e) {
        Value v;
        v = CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.STROKE_WIDTH_INDEX);
        float width = v.getFloatValue();
        if (width == 0.0f)
            return null; // Stop here no stroke should be painted.

        v = CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.STROKE_LINECAP_INDEX);
        int linecap = convertStrokeLinecap(v);
        v = CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.STROKE_LINEJOIN_INDEX);
        int linejoin = convertStrokeLinejoin(v);
        v = CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.STROKE_MITERLIMIT_INDEX);
        float miterlimit = convertStrokeMiterlimit(v);
        v = CSSUtilities.getComputedStyle
            (e, SVGCSSEngine.STROKE_DASHARRAY_INDEX);
        float[] dasharray = convertStrokeDasharray(v);

        float dashoffset = 0;
        if (dasharray != null) {
            v =  CSSUtilities.getComputedStyle
                (e, SVGCSSEngine.STROKE_DASHOFFSET_INDEX);
            dashoffset = v.getFloatValue();

            // make the dashoffset positive since BasicStroke cannot handle
            // negative values
            if ( dashoffset < 0 ) {
                float dashpatternlength = 0;
                for (float aDasharray : dasharray) {
                    dashpatternlength += aDasharray;
                }
                // if the dash pattern consists of an odd number of elements,
                // the pattern length must be doubled
                if ( (dasharray.length % 2) != 0 )
                    dashpatternlength *= 2;

                if (dashpatternlength ==0) {
                    dashoffset=0;
                } else {
                    while (dashoffset < 0)
                        dashoffset += dashpatternlength;
                }
            }
        }
        return new BasicStroke(width,
                               linecap,
                               linejoin,
                               miterlimit,
                               dasharray,
                               dashoffset);
    }

    /////////////////////////////////////////////////////////////////////////
    // Stroke utility methods
    /////////////////////////////////////////////////////////////////////////

    /**
     * Converts the 'stroke-dasharray' property to a list of float
     * number in user units.
     *
     * @param v the CSS value describing the dasharray property
     */
    public static float [] convertStrokeDasharray(Value v) {
        float [] dasharray = null;
        if (v.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
            int length = v.getLength();
            dasharray = new float[length];
            float sum = 0;
            for (int i = 0; i < dasharray.length; ++i) {
                dasharray[i] = v.item(i).getFloatValue();
                sum += dasharray[i];
            }
            if (sum == 0) {
                /* 11.4 - If the sum of the <length>'s is zero, then
                 * the stroke is rendered as if a value of none were specified.
                 */
                dasharray = null;
            }
        }
        return dasharray;
    }

    /**
     * Converts the 'miterlimit' property to the appropriate float number.
     * @param v the CSS value describing the miterlimit property
     */
    public static float convertStrokeMiterlimit(Value v) {
        float miterlimit = v.getFloatValue();
        return (miterlimit < 1.0f) ? 1.0f : miterlimit;
    }

    /**
     * Converts the 'linecap' property to the appropriate BasicStroke constant.
     * @param v the CSS value describing the linecap property
     */
    public static int convertStrokeLinecap(Value v) {
        String s = v.getStringValue();
        switch (s.charAt(0)) {
        case 'b':
            return BasicStroke.CAP_BUTT;
        case 'r':
            return BasicStroke.CAP_ROUND;
        case 's':
            return BasicStroke.CAP_SQUARE;
        default:
            throw new IllegalArgumentException
                ("Linecap argument is not an appropriate CSS value");
        }
    }

    /**
     * Converts the 'linejoin' property to the appropriate BasicStroke
     * constant.
     * @param v the CSS value describing the linejoin property
     */
    public static int convertStrokeLinejoin(Value v) {
        String s = v.getStringValue();
        switch (s.charAt(0)) {
        case 'm':
            return BasicStroke.JOIN_MITER;
        case 'r':
            return BasicStroke.JOIN_ROUND;
        case 'b':
            return BasicStroke.JOIN_BEVEL;
        default:
            throw new IllegalArgumentException
                ("Linejoin argument is not an appropriate CSS value");
        }
    }

    /////////////////////////////////////////////////////////////////////////
    // Paint utility methods
    /////////////////////////////////////////////////////////////////////////

    /**
     * Returns the value of one color component (0 &lt;= result &lt;= 255).
     * @param v the value that defines the color component
     */
    public static int resolveColorComponent(Value v) {
        float f;
        switch(v.getPrimitiveType()) {
        case CSSPrimitiveValue.CSS_PERCENTAGE:
            f = v.getFloatValue();
            f = (f > 100f) ? 100f : (f < 0f) ? 0f : f;
            return Math.round(255f * f / 100f);
        case CSSPrimitiveValue.CSS_NUMBER:
            f = v.getFloatValue();
            f = (f > 255f) ? 255f : (f < 0f) ? 0f : f;
            return Math.round(f);
        default:
            throw new IllegalArgumentException
                ("Color component argument is not an appropriate CSS value");
        }
    }

    /**
     * Returns the opacity represented by the specified CSSValue.
     * @param v the value that represents the opacity
     * @return the opacity between 0 and 1
     */
    public static float convertOpacity(Value v) {
        float r = v.getFloatValue();
        return (r < 0f) ? 0f : (r > 1.0f) ? 1.0f : r;
    }
}
