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.j2d.GraphicsProperties;
029: import com.sun.perseus.j2d.RenderGraphics;
030:
031: import com.sun.perseus.util.SVGConstants;
032:
033: import org.w3c.dom.DOMException;
034:
035: import com.sun.perseus.j2d.Box;
036: import com.sun.perseus.j2d.PathSupport;
037: import com.sun.perseus.j2d.Transform;
038:
039: /**
040: * A <code>Line</code> node models an SVG <code><line></code>
041: * element.
042: *
043: * @version $Id: Line.java,v 1.9 2006/06/29 10:47:32 ln156897 Exp $
044: */
045: public class Line extends AbstractShapeNode {
046: /**
047: * Starting position along the x-axis
048: */
049: protected float x1;
050:
051: /**
052: * Starting position along the y-axis
053: */
054: protected float y1;
055:
056: /**
057: * Ending position along the x-axis
058: */
059: protected float x2;
060:
061: /**
062: * Ending position along the y-axis
063: */
064: protected float y2;
065:
066: /**
067: * Constructor.
068: *
069: * @param ownerDocument this element's owner <code>DocumentNode</code>
070: */
071: public Line(final DocumentNode ownerDocument) {
072: super (ownerDocument);
073: }
074:
075: /**
076: * @return the SVGConstants.SVG_LINE_TAG value
077: */
078: public String getLocalName() {
079: return SVGConstants.SVG_LINE_TAG;
080: }
081:
082: /**
083: * Used by <code>DocumentNode</code> to create a new instance from
084: * a prototype <code>Line</code>.
085: *
086: * @param doc the <code>DocumentNode</code> for which a new node is
087: * should be created.
088: * @return a new <code>Line</code> for the requested document.
089: */
090: public ElementNode newInstance(final DocumentNode doc) {
091: return new Line(doc);
092: }
093:
094: /**
095: * @return x-axis coordinate of the starting point
096: */
097: public float getX1() {
098: return x1;
099: }
100:
101: /**
102: * @return y-axis coordinate of the starting point
103: */
104: public float getY1() {
105: return y1;
106: }
107:
108: /**
109: * @return x-axis coordinate of the termination point
110: */
111: public float getX2() {
112: return x2;
113: }
114:
115: /**
116: * @return y-axis coordinate of the termination point
117: */
118: public float getY2() {
119: return y2;
120: }
121:
122: /**
123: * @param newX1 new value for the termination point on the x-axis
124: */
125: public void setX1(final float newX1) {
126: if (newX1 == x1) {
127: return;
128: }
129: modifyingNode();
130: renderingDirty();
131: x1 = newX1;
132: modifiedNode();
133: }
134:
135: /**
136: * @param newX2 new value for the termination point on the x-axis
137: */
138: public void setX2(final float newX2) {
139: if (newX2 == x2) {
140: return;
141: }
142: modifyingNode();
143: renderingDirty();
144: x2 = newX2;
145: modifiedNode();
146: }
147:
148: /**
149: * @param newY1 new value for the starting point on the y-axis
150: */
151: public void setY1(final float newY1) {
152: if (newY1 == y1) {
153: return;
154: }
155: modifyingNode();
156: renderingDirty();
157: y1 = newY1;
158: modifiedNode();
159: }
160:
161: /**
162: * @param newY2 new value for the termination point on the y-axis
163: */
164: public void setY2(final float newY2) {
165: if (newY2 == y2) {
166: return;
167: }
168: modifyingNode();
169: renderingDirty();
170: y2 = newY2;
171: modifiedNode();
172: }
173:
174: /**
175: * @param rg the RenderGraphics on which to fill the shape.
176: */
177: public void fillShape(final RenderGraphics rg) {
178: }
179:
180: /**
181: * @param rg the RenderGraphics on which to draw the shape.
182: */
183: public void drawShape(final RenderGraphics rg) {
184: rg.drawLine(x1, y1, x2, y2);
185: }
186:
187: /**
188: * @param x the hit point coordinate along the x-axis, in user space.
189: * @param y the hit point coordinate along the y-axis, in user space.
190: * @param fillRule the fillRule to apply when testing for containment.
191: * @return true if the hit point is contained within the shape.
192: */
193: public boolean contains(final float x, final float y,
194: final int fillRule) {
195: return false;
196: }
197:
198: /**
199: * Returns the stroked shape, using the given stroke properties.
200: *
201: * @param gp the <code>GraphicsProperties</code> defining the rendering
202: * context.
203: * @return the shape's stroked path.
204: */
205: Object getStrokedPath(final GraphicsProperties gp) {
206: return PathSupport.getStrokedLine(x1, y1, x2, y2, gp);
207: }
208:
209: /**
210: * Supported traits: x1, x2, y1, y2
211: *
212: * @param traitName the name of the trait which the element may support.
213: * @return true if this element supports the given trait in one of the
214: * trait accessor methods.
215: */
216: boolean supportsTrait(final String traitName) {
217: if (SVGConstants.SVG_X1_ATTRIBUTE.equals(traitName)
218: || SVGConstants.SVG_X2_ATTRIBUTE.equals(traitName)
219: || SVGConstants.SVG_Y1_ATTRIBUTE.equals(traitName)
220: || SVGConstants.SVG_Y2_ATTRIBUTE.equals(traitName)) {
221: return true;
222: } else {
223: return super .supportsTrait(traitName);
224: }
225: }
226:
227: /**
228: * Supported traits: x1, x2, y1, y2
229: *
230: * @param name the requested trait's name.
231: * @return the trait's string value.
232: *
233: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
234: * trait is not supported on this element or null.
235: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
236: * trait's computed value cannot be converted to a String (SVG Tiny only).
237: */
238: public String getTraitImpl(final String name) throws DOMException {
239: if (SVGConstants.SVG_X1_ATTRIBUTE == name) {
240: return Float.toString(x1);
241: } else if (SVGConstants.SVG_X2_ATTRIBUTE == name) {
242: return Float.toString(x2);
243: } else if (SVGConstants.SVG_Y1_ATTRIBUTE == name) {
244: return Float.toString(y1);
245: } else if (SVGConstants.SVG_Y2_ATTRIBUTE == name) {
246: return Float.toString(y2);
247: } else {
248: return super .getTraitImpl(name);
249: }
250: }
251:
252: /**
253: * Supported traits: x1, x2, y1, y2
254: *
255: * @param name the requested trait's name.
256: * @return the requested trait's float value.
257: *
258: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
259: * trait is not supported on this element or null.
260: * @throws DOMException with error code TYPE_MISMATCH_ERR if requested
261: * trait's computed value cannot be converted to a float
262: * @throws SecurityException if the application does not have the necessary
263: * privilege rights to access this (SVG) content.
264: */
265: float getFloatTraitImpl(final String name) throws DOMException {
266: if (SVGConstants.SVG_X1_ATTRIBUTE == name) {
267: return x1;
268: } else if (SVGConstants.SVG_X2_ATTRIBUTE == name) {
269: return x2;
270: } else if (SVGConstants.SVG_Y1_ATTRIBUTE == name) {
271: return y1;
272: } else if (SVGConstants.SVG_Y2_ATTRIBUTE == name) {
273: return y2;
274: } else {
275: return super .getFloatTraitImpl(name);
276: }
277: }
278:
279: /**
280: * @param traitName the trait name.
281: */
282: TraitAnim createTraitAnimImpl(final String traitName) {
283: if (SVGConstants.SVG_X1_ATTRIBUTE == traitName
284: || SVGConstants.SVG_Y1_ATTRIBUTE == traitName
285: || SVGConstants.SVG_X2_ATTRIBUTE == traitName
286: || SVGConstants.SVG_Y2_ATTRIBUTE == traitName) {
287: return new FloatTraitAnim(this , traitName, TRAIT_TYPE_FLOAT);
288: } else {
289: return super .createTraitAnimImpl(traitName);
290: }
291: }
292:
293: /**
294: * Set the trait value as float.
295: *
296: * @param name the trait's name.
297: * @param value the trait's value.
298: *
299: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
300: * trait is not supported on this element.
301: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
302: * trait's value cannot be specified as a float
303: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
304: * value is an invalid value for the given trait.
305: */
306: void setFloatArrayTrait(final String name, final float[][] value)
307: throws DOMException {
308: if (SVGConstants.SVG_X1_ATTRIBUTE == name) {
309: setX1(value[0][0]);
310: } else if (SVGConstants.SVG_Y1_ATTRIBUTE == name) {
311: setY1(value[0][0]);
312: } else if (SVGConstants.SVG_X2_ATTRIBUTE == name) {
313: checkPositive(name, value[0][0]);
314: setX2(value[0][0]);
315: } else if (SVGConstants.SVG_Y2_ATTRIBUTE == name) {
316: checkPositive(name, value[0][0]);
317: setY2(value[0][0]);
318: } else {
319: super .setFloatArrayTrait(name, value);
320: }
321: }
322:
323: /**
324: * Validates the input trait value.
325: *
326: * @param traitName the name of the trait to be validated.
327: * @param value the value to be validated
328: * @param reqNamespaceURI the namespace of the element requesting
329: * validation.
330: * @param reqLocalName the local name of the element requesting validation.
331: * @param reqTraitNamespace the namespace of the trait which has the values
332: * value on the requesting element.
333: * @param reqTraitName the name of the trait which has the values value on
334: * the requesting element.
335: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
336: * value is incompatible with the given trait.
337: */
338: public float[][] validateFloatArrayTrait(final String traitName,
339: final String value, final String reqNamespaceURI,
340: final String reqLocalName, final String reqTraitNamespace,
341: final String reqTraitName) throws DOMException {
342: if (SVGConstants.SVG_X1_ATTRIBUTE == traitName
343: || SVGConstants.SVG_X2_ATTRIBUTE == traitName
344: || SVGConstants.SVG_Y1_ATTRIBUTE == traitName
345: || SVGConstants.SVG_Y2_ATTRIBUTE == traitName) {
346: return new float[][] { { parseFloatTrait(traitName, value) } };
347: } else {
348: return super .validateFloatArrayTrait(traitName, value,
349: reqNamespaceURI, reqLocalName, reqTraitNamespace,
350: reqTraitName);
351: }
352: }
353:
354: /**
355: * Supported traits: x1, x2, y1, y2
356: *
357: * @param name the trait's name.
358: * @param value the trait's new string value.
359: *
360: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
361: * trait is not supported on this element or null.
362: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
363: * trait's value cannot be specified as a String
364: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
365: * value is an invalid value for the given trait or null.
366: * @throws DOMException with error code NO_MODIFICATION_ALLOWED_ERR: if
367: * attempt is made to change readonly trait.
368: */
369: public void setTraitImpl(final String name, final String value)
370: throws DOMException {
371: if (SVGConstants.SVG_X1_ATTRIBUTE == name) {
372: setX1(parseFloatTrait(name, value));
373: } else if (SVGConstants.SVG_X2_ATTRIBUTE == name) {
374: setX2(parseFloatTrait(name, value));
375: } else if (SVGConstants.SVG_Y1_ATTRIBUTE == name) {
376: setY1(parseFloatTrait(name, value));
377: } else if (SVGConstants.SVG_Y2_ATTRIBUTE == name) {
378: setY2(parseFloatTrait(name, value));
379: } else {
380: super .setTraitImpl(name, value);
381: }
382: }
383:
384: /**
385: * Supported traits: x1, x2, y1, y2
386: *
387: * @param name the trait's name.
388: * @param value the new trait float value.
389: *
390: * @throws DOMException with error code NOT_SUPPORTED_ERROR if the requested
391: * trait is not supported on this element.
392: * @throws DOMException with error code TYPE_MISMATCH_ERR if the requested
393: * trait's value cannot be specified as a float
394: * @throws DOMException with error code INVALID_ACCESS_ERR if the input
395: * value is an invalid value for the given trait.
396: * @throws SecurityException if the application does not have the necessary
397: * privilege rights to access this (SVG) content.
398: */
399: public void setFloatTraitImpl(final String name, final float value)
400: throws DOMException {
401: if (SVGConstants.SVG_X1_ATTRIBUTE == name) {
402: setX1(value);
403: } else if (SVGConstants.SVG_X2_ATTRIBUTE == name) {
404: setX2(value);
405: } else if (SVGConstants.SVG_Y1_ATTRIBUTE == name) {
406: setY1(value);
407: } else if (SVGConstants.SVG_Y2_ATTRIBUTE == name) {
408: setY2(value);
409: } else {
410: super .setFloatTraitImpl(name, value);
411: }
412: }
413:
414: /**
415: * @param name the name of the trait to convert.
416: * @param value the float trait value to convert.
417: */
418: String toStringTrait(final String name, final float[][] value) {
419: if (SVGConstants.SVG_X1_ATTRIBUTE == name
420: || SVGConstants.SVG_X2_ATTRIBUTE == name
421: || SVGConstants.SVG_Y1_ATTRIBUTE == name
422: || SVGConstants.SVG_Y2_ATTRIBUTE == name) {
423: return Float.toString(value[0][0]);
424: } else {
425: return super .toStringTrait(name, value);
426: }
427: }
428:
429: /**
430: * @param bbox the bounding box to which this node's bounding box should be
431: * appended. That bounding box is in the target coordinate space. It
432: * may be null, in which case this node should create a new one.
433: * @param t the transform from the node coordinate system to the coordinate
434: * system into which the bounds should be computed.
435: * @return the bounding box of this node, in the target coordinate space,
436: */
437: Box addNodeBBox(Box bbox, final Transform t) {
438: float x1 = this .x1;
439: float x2 = this .x2;
440: float y1 = this .y1;
441: float y2 = this .y2;
442:
443: if (t != null) {
444: x1 = t.getComponent(0) * this .x1 + t.getComponent(2)
445: * this .y1 + t.getComponent(4);
446: y1 = t.getComponent(1) * this .x1 + t.getComponent(3)
447: * this .y1 + t.getComponent(5);
448: x2 = t.getComponent(0) * this .x2 + t.getComponent(2)
449: * this .y2 + t.getComponent(4);
450: y2 = t.getComponent(1) * this .x2 + t.getComponent(3)
451: * this .y2 + t.getComponent(5);
452: }
453:
454: if (x1 > x2) {
455: float x = x2;
456: x2 = x1;
457: x1 = x;
458: }
459:
460: if (y1 > y2) {
461: float y = y2;
462: y2 = y1;
463: y1 = y;
464: }
465:
466: return addBBox(bbox, x1, y1, x2 - x1, y2 - y1);
467: }
468: }
|