1 /**********************************************
2 * Copyright (C) 2010 Lukas Laag
3 * This file is part of lib-gwt-svg.
4 *
5 * libgwtsvg is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * libgwtsvg is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with libgwtsvg. If not, see http://www.gnu.org/licenses/
17 **********************************************/
18 /*
19 * Copyright (c) 2004 World Wide Web Consortium,
20 *
21 * (Massachusetts Institute of Technology, European Research Consortium for
22 * Informatics and Mathematics, Keio University). All Rights Reserved. This
23 * work is distributed under the W3C(r) Software License [1] in the hope that
24 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
25 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26 *
27 * [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
28 */
29
30 package org.vectomatic.dom.svg;
31
32 import com.google.gwt.core.client.JavaScriptException;
33 import com.google.gwt.core.client.JavaScriptObject;
34
35 /**
36 * <p>Represents rectangular geometry. Rectangles are defined as consisting
37 * of a (x,y) coordinate pair identifying a minimum X value, a minimum Y value,
38 * and a width and height, which are usually constrained to be non-negative.</p>
39 * <p id="ReadOnlyRect">An {@link org.vectomatic.dom.svg.OMSVGRect} object
40 * can be designated as <em>read only</em>, which means that attempts to modify
41 * the object will result in an exception being thrown, as described below.</p>
42 */
43 public class OMSVGRect extends JavaScriptObject {
44 protected OMSVGRect() {
45 }
46
47 // Implementation of the svg::SVGRect W3C IDL interface
48 /**
49 * The <var>x</var> coordinate of the rectangle, in user units.
50 */
51 public final native float getX() /*-{
52 return this.x;
53 }-*/;
54 /**
55 * The <var>x</var> coordinate of the rectangle, in user units.
56 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised when the rectangle
57 * corresponds to a <a href="svgdom.html#ReadOnlyNodes">read only attribute</a>
58 * or when the object itself is <a href="#ReadOnlyRect">read only</a>.
59 */
60 public final native void setX(float value) throws JavaScriptException /*-{
61 this.x = value;
62 }-*/;
63 /**
64 * The <var>y</var> coordinate of the rectangle, in user units.
65 */
66 public final native float getY() /*-{
67 return this.y;
68 }-*/;
69 /**
70 * The <var>y</var> coordinate of the rectangle, in user units.
71 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised when the rectangle
72 * corresponds to a <a href="svgdom.html#ReadOnlyNodes">read only attribute</a>
73 * or when the object itself is <a href="#ReadOnlyRect">read only</a>.
74 */
75 public final native void setY(float value) throws JavaScriptException /*-{
76 this.y = value;
77 }-*/;
78 /**
79 * The <var>width</var> coordinate of the rectangle, in user units.
80 */
81 public final native float getWidth() /*-{
82 return this.width;
83 }-*/;
84 /**
85 * The <var>width</var> coordinate of the rectangle, in user units.
86 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised when the rectangle
87 * corresponds to a <a href="svgdom.html#ReadOnlyNodes">read only attribute</a>
88 * or when the object itself is <a href="#ReadOnlyRect">read only</a>.
89 */
90 public final native void setWidth(float value) throws JavaScriptException /*-{
91 this.width = value;
92 }-*/;
93 /**
94 * The <var>height</var> coordinate of the rectangle, in user units.
95 */
96 public final native float getHeight() /*-{
97 return this.height;
98 }-*/;
99 /**
100 * The <var>height</var> coordinate of the rectangle, in user units.
101 * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised when the rectangle
102 * corresponds to a <a href="svgdom.html#ReadOnlyNodes">read only attribute</a>
103 * or when the object itself is <a href="#ReadOnlyRect">read only</a>.
104 */
105 public final native void setHeight(float value) throws JavaScriptException /*-{
106 this.height = value;
107 }-*/;
108
109 // Helper methods
110 /**
111 * Returns the X coordinate of the center of this rectangle.
112 * @return the X coordinate of the center of this rectangle.
113 */
114 public final float getCenterX() {
115 return getX() + 0.5f * getWidth();
116 }
117 /**
118 * Returns the Y coordinate of the center of this rectangle.
119 * @return the Y coordinate of the center of this rectangle.
120 */
121 public final float getCenterY() {
122 return getY() + 0.5f * getHeight();
123 }
124 /**
125 * Returns the X coordinate of the right corners of this rectangle.
126 * @return the X coordinate of the right corners of this rectangle.
127 */
128 public final float getMaxX() {
129 return getX() + getWidth();
130 }
131 /**
132 * Returns the X coordinate of the bottom corners of this rectangle.
133 * @return the X coordinate of the bottom corners of this rectangle.
134 */
135 public final float getMaxY() {
136 return getY() + getHeight();
137 }
138 /**
139 * Computes the intersection of this rectangle with the
140 * specified rectangle and puts the result in this rectangle.
141 * The method returns null if the two rectangles have no intersection.
142 * @param r the rectangle to intersect
143 * @return the rectangle resulting from the intersection of
144 * this rectangle with the specified rectangle or
145 * null if the two rectangles have no intersection.
146 */
147 public final OMSVGRect intersection(OMSVGRect r) {
148 return intersection(r, this);
149 }
150 /**
151 * Computes the intersection of this rectangle with the
152 * specified rectangle and puts the result in the destination rectangle.
153 * The method returns null if the two rectangles have no intersection.
154 * @param r the rectangle to intersect
155 * @param destination a rectangle to store the intersection
156 * @return the rectangle resulting from the intersection of
157 * this rectangle with the specified rectangle or
158 * null if the two rectangles have no intersection.
159 */
160 public final OMSVGRect intersection(OMSVGRect r, OMSVGRect destination) {
161 if (getX() < r.getX() && r.getX() < getMaxX()) {
162 if (getY() < r.getY() && r.getY() < getMaxY()) {
163 destination.setWidth(getMaxX() - r.getX());
164 destination.setX(r.getX());
165 destination.setHeight(getMaxY() - r.getY());
166 destination.setY(r.getY());
167 return destination;
168 } else if (r.getY() < getY() && getY() < r.getMaxY()) {
169 destination.setWidth(getMaxX() - r.getX());
170 destination.setX(r.getX());
171 destination.setHeight(r.getMaxY() - getY());
172 destination.setY(getY());
173 return destination;
174 }
175 } else if (r.getX() < getX() && getX() < r.getMaxX()) {
176 if (getY() < r.getY() && r.getY() < getMaxY()) {
177 destination.setWidth(r.getMaxX() - getX());
178 destination.setX(getX());
179 destination.setHeight(getMaxY() - r.getY());
180 destination.setY(r.getY());
181 return destination;
182 } else if (r.getY() < getY() && getY() < r.getMaxY()) {
183 destination.setWidth(r.getMaxX() - getX());
184 destination.setX(getX());
185 destination.setHeight(r.getMaxY() - getY());
186 destination.setY(getY());
187 return destination;
188 }
189 }
190 return null;
191 }
192 /**
193 * Computes the union of this rectangle with the
194 * specified rectangle and puts the result in this rectangle.
195 * @param r the rectangle with which to compute the union
196 * @return the rectangle resulting from the union of
197 * this rectangle with the specified rectangle.
198 */
199 public final OMSVGRect union(OMSVGRect r) {
200 return union(r, this);
201 }
202 /**
203 * Computes the union of this rectangle with the
204 * specified rectangle and puts the result in the destination rectangle.
205 * @param r the rectangle with which to compute the union
206 * @param destination a rectangle to store the union
207 * @return the rectangle resulting from the union of
208 * this rectangle with the specified rectangle.
209 */
210 public final OMSVGRect union(OMSVGRect r, OMSVGRect destination) {
211 float x = Math.min(getX(), r.getX());
212 float y = Math.min(getY(), r.getY());
213 destination.setWidth(Math.max(getMaxX(), r.getMaxX()) - x);
214 destination.setHeight(Math.max(getMaxY(), r.getMaxY()) - y);
215 destination.setX(x);
216 destination.setY(y);
217 return destination;
218 }
219 /**
220 * Returns true if the specified point is inside this rectangle,
221 * false otherwise.
222 * @param p The point to test
223 * @return true if the specified point is inside this rectangle,
224 * false otherwise.
225 */
226 public final boolean contains(OMSVGPoint p) {
227 return p.getX() >= getX() && p.getY() >= getY() && p.getX() <= getMaxX() && p.getY() <= getMaxY();
228 }
229 /**
230 * Copies this rectangle to the specified destination rectangle.
231 * @param destination the destination rectangle.
232 * @return the destination rectangle.
233 */
234 public final native OMSVGRect assignTo(OMSVGRect destination) /*-{
235 destination.x = this.x;
236 destination.y = this.y;
237 destination.width = this.width;
238 destination.height = this.height;
239 return destination;
240 }-*/;
241 /**
242 * Returns a textual description of the rectangle for debugging purposes.
243 * @return a textual description of the rectangle.
244 */
245 public final String getDescription() {
246 StringBuilder builder = new StringBuilder("{");
247 builder.append(getX());
248 builder.append(" ");
249 builder.append(getY());
250 builder.append(" ");
251 builder.append(getWidth());
252 builder.append(" ");
253 builder.append(getHeight());
254 builder.append("}");
255 return builder.toString();
256 }
257 /**
258 * Modifies the position and size of this rectangle by adding
259 * the specified margin to it.
260 * @param x the horizontal margin
261 * @param y the vertical margin
262 * @return this rectangle
263 */
264 public final OMSVGRect inset(float x, float y) {
265 return inset(this, x, y);
266 }
267 /**
268 * Modifies the position and size of this rectangle by adding
269 * the specified margin to it and puts the result in the destination
270 * rectangle.
271 * @param destination the destination rectangle.
272 * @param x the horizontal margin
273 * @param y the vertical margin
274 * @return the destination rectangle.
275 */
276 public final OMSVGRect inset(OMSVGRect destination, float x, float y) {
277 destination.setX(getX() + x);
278 destination.setY(getY() + y);
279 destination.setWidth(getWidth() - x * 2);
280 destination.setHeight(getHeight() - y * 2);
281 return destination;
282 }
283 }