FileDocCategorySizeDatePackage
TransformTraitAnim.javaAPI DocphoneME MR2 API (J2ME)8480Wed May 02 18:00:34 BST 2007com.sun.perseus.model

TransformTraitAnim.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.model;

import com.sun.perseus.platform.MathSupport;

import org.w3c.dom.DOMException;

/**
 * @version $Id: TransformTraitAnim.java,v 1.3 2006/06/29 10:47:36 ln156897 Exp $
 */
class TransformTraitAnim extends FloatTraitAnim {
    /**
     * Constructs a new TransformTraitAnim for a given ElementNode trait.
     *
     * @param targetElement the ElementNode whose trait is animated.
     * @param targetTrait the name of the animated trait.
     */
    public TransformTraitAnim(final ElementNode targetElement,
                              final String traitName) {
        super(targetElement, 
              traitName, 
              ElementNode.TRAIT_TYPE_SVG_MATRIX);
    }

    /**
     * Converts the input values set to a RefValues object.
     *
     * @param anim the <code>Animation</code> for which the values should be
     *        converted.
     * @param values a semi-colon seperated list of values which need to be
     * validated.
     * @param reqTraitNamespace the namespace of the trait which has the values
     *        value on the requesting element.
     * @param reqTraitName the name of the trait which has the values value on 
     *        the requesting element.
     * @throws DOMException with error code INVALID_ACCESS_ERR if the input
     * value is incompatible with the given trait.
     * @throws NullPointerException if values is null.
     */
    RefValues toRefValues(final Animation anim,
                          String[] values,
                          final String reqTraitNamespace,
                          final String reqTraitName) throws DOMException {
        // If we are dealing with a generic animation, the values should be 
        // as in the transform attribute: we can use the default FloatTraitAnim
        // toRefValues.
        if (anim.type == Animation.TYPE_GENERIC) {
            return super.toRefValues(anim, values, reqTraitNamespace, 
                                     reqTraitName);
        }

        // The interpretation of values depends on the animation type.
        TransformRefValues refValues = new TransformRefValues();
        
        if (values.length < 1) {
            throw new IllegalArgumentException();
        }

        if (values.length == 1) {
            String[] tmpValues = new String[2];
            tmpValues[0] = values[0];
            tmpValues[1] = values[0];
            values = tmpValues;
        }

        int nSegments = values.length - 1;
        TransformSegment[] segments = new TransformSegment[nSegments];

        // Build the first segment.
        segments[0] = new TransformSegment();
        segments[0].start = 
            validateValue(anim,
                          reqTraitNamespace,
                          reqTraitName,
                          values[0]);
        segments[0].end = 
            validateValue(anim,
                          reqTraitNamespace,
                          reqTraitName,
                          values[1]);
        segments[0].type = anim.type;

        TransformSegment prevSegment = segments[0];

        for (int i = 1; i < nSegments; i++) {
            segments[i] = new TransformSegment();
            segments[i].start = prevSegment.end;
            segments[i].end = 
                validateValue(anim,
                              reqTraitNamespace,
                              reqTraitName,
                              values[i + 1]);
            segments[i].type = anim.type;
            prevSegment = segments[i];
        }

        refValues.segments = segments;
        return refValues;
    }

    /**
     * Validates the input trait value.
     *
     * @param anim the animation for which the value is validated
     * @param traitNamespace the namespace trait
     * @param traitName the name of the trait to be validated.
     * @param value the value to be validated
     * @throws DOMException with error code INVALID_ACCESS_ERR if the input
     * value is incompatible with the given trait.
     */
    public float[] validateValue(final Animation anim,
                                 final String traitNamespace,
                                 final String traitName,
                                 final String value) {
        float[] v = null;

        switch (anim.type) {
        case AnimateTransform.TYPE_TRANSLATE:
            v = anim.parseFloatArrayTrait(traitName, value);
            if (v.length < 1 || v.length > 2) {
                throw anim.illegalTraitValue(traitName, value);
            }

            if (v.length == 1) {
                float[] tv = new float[2];
                tv[0] = v[0];
                tv[1] = 0;
                v = tv;
            }

            return v;

        case AnimateTransform.TYPE_SCALE:
            v = anim.parseFloatArrayTrait(traitName, value);
            if (v.length < 1 || v.length > 2) {
                throw anim.illegalTraitValue(traitName, value);
            }

            if (v.length == 1) {
                float[] tv = new float[2];
                tv[0] = v[0];
                tv[1] = v[0];
                v = tv;
            }

            return v;

        case AnimateTransform.TYPE_ROTATE:
            // This should be enhanced to support
            v = anim.parseFloatArrayTrait(traitName, value);
            if (v.length != 1 && v.length != 3) {
                throw anim.illegalTraitValue(traitName, value);
            }

            if (v.length != 3) {
                float[] tv = new float[3];
                tv[0] = v[0];
                tv[1] = 0;
                tv[2] = 0;
                v = tv;
            }

            v[0] = MathSupport.toRadians(v[0]);
            return v;

        case AnimateTransform.TYPE_SKEW_X:
        case AnimateTransform.TYPE_SKEW_Y:
        default:
            v = new float[] {anim.parseFloatTrait(traitName, value)};
            v[0] = MathSupport.toRadians(v[0]); 
            return v;
        }
    }

    /**
     * Used to sum two animated trait values.
     *
     * @param valueA the base value. May be null.
     * @param valueB the value to add to the base value. If the baseValue 
     */
    public Object[] sum(Object[] valueA, Object[] valueB) {
        if (valueA == null) {
            return valueB;
        }

        float[][] fva = (float[][]) valueA;
        float[][] fvb = (float[][]) valueB;

        // For transforms, we should do matrices multiplication, not
        // simple float additions.
        float[][] fv = new float[6][1];

        fv[0][0] = fvb[0][0] * fva[0][0] + fvb[1][0] * fva[2][0];
        fv[1][0] = fvb[0][0] * fva[1][0] + fvb[1][0] * fva[3][0];

        fv[2][0] = fvb[2][0] * fva[0][0] + fvb[3][0] * fva[2][0];
        fv[3][0] = fvb[2][0] * fva[1][0] + fvb[3][0] * fva[3][0];

        fv[4][0] = fvb[4][0] * fva[0][0] + fvb[5][0] * fva[2][0] + fva[4][0];
        fv[5][0] = fvb[4][0] * fva[1][0] + fvb[5][0] * fva[3][0] + fva[5][0];

        return fv;
    }

    /**
     * Used to multiply an animated trait value by a number of iterations.
     *
     * @param value the animated trait value to multiply.
     * @param iter the number of iteration to account for.
     * @return the multiply result.
     */
    public Object[] multiply(Object[] value, int iter) {
        for (int i = 1; i < iter; i++) {
            value = sum(value, value);
        }
                 
        return value;
    }

}