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 }