001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.model;
027:
028: import com.sun.perseus.platform.MathSupport;
029:
030: import com.sun.perseus.util.SVGConstants;
031:
032: import org.w3c.dom.DOMException;
033:
034: import org.w3c.dom.svg.SVGRect;
035: import org.w3c.dom.svg.SVGMatrix;
036: import org.w3c.dom.svg.SVGPath;
037: import org.w3c.dom.svg.SVGPoint;
038: import org.w3c.dom.svg.SVGRGBColor;
039: import org.w3c.dom.svg.SVGException;
040: import org.w3c.dom.svg.SVGSVGElement;
041:
042: import com.sun.perseus.j2d.Box;
043: import com.sun.perseus.j2d.Transform;
044: import com.sun.perseus.j2d.RGB;
045: import com.sun.perseus.j2d.Path;
046:
047: /**
048: * An <code>SVG</code> node represents an <code><code></code>
049: * element. In addition to a standard <code>StructureNode</code>, an
050: * <code>SVG</code> node can have a view box which causes a transform
051: * to be applied before drawing its children. This transform maps children
052: * viewBox coordinates into the SVG's parent <code>Viewport</code>
053: * coordinate system.
054: *
055: * @see Viewport
056: *
057: * @version $Id: SVG.java,v 1.12 2006/06/29 10:47:34 ln156897 Exp $
058: */
059: public class SVG extends StructureNode implements SVGSVGElement,
060: SVGPoint {
061: /**
062: * This SVG node's viewBox. If null, then there is
063: * no viewBox.
064: */
065: protected float[][] viewBox;
066:
067: /**
068: * Controls the way the svg viewBox is aligned in
069: * the parent viewport. For SVG Tiny, one of
070: * ALIGN_XMIDYMID or ALIGN_NONE.
071: */
072: protected int align = ALIGN_XMIDYMID;
073:
074: /**
075: * The SVG document's requested width
076: */
077: protected float width = 100;
078:
079: /**
080: * The SVG document's requested height
081: */
082: protected float height = 100;
083:
084: /**
085: * The current scale
086: */
087: protected float currentScale = 1;
088:
089: /**
090: * The current translate along the x axis
091: */
092: protected float tx;
093:
094: /**
095: * The current translate along the y axis
096: */
097: protected float ty;
098:
099: /**
100: * The current rotation angle.
101: */
102: protected float currentRotate;
103:
104: /**
105: * Precision adjustment, needed to keep the delta between the current
106: * time and the long values used internally.
107: */
108: protected float currentTimeDelta = 0f;
109:
110: /**
111: * Constructor.
112: *
113: * @param ownerDocument this element's owner <code>DocumentNode</code>
114: */
115: public SVG(final DocumentNode ownerDocument) {
116: super (ownerDocument);
117: }
118:
119: /**
120: * @return the SVGConstants.SVG_SVG_TAG value
121: */
122: public String getLocalName() {
123: return SVGConstants.SVG_SVG_TAG;
124: }
125:
126: /**
127: * The default value for the width trait and the height trait
128: * is '100%'.
129: *
130: * @return an array of trait default values, used if this element
131: * requires that the default trait value be explicitly
132: * set through a setTrait call. This happens, for example,
133: * with the begin trait value on animation elements.
134: */
135: public String[][] getDefaultTraits() {
136: return new String[][] {
137: { SVGConstants.SVG_WIDTH_ATTRIBUTE, "100%" },
138: { SVGConstants.SVG_HEIGHT_ATTRIBUTE, "100%" } };
139: }
140:
141: /**
142: * Used by <code>DocumentNode</code> to create a new instance from
143: * a prototype <code>SVG</code>.
144: *
145: * @param doc the <code>DocumentNode</code> for which a new node is
146: * should be created.
147: * @return a new <code>SVG</code> for the requested document.
148: */
149: public ElementNode newInstance(final DocumentNode doc) {
150: return new SVG(doc);
151: }
152:
153: /**
154: * Sets the viewport width.
155: * @param newWidth Should be greater than 0
156: */
157: public void setWidth(final float newWidth) {
158: if (newWidth < 0) {
159: throw new IllegalArgumentException();
160: }
161:
162: if (newWidth == width) {
163: return;
164: }
165:
166: modifyingNode();
167: this .width = newWidth;
168: computeCanRenderWidthBit(width);
169:
170: modifiedNode();
171: }
172:
173: /**
174: * @return the viewport's width
175: */
176: public float getWidth() {
177: return this .width;
178: }
179:
180: /**
181: * Sets the viewport height.
182: * @param newHeight Should be greater than 0
183: */
184: public void setHeight(final float newHeight) {
185: if (newHeight < 0) {
186: throw new IllegalArgumentException();
187: }
188:
189: if (newHeight == height) {
190: return;
191: }
192:
193: modifyingNode();
194: this .height = newHeight;
195: computeCanRenderHeightBit(height);
196: modifiedNode();
197: }
198:
199: /**
200: * @return the viewport height
201: */
202: public float getHeight() {
203: return this .height;
204: }
205:
206: /**
207: * Sets a new value for the viewBox.
208: * @param newViewBox the new viewBox for this <tt>SVG</tt>
209: *
210: * @throws IllegalArgumentException if the input viewBox is
211: * not null and not of a float {float[2], float[1], float[1]} array.
212: */
213: public void setViewBox(final float[][] newViewBox) {
214:
215: if (newViewBox != null) {
216: if (newViewBox.length != 3 || newViewBox[0] == null
217: || newViewBox[1] == null || newViewBox[2] == null
218: || newViewBox[0].length != 2
219: || newViewBox[1][0] < 0 || newViewBox[2][0] < 0) {
220: throw new IllegalArgumentException();
221: }
222: }
223:
224: if (equal(newViewBox, viewBox)) {
225: return;
226: }
227:
228: modifyingNode();
229:
230: if (newViewBox == null) {
231: viewBox = null;
232: } else {
233: if (viewBox == null) {
234: viewBox = new float[3][];
235: viewBox[0] = new float[2];
236: viewBox[1] = new float[1];
237: viewBox[2] = new float[1];
238: }
239:
240: viewBox[0][0] = newViewBox[0][0];
241: viewBox[0][1] = newViewBox[0][1];
242: viewBox[1][0] = newViewBox[1][0];
243: viewBox[2][0] = newViewBox[2][0];
244: }
245:
246: recomputeTransformState();
247: computeCanRenderEmptyViewBoxBit(viewBox);
248: modifiedNode();
249: }
250:
251: /**
252: * @return this SVG's viewBox
253: */
254: public float[][] getViewBox() {
255: return viewBox;
256: }
257:
258: /**
259: * @param newAlign new alignment property
260: */
261: public void setAlign(final int newAlign) {
262: if (newAlign != ALIGN_XMIDYMID && newAlign != ALIGN_NONE) {
263: throw new IllegalArgumentException();
264: }
265:
266: if (newAlign == align) {
267: return;
268: }
269:
270: modifyingNode();
271: this .align = newAlign;
272: recomputeTransformState();
273: modifiedNode();
274: }
275:
276: /**
277: * @return this node's align property
278: */
279: public int getAlign() {
280: return align;
281: }
282:
283: /**
284: * Appends the viewBox to viewport transform, if there is a viewBox.
285: *
286: * @param tx the <code>Transform</code> to apply additional node
287: * transforms to. This may be null.
288: * @param workTx a <code>Transform</code> which can be re-used if a
289: * new <code>Transform</code> needs to be created and workTx
290: * is not the same instance as tx.
291: * @return a transform with this node's transform added.
292: */
293: protected Transform appendTransform(Transform tx,
294: final Transform workTx) {
295: if (viewBox == null) {
296: return tx;
297: }
298:
299: tx = recycleTransform(tx, workTx);
300:
301: Viewport vp = (Viewport) getOwnerDocument();
302: float w = vp.getWidth();
303: float h = vp.getHeight();
304: getFittingTransform(viewBox[0][0], viewBox[0][1],
305: viewBox[1][0], viewBox[2][0], 0, 0, w, h, align, tx);
306:
307: return tx;
308: }
309:
310: /**
311: * SVG handles the version, baseProfile, viewBox, zoomAndPan,
312: * width, height and preserveAspectRatio traits.
313: *
314: * @param traitName the name of the trait which the element may support.
315: * @return true if this element supports the given trait in one of the
316: * trait accessor methods.
317: */
318: boolean supportsTrait(final String traitName) {
319: if (SVGConstants.SVG_BASE_PROFILE_ATTRIBUTE == traitName
320: || SVGConstants.SVG_VERSION_ATTRIBUTE == traitName
321: || SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName
322: || SVGConstants.SVG_ZOOM_AND_PAN_ATTRIBUTE == traitName
323: || SVGConstants.SVG_WIDTH_ATTRIBUTE == traitName
324: || SVGConstants.SVG_HEIGHT_ATTRIBUTE == traitName
325: || SVGConstants.SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE == traitName) {
326: return true;
327: } else {
328: return super .supportsTrait(traitName);
329: }
330: }
331:
332: /**
333: * SVG handles the version, baseProfile, viewBox and zoomAndPan traits.
334: *
335: * @param name the requested trait's name (e.g., "zoomAndPan")
336: * @return the requested trait string value (e.g., "disable")
337: *
338: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
339: * trait is not supported on this element or null.
340: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
341: * trait's computed value cannot be converted to a String (SVG Tiny only).
342: */
343: public String getTraitImpl(final String name) throws DOMException {
344: if (SVGConstants.SVG_VERSION_ATTRIBUTE == name) {
345: return SVGConstants.SVG_VERSION_1_1_VALUE;
346: } else if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
347: if (viewBox == null) {
348: return "";
349: } else {
350: return "" + viewBox[0][0] + SVGConstants.COMMA
351: + viewBox[0][1] + SVGConstants.COMMA
352: + viewBox[1][0] + SVGConstants.COMMA
353: + viewBox[2][0];
354: }
355: } else if (SVGConstants.SVG_ZOOM_AND_PAN_ATTRIBUTE == name) {
356: switch (ownerDocument.zoomAndPan) {
357: case Viewport.ZOOM_PAN_MAGNIFY:
358: return SVGConstants.SVG_MAGNIFY_VALUE;
359: case Viewport.ZOOM_PAN_DISABLE:
360: return SVGConstants.SVG_DISABLE_VALUE;
361: default:
362: throw new Error();
363: }
364: } else if (SVGConstants.SVG_BASE_PROFILE_ATTRIBUTE == name) {
365: return SVGConstants.SVG_BASE_PROFILE_TINY_VALUE;
366: } else if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name) {
367: return Float.toString(getWidth());
368: } else if (SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
369: return Float.toString(getHeight());
370: } else if (SVGConstants.SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE == name) {
371: return alignToStringTrait(align);
372: } else {
373: return super .getTraitImpl(name);
374: }
375: }
376:
377: /**
378: * SVG handles width and height float traits.
379: * Other attributes are handled by the super class.
380: *
381: * @param name the requested trait name.
382: * @param the requested trait's floating point value.
383: *
384: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
385: * trait is not supported on this element or null.
386: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
387: * trait's computed value cannot be converted to a float
388: * @throws SecurityException if the application does not have the necessary
389: * privilege rights to access this (SVG) content.
390: */
391: float getFloatTraitImpl(final String name) throws DOMException {
392: if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name) {
393: return getWidth();
394: } else if (SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
395: return getHeight();
396: } else {
397: return super .getFloatTraitImpl(name);
398: }
399: }
400:
401: /**
402: * SVG handles the viewBox Rect trait.
403: *
404: * @param name the requested trait name (e.g., "viewBox")
405: * @return the requested trait SVGRect value.
406: *
407: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
408: * trait is not supported on this element or null.
409: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
410: * trait's computed value cannot be converted to {@link
411: * org.w3c.dom.svg.SVGRect SVGRect}
412: * @throws SecurityException if the application does not have the necessary
413: * privilege rights to access this (SVG) content.
414: */
415: SVGRect getRectTraitImpl(final String name) throws DOMException {
416: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE.equals(name)) {
417: return toSVGRect(viewBox);
418: } else {
419: return super .getRectTraitImpl(name);
420: }
421: }
422:
423: /**
424: * @param traitName the trait name.
425: */
426: TraitAnim createTraitAnimImpl(final String traitName) {
427: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName) {
428: return new FloatTraitAnim(this , traitName,
429: TRAIT_TYPE_SVG_RECT);
430: } else {
431: return super .createTraitAnimImpl(traitName);
432: }
433: }
434:
435: /**
436: * Set the trait value as float.
437: *
438: * @param name the trait's name.
439: * @param value the trait's value.
440: *
441: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
442: * trait is not supported on this element.
443: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
444: * trait's value cannot be specified as a float
445: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
446: * value is an invalid value for the given trait.
447: */
448: void setFloatArrayTrait(final String name, final float[][] value)
449: throws DOMException {
450: if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name) {
451: checkPositive(name, value[0][0]);
452: setWidth(value[0][0]);
453: } else if (SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
454: checkPositive(name, value[0][0]);
455: setHeight(value[0][0]);
456: } else if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
457: setViewBox(value);
458: } else {
459: super .setFloatArrayTrait(name, value);
460: }
461: }
462:
463: /**
464: * Validates the input trait value.
465: *
466: * @param traitName the name of the trait to be validated.
467: * @param value the value to be validated
468: * @param reqNamespaceURI the namespace of the element requesting
469: * validation.
470: * @param reqLocalName the local name of the element requesting validation.
471: * @param reqTraitNamespace the namespace of the trait which has the values
472: * value on the requesting element.
473: * @param reqTraitName the name of the trait which has the values value on
474: * the requesting element.
475: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
476: * value is incompatible with the given trait.
477: */
478: public float[][] validateFloatArrayTrait(final String traitName,
479: final String value, final String reqNamespaceURI,
480: final String reqLocalName, final String reqTraitNamespace,
481: final String reqTraitName) throws DOMException {
482: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName) {
483: return ownerDocument.viewBoxParser.parseViewBox(value);
484: } else if (SVGConstants.SVG_WIDTH_ATTRIBUTE == traitName
485: || SVGConstants.SVG_HEIGHT_ATTRIBUTE == traitName) {
486: return new float[][] { { parsePositiveLengthTrait(
487: traitName, value, false) } };
488: } else {
489: return super .validateFloatArrayTrait(traitName, value,
490: reqNamespaceURI, reqLocalName, reqTraitNamespace,
491: reqTraitName);
492: }
493: }
494:
495: /**
496: * SVG handles the version, baseProfile, viewBox and zoomAndPan traits.
497: *
498: * @param name the trait's name (e.g., "viewBox")
499: * @param value the new trait's string value (e.g., "0 0 400 300")
500: *
501: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
502: * trait is not supported on this element or null.
503: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
504: * value is an invalid value for the given trait or null.
505: * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
506: * attempt is made to change readonly trait.
507: */
508: public void setTraitImpl(final String name, final String value)
509: throws DOMException {
510: if (SVGConstants.SVG_VERSION_ATTRIBUTE == name) {
511: checkWriteLoading(name);
512: if (!SVGConstants.SVG_VERSION_1_1_VALUE.equals(value)
513: && !SVGConstants.SVG_VERSION_1_2_VALUE
514: .equals(value)) {
515: throw illegalTraitValue(name, value);
516: }
517: } else if (SVGConstants.SVG_BASE_PROFILE_ATTRIBUTE == name) {
518: checkWriteLoading(name);
519: if (!SVGConstants.SVG_BASE_PROFILE_TINY_VALUE.equals(value)) {
520: throw illegalTraitValue(name, value);
521: }
522: } else if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
523: setViewBox(toViewBox(name, value));
524: } else if (SVGConstants.SVG_ZOOM_AND_PAN_ATTRIBUTE == name) {
525: if (SVGConstants.SVG_MAGNIFY_VALUE.equals(value)) {
526: ownerDocument.setZoomAndPan(Viewport.ZOOM_PAN_MAGNIFY);
527: applyUserTransform();
528: } else if (SVGConstants.SVG_DISABLE_VALUE.equals(value)) {
529: ownerDocument.setZoomAndPan(Viewport.ZOOM_PAN_DISABLE);
530: applyUserTransform();
531: } else {
532: throw illegalTraitValue(name, value);
533: }
534: } else if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name) {
535: checkWriteLoading(name);
536: setWidth(parsePositiveLengthTrait(name, value, true));
537: } else if (SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
538: checkWriteLoading(name);
539: setHeight(parsePositiveLengthTrait(name, value, false));
540: } else if (SVGConstants.SVG_PRESERVE_ASPECT_RATIO_ATTRIBUTE == name) {
541: checkWriteLoading(name);
542: if (SVGConstants.SVG_SVG_PRESERVE_ASPECT_RATIO_DEFAULT_VALUE
543: .equals(value)) {
544: setAlign(ALIGN_XMIDYMID);
545: } else if (SVGConstants.SVG_NONE_VALUE.equals(value)) {
546: setAlign(ALIGN_NONE);
547: } else {
548: throw illegalTraitValue(name, value);
549: }
550: } else {
551: super .setTraitImpl(name, value);
552: }
553: }
554:
555: /**
556: * SVG handles the viewBox Rect trait.
557: *
558: * @param name the trait name (e.g., "viewBox"
559: * @param rect the trait value
560: *
561: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
562: * trait is not supported on this element or null.
563: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
564: * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGRect
565: * SVGRect}
566: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
567: * value is an invalid value for the given trait or null. SVGRect is
568: * invalid if the width or height values are set to negative.
569: * @throws SecurityException if the application does not have the necessary
570: * privilege rights to access this (SVG) content.
571: */
572: public void setRectTraitImpl(final String name, final SVGRect rect)
573: throws DOMException {
574: // Note that here, we use equals because the string
575: // has not been interned.
576: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE.equals(name)) {
577: if (rect == null) {
578: throw illegalTraitValue(name, null);
579: }
580:
581: if (rect.getWidth() < 0 || rect.getHeight() < 0) {
582: throw illegalTraitValue(name,
583: toStringTrait(new float[] { rect.getX(),
584: rect.getY(), rect.getWidth(),
585: rect.getHeight() }));
586: }
587:
588: setViewBox(new float[][] {
589: new float[] { rect.getX(), rect.getY() },
590: new float[] { rect.getWidth() },
591: new float[] { rect.getHeight() } });
592:
593: } else {
594: super .setRectTraitImpl(name, rect);
595: }
596: }
597:
598: /**
599: * SVG handles width and height traits.
600: * Other traits are handled by the super class.
601: *
602: * @param name the trait's name.
603: * @param value the new trait's floating point value.
604: *
605: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
606: * trait is not supported on this element.
607: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
608: * trait's value cannot be specified as a float
609: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
610: * value is an invalid value for the given trait.
611: * @throws SecurityException if the application does not have the necessary
612: * privilege rights to access this (SVG) content.
613: */
614: public void setFloatTraitImpl(final String name, final float value)
615: throws DOMException {
616: try {
617: if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name) {
618: setWidth(value);
619: } else if (SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
620: setHeight(value);
621: } else {
622: super .setFloatTraitImpl(name, value);
623: }
624: } catch (IllegalArgumentException iae) {
625: throw illegalTraitValue(name, Float.toString(value));
626: }
627: }
628:
629: /**
630: * @param name the name of the trait to convert.
631: * @param value the float trait value to convert.
632: */
633: String toStringTrait(final String name, final float[][] value) {
634: if (SVGConstants.SVG_WIDTH_ATTRIBUTE == name
635: || SVGConstants.SVG_HEIGHT_ATTRIBUTE == name) {
636: return Float.toString(value[0][0]);
637: } else if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
638: float[] vb = { value[0][0], value[0][1], value[1][0],
639: value[2][0] };
640: return toStringTrait(vb);
641: } else {
642: return super .toStringTrait(name, value);
643: }
644: }
645:
646: // ========================================================================
647:
648: /**
649: *
650: */
651: public void setCurrentScale(final float value) throws DOMException {
652: if (value == 0) {
653: throw new DOMException(DOMException.INVALID_ACCESS_ERR,
654: Messages.formatMessage(
655: Messages.ERROR_INVALID_PARAMETER_VALUE,
656: new String[] { "SVGSVGElement",
657: "setCurrentScale", "value",
658: Float.toString(value) }));
659: } else {
660: currentScale = value;
661: applyUserTransform();
662: }
663: }
664:
665: /**
666: * @return the state of the animation timeline.
667: */
668: public boolean animationsPaused() {
669: throw new Error("NOT IMPLEMENTED");
670: }
671:
672: /**
673: * Pauses animation timeline. If user agent has pause/play control that
674: * control is changed to paused state. Has no effect if timeline already
675: * paused.
676: */
677: public void pauseAnimations() {
678: throw new Error("NOT IMPLEMENTED");
679: }
680:
681: /**
682: * Resumes animation timeline. If user agent has pause/play control that
683: * control is changed to playing state. Has no effect if timeline is already
684: * playing.
685: */
686: public void unpauseAnimations() {
687: throw new Error("NOT IMPLEMENTED");
688: }
689:
690: /**
691: *
692: */
693: public float getCurrentScale() {
694: return currentScale;
695: }
696:
697: /**
698: * <The position and size of the viewport (implicit or explicit) that
699: * corresponds to this 'svg' element. When the user agent is actually
700: * rendering the content, then the position and size values represent the
701: * actual values when rendering. If this SVG document is embedded as part
702: * of another document (e.g., via the HTML 'object' element), then the
703: * position and size are unitless values in the coordinate system of the
704: * parent document. (If the parent uses CSS or XSL layout, then unitless
705: * values represent pixel units for the current CSS or XSL viewport, as
706: * described in the CSS2 specification.) If the parent element does not
707: * have a coordinate system, then the user agent should provide reasonable
708: * default values for this attribute.
709: *
710: * <p> The object itself and its contents are both readonly. {@link
711: * org.w3c.dom.DOMException DOMException} with error code
712: * NO_MODIFICATION_ALLOWED_ERR is raised if attempt is made to modify
713: * it. The returned SVGRect object is "live", i.e. its x, y, width, height
714: * is automatically updated if viewport size or position changes. </p>
715: */
716: public SVGRect getViewport() {
717: throw new Error("NOT IMPLEMENTED");
718: }
719:
720: /**
721: *
722: */
723: public void setCurrentRotate(final float value) {
724: currentRotate = value;
725: applyUserTransform();
726: }
727:
728: /**
729: *
730: */
731: public float getCurrentRotate() {
732: return currentRotate;
733: }
734:
735: /**
736: * The initial values for currentTranslate is SVGPoint(0,0).
737: */
738: public SVGPoint getCurrentTranslate() {
739: return this ;
740: }
741:
742: /**
743: *
744: */
745: public float getCurrentTime() {
746: return ownerDocument.timeContainerRootSupport.lastSampleTime.value
747: / 1000f + currentTimeDelta;
748: }
749:
750: // JAVADOC COMMENT ELIDED
751: public void setCurrentTime(final float seconds) {
752: currentTimeDelta = seconds - ((long) (seconds * 1000)) / 1000f;
753: ownerDocument.timeContainerRootSupport.seekTo(new Time(
754: (long) (seconds * 1000)));
755: ownerDocument.applyAnimations();
756: }
757:
758: /**
759: * This
760: * object can be used to modify value of traits which are compatible with
761: * {@link org.w3c.dom.svg.SVGMatrix SVGMatrix} type using {@link
762: * org.w3c.dom.svg.SVGElement#setMatrixTrait setMatrixTrait} method. The
763: * internal representation of the matrix is as follows: <p>
764: *
765: * <pre>
766: * [ a c e ]
767: * [ b d f ]
768: * [ 0 0 1 ]
769: * </pre>
770: * </p>
771: *
772: * @see org.w3c.dom.svg.SVGMatrix
773: * @param a the 0,0 matrix parameter
774: * @param b the 1,0 matrix parameter
775: * @param c the 0,1 matrix parameter
776: * @param d the 1,1 matrix parameter
777: * @param e the 0,2 matrix parameter
778: * @param f the 1,2 matrix parameter
779: * @return a new <code>SVGMatrix</code> object with the requested
780: * components.
781: */
782:
783: public SVGMatrix createSVGMatrixComponents(final float a,
784: final float b, final float c, final float d, final float e,
785: final float f) {
786: return new Transform(a, b, c, d, e, f);
787: }
788:
789: /**
790: * @return a new {@link org.w3c.dom.svg.SVGRect SVGRect} object. This object
791: * can be used to modify value of traits which are compatible with {@link
792: * org.w3c.dom.svg.SVGRect SVGRect} type using {@link
793: * org.w3c.dom.svg.SVGElement#setRectTrait setRectTrait} method. The intial
794: * values for x, y, width, height of this new SVGRect are zero.
795: */
796: public SVGRect createSVGRect() {
797: return new Box(0, 0, 0, 0);
798: }
799:
800: /**
801: * @return new {@link org.w3c.dom.svg.SVGPath SVGPath} object. This object
802: * can be used to modify value of traits which are compatible with {@link
803: * org.w3c.dom.svg.SVGPath SVGPath} type using {@link
804: * org.w3c.dom.svg.SVGElement#setPathTrait setPathTrait} method.
805: */
806: public SVGPath createSVGPath() {
807: return new Path();
808: }
809:
810: /**
811: * @return new {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor} object. This
812: * object can be used to modify value of traits which are compatible with
813: * {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor} type using {@link
814: * org.w3c.dom.svg.SVGElement#setRGBColorTrait setRGBColorTrait} method.
815: * @throws SVGException with error code SVG_INVALID_VALUE_ERR: if any of the
816: * parameters is not in the 0..255 range.</li>
817: * @param red the red rgb component.
818: * @param green the green rgb component.
819: * @param blue the blue rgb component.
820: */
821: public SVGRGBColor createSVGRGBColor(final int red,
822: final int green, final int blue) throws SVGException {
823: if (red < 0 || red > 255 || green < 0 || green > 255
824: || blue < 0 || blue > 255) {
825: throw new SVGException(SVGException.SVG_INVALID_VALUE_ERR,
826: null);
827: }
828:
829: return new RGB(red, green, blue);
830: }
831:
832: /**
833: * Sets the x component of the point to the specified float value.
834: *
835: * @param value the x component value
836: *
837: */
838: public void setX(final float value) {
839: tx = value;
840: applyUserTransform();
841: }
842:
843: /**
844: * Sets the y component of the point to the specified float value.
845: *
846: * @param value the y component value
847: *
848: */
849:
850: public void setY(final float value) {
851: ty = value;
852: applyUserTransform();
853: }
854:
855: /**
856: * Returns the x component of the point.
857: *
858: * @return the x component of the point.
859: *
860: */
861: public float getX() {
862: return tx;
863: }
864:
865: /**
866: * Returns the y component of the point.
867: *
868: * @return the y component of the point.
869: *
870: */
871: public float getY() {
872: return ty;
873: }
874:
875: /**
876: * Uses currentScale, currentRotate, tx and ty to compute the
877: * owner document's transform.
878: */
879: void applyUserTransform() {
880: if (ownerDocument.zoomAndPan == Viewport.ZOOM_PAN_MAGNIFY) {
881: Transform txf = new Transform(currentScale, 0, 0,
882: currentScale, tx, ty);
883: txf.mRotate(currentRotate);
884:
885: ownerDocument.setTransform(txf);
886:
887: } else {
888: if (ownerDocument.getTransform() != null) {
889: // ownerDocument's transform has been touched
890: // so, set it to identity
891: ownerDocument.setTransform(new Transform(null));
892: }
893: }
894: }
895:
896: }
|