FileDocCategorySizeDatePackage
LinearGradientPaintDef.javaAPI DocphoneME MR2 API (J2ME)7584Wed May 02 18:00:34 BST 2007com.sun.perseus.j2d

LinearGradientPaintDef.java

/*
 *
 *
 * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */
package com.sun.perseus.j2d;

import com.sun.pisces.PiscesRenderer;
import com.sun.pisces.Transform6;

import org.w3c.dom.svg.SVGRect;

/**
 * LinearGradientPaint support.
 *
 * @version $Id: LinearGradientPaintDef.java,v 1.4 2006/04/21 06:35:26 st125089 Exp $
 */
public class LinearGradientPaintDef implements PaintDef {
    public static final int CYCLE_NONE = 0;
    public static final int CYCLE_REPEAT = 1;
    public static final int CYCLE_REFLECT = 2;

    private Transform6 IDENTITY = new Transform6();
    
    /**
     * The gradient starting point along the x-axis
     */
    float x0;

    /**
     * The gradient starting point along the y-axis
     */
    float y0;

    /**
     * The gradient end point along the x-axis
     */
    float x1;

    /**
     * The gradient end point along the y-axis.
     */
    float y1;

    /**
     * The array of stop values.
     */
    float[] fractions;

    /**
     * The array of stop values, as fixed point values.
     */
    int[] frac;

    /**
     * The array of ARGB color values.
     */
    int[] rgba;

    /**
     * The last used rgba array, accounting for operation opacity.
     */
    int[] lrgba;

    /**
     * The last paintOpacity.
     */
    int lastPaintOpacity = 255;

    /**
     * One of the cycle methods (CYCLE_NONE,
     *        CYCLE_REPEAT, CYCLE_REFLECT
     */
    int cycleMethod;

    /**
     * Set to true if this gradient is in objectBoundingBox space.
     */
    protected boolean isObjectBBox = false;

    /**
     * An additional transform from the gradient space. This corresponds to a
     * SVG gradientTransform attribute.
     */
    protected Transform gradientTransform;

    /**
     * Constructs an <code>LinearGradientPaint</code>.
     *
     * @param x0 the gradient starting point along the x-axis
     * @param y0 the gradient starting point along the y-axis
     * @param x1 the gradient end point along the x-axis
     * @param y1 the gradient end point along the y-axis.
     * @param fractions the array of stop values.
     * @param rgba the array of ARGB color values
     * @param cycleMethod one of the cycle methods (CYCLE_NONE,
     *        CYCLE_REPEAT, CYCLE_REFLECT
     * @param isObjectBBox if set to true, the RenderGraphic's current 
     *        paintTarget object bounding box should be used to append
     *        and additional transform to the gradientTransform. The objectBoundingBox
     *        transform is appended to the right of the gradientTransform.
     * @param gradientTransform an additional transform to add between the
     *        device coordinate space and the gradient's coordinate space.
     */
    public LinearGradientPaintDef (final float x0,
                                   final float y0,
                                   final float x1,
                                   final float y1,
                                   final float[] fractions,
                                   final int[] rgba,
                                   final int cycleMethod,
                                   final boolean isObjectBBox,
                                   final Transform gradientTransform) {
        this.x0 = x0;
        this.y0 = y0;
        this.x1 = x1;
        this.y1 = y1;
        this.fractions = fractions;
        this.rgba = rgba;
        this.cycleMethod = cycleMethod;
        this.isObjectBBox = isObjectBBox;
        this.gradientTransform = gradientTransform;
    }

    /**
     * Sets the paint on a PiscesRender.
     *
     * @param rg the RenderGraphics on requesting the paint to be set.
     * @param renderer the PiscesRender on which to set the paint.
     * @param paintOpacity additional paint opacity.
     */
    public void setPaint(final PiscesRenderGraphics rg,
                         final PiscesRenderer pr,
                         final int paintOpacity) {
        // First, lazilly compute the fractions in fixed point.
        if (frac == null) {
            frac = new int[fractions.length];
            for (int i = 0; i < fractions.length; i++) {
                frac[i] = (int) (fractions[i] * 65536);
            }
        }

        // Now, lazilly compute the offset colors accounting for the current 
        // paint opacity.
        int[] c = rgba;
        if (paintOpacity != 255) {
            c = lrgba;
            if (paintOpacity != lastPaintOpacity) {
                if (lrgba == null) {
                    lrgba = new int[rgba.length];
                }
                int a = 0;
                for (int i = 0; i < rgba.length; i++) {
                    lrgba[i] = (rgba[i] & 0x00ffffff);
                    a = (paintOpacity * (0xff & (rgba[i] >> 24)) / 255);
                    lrgba[i] |= (a << 24);
                }
                lastPaintOpacity = paintOpacity;
            }
        }

        // Finally, compute the paint transform.

        // Start with the paintTarget's user space coordinate system.
        Transform txf = null;
        if (rg.paintTransform != null) {
            txf = new Transform(rg.paintTransform);
        } else {
            txf = new Transform(rg.transform.m00 / 65536f,
                                rg.transform.m10 / 65536f,
                                rg.transform.m01 / 65536f,
                                rg.transform.m11 / 65536f,
                                rg.transform.m02 / 65536f,
                                rg.transform.m12 / 65536f);
        }

        // Append the objectBoundingBox space to user space transform.
        if (isObjectBBox) {
            SVGRect bbox = rg.paintTarget.getBBox();
            txf.mTranslate(bbox.getX(), bbox.getY());
            txf.mScale(bbox.getWidth(), bbox.getHeight());
        } 

        // Now, append the gradient transform.
        if (gradientTransform != null) {
            txf.mMultiply(gradientTransform);
        }
        
        Transform6 t = new Transform6();
        t.m00 = (int) (txf.m0 * 65536);
        t.m10 = (int) (txf.m1 * 65536);
        t.m01 = (int) (txf.m2 * 65536);
        t.m11 = (int) (txf.m3 * 65536);
        t.m02 = (int) (txf.m4 * 65536);
        t.m12 = (int) (txf.m5 * 65536);
        
        pr.setLinearGradient((int) (x0 * 65536), 
                             (int) (y0 * 65536), 
                             (int) (x1 * 65536), 
                             (int) (y1 * 65536), 
                             frac, 
                             c, 
                             cycleMethod, 
                             t);
    }
}