/* * $RCSfile: TransformTraitAnim.java,v $ * * Copyright 1990-2009 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>TraitAnimationNode</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 TraitAnimationNode 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 == TraitAnimationNode.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 TraitAnimationNode 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; } }