View Javadoc

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 org.vectomatic.dom.svg.utils.SVGConstants;
33  
34  import com.google.gwt.core.client.JavaScriptException;
35  import com.google.gwt.core.client.JavaScriptObject;
36  
37  /**
38   * {@link org.vectomatic.dom.svg.OMSVGTransform} is the interface for one
39   * of the component transformations within an {@link org.vectomatic.dom.svg.OMSVGTransformList};
40   * thus, an {@link org.vectomatic.dom.svg.OMSVGTransform} object corresponds
41   * to a single component (e.g., <span class='attr-value'>'scale(…)'</span>
42   * or <span class='attr-value'>'matrix(…)'</span>) within a <code>transform</code>
43   * attribute specification.
44   */
45  public class OMSVGTransform extends JavaScriptObject {
46  /**
47   * The unit type is not one of predefined types. It is invalid to attempt
48   * to define a new value of this type or to attempt to switch an existing
49   * value to this type.
50   */
51    public static final short SVG_TRANSFORM_UNKNOWN = 0;
52  /**
53   * A <span class='attr-value'>'matrix(…)'</span> transformation.
54   */
55    public static final short SVG_TRANSFORM_MATRIX = 1;
56  /**
57   * A <span class='attr-value'>'translate(…)'</span> transformation.
58   */
59    public static final short SVG_TRANSFORM_TRANSLATE = 2;
60  /**
61   * A <span class='attr-value'>'scale(…)'</span> transformation.
62   */
63    public static final short SVG_TRANSFORM_SCALE = 3;
64  /**
65   * A <span class='attr-value'>'rotate(…)'</span> transformation.
66   */
67    public static final short SVG_TRANSFORM_ROTATE = 4;
68  /**
69   * A <span class='attr-value'>'skewX(…)'</span> transformation.
70   */
71    public static final short SVG_TRANSFORM_SKEWX = 5;
72  /**
73   * A <span class='attr-value'>'skewY(…)'</span> transformation.
74   */
75    public static final short SVG_TRANSFORM_SKEWY = 6;
76    protected OMSVGTransform() {
77    }
78  
79    // Implementation of the svg::SVGTransform W3C IDL interface
80    /**
81     * The type of the value as specified by one of the SVG_TRANSFORM_ constants
82     * defined on this interface.
83     */
84    public final native short getType() /*-{
85      return this.type;
86    }-*/;
87    /**
88     * <p>The matrix that represents this transformation.  The matrix object is
89     * live, meaning that any changes made to the SVGTransform object are immediately
90     * reflected in the matrix object and vice versa.  In case the matrix object
91     * is changed directly (i.e., without using the methods on the SVGTransform
92     * interface itself) then the type of the SVGTransform changes to SVG_TRANSFORM_MATRIX.
93     * </p> <ul>   <li>For SVG_TRANSFORM_MATRIX, the matrix contains the   {@link
94     * org.vectomatic.dom.svg.OMSVGMatrix#getA()}, {@link org.vectomatic.dom.svg.OMSVGMatrix#getB()},
95     * {@link org.vectomatic.dom.svg.OMSVGMatrix#getC()}, {@link org.vectomatic.dom.svg.OMSVGMatrix#getD()},
96     * {@link org.vectomatic.dom.svg.OMSVGMatrix#getE()},   {@link org.vectomatic.dom.svg.OMSVGMatrix#getF()}
97     * values supplied by the user.</li>   <li>For SVG_TRANSFORM_TRANSLATE, {@link
98     * org.vectomatic.dom.svg.OMSVGMatrix#getE()} and {@link org.vectomatic.dom.svg.OMSVGMatrix#getF()}
99     * represent the translation amounts ({@link org.vectomatic.dom.svg.OMSVGMatrix#getA()}=1,
100    * {@link org.vectomatic.dom.svg.OMSVGMatrix#getB()}=0,   {@link org.vectomatic.dom.svg.OMSVGMatrix#getC()}=0
101    * and {@link org.vectomatic.dom.svg.OMSVGMatrix#getD()}=1).</li>   <li>For
102    * SVG_TRANSFORM_SCALE, {@link org.vectomatic.dom.svg.OMSVGMatrix#getA()}
103    * and {@link org.vectomatic.dom.svg.OMSVGMatrix#getD()}   represent the translation
104    * amounts ({@link org.vectomatic.dom.svg.OMSVGMatrix#getB()}=0, {@link org.vectomatic.dom.svg.OMSVGMatrix#getC()}=0,
105    * {@link org.vectomatic.dom.svg.OMSVGMatrix#getE()}=0 and {@link org.vectomatic.dom.svg.OMSVGMatrix#getF()}=0).</li>
106    * <li>For SVG_TRANSFORM_ROTATE, SVG_TRANSFORM_SKEWX and   SVG_TRANSFORM_SKEWY,
107    * {@link org.vectomatic.dom.svg.OMSVGMatrix#getA()}, {@link org.vectomatic.dom.svg.OMSVGMatrix#getB()},
108    * {@link org.vectomatic.dom.svg.OMSVGMatrix#getC()} and {@link org.vectomatic.dom.svg.OMSVGMatrix#getD()}
109    * represent the matrix which will result in the given transformation   ({@link
110    * org.vectomatic.dom.svg.OMSVGMatrix#getE()}=0 and {@link org.vectomatic.dom.svg.OMSVGMatrix#getF()}=0).</li>
111    * </ul>
112    */
113   public final native OMSVGMatrix getMatrix() /*-{
114     return this.matrix;
115   }-*/;
116   /**
117    * <p>A convenience attribute for SVG_TRANSFORM_ROTATE, SVG_TRANSFORM_SKEWX
118    * and SVG_TRANSFORM_SKEWY.  It holds the angle that was specified.</p> <p>For
119    * SVG_TRANSFORM_MATRIX, SVG_TRANSFORM_TRANSLATE and SVG_TRANSFORM_SCALE,
120    * {@link org.vectomatic.dom.svg.OMSVGTransform#getAngle()} will be zero.</p>
121    */
122   public final native float getAngle() /*-{
123     return this.angle;
124   }-*/;
125   /**
126    * <p xmlns:edit="http://xmlns.grorg.org/SVGT12NG/"> Sets the transform type
127    * to SVG_TRANSFORM_MATRIX, with parameter <var>matrix</var> defining the
128    * new transformation.  The values from the parameter <var>matrix</var> are
129    * copied, the <var>matrix</var> parameter does not replace <a edit:format="expanded">SVGTransform::matrix</a>.
130    * </p>
131    * @param matrix The new matrix for the transformation.
132    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
133    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
134    * attribute</a>.
135    */
136   public final native void setMatrix(OMSVGMatrix matrix) throws JavaScriptException /*-{
137     this.setMatrix(matrix);
138   }-*/;
139   /**
140    * Sets the transform type to SVG_TRANSFORM_TRANSLATE, with parameters <var>tx</var>
141    * and <var>ty</var> defining the translation amounts.
142    * @param tx The translation amount in X.
143    * @param ty The translation amount in Y.
144    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
145    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
146    * attribute</a>.
147    */
148   public final native void setTranslate(float tx, float ty) throws JavaScriptException /*-{
149     this.setTranslate(tx, ty);
150   }-*/;
151   /**
152    * Sets the transform type to SVG_TRANSFORM_SCALE, with parameters <var>sx</var>
153    * and <var>sy</var> defining the scale amounts.
154    * @param sx The scale amount in X.
155    * @param sy The scale amount in Y.
156    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
157    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
158    * attribute</a>.
159    */
160   public final native void setScale(float sx, float sy) throws JavaScriptException /*-{
161     this.setScale(sx, sy);
162   }-*/;
163   /**
164    * Sets the transform type to SVG_TRANSFORM_ROTATE, with parameter <var>angle</var>
165    * defining the rotation angle and parameters <var>cx</var> and <var>cy</var>
166    * defining the optional center of rotation.
167    * @param angle The rotation angle.
168    * @param cx The x coordinate of center of rotation.
169    * @param cy The y coordinate of center of rotation.
170    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
171    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
172    * attribute</a>.
173    */
174   public final native void setRotate(float angle, float cx, float cy) throws JavaScriptException /*-{
175     this.setRotate(angle, cx, cy);
176   }-*/;
177   /**
178    * Sets the transform type to SVG_TRANSFORM_SKEWX, with parameter <var>angle</var>
179    * defining the amount of skew.
180    * @param angle The skew angle.
181    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
182    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
183    * attribute</a>.
184    */
185   public final native void setSkewX(float angle) throws JavaScriptException /*-{
186     this.setSkewX(angle);
187   }-*/;
188   /**
189    * Sets the transform type to SVG_TRANSFORM_SKEWY, with parameter <var>angle</var>
190    * defining the amount of skew.
191    * @param angle The skew angle.
192    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
193    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
194    * attribute</a>.
195    */
196   public final native void setSkewY(float angle) throws JavaScriptException /*-{
197     this.setSkewY(angle);
198   }-*/;
199 
200   // Helper methods
201   /**
202    * Returns a textual description of the transform for debugging purposes.
203    * @return a textual description of the transform.
204    */
205   public final String getDescription() {
206 	StringBuilder builder = new StringBuilder();
207 	switch(getType()) {
208 		case SVG_TRANSFORM_MATRIX:
209 			builder.append(SVGConstants.TRANSFORM_MATRIX + "(");
210 			builder.append(getMatrix().getDescription());
211 			builder.append(")");
212 			break;
213 		case SVG_TRANSFORM_TRANSLATE:
214 			builder.append(SVGConstants.TRANSFORM_TRANSLATE + "(");
215 			builder.append(getMatrix().getE());
216 			builder.append(",");
217 			builder.append(getMatrix().getF());
218 			builder.append(")");
219 			break;
220 		case SVG_TRANSFORM_SCALE:
221 			builder.append(SVGConstants.TRANSFORM_SCALE + "(");
222 			builder.append(getMatrix().getA());
223 			builder.append(",");
224 			builder.append(getMatrix().getD());
225 			builder.append(")");
226 			break;
227 		case SVG_TRANSFORM_ROTATE:
228 			builder.append(SVGConstants.TRANSFORM_ROTATE + "(");
229 			builder.append(getAngle());
230 			if (getMatrix().getE() != 0f || getMatrix().getF() != 0f) {
231 				if (getAngle() == 0f) {
232 					builder.append(",");
233 					builder.append(getMatrix().getE());
234 					builder.append(",");
235 					builder.append(getMatrix().getF());
236 				} else {
237 					float a = (float)(1 - Math.cos(getAngle() * 2  * Math.PI / 360));
238 					float b = (float)Math.sin(getAngle() * 2  * Math.PI / 360);
239 					float c = -b;
240 					float d = a;
241 					float det = a * d - b * c;
242 					float x = (getMatrix().getE() * d - b * getMatrix().getF()) / det;
243 					float y = (a * getMatrix().getF() - getMatrix().getE() * c) / det;
244 					builder.append(",");
245 					builder.append(x);
246 					builder.append(",");
247 					builder.append(y);
248 				}
249 			}
250 			builder.append(")");
251 			break;
252 		case SVG_TRANSFORM_SKEWX:
253 			builder.append(SVGConstants.TRANSFORM_SKEWX + "(");
254 			builder.append(getAngle());
255 			builder.append(")");
256 			break;
257 		case SVG_TRANSFORM_SKEWY:
258 			builder.append(SVGConstants.TRANSFORM_SKEWY + "(");
259 			builder.append(getAngle());
260 			builder.append(")");
261 			break;
262 		case SVG_TRANSFORM_UNKNOWN:
263 		default:
264 			builder.append(toString());
265 			break;
266 	}
267 	return builder.toString();
268   }
269   /**
270    * Specifies a scaling transform around a center point. 
271    * The resulting transform type is set to SVG_TRANSFORM_MATRIX.
272    * @param sx The scale amount in X.
273    * @param sy The scale amount in Y.
274    * @param tx The X coordinate of the scaling center.
275    * @param ty The Y coordinate of the scaling center.
276    * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) Raised on an attempt
277    * to change the value of a <a href="svgdom.html#ReadOnlyNodes">read only
278    * attribute</a>.
279    */
280   public final void setScale(float sx, float sy, float tx, float ty) throws JavaScriptException {
281     OMSVGMatrix m = getMatrix();
282     m.setA(sx);
283     m.setB(0);
284     m.setC(0);
285     m.setD(sy);
286     m.setE(tx * ( 1 - sx ));
287     m.setF(ty * ( 1 - sy ));
288   }
289 }