001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.anim.values;
020:
021: import org.apache.batik.dom.anim.AnimationTarget;
022:
023: import org.w3c.dom.svg.SVGLength;
024:
025: /**
026: * An SVG length list value in the animation system.
027: *
028: * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
029: * @version $Id: AnimatableLengthListValue.java 475477 2006-11-15 22:44:28Z cam $
030: */
031: public class AnimatableLengthListValue extends AnimatableValue {
032:
033: /**
034: * The length types.
035: */
036: protected short[] lengthTypes;
037:
038: /**
039: * The length values. These should be one of the constants defined in
040: * {@link SVGLength}.
041: */
042: protected float[] lengthValues;
043:
044: /**
045: * How to interpret percentage values. These should be one of the
046: * {@link AnimationTarget}.PERCENTAGE_* constants.
047: */
048: protected short percentageInterpretation;
049:
050: /**
051: * Creates a new, uninitialized AnimatableLengthListValue.
052: */
053: protected AnimatableLengthListValue(AnimationTarget target) {
054: super (target);
055: }
056:
057: /**
058: * Creates a new AnimatableLengthListValue.
059: */
060: public AnimatableLengthListValue(AnimationTarget target,
061: short[] types, float[] values, short pcInterp) {
062: super (target);
063: this .lengthTypes = types;
064: this .lengthValues = values;
065: this .percentageInterpretation = pcInterp;
066: }
067:
068: /**
069: * Performs interpolation to the given value.
070: */
071: public AnimatableValue interpolate(AnimatableValue result,
072: AnimatableValue to, float interpolation,
073: AnimatableValue accumulation, int multiplier) {
074: AnimatableLengthListValue toLengthList = (AnimatableLengthListValue) to;
075: AnimatableLengthListValue accLengthList = (AnimatableLengthListValue) accumulation;
076:
077: boolean hasTo = to != null;
078: boolean hasAcc = accumulation != null;
079: boolean canInterpolate = !(hasTo && toLengthList.lengthTypes.length != lengthTypes.length)
080: && !(hasAcc && accLengthList.lengthTypes.length != lengthTypes.length);
081:
082: short[] baseLengthTypes;
083: float[] baseLengthValues;
084: if (!canInterpolate && hasTo && interpolation >= 0.5) {
085: baseLengthTypes = toLengthList.lengthTypes;
086: baseLengthValues = toLengthList.lengthValues;
087: } else {
088: baseLengthTypes = lengthTypes;
089: baseLengthValues = lengthValues;
090: }
091: int len = baseLengthTypes.length;
092:
093: AnimatableLengthListValue res;
094: if (result == null) {
095: res = new AnimatableLengthListValue(target);
096: res.lengthTypes = new short[len];
097: res.lengthValues = new float[len];
098: } else {
099: res = (AnimatableLengthListValue) result;
100: if (res.lengthTypes == null
101: || res.lengthTypes.length != len) {
102: res.lengthTypes = new short[len];
103: res.lengthValues = new float[len];
104: }
105: }
106:
107: res.hasChanged = percentageInterpretation != res.percentageInterpretation;
108: res.percentageInterpretation = percentageInterpretation;
109:
110: for (int i = 0; i < len; i++) {
111: float toV = 0, accV = 0;
112: short newLengthType = baseLengthTypes[i];
113: float newLengthValue = baseLengthValues[i];
114: if (canInterpolate) {
115: if (hasTo
116: && !AnimatableLengthValue.compatibleTypes(
117: newLengthType,
118: percentageInterpretation,
119: toLengthList.lengthTypes[i],
120: toLengthList.percentageInterpretation)
121: || hasAcc
122: && !AnimatableLengthValue.compatibleTypes(
123: newLengthType,
124: percentageInterpretation,
125: accLengthList.lengthTypes[i],
126: accLengthList.percentageInterpretation)) {
127: newLengthValue = target.svgToUserSpace(
128: newLengthValue, newLengthType,
129: percentageInterpretation);
130: newLengthType = SVGLength.SVG_LENGTHTYPE_NUMBER;
131: if (hasTo) {
132: toV = to.target.svgToUserSpace(
133: toLengthList.lengthValues[i],
134: toLengthList.lengthTypes[i],
135: toLengthList.percentageInterpretation);
136: }
137: if (hasAcc) {
138: accV = accumulation.target.svgToUserSpace(
139: accLengthList.lengthValues[i],
140: accLengthList.lengthTypes[i],
141: accLengthList.percentageInterpretation);
142: }
143: } else {
144: if (hasTo) {
145: toV = toLengthList.lengthValues[i];
146: }
147: if (hasAcc) {
148: accV = accLengthList.lengthValues[i];
149: }
150: }
151: newLengthValue += interpolation
152: * (toV - newLengthValue) + multiplier * accV;
153: }
154: if (!res.hasChanged) {
155: res.hasChanged = newLengthType != res.lengthTypes[i]
156: || newLengthValue != res.lengthValues[i];
157: }
158: res.lengthTypes[i] = newLengthType;
159: res.lengthValues[i] = newLengthValue;
160: }
161:
162: return res;
163: }
164:
165: /**
166: * Gets the length types.
167: */
168: public short[] getLengthTypes() {
169: return lengthTypes;
170: }
171:
172: /**
173: * Gets the length values.
174: */
175: public float[] getLengthValues() {
176: return lengthValues;
177: }
178:
179: /**
180: * Returns whether two values of this type can have their distance
181: * computed, as needed by paced animation.
182: */
183: public boolean canPace() {
184: return false;
185: }
186:
187: /**
188: * Returns the absolute distance between this value and the specified other
189: * value.
190: */
191: public float distanceTo(AnimatableValue other) {
192: return 0f;
193: }
194:
195: /**
196: * Returns a zero value of this AnimatableValue's type.
197: */
198: public AnimatableValue getZeroValue() {
199: float[] vs = new float[lengthValues.length];
200: return new AnimatableLengthListValue(target, lengthTypes, vs,
201: percentageInterpretation);
202: }
203:
204: /**
205: * Returns the CSS text representation of the value.
206: * Length lists can never be used for CSS properties.
207: */
208: public String getCssText() {
209: StringBuffer sb = new StringBuffer();
210: if (lengthValues.length > 0) {
211: sb.append(formatNumber(lengthValues[0]));
212: sb.append(AnimatableLengthValue.UNITS[lengthTypes[0] - 1]);
213: }
214: for (int i = 1; i < lengthValues.length; i++) {
215: sb.append(',');
216: sb.append(formatNumber(lengthValues[i]));
217: sb.append(AnimatableLengthValue.UNITS[lengthTypes[i] - 1]);
218: }
219: return sb.toString();
220: }
221: }
|