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.dom.svg;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023:
024: import org.apache.batik.anim.values.AnimatablePathDataValue;
025: import org.apache.batik.anim.values.AnimatableValue;
026: import org.apache.batik.dom.anim.AnimationTarget;
027:
028: import org.apache.batik.parser.ParseException;
029: import org.apache.batik.parser.PathArrayProducer;
030:
031: import org.w3c.dom.Attr;
032: import org.w3c.dom.DOMException;
033: import org.w3c.dom.svg.SVGAnimatedPathData;
034: import org.w3c.dom.svg.SVGException;
035: import org.w3c.dom.svg.SVGPathSeg;
036: import org.w3c.dom.svg.SVGPathSegList;
037:
038: /**
039: * This class is the implementation of the {@link SVGAnimatedPathData}
040: * interface.
041: *
042: * @author <a href="mailto:nicolas.socheleau@bitflash.com">Nicolas Socheleau</a>
043: * @author <a href="mailto:andrest@world-affair.com">Andres Toussaint</a>
044: * @version $Id: SVGOMAnimatedPathData.java 490655 2006-12-28 05:19:44Z cam $
045: */
046: public class SVGOMAnimatedPathData extends AbstractSVGAnimatedValue
047: implements SVGAnimatedPathData {
048:
049: /**
050: * Whether the list is changing.
051: */
052: protected boolean changing;
053:
054: /**
055: * The base path data value.
056: */
057: protected BaseSVGPathSegList pathSegs;
058:
059: /**
060: * The normalized base path data value.
061: */
062: protected NormalizedBaseSVGPathSegList normalizedPathSegs;
063:
064: /**
065: * The animated path data value.
066: */
067: protected AnimSVGPathSegList animPathSegs;
068:
069: // /**
070: // * The normalized animated base path data value.
071: // */
072: // protected NormalizedAnimSVGPathSegList normalizedPathSegs;
073:
074: /**
075: * Default value for the 'd' attribute.
076: */
077: protected String defaultValue;
078:
079: /**
080: * Creates a new SVGOMAnimatedPathData.
081: * @param elt The associated element.
082: * @param ns The attribute's namespace URI.
083: * @param ln The attribute's local name.
084: * @param defaultValue The default value if the attribute is not specified.
085: */
086: public SVGOMAnimatedPathData(AbstractElement elt, String ns,
087: String ln, String defaultValue) {
088: super (elt, ns, ln);
089: this .defaultValue = defaultValue;
090: }
091:
092: /**
093: * <b>DOM</b>: Implements {@link
094: * SVGAnimatedPathData#getAnimatedNormalizedPathSegList()}.
095: */
096: public SVGPathSegList getAnimatedNormalizedPathSegList() {
097: throw new UnsupportedOperationException(
098: "SVGAnimatedPathData.getAnimatedNormalizedPathSegList is not implemented"); // XXX
099: }
100:
101: /**
102: * <b>DOM</b>: Implements {@link
103: * SVGAnimatedPathData#getAnimatedPathSegList()}.
104: */
105: public SVGPathSegList getAnimatedPathSegList() {
106: if (animPathSegs == null) {
107: animPathSegs = new AnimSVGPathSegList();
108: }
109: return animPathSegs;
110: }
111:
112: /**
113: * <b>DOM</b>: Implements {@link
114: * SVGAnimatedPathData#getNormalizedPathSegList()}.
115: * <p>
116: * Returns the SVGPathSegList mapping the normalized static 'd' attribute
117: * of the element.
118: * </p>
119: * <p>
120: * A normalized path is composed only of absolute moveto, lineto and
121: * cubicto path segments (M, L and C). Using this subset, the path
122: * description can be represented with fewer segment types. Be aware that
123: * the normalized 'd' attribute will be a larger String that the original.
124: * </p>
125: * <p>
126: * Relative values are transformed into absolute, quadratic curves are
127: * promoted to cubic curves, and arcs are converted into one or more
128: * cubic curves (one per quadrant).
129: * </p>
130: * <p>
131: * Modifications to the normalized SVGPathSegList will result
132: * in substituting the original path with a set of normalized path
133: * segments.
134: * </p>
135: * @return a path segment list containing the normalized version of the path.
136: */
137: public SVGPathSegList getNormalizedPathSegList() {
138: if (normalizedPathSegs == null) {
139: normalizedPathSegs = new NormalizedBaseSVGPathSegList();
140: }
141: return normalizedPathSegs;
142: }
143:
144: /**
145: * <b>DOM</b>: Implements {@link
146: * SVGAnimatedPathData#getPathSegList()}.
147: */
148: public SVGPathSegList getPathSegList() {
149: if (pathSegs == null) {
150: pathSegs = new BaseSVGPathSegList();
151: }
152: return pathSegs;
153: }
154:
155: /**
156: * Returns the base value of the attribute as an {@link AnimatableValue}.
157: */
158: public AnimatableValue getUnderlyingValue(AnimationTarget target) {
159: SVGPathSegList psl = getPathSegList();
160: PathArrayProducer pp = new PathArrayProducer();
161: SVGAnimatedPathDataSupport.handlePathSegList(psl, pp);
162: return new AnimatablePathDataValue(target,
163: pp.getPathCommands(), pp.getPathParameters());
164: }
165:
166: /**
167: * Updates the animated value with the given {@link AnimatableValue}.
168: */
169: protected void updateAnimatedValue(AnimatableValue val) {
170: if (val == null) {
171: hasAnimVal = false;
172: } else {
173: hasAnimVal = true;
174: AnimatablePathDataValue animPath = (AnimatablePathDataValue) val;
175: if (animPathSegs == null) {
176: animPathSegs = new AnimSVGPathSegList();
177: }
178: animPathSegs.setAnimatedValue(animPath.getCommands(),
179: animPath.getParameters());
180: }
181: fireAnimatedAttributeListeners();
182: }
183:
184: /**
185: * Called when an Attr node has been added.
186: */
187: public void attrAdded(Attr node, String newv) {
188: if (!changing) {
189: if (pathSegs != null) {
190: pathSegs.invalidate();
191: }
192: if (normalizedPathSegs != null) {
193: normalizedPathSegs.invalidate();
194: }
195: }
196: fireBaseAttributeListeners();
197: if (!hasAnimVal) {
198: fireAnimatedAttributeListeners();
199: }
200: }
201:
202: /**
203: * Called when an Attr node has been modified.
204: */
205: public void attrModified(Attr node, String oldv, String newv) {
206: if (!changing) {
207: if (pathSegs != null) {
208: pathSegs.invalidate();
209: }
210: if (normalizedPathSegs != null) {
211: normalizedPathSegs.invalidate();
212: }
213: }
214: fireBaseAttributeListeners();
215: if (!hasAnimVal) {
216: fireAnimatedAttributeListeners();
217: }
218: }
219:
220: /**
221: * Called when an Attr node has been removed.
222: */
223: public void attrRemoved(Attr node, String oldv) {
224: if (!changing) {
225: if (pathSegs != null) {
226: pathSegs.invalidate();
227: }
228: if (normalizedPathSegs != null) {
229: normalizedPathSegs.invalidate();
230: }
231: }
232: fireBaseAttributeListeners();
233: if (!hasAnimVal) {
234: fireAnimatedAttributeListeners();
235: }
236: }
237:
238: /**
239: * {@link SVGPathSegList} implementation for the base path data value.
240: */
241: public class BaseSVGPathSegList extends AbstractSVGPathSegList {
242:
243: /**
244: * Create a DOMException.
245: */
246: protected DOMException createDOMException(short type,
247: String key, Object[] args) {
248: return element.createDOMException(type, key, args);
249: }
250:
251: /**
252: * Create a SVGException.
253: */
254: protected SVGException createSVGException(short type,
255: String key, Object[] args) {
256: return ((SVGOMElement) element).createSVGException(type,
257: key, args);
258: }
259:
260: /**
261: * Returns the value of the DOM attribute containing the path data.
262: */
263: protected String getValueAsString() {
264: Attr attr = element.getAttributeNodeNS(namespaceURI,
265: localName);
266: if (attr == null) {
267: return defaultValue;
268: }
269: return attr.getValue();
270: }
271:
272: /**
273: * Sets the DOM attribute value containing the path data.
274: */
275: protected void setAttributeValue(String value) {
276: try {
277: changing = true;
278: element.setAttributeNS(namespaceURI, localName, value);
279: } finally {
280: changing = false;
281: }
282: }
283:
284: /**
285: * Initializes the list, if needed.
286: */
287: protected void revalidate() {
288: if (valid) {
289: return;
290: }
291:
292: String s = getValueAsString();
293: if (s == null) {
294: throw new LiveAttributeException(element, localName,
295: LiveAttributeException.ERR_ATTRIBUTE_MISSING,
296: null);
297: }
298: try {
299: ListBuilder builder = new ListBuilder();
300:
301: doParse(s, builder);
302:
303: if (builder.getList() != null) {
304: clear(itemList);
305: }
306: itemList = builder.getList();
307: } catch (ParseException e) {
308: itemList = new ArrayList(1);
309: throw new LiveAttributeException(element, localName,
310: LiveAttributeException.ERR_ATTRIBUTE_MALFORMED,
311: s);
312: } finally {
313: valid = true;
314: }
315: }
316: }
317:
318: /**
319: * {@link SVGPathSegList} implementation for the normalized version of the
320: * base path data value.
321: */
322: public class NormalizedBaseSVGPathSegList extends
323: AbstractSVGNormPathSegList {
324:
325: /**
326: * Create a DOMException.
327: */
328: protected DOMException createDOMException(short type,
329: String key, Object[] args) {
330: return element.createDOMException(type, key, args);
331: }
332:
333: /**
334: * Create a SVGException.
335: */
336: protected SVGException createSVGException(short type,
337: String key, Object[] args) {
338: return ((SVGOMElement) element).createSVGException(type,
339: key, args);
340: }
341:
342: /**
343: * Returns the value of the DOM attribute containing the path data.
344: */
345: protected String getValueAsString() throws SVGException {
346: Attr attr = element.getAttributeNodeNS(namespaceURI,
347: localName);
348: if (attr == null) {
349: return defaultValue;
350: }
351: return attr.getValue();
352: }
353:
354: /**
355: * Sets the DOM attribute value containing the path data.
356: */
357: protected void setAttributeValue(String value) {
358: try {
359: changing = true;
360: element.setAttributeNS(namespaceURI, localName, value);
361: } finally {
362: changing = false;
363: }
364: }
365:
366: /**
367: * Initializes the list, if needed.
368: */
369: protected void revalidate() {
370: if (valid) {
371: return;
372: }
373:
374: String s = getValueAsString();
375: if (s == null) {
376: throw new LiveAttributeException(element, localName,
377: LiveAttributeException.ERR_ATTRIBUTE_MISSING,
378: null);
379: }
380: try {
381: ListBuilder builder = new ListBuilder();
382:
383: doParse(s, builder);
384:
385: if (builder.getList() != null) {
386: clear(itemList);
387: }
388: itemList = builder.getList();
389: } catch (ParseException e) {
390: itemList = new ArrayList(1);
391: throw new LiveAttributeException(element, localName,
392: LiveAttributeException.ERR_ATTRIBUTE_MALFORMED,
393: s);
394: } finally {
395: valid = true;
396: }
397: }
398: }
399:
400: /**
401: * {@link SVGPathSegList} implementation for the animated path data value.
402: */
403: public class AnimSVGPathSegList extends AbstractSVGPathSegList {
404:
405: /**
406: * Creates a new AnimSVGPathSegList.
407: */
408: public AnimSVGPathSegList() {
409: itemList = new ArrayList(1);
410: }
411:
412: /**
413: * Create a DOMException.
414: */
415: protected DOMException createDOMException(short type,
416: String key, Object[] args) {
417: return element.createDOMException(type, key, args);
418: }
419:
420: /**
421: * Create a SVGException.
422: */
423: protected SVGException createSVGException(short type,
424: String key, Object[] args) {
425: return ((SVGOMElement) element).createSVGException(type,
426: key, args);
427: }
428:
429: /**
430: * <b>DOM</b>: Implements {@link SVGPathSegList#getNumberOfItems()}.
431: */
432: public int getNumberOfItems() {
433: if (hasAnimVal) {
434: return super .getNumberOfItems();
435: }
436: return getPathSegList().getNumberOfItems();
437: }
438:
439: /**
440: * <b>DOM</b>: Implements {@link SVGPathSegList#getItem(int)}.
441: */
442: public SVGPathSeg getItem(int index) throws DOMException {
443: if (hasAnimVal) {
444: return super .getItem(index);
445: }
446: return getPathSegList().getItem(index);
447: }
448:
449: /**
450: * Returns the value of the DOM attribute containing the point list.
451: */
452: protected String getValueAsString() {
453: if (itemList.size() == 0) {
454: return "";
455: }
456: StringBuffer sb = new StringBuffer(itemList.size() * 8);
457: Iterator i = itemList.iterator();
458: if (i.hasNext()) {
459: sb.append(((SVGItem) i.next()).getValueAsString());
460: }
461: while (i.hasNext()) {
462: sb.append(getItemSeparator());
463: sb.append(((SVGItem) i.next()).getValueAsString());
464: }
465: return sb.toString();
466: }
467:
468: /**
469: * Sets the DOM attribute value containing the point list.
470: */
471: protected void setAttributeValue(String value) {
472: }
473:
474: /**
475: * <b>DOM</b>: Implements {@link SVGPathSegList#clear()}.
476: */
477: public void clear() throws DOMException {
478: throw element.createDOMException(
479: DOMException.NO_MODIFICATION_ALLOWED_ERR,
480: "readonly.pathseg.list", null);
481: }
482:
483: /**
484: * <b>DOM</b>: Implements {@link SVGPathSegList#initialize(SVGPathSeg)}.
485: */
486: public SVGPathSeg initialize(SVGPathSeg newItem)
487: throws DOMException, SVGException {
488: throw element.createDOMException(
489: DOMException.NO_MODIFICATION_ALLOWED_ERR,
490: "readonly.pathseg.list", null);
491: }
492:
493: /**
494: * <b>DOM</b>: Implements {@link
495: * SVGPathSegList#insertItemBefore(SVGPathSeg, int)}.
496: */
497: public SVGPathSeg insertItemBefore(SVGPathSeg newItem, int index)
498: throws DOMException, SVGException {
499: throw element.createDOMException(
500: DOMException.NO_MODIFICATION_ALLOWED_ERR,
501: "readonly.pathseg.list", null);
502: }
503:
504: /**
505: * <b>DOM</b>: Implements {@link
506: * SVGPathSegList#replaceItem(SVGPathSeg, int)}.
507: */
508: public SVGPathSeg replaceItem(SVGPathSeg newItem, int index)
509: throws DOMException, SVGException {
510: throw element.createDOMException(
511: DOMException.NO_MODIFICATION_ALLOWED_ERR,
512: "readonly.pathseg.list", null);
513: }
514:
515: /**
516: * <b>DOM</b>: Implements {@link SVGPathSegList#removeItem(int)}.
517: */
518: public SVGPathSeg removeItem(int index) throws DOMException {
519: throw element.createDOMException(
520: DOMException.NO_MODIFICATION_ALLOWED_ERR,
521: "readonly.pathseg.list", null);
522: }
523:
524: /**
525: * <b>DOM</b>: Implements {@link SVGPathSegList#appendItem(SVGPathSeg)}.
526: */
527: public SVGPathSeg appendItem(SVGPathSeg newItem)
528: throws DOMException {
529: throw element.createDOMException(
530: DOMException.NO_MODIFICATION_ALLOWED_ERR,
531: "readonly.pathseg.list", null);
532: }
533:
534: /**
535: * Pass by reference integer for use by newItem.
536: */
537: private int[] parameterIndex = new int[1];
538:
539: /**
540: * Creates a new SVGPathSegItem from the given path command and array
541: * of parameter values.
542: */
543: protected SVGPathSegItem newItem(short command,
544: float[] parameters, int[] j) {
545: switch (command) {
546: case SVGPathSeg.PATHSEG_ARC_ABS:
547: case SVGPathSeg.PATHSEG_ARC_REL:
548: return new SVGPathSegArcItem(command,
549: PATHSEG_LETTERS[command], parameters[j[0]++],
550: parameters[j[0]++], parameters[j[0]++],
551: parameters[j[0]++] != 0,
552: parameters[j[0]++] != 0, parameters[j[0]++],
553: parameters[j[0]++]);
554: case SVGPathSeg.PATHSEG_CLOSEPATH:
555: return new SVGPathSegItem(command,
556: PATHSEG_LETTERS[command]);
557: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
558: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
559: return new SVGPathSegCurvetoCubicItem(command,
560: PATHSEG_LETTERS[command], parameters[j[0]++],
561: parameters[j[0]++], parameters[j[0]++],
562: parameters[j[0]++], parameters[j[0]++],
563: parameters[j[0]++]);
564: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
565: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
566: return new SVGPathSegCurvetoCubicSmoothItem(command,
567: PATHSEG_LETTERS[command], parameters[j[0]++],
568: parameters[j[0]++], parameters[j[0]++],
569: parameters[j[0]++]);
570: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
571: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
572: return new SVGPathSegCurvetoQuadraticItem(command,
573: PATHSEG_LETTERS[command], parameters[j[0]++],
574: parameters[j[0]++], parameters[j[0]++],
575: parameters[j[0]++]);
576: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
577: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
578: return new SVGPathSegCurvetoQuadraticSmoothItem(
579: command, PATHSEG_LETTERS[command],
580: parameters[j[0]++], parameters[j[0]++]);
581: case SVGPathSeg.PATHSEG_LINETO_ABS:
582: case SVGPathSeg.PATHSEG_LINETO_REL:
583: case SVGPathSeg.PATHSEG_MOVETO_ABS:
584: case SVGPathSeg.PATHSEG_MOVETO_REL:
585: return new SVGPathSegMovetoLinetoItem(command,
586: PATHSEG_LETTERS[command], parameters[j[0]++],
587: parameters[j[0]++]);
588: case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
589: case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
590: return new SVGPathSegLinetoHorizontalItem(command,
591: PATHSEG_LETTERS[command], parameters[j[0]++]);
592: case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
593: case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
594: return new SVGPathSegLinetoVerticalItem(command,
595: PATHSEG_LETTERS[command], parameters[j[0]++]);
596: }
597: System.err.println("command == " + command);
598: return null;
599: }
600:
601: /**
602: * Sets the animated value.
603: */
604: protected void setAnimatedValue(short[] commands,
605: float[] parameters) {
606: int size = itemList.size();
607: int i = 0;
608: int[] j = parameterIndex;
609: j[0] = 0;
610: while (i < size && i < commands.length) {
611: SVGPathSeg s = (SVGPathSeg) itemList.get(i);
612: if (s.getPathSegType() != commands[i]) {
613: s = newItem(commands[i], parameters, j);
614: } else {
615: switch (commands[i]) {
616: case SVGPathSeg.PATHSEG_ARC_ABS:
617: case SVGPathSeg.PATHSEG_ARC_REL: {
618: SVGPathSegArcItem ps = (SVGPathSegArcItem) s;
619: ps.r1 = parameters[j[0]++];
620: ps.r2 = parameters[j[0]++];
621: ps.angle = parameters[j[0]++];
622: ps.largeArcFlag = parameters[j[0]++] != 0;
623: ps.sweepFlag = parameters[j[0]++] != 0;
624: ps.x = parameters[j[0]++];
625: ps.y = parameters[j[0]++];
626: break;
627: }
628: case SVGPathSeg.PATHSEG_CLOSEPATH:
629: // Nothing to update.
630: break;
631: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
632: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL: {
633: SVGPathSegCurvetoCubicItem ps = (SVGPathSegCurvetoCubicItem) s;
634: ps.x1 = parameters[j[0]++];
635: ps.y1 = parameters[j[0]++];
636: ps.x2 = parameters[j[0]++];
637: ps.y2 = parameters[j[0]++];
638: ps.x = parameters[j[0]++];
639: ps.y = parameters[j[0]++];
640: break;
641: }
642: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
643: case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL: {
644: SVGPathSegCurvetoCubicSmoothItem ps = (SVGPathSegCurvetoCubicSmoothItem) s;
645: ps.x2 = parameters[j[0]++];
646: ps.y2 = parameters[j[0]++];
647: ps.x = parameters[j[0]++];
648: ps.y = parameters[j[0]++];
649: break;
650: }
651: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
652: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL: {
653: SVGPathSegCurvetoQuadraticItem ps = (SVGPathSegCurvetoQuadraticItem) s;
654: ps.x1 = parameters[j[0]++];
655: ps.y1 = parameters[j[0]++];
656: ps.x = parameters[j[0]++];
657: ps.y = parameters[j[0]++];
658: break;
659: }
660: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
661: case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: {
662: SVGPathSegCurvetoQuadraticSmoothItem ps = (SVGPathSegCurvetoQuadraticSmoothItem) s;
663: ps.x = parameters[j[0]++];
664: ps.y = parameters[j[0]++];
665: break;
666: }
667: case SVGPathSeg.PATHSEG_LINETO_ABS:
668: case SVGPathSeg.PATHSEG_LINETO_REL:
669: case SVGPathSeg.PATHSEG_MOVETO_ABS:
670: case SVGPathSeg.PATHSEG_MOVETO_REL: {
671: SVGPathSegMovetoLinetoItem ps = (SVGPathSegMovetoLinetoItem) s;
672: ps.x = parameters[j[0]++];
673: ps.y = parameters[j[0]++];
674: break;
675: }
676: case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
677: case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS: {
678: SVGPathSegLinetoHorizontalItem ps = (SVGPathSegLinetoHorizontalItem) s;
679: ps.x = parameters[j[0]++];
680: break;
681: }
682: case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
683: case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS: {
684: SVGPathSegLinetoVerticalItem ps = (SVGPathSegLinetoVerticalItem) s;
685: ps.y = parameters[j[0]++];
686: break;
687: }
688: }
689: }
690: i++;
691: }
692: while (i < commands.length) {
693: appendItemImpl(newItem(commands[i], parameters, j));
694: i++;
695: }
696: while (size > commands.length) {
697: removeItemImpl(--size);
698: }
699: }
700:
701: /**
702: * Resets the value of the associated attribute. Does nothing, since
703: * there is no attribute for an animated value.
704: */
705: protected void resetAttribute() {
706: }
707:
708: /**
709: * Resets the value of the associated attribute. Does nothing, since
710: * there is no attribute for an animated value.
711: */
712: protected void resetAttribute(SVGItem item) {
713: }
714:
715: /**
716: * Initializes the list, if needed. Does nothing, since there is no
717: * attribute to read the list from.
718: */
719: protected void revalidate() {
720: valid = true;
721: }
722: }
723: }
|