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: */package com.sun.perseus.model;
026:
027: import com.sun.perseus.platform.URLResolver;
028:
029: import com.sun.perseus.util.SVGConstants;
030:
031: import org.w3c.dom.DOMException;
032:
033: import org.w3c.dom.svg.SVGMatrix;
034: import org.w3c.dom.svg.SVGRect;
035:
036: import com.sun.perseus.j2d.Transform;
037:
038: /**
039: * Represents an SVG Tiny <code><a></code> element.
040: * An symbol is a simple <code>Group</code> extension which
041: * simply has a href and a target attribute.
042: *
043: * @version $Id: Symbol.java,v 1.6 2006/06/29 10:47:35 ln156897 Exp $
044: */
045: public class Symbol extends Group {
046: /**
047: * This SVG node's viewBox. If null, then there is
048: * no viewBox.
049: */
050: protected float[][] viewBox;
051:
052: /**
053: * Constructor.
054: *
055: * @param ownerDocument this element's owner <code>DocumentNode</code>
056: */
057: public Symbol(final DocumentNode ownerDocument) {
058: super (ownerDocument);
059: }
060:
061: /**
062: * @return the SVGConstants.SVG_A_TAG value
063: */
064: public String getLocalName() {
065: return SVGConstants.SVG_SYMBOL_TAG;
066: }
067:
068: /**
069: * Used by <code>DocumentNode</code> to create a new instance from
070: * a prototype <code>SymbolNode</code>.
071: *
072: * @param doc the <code>DocumentNode</code> for which a new node is
073: * should be created.
074: * @return a new <code>Symbol</code> for the requested document.
075: */
076: public ElementNode newInstance(final DocumentNode doc) {
077: return new Symbol(doc);
078: }
079:
080: /**
081: * Apply this node's viewBox x/y translation if it is not (0,0).
082: *
083: * @param tx the <code>Transform</code> to apply additional node
084: * transforms to. This may be null.
085: * @param workTx a <code>Transform</code> which can be re-used if a
086: * new <code>Transform</code> needs to be created and workTx
087: * is not the same instance as tx.
088: * @return a transform with this node's transform added.
089: */
090: protected Transform appendTransform(Transform tx,
091: final Transform workTx) {
092: if (viewBox == null
093: || (viewBox[0][0] == 0 && viewBox[0][1] == 0)) {
094: return tx;
095: }
096:
097: tx = recycleTransform(tx, workTx);
098:
099: if (viewBox != null) {
100: tx.mTranslate(-viewBox[0][0], -viewBox[0][1]);
101: }
102:
103: return tx;
104: }
105:
106: // JAVADOC COMMENT ELIDED
107: public SVGRect getBBox() {
108: if (viewBox != null) {
109: Transform t = new Transform(1, 0, 0, 1, -viewBox[0][0],
110: -viewBox[0][1]);
111: return addBBox(null, t);
112: }
113:
114: return addBBox(null, null);
115: }
116:
117: // JAVADOC COMMENT ELIDED
118: public SVGMatrix getScreenCTM() {
119: SVGMatrix m = super .getScreenCTM();
120: if (m != null) {
121: if (viewBox != null) {
122: m = m.mTranslate(viewBox[0][0], viewBox[0][1]);
123: }
124: }
125:
126: return m;
127: }
128:
129: /**
130: * Sets a new value for the viewBox. If there viewBox is
131: * not null, it should be of size 4
132: * @param newViewBox the new viewBox for this <tt>SVG</tt>
133: *
134: * @throws IllegalArgumentException if the input viewBox is
135: * not null and of size other than 4.
136: */
137: public void setViewBox(final float[][] newViewBox) {
138:
139: if (newViewBox != null) {
140: if (newViewBox.length != 3 || newViewBox[0] == null
141: || newViewBox[1] == null || newViewBox[2] == null
142: || newViewBox[0].length != 2
143: || newViewBox[1][0] < 0 || newViewBox[2][0] < 0) {
144: throw new IllegalArgumentException();
145: }
146: }
147:
148: modifyingNode();
149:
150: if (viewBox == null) {
151: viewBox = new float[3][];
152: viewBox[0] = new float[2];
153: viewBox[1] = new float[1];
154: viewBox[2] = new float[1];
155: }
156:
157: viewBox[0][0] = newViewBox[0][0];
158: viewBox[0][1] = newViewBox[0][1];
159: viewBox[1][0] = newViewBox[1][0];
160: viewBox[2][0] = newViewBox[2][0];
161:
162: recomputeTransformState();
163: recomputeProxyTransformState();
164: computeCanRenderEmptyViewBoxBit(viewBox);
165: modifiedNode();
166: }
167:
168: /**
169: * @return this Symbol's viewBox
170: */
171: public float[][] getViewBox() {
172: return viewBox;
173: }
174:
175: /**
176: * Symbol handles the target trait.
177: *
178: * @param traitName the name of the trait which the element may support.
179: * @return true if this element supports the given trait in one of the
180: * trait accessor methods.
181: */
182: boolean supportsTrait(final String traitName) {
183: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName) {
184: return true;
185: } else {
186: return super .supportsTrait(traitName);
187: }
188: }
189:
190: /**
191: * Symbol handles the viewBox trait.
192: *
193: * @param name the requested trait name
194: * @return the requested trait's value.
195: *
196: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
197: * trait is not supported on this element or null.
198: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
199: * trait's computed value cannot be converted to a String (SVG Tiny only).
200: */
201: public String getTraitImpl(final String name) throws DOMException {
202: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
203: if (viewBox == null) {
204: return "";
205: } else {
206: return "" + viewBox[0][0] + SVGConstants.COMMA
207: + viewBox[0][1] + SVGConstants.COMMA
208: + viewBox[1][0] + SVGConstants.COMMA
209: + viewBox[2][0];
210: }
211: } else {
212: return super .getTraitImpl(name);
213: }
214: }
215:
216: /**
217: * @param name the name of the trait to convert.
218: * @param value the float trait value to convert.
219: */
220: String toStringTrait(final String name, final float[][] value) {
221: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
222: float[] vb = { value[0][0], value[0][1], value[1][0],
223: value[2][0] };
224: return toStringTrait(vb);
225: } else {
226: return super .toStringTrait(name, value);
227: }
228: }
229:
230: /**
231: * Symbol handles the viewBox Rect trait.
232: *
233: * @param name the requested trait name (e.g., "viewBox")
234: * @return the requested trait SVGRect value.
235: *
236: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
237: * trait is not supported on this element or null.
238: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
239: * trait's computed value cannot be converted to {@link
240: * org.w3c.dom.svg.SVGRect SVGRect}
241: * @throws SecurityException if the application does not have the necessary
242: * privilege rights to access this (SVG) content.
243: */
244: SVGRect getRectTraitImpl(final String name) throws DOMException {
245: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE.equals(name)) {
246: return toSVGRect(viewBox);
247: } else {
248: return super .getRectTraitImpl(name);
249: }
250: }
251:
252: /**
253: * @param traitName the trait name.
254: */
255: TraitAnim createTraitAnimImpl(final String traitName) {
256: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName) {
257: return new FloatTraitAnim(this , traitName,
258: TRAIT_TYPE_SVG_RECT);
259: } else {
260: return super .createTraitAnimImpl(traitName);
261: }
262: }
263:
264: /**
265: * Symbol handles the viewBox trait.
266: *
267: * @param name the name of the trait to set.
268: * @param value the value of the trait to set.
269: *
270: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
271: * trait is not supported on this element or null.
272: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
273: * trait's value cannot be specified as a String
274: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
275: * value is an invalid value for the given trait or null.
276: * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
277: * attempt is made to change readonly trait.
278: */
279: public void setTraitImpl(final String name, final String value)
280: throws DOMException {
281: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
282: setViewBox(toViewBox(name, value));
283: } else {
284: super .setTraitImpl(name, value);
285: }
286: }
287:
288: /**
289: * Symbol handles the viewBox Rect trait.
290: *
291: * @param name the trait name (e.g., "viewBox"
292: * @param rect the trait value
293: *
294: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
295: * trait is not supported on this element or null.
296: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
297: * trait's value cannot be specified as an {@link org.w3c.dom.svg.SVGRect
298: * SVGRect}
299: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
300: * value is an invalid value for the given trait or null. SVGRect is
301: * invalid if the width or height values are set to negative.
302: * @throws SecurityException if the application does not have the necessary
303: * privilege rights to access this (SVG) content.
304: */
305: public void setRectTraitImpl(final String name, final SVGRect rect)
306: throws DOMException {
307: // Note that here, we use equals because the string
308: // has not been interned.
309: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE.equals(name)) {
310: if (rect == null) {
311: throw illegalTraitValue(name, null);
312: }
313:
314: if (rect.getWidth() < 0 || rect.getHeight() < 0) {
315: throw illegalTraitValue(name,
316: toStringTrait(new float[] { rect.getX(),
317: rect.getY(), rect.getWidth(),
318: rect.getHeight() }));
319: }
320:
321: setViewBox(new float[][] {
322: new float[] { rect.getX(), rect.getY() },
323: new float[] { rect.getWidth() },
324: new float[] { rect.getHeight() } });
325:
326: } else {
327: super .setRectTraitImpl(name, rect);
328: }
329: }
330:
331: /**
332: * Set the trait value as float.
333: *
334: * @param name the trait's name.
335: * @param value the trait's value.
336: *
337: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
338: * trait is not supported on this element.
339: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
340: * trait's value cannot be specified as a float
341: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
342: * value is an invalid value for the given trait.
343: */
344: void setFloatArrayTrait(final String name, final float[][] value)
345: throws DOMException {
346: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == name) {
347: setViewBox(value);
348: } else {
349: super .setFloatArrayTrait(name, value);
350: }
351: }
352:
353: /**
354: * Validates the input trait value.
355: *
356: * @param traitName the name of the trait to be validated.
357: * @param value the value to be validated
358: * @param reqNamespaceURI the namespace of the element requesting
359: * validation.
360: * @param reqLocalName the local name of the element requesting validation.
361: * @param reqTraitNamespace the namespace of the trait which has the values
362: * value on the requesting element.
363: * @param reqTraitName the name of the trait which has the values value on
364: * the requesting element.
365: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
366: * value is incompatible with the given trait.
367: */
368: public float[][] validateFloatArrayTrait(final String traitName,
369: final String value, final String reqNamespaceURI,
370: final String reqLocalName, final String reqTraitNamespace,
371: final String reqTraitName) throws DOMException {
372: if (SVGConstants.SVG_VIEW_BOX_ATTRIBUTE == traitName) {
373: return ownerDocument.viewBoxParser.parseViewBox(value);
374: } else {
375: return super.validateFloatArrayTrait(traitName, value,
376: reqNamespaceURI, reqLocalName, reqTraitNamespace,
377: reqTraitName);
378: }
379: }
380:
381: }
|