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.util.SVGConstants;
029:
030: import org.w3c.dom.DOMException;
031:
032: import org.w3c.dom.svg.SVGRGBColor;
033:
034: import com.sun.perseus.j2d.RGB;
035:
036: /**
037: * <code>Stop</code> class represents the <code><stop></code>
038: * SVG Tiny 1.2 element.
039: *
040: * @version $Id: Stop.java,v 1.5 2006/06/29 10:47:34 ln156897 Exp $
041: */
042: public class Stop extends CompositeGraphicsNode {
043: /**
044: * offset is required on <stop>
045: */
046: static final String[] REQUIRED_TRAITS = { SVGConstants.SVG_OFFSET_ATTRIBUTE };
047:
048: /**
049: * The default stop color.
050: */
051: static final RGB DEFAULT_STOP_COLOR = RGB.black;
052:
053: /**
054: * The default stop opacity.
055: */
056: static final float DEFAULT_STOP_OPACITY = 1;
057: /**
058: * The stop's color
059: */
060: RGB stopColor = DEFAULT_STOP_COLOR;
061:
062: /**
063: * The stop's opacity
064: */
065: float stopOpacity = DEFAULT_STOP_OPACITY;
066:
067: /**
068: * The stop offset value.
069: */
070: float offset;
071:
072: /**
073: * Constructor.
074: *
075: * @param ownerDocument this element's owner <code>DocumentNode</code>
076: */
077: public Stop(final DocumentNode ownerDocument) {
078: super (ownerDocument);
079: }
080:
081: /**
082: * @return an adequate <code>ElementNodeProxy</code> for this node.
083: */
084: ElementNodeProxy buildProxy() {
085: return new CompositeGraphicsNodeProxy(this );
086: }
087:
088: /**
089: * @return the SVGConstants.SVG_STOP_TAG value
090: */
091: public String getLocalName() {
092: return SVGConstants.SVG_STOP_TAG;
093: }
094:
095: /**
096: * Used by <code>DocumentNode</code> to create a new instance from
097: * a prototype <code>Stop</code>.
098: *
099: * @param doc the <code>DocumentNode</code> for which a new node is
100: * should be created.
101: * @return a new <code>SolidColor</code> for the requested document.
102: */
103: public ElementNode newInstance(final DocumentNode doc) {
104: return new Stop(doc);
105: }
106:
107: /**
108: * Sets the stop-color property.
109: *
110: * @param newStopColor the new stop-color property
111: */
112: public void setStopColor(final RGB newStopColor) {
113: if (stopColor.equals(newStopColor)) {
114: return;
115: }
116:
117: stopColor = newStopColor;
118: updateGradient();
119: }
120:
121: /**
122: * @return the current stopColor property.
123: */
124: public RGB getStopColor() {
125: return stopColor;
126: }
127:
128: /**
129: * Sets the stop-opacity property.
130: *
131: * @param newStopOpacity the new stop-opacity property
132: */
133: public void setStopOpacity(final float newStopOpacity) {
134: if (newStopOpacity == stopOpacity) {
135: return;
136: }
137:
138: stopOpacity = newStopOpacity;
139: updateGradient();
140: }
141:
142: /**
143: * @return the current stopOpacity property.
144: */
145: public float getStopOpacity() {
146: return stopOpacity;
147: }
148:
149: /**
150: * Sets the stop offset
151: *
152: * @param newOffset the new offset
153: */
154: public void setOffset(final float newOffset) {
155: if (newOffset == offset) {
156: return;
157: }
158:
159: offset = newOffset;
160: updateGradient();
161: }
162:
163: /**
164: * @return the stop's offset
165: */
166: public float getOffset() {
167: return offset;
168: }
169:
170: /**
171: * Should be called by the stop every time its parent gradient
172: * should recompute its state.
173: */
174: void updateGradient() {
175: if (parent != null) {
176: if (parent instanceof GradientElement) {
177: ((GradientElement) parent).onPaintChange();
178: }
179: }
180: }
181:
182: /**
183: * @return the number of properties supported by this node
184: */
185: public int getNumberOfProperties() {
186: return GraphicsNode.NUMBER_OF_PROPERTIES;
187: }
188:
189: /**
190: * @param traitName the name of the trait which the element may support.
191: * @return true if this element supports the given trait in one of the
192: * trait accessor methods.
193: */
194: boolean supportsTrait(final String traitName) {
195: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == traitName
196: || SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == traitName
197: || SVGConstants.SVG_OFFSET_ATTRIBUTE == traitName) {
198: return true;
199: } else {
200: return super .supportsTrait(traitName);
201: }
202: }
203:
204: /**
205: * @return an array of traits that are required by this element.
206: */
207: public String[] getRequiredTraits() {
208: return REQUIRED_TRAITS;
209: }
210:
211: /**
212: * @param traitName the trait name.
213: */
214: TraitAnim createTraitAnimImpl(final String traitName) {
215: if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == traitName
216: || SVGConstants.SVG_OFFSET_ATTRIBUTE == traitName) {
217: return new FloatTraitAnim(this , traitName, TRAIT_TYPE_FLOAT);
218: } else if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == traitName) {
219: return new FloatTraitAnim(this , traitName,
220: TRAIT_TYPE_SVG_RGB_COLOR);
221: } else {
222: return super .createTraitAnimImpl(traitName);
223: }
224: }
225:
226: /**
227: * @param name the requested trait name (e.g., "ry")
228: * @return the trait's value, as a string.
229: *
230: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
231: * trait is not supported on this element or null.
232: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
233: * trait's computed value cannot be converted to a String (SVG Tiny only).
234: */
235: public String getTraitImpl(final String name) throws DOMException {
236: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == name) {
237: return stopColor.toString();
238: } else if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name) {
239: return Float.toString(stopOpacity);
240: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
241: return Float.toString(offset);
242: } else {
243: return super .getTraitImpl(name);
244: }
245: }
246:
247: /**
248: * @param name the requested trait name (e.g., "y")
249: * @return the requested trait value
250: *
251: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
252: * trait is not supported on this element or null.
253: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
254: * trait's computed value cannot be converted to a float
255: * @throws SecurityException if the application does not have the necessary
256: * privilege rights to access this (SVG) content.
257: */
258: float getFloatTraitImpl(final String name) throws DOMException {
259: if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name) {
260: return stopOpacity;
261: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
262: return offset;
263: } else {
264: return super .getFloatTraitImpl(name);
265: }
266: }
267:
268: /**
269: * @param name the requested trait's name.
270: * @return the requested trait's value, as an <code>SVGRGBColor</code>.
271: *
272: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
273: * trait is not supported on this element or null.
274: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
275: * trait's computed value cannot be converted to {@link
276: * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
277: * @throws SecurityException if the application does not have the necessary
278: * privilege rights to access this (SVG) content.
279: */
280: SVGRGBColor getRGBColorTraitImpl(final String name)
281: throws DOMException {
282: // We use .equals here because name is not interned.
283: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE.equals(name)) {
284: return stopColor;
285: } else {
286: return super .getRGBColorTraitImpl(name);
287: }
288: }
289:
290: /**
291: * Set the trait value as float array.
292: *
293: * @param name the trait's name.
294: * @param value the trait's value.
295: *
296: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
297: * trait is not supported on this element.
298: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
299: * trait's value cannot be specified as a float
300: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
301: * value is an invalid value for the given trait.
302: */
303: void setFloatArrayTrait(final String name, final float[][] value)
304: throws DOMException {
305: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == name) {
306: setStopColor(toRGB(name, value));
307: } else if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name) {
308: if (value[0][0] < 0 || value[0][0] > 1) {
309: throw illegalTraitValue(name, Float
310: .toString(value[0][0]));
311: }
312: setStopOpacity(value[0][0]);
313: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
314: setOffset(value[0][0]);
315: } else {
316: super .setFloatArrayTrait(name, value);
317: }
318: }
319:
320: /**
321: * Validates the input trait value.
322: *
323: * @param traitName the name of the trait to be validated.
324: * @param value the value to be validated
325: * @param reqNamespaceURI the namespace of the element requesting
326: * validation.
327: * @param reqLocalName the local name of the element requesting validation.
328: * @param reqTraitNamespace the namespace of the trait which has the values
329: * value on the requesting element.
330: * @param reqTraitName the name of the trait which has the values value on
331: * the requesting element.
332: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
333: * value is incompatible with the given trait.
334: */
335: public float[][] validateFloatArrayTrait(final String traitName,
336: final String value, final String reqNamespaceURI,
337: final String reqLocalName, final String reqTraitNamespace,
338: final String reqTraitName) throws DOMException {
339: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == traitName) {
340: RGB color = parseColorTrait(
341: SVGConstants.SVG_COLOR_ATTRIBUTE, value);
342: if (color == null) {
343: throw illegalTraitValue(traitName, value);
344: }
345: return new float[][] { { color.getRed(), color.getGreen(),
346: color.getBlue() } };
347: } else if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == traitName) {
348: return new float[][] { { parseFloatTrait(traitName, value) } };
349: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == traitName) {
350: return new float[][] { { parseFloatTrait(traitName, value) } };
351: } else {
352: return super .validateFloatArrayTrait(traitName, value,
353: reqNamespaceURI, reqLocalName, reqTraitNamespace,
354: reqTraitName);
355: }
356:
357: }
358:
359: /**
360: * CompositeGraphicsNode handles the graphics node traits.
361: * Other attributes are handled by the super class.
362: *
363: * Supported traits: stroke-width, stroke-miterlimit, stroke-dashoffset,
364: * fill-rule, stroke-linejoin, stroke-linecap, display, visibility,
365: * color, fill, stroke, fill-opacity, stroke-opacity, stroke-dasharray
366: *
367: * @param name the name of the trait to set.
368: * @param value the value of the trait to set.
369: *
370: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
371: * trait is not supported on this element or null.
372: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
373: * trait's value cannot be specified as a String
374: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
375: * value is an invalid value for the given trait or null.
376: * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
377: * attempt is made to change readonly trait.
378: */
379: public void setTraitImpl(final String name, final String value)
380: throws DOMException {
381: if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name) {
382:
383: // ======================= stop-opacity ===================== //
384:
385: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
386: setStopOpacity(DEFAULT_STOP_OPACITY);
387: } else {
388: setStopOpacity(parsePositiveFloatTrait(name, value));
389: }
390: } else if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE.equals(name)) {
391:
392: // ======================== stop-color ===================== //
393:
394: if (SVGConstants.CSS_INHERIT_VALUE.equals(value)) {
395: setStopColor(DEFAULT_STOP_COLOR);
396: } else if (SVGConstants.CSS_CURRENTCOLOR_VALUE
397: .equals(value)) {
398: setStopColor(getColor());
399: } else {
400: setStopColor(parseColorTrait(
401: SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, value));
402: }
403: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
404: setOffset(parseFloatTrait(name, value));
405: } else {
406: super .setTraitImpl(name, value);
407: }
408: }
409:
410: /**
411: * Set the trait value as float.
412: *
413: * Supported float traits: stroke-width, stroke-miterlimit,
414: * stroke-dashoffset, fill-opacity, stroke-opacity.
415: *
416: * @param name the name of the trait to set.
417: * @param value the value of the trait to set.
418: *
419: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
420: * trait is not supported on this element.
421: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
422: * trait's value cannot be specified as a float
423: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
424: * value is an invalid value for the given trait.
425: * @throws SecurityException if the application does not have the necessary
426: * privilege rights to access this (SVG) content.
427: */
428: public void setFloatTraitImpl(final String name, final float value)
429: throws DOMException {
430: if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name) {
431: setStopOpacity(value);
432: } else if (SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
433: setOffset(value);
434: } else {
435: super .setFloatTraitImpl(name, value);
436: }
437: }
438:
439: /**
440: * @param name the name of the trait to convert.
441: * @param value the float trait value to convert.
442: */
443: String toStringTrait(final String name, final float[][] value) {
444: if (SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE == name
445: || SVGConstants.SVG_OFFSET_ATTRIBUTE == name) {
446: return Float.toString(value[0][0]);
447: } else if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE == name) {
448: return toRGBString(name, value);
449: } else {
450: return super .toStringTrait(name, value);
451: }
452: }
453:
454: /**
455: * Set the trait value as {@link org.w3c.dom.svg.SVGRGBColor SVGRGBColor}.
456: *
457: * Supported color traits: color, fill, stroke
458: *
459: * @param name the name of the trait to set.
460: * @param value the value of the trait to set.
461: *
462: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
463: * trait is not supported on this element or null.
464: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
465: * trait's value cannot be specified as an {@link
466: * org.w3c.dom.svg.SVGRGBColor SVGRGBColor}
467: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
468: * value is null.
469: * @throws SecurityException if the application does not have the necessary
470: * privilege rights to access this (SVG) content.
471: */
472: void setRGBColorTraitImpl(final String name, final SVGRGBColor color)
473: throws DOMException {
474: try {
475: if (SVGConstants.SVG_STOP_COLOR_ATTRIBUTE.equals(name)) {
476: setStopColor((RGB) color);
477: } else {
478: super .setRGBColorTraitImpl(name, color);
479: }
480: } catch (IllegalArgumentException iae) {
481: throw new DOMException(DOMException.INVALID_ACCESS_ERR, iae
482: .getMessage());
483: }
484: }
485:
486: }
|