source: other-projects/nz-flag-design/trunk/design-2d/Original editor.method.ac/method-draw/src/svgtransformlist.js@ 29468

Last change on this file since 29468 was 29468, checked in by sjs49, 9 years ago

Initial commit for editor.method.ac for flag design

  • Property svn:executable set to *
File size: 7.7 KB
Line 
1/**
2 * SVGTransformList
3 *
4 * Licensed under the Apache License, Version 2
5 *
6 * Copyright(c) 2010 Alexis Deveria
7 * Copyright(c) 2010 Jeff Schiller
8 */
9
10// Dependencies:
11// 1) browser.js
12
13var svgedit = svgedit || {};
14
15(function() {
16
17if (!svgedit.transformlist) {
18 svgedit.transformlist = {};
19}
20
21var svgroot = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
22
23// Helper function.
24function transformToString(xform) {
25 var m = xform.matrix,
26 text = "";
27 switch(xform.type) {
28 case 1: // MATRIX
29 text = "matrix(" + [m.a,m.b,m.c,m.d,m.e,m.f].join(",") + ")";
30 break;
31 case 2: // TRANSLATE
32 text = "translate(" + m.e + "," + m.f + ")";
33 break;
34 case 3: // SCALE
35 if (m.a == m.d) text = "scale(" + m.a + ")";
36 else text = "scale(" + m.a + "," + m.d + ")";
37 break;
38 case 4: // ROTATE
39 var cx = 0, cy = 0;
40 // this prevents divide by zero
41 if (xform.angle != 0) {
42 var K = 1 - m.a;
43 cy = ( K * m.f + m.b*m.e ) / ( K*K + m.b*m.b );
44 cx = ( m.e - m.b * cy ) / K;
45 }
46 text = "rotate(" + xform.angle + " " + cx + "," + cy + ")";
47 break;
48 }
49 return text;
50};
51
52
53/**
54 * Map of SVGTransformList objects.
55 */
56var listMap_ = {};
57
58
59// **************************************************************************************
60// SVGTransformList implementation for Webkit
61// These methods do not currently raise any exceptions.
62// These methods also do not check that transforms are being inserted. This is basically
63// implementing as much of SVGTransformList that we need to get the job done.
64//
65// interface SVGEditTransformList {
66// attribute unsigned long numberOfItems;
67// void clear ( )
68// SVGTransform initialize ( in SVGTransform newItem )
69// SVGTransform getItem ( in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
70// SVGTransform insertItemBefore ( in SVGTransform newItem, in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
71// SVGTransform replaceItem ( in SVGTransform newItem, in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
72// SVGTransform removeItem ( in unsigned long index ) (DOES NOT THROW DOMException, INDEX_SIZE_ERR)
73// SVGTransform appendItem ( in SVGTransform newItem )
74// NOT IMPLEMENTED: SVGTransform createSVGTransformFromMatrix ( in SVGMatrix matrix );
75// NOT IMPLEMENTED: SVGTransform consolidate ( );
76// }
77// **************************************************************************************
78svgedit.transformlist.SVGTransformList = function(elem) {
79 this._elem = elem || null;
80 this._xforms = [];
81 // TODO: how do we capture the undo-ability in the changed transform list?
82 this._update = function() {
83 var tstr = "";
84 var concatMatrix = svgroot.createSVGMatrix();
85 for (var i = 0; i < this.numberOfItems; ++i) {
86 var xform = this._list.getItem(i);
87 tstr += transformToString(xform) + " ";
88 }
89 this._elem.setAttribute("transform", tstr);
90 };
91 this._list = this;
92 this._init = function() {
93 // Transform attribute parser
94 var str = this._elem.getAttribute("transform");
95 if(!str) return;
96
97 // TODO: Add skew support in future
98 var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
99 var arr = [];
100 var m = true;
101 while(m) {
102 m = str.match(re);
103 str = str.replace(re,'');
104 if(m && m[1]) {
105 var x = m[1];
106 var bits = x.split(/\s*\(/);
107 var name = bits[0];
108 var val_bits = bits[1].match(/\s*(.*?)\s*\)/);
109 val_bits[1] = val_bits[1].replace(/(\d)-/g, "$1 -");
110 var val_arr = val_bits[1].split(/[, ]+/);
111 var letters = 'abcdef'.split('');
112 var mtx = svgroot.createSVGMatrix();
113 $.each(val_arr, function(i, item) {
114 val_arr[i] = parseFloat(item);
115 if(name == 'matrix') {
116 mtx[letters[i]] = val_arr[i];
117 }
118 });
119 var xform = svgroot.createSVGTransform();
120 var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
121 var values = name=='matrix'?[mtx]:val_arr;
122
123 if (name == 'scale' && values.length == 1) {
124 values.push(values[0]);
125 } else if (name == 'translate' && values.length == 1) {
126 values.push(0);
127 } else if (name == 'rotate' && values.length == 1) {
128 values.push(0);
129 values.push(0);
130 }
131 xform[fname].apply(xform, values);
132 this._list.appendItem(xform);
133 }
134 }
135 };
136 this._removeFromOtherLists = function(item) {
137 if (item) {
138 // Check if this transform is already in a transformlist, and
139 // remove it if so.
140 var found = false;
141 for (var id in listMap_) {
142 var tl = listMap_[id];
143 for (var i = 0, len = tl._xforms.length; i < len; ++i) {
144 if(tl._xforms[i] == item) {
145 found = true;
146 tl.removeItem(i);
147 break;
148 }
149 }
150 if (found) {
151 break;
152 }
153 }
154 }
155 };
156
157 this.numberOfItems = 0;
158 this.clear = function() {
159 this.numberOfItems = 0;
160 this._xforms = [];
161 };
162
163 this.initialize = function(newItem) {
164 this.numberOfItems = 1;
165 this._removeFromOtherLists(newItem);
166 this._xforms = [newItem];
167 };
168
169 this.getItem = function(index) {
170 if (index < this.numberOfItems && index >= 0) {
171 return this._xforms[index];
172 }
173 throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR
174 };
175
176 this.insertItemBefore = function(newItem, index) {
177 var retValue = null;
178 if (index >= 0) {
179 if (index < this.numberOfItems) {
180 this._removeFromOtherLists(newItem);
181 var newxforms = new Array(this.numberOfItems + 1);
182 // TODO: use array copying and slicing
183 for ( var i = 0; i < index; ++i) {
184 newxforms[i] = this._xforms[i];
185 }
186 newxforms[i] = newItem;
187 for ( var j = i+1; i < this.numberOfItems; ++j, ++i) {
188 newxforms[j] = this._xforms[i];
189 }
190 this.numberOfItems++;
191 this._xforms = newxforms;
192 retValue = newItem;
193 this._list._update();
194 }
195 else {
196 retValue = this._list.appendItem(newItem);
197 }
198 }
199 return retValue;
200 };
201
202 this.replaceItem = function(newItem, index) {
203 var retValue = null;
204 if (index < this.numberOfItems && index >= 0) {
205 this._removeFromOtherLists(newItem);
206 this._xforms[index] = newItem;
207 retValue = newItem;
208 this._list._update();
209 }
210 return retValue;
211 };
212
213 this.removeItem = function(index) {
214 if (index < this.numberOfItems && index >= 0) {
215 var retValue = this._xforms[index];
216 var newxforms = new Array(this.numberOfItems - 1);
217 for (var i = 0; i < index; ++i) {
218 newxforms[i] = this._xforms[i];
219 }
220 for (var j = i; j < this.numberOfItems-1; ++j, ++i) {
221 newxforms[j] = this._xforms[i+1];
222 }
223 this.numberOfItems--;
224 this._xforms = newxforms;
225 this._list._update();
226 return retValue;
227 } else {
228 throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR
229 }
230 };
231
232 this.appendItem = function(newItem) {
233 this._removeFromOtherLists(newItem);
234 this._xforms.push(newItem);
235 this.numberOfItems++;
236 this._list._update();
237 return newItem;
238 };
239};
240
241
242svgedit.transformlist.resetListMap = function() {
243 listMap_ = {};
244};
245
246/**
247 * Removes transforms of the given element from the map.
248 * Parameters:
249 * elem - a DOM Element
250 */
251svgedit.transformlist.removeElementFromListMap = function(elem) {
252 if (elem.id && listMap_[elem.id]) {
253 delete listMap_[elem.id];
254 }
255};
256
257// Function: getTransformList
258// Returns an object that behaves like a SVGTransformList for the given DOM element
259//
260// Parameters:
261// elem - DOM element to get a transformlist from
262svgedit.transformlist.getTransformList = function(elem) {
263 if (!svgedit.browser.supportsNativeTransformLists()) {
264 var id = elem.id;
265 if(!id) {
266 // Get unique ID for temporary element
267 id = 'temp';
268 }
269 var t = listMap_[id];
270 if (!t || id == 'temp') {
271 listMap_[id] = new svgedit.transformlist.SVGTransformList(elem);
272 listMap_[id]._init();
273 t = listMap_[id];
274 }
275 return t;
276 }
277 else if (elem.transform) {
278 return elem.transform.baseVal;
279 }
280 else if (elem.gradientTransform) {
281 return elem.gradientTransform.baseVal;
282 }
283 else if (elem.patternTransform) {
284 return elem.patternTransform.baseVal;
285 }
286
287 return null;
288};
289
290
291})();
Note: See TracBrowser for help on using the repository browser.