1 | define(["dojo/_base/kernel", "dojo/_base/lang", "./_base", "./matrix", "./path", "dojo/_base/Color", "./vml"], |
---|
2 | function (kernel, lang, g, m, pathLib, Color, vml){ |
---|
3 | |
---|
4 | kernel.experimental("dojox.gfx.vml_attach"); |
---|
5 | |
---|
6 | vml.attachNode = function(node){ |
---|
7 | // summary: creates a shape from a Node |
---|
8 | // node: Node: an VML node |
---|
9 | if(!node) return null; |
---|
10 | var s = null; |
---|
11 | switch(node.tagName.toLowerCase()){ |
---|
12 | case vml.Rect.nodeType: |
---|
13 | s = new vml.Rect(node); |
---|
14 | attachRect(s); |
---|
15 | break; |
---|
16 | case vml.Ellipse.nodeType: |
---|
17 | if(node.style.width == node.style.height){ |
---|
18 | s = new vml.Circle(node); |
---|
19 | attachCircle(s); |
---|
20 | }else{ |
---|
21 | s = new vml.Ellipse(node); |
---|
22 | attachEllipse(s); |
---|
23 | } |
---|
24 | break; |
---|
25 | case vml.Path.nodeType: |
---|
26 | switch(node.getAttribute("dojoGfxType")){ |
---|
27 | case "line": |
---|
28 | s = new vml.Line(node); |
---|
29 | attachLine(s); |
---|
30 | break; |
---|
31 | case "polyline": |
---|
32 | s = new vml.Polyline(node); |
---|
33 | attachPolyline(s); |
---|
34 | break; |
---|
35 | case "path": |
---|
36 | s = new vml.Path(node); |
---|
37 | attachPath(s); |
---|
38 | break; |
---|
39 | case "text": |
---|
40 | s = new vml.Text(node); |
---|
41 | attachText(s); |
---|
42 | attachFont(s); |
---|
43 | attachTextTransform(s); |
---|
44 | break; |
---|
45 | case "textpath": |
---|
46 | s = new vml.TextPath(node); |
---|
47 | attachPath(s); |
---|
48 | attachText(s); |
---|
49 | attachFont(s); |
---|
50 | break; |
---|
51 | } |
---|
52 | break; |
---|
53 | case vml.Image.nodeType: |
---|
54 | switch(node.getAttribute("dojoGfxType")){ |
---|
55 | case "image": |
---|
56 | s = new vml.Image(node); |
---|
57 | attachImage(s); |
---|
58 | attachImageTransform(s); |
---|
59 | break; |
---|
60 | } |
---|
61 | break; |
---|
62 | default: |
---|
63 | //console.debug("FATAL ERROR! tagName = " + node.tagName); |
---|
64 | return null; |
---|
65 | } |
---|
66 | if(!(s instanceof vml.Image)){ |
---|
67 | attachFill(s); |
---|
68 | attachStroke(s); |
---|
69 | if(!(s instanceof vml.Text)){ |
---|
70 | attachTransform(s); |
---|
71 | } |
---|
72 | } |
---|
73 | return s; // dojox.gfx.Shape |
---|
74 | }; |
---|
75 | |
---|
76 | vml.attachSurface = function(node){ |
---|
77 | // summary: creates a surface from a Node |
---|
78 | // node: Node: an VML node |
---|
79 | var s = new vml.Surface(); |
---|
80 | s.clipNode = node; |
---|
81 | var r = s.rawNode = node.firstChild; |
---|
82 | var b = r.firstChild; |
---|
83 | if(!b || b.tagName != "rect"){ |
---|
84 | return null; // dojox.gfx.Surface |
---|
85 | } |
---|
86 | s.bgNode = r; |
---|
87 | return s; // dojox.gfx.Surface |
---|
88 | }; |
---|
89 | |
---|
90 | var attachFill = function(object){ |
---|
91 | // summary: deduces a fill style from a node. |
---|
92 | // object: dojox.gfx.Shape: an VML shape |
---|
93 | var fillStyle = null, r = object.rawNode, fo = r.fill, stops, i, t; |
---|
94 | if(fo.on && fo.type == "gradient"){ |
---|
95 | fillStyle = lang.clone(g.defaultLinearGradient), |
---|
96 | rad = m._degToRad(fo.angle); |
---|
97 | fillStyle.x2 = Math.cos(rad); |
---|
98 | fillStyle.y2 = Math.sin(rad); |
---|
99 | fillStyle.colors = []; |
---|
100 | stops = fo.colors.value.split(";"); |
---|
101 | for(i = 0; i < stops.length; ++i){ |
---|
102 | t = stops[i].match(/\S+/g); |
---|
103 | if(!t || t.length != 2){ continue; } |
---|
104 | fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new Color(t[1])}); |
---|
105 | } |
---|
106 | }else if(fo.on && fo.type == "gradientradial"){ |
---|
107 | fillStyle = lang.clone(g.defaultRadialGradient), |
---|
108 | w = parseFloat(r.style.width), h = parseFloat(r.style.height); |
---|
109 | fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w; |
---|
110 | fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h; |
---|
111 | fillStyle.r = isNaN(w) ? 1 : w / 2; |
---|
112 | fillStyle.colors = []; |
---|
113 | stops = fo.colors.value.split(";"); |
---|
114 | for(i = stops.length - 1; i >= 0; --i){ |
---|
115 | t = stops[i].match(/\S+/g); |
---|
116 | if(!t || t.length != 2){ continue; } |
---|
117 | fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new Color(t[1])}); |
---|
118 | } |
---|
119 | }else if(fo.on && fo.type == "tile"){ |
---|
120 | fillStyle = lang.clone(g.defaultPattern); |
---|
121 | fillStyle.width = g.pt2px(fo.size.x); // from pt |
---|
122 | fillStyle.height = g.pt2px(fo.size.y); // from pt |
---|
123 | fillStyle.x = fo.origin.x * fillStyle.width; |
---|
124 | fillStyle.y = fo.origin.y * fillStyle.height; |
---|
125 | fillStyle.src = fo.src; |
---|
126 | }else if(fo.on && r.fillcolor){ |
---|
127 | // a color object ! |
---|
128 | fillStyle = new Color(r.fillcolor+""); |
---|
129 | fillStyle.a = fo.opacity; |
---|
130 | } |
---|
131 | object.fillStyle = fillStyle; |
---|
132 | }; |
---|
133 | |
---|
134 | var attachStroke = function(object) { |
---|
135 | // summary: deduces a stroke style from a node. |
---|
136 | // object: dojox.gfx.Shape: an VML shape |
---|
137 | var r = object.rawNode; |
---|
138 | if(!r.stroked){ |
---|
139 | object.strokeStyle = null; |
---|
140 | return; |
---|
141 | } |
---|
142 | var strokeStyle = object.strokeStyle = lang.clone(g.defaultStroke), |
---|
143 | rs = r.stroke; |
---|
144 | strokeStyle.color = new Color(r.strokecolor.value); |
---|
145 | strokeStyle.width = g.normalizedLength(r.strokeweight+""); |
---|
146 | strokeStyle.color.a = rs.opacity; |
---|
147 | strokeStyle.cap = this._translate(this._capMapReversed, rs.endcap); |
---|
148 | strokeStyle.join = rs.joinstyle == "miter" ? rs.miterlimit : rs.joinstyle; |
---|
149 | strokeStyle.style = rs.dashstyle; |
---|
150 | }; |
---|
151 | |
---|
152 | var attachTransform = function(object) { |
---|
153 | // summary: deduces a transformation matrix from a node. |
---|
154 | // object: dojox.gfx.Shape: an VML shape |
---|
155 | var s = object.rawNode.skew, sm = s.matrix, so = s.offset; |
---|
156 | object.matrix = m.normalize({ |
---|
157 | xx: sm.xtox, |
---|
158 | xy: sm.ytox, |
---|
159 | yx: sm.xtoy, |
---|
160 | yy: sm.ytoy, |
---|
161 | dx: g.pt2px(so.x), |
---|
162 | dy: g.pt2px(so.y) |
---|
163 | }); |
---|
164 | }; |
---|
165 | |
---|
166 | var attachGroup = function(object){ |
---|
167 | // summary: reconstructs all group shape parameters from a node (VML). |
---|
168 | // object: dojox.gfx.Shape: an VML shape |
---|
169 | // attach the background |
---|
170 | object.bgNode = object.rawNode.firstChild; // TODO: check it first |
---|
171 | }; |
---|
172 | |
---|
173 | var attachRect = function(object){ |
---|
174 | // summary: builds a rectangle shape from a node. |
---|
175 | // object: dojox.gfx.Shape: an VML shape |
---|
176 | // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node |
---|
177 | var r = object.rawNode, arcsize = r.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1], |
---|
178 | style = r.style, width = parseFloat(style.width), height = parseFloat(style.height); |
---|
179 | arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : vml._parseFloat(arcsize); |
---|
180 | // make an object |
---|
181 | object.shape = g.makeParameters(g.defaultRect, { |
---|
182 | x: parseInt(style.left), |
---|
183 | y: parseInt(style.top), |
---|
184 | width: width, |
---|
185 | height: height, |
---|
186 | r: Math.min(width, height) * arcsize |
---|
187 | }); |
---|
188 | }; |
---|
189 | |
---|
190 | var attachEllipse = function(object){ |
---|
191 | // summary: builds an ellipse shape from a node. |
---|
192 | // object: dojox.gfx.Shape: an VML shape |
---|
193 | var style = object.rawNode.style, |
---|
194 | rx = parseInt(style.width ) / 2, |
---|
195 | ry = parseInt(style.height) / 2; |
---|
196 | object.shape = g.makeParameters(g.defaultEllipse, { |
---|
197 | cx: parseInt(style.left) + rx, |
---|
198 | cy: parseInt(style.top ) + ry, |
---|
199 | rx: rx, |
---|
200 | ry: ry |
---|
201 | }); |
---|
202 | }; |
---|
203 | |
---|
204 | var attachCircle = function(object){ |
---|
205 | // summary: builds a circle shape from a node. |
---|
206 | // object: dojox.gfx.Shape: an VML shape |
---|
207 | var style = object.rawNode.style, r = parseInt(style.width) / 2; |
---|
208 | object.shape = g.makeParameters(g.defaultCircle, { |
---|
209 | cx: parseInt(style.left) + r, |
---|
210 | cy: parseInt(style.top) + r, |
---|
211 | r: r |
---|
212 | }); |
---|
213 | }; |
---|
214 | |
---|
215 | var attachLine = function(object){ |
---|
216 | // summary: builds a line shape from a node. |
---|
217 | // object: dojox.gfx.Shape: an VML shape |
---|
218 | var shape = object.shape = lang.clone(g.defaultLine), |
---|
219 | p = object.rawNode.path.v.match(g.pathVmlRegExp); |
---|
220 | do{ |
---|
221 | if(p.length < 7 || p[0] != "m" || p[3] != "l" || p[6] != "e"){ break; } |
---|
222 | shape.x1 = parseInt(p[1]); |
---|
223 | shape.y1 = parseInt(p[2]); |
---|
224 | shape.x2 = parseInt(p[4]); |
---|
225 | shape.y2 = parseInt(p[5]); |
---|
226 | }while(false); |
---|
227 | }; |
---|
228 | |
---|
229 | var attachPolyline = function(object){ |
---|
230 | // summary: builds a polyline/polygon shape from a node. |
---|
231 | // object: dojox.gfx.Shape: an VML shape |
---|
232 | var shape = object.shape = lang.clone(g.defaultPolyline), |
---|
233 | p = object.rawNode.path.v.match(g.pathVmlRegExp); |
---|
234 | do{ |
---|
235 | if(p.length < 3 || p[0] != "m"){ break; } |
---|
236 | var x = parseInt(p[0]), y = parseInt(p[1]); |
---|
237 | if(isNaN(x) || isNaN(y)){ break; } |
---|
238 | shape.points.push({x: x, y: y}); |
---|
239 | if(p.length < 6 || p[3] != "l"){ break; } |
---|
240 | for(var i = 4; i < p.length; i += 2){ |
---|
241 | x = parseInt(p[i]); |
---|
242 | y = parseInt(p[i + 1]); |
---|
243 | if(isNaN(x) || isNaN(y)){ break; } |
---|
244 | shape.points.push({x: x, y: y}); |
---|
245 | } |
---|
246 | }while(false); |
---|
247 | }; |
---|
248 | |
---|
249 | var attachImage = function(object){ |
---|
250 | // summary: builds an image shape from a node. |
---|
251 | // object: dojox.gfx.Shape: an VML shape |
---|
252 | object.shape = lang.clone(g.defaultImage); |
---|
253 | object.shape.src = object.rawNode.firstChild.src; |
---|
254 | }; |
---|
255 | |
---|
256 | var attachImageTransform = function(object) { |
---|
257 | // summary: deduces a transformation matrix from a node. |
---|
258 | // object: dojox.gfx.Shape: an VML shape |
---|
259 | var mm = object.rawNode.filters["DXImageTransform.Microsoft.Matrix"]; |
---|
260 | object.matrix = m.normalize({ |
---|
261 | xx: mm.M11, |
---|
262 | xy: mm.M12, |
---|
263 | yx: mm.M21, |
---|
264 | yy: mm.M22, |
---|
265 | dx: mm.Dx, |
---|
266 | dy: mm.Dy |
---|
267 | }); |
---|
268 | }; |
---|
269 | |
---|
270 | var attachText = function(object){ |
---|
271 | // summary: builds a text shape from a node. |
---|
272 | // object: dojox.gfx.Shape: an VML shape |
---|
273 | var shape = object.shape = lang.clone(g.defaultText), |
---|
274 | r = object.rawNode, p = r.path.v.match(g.pathVmlRegExp); |
---|
275 | do{ |
---|
276 | if(!p || p.length != 7){ break; } |
---|
277 | var c = r.childNodes, i = 0; |
---|
278 | for(; i < c.length && c[i].tagName != "textpath"; ++i); |
---|
279 | if(i >= c.length){ break; } |
---|
280 | var s = c[i].style; |
---|
281 | shape.text = c[i].string; |
---|
282 | switch(s["v-text-align"]){ |
---|
283 | case "left": |
---|
284 | shape.x = parseInt(p[1]); |
---|
285 | shape.align = "start"; |
---|
286 | break; |
---|
287 | case "center": |
---|
288 | shape.x = (parseInt(p[1]) + parseInt(p[4])) / 2; |
---|
289 | shape.align = "middle"; |
---|
290 | break; |
---|
291 | case "right": |
---|
292 | shape.x = parseInt(p[4]); |
---|
293 | shape.align = "end"; |
---|
294 | break; |
---|
295 | } |
---|
296 | shape.y = parseInt(p[2]); |
---|
297 | shape.decoration = s["text-decoration"]; |
---|
298 | shape.rotated = s["v-rotate-letters"].toLowerCase() in vml._bool; |
---|
299 | shape.kerning = s["v-text-kern"].toLowerCase() in vml._bool; |
---|
300 | return; |
---|
301 | }while(false); |
---|
302 | object.shape = null; |
---|
303 | }; |
---|
304 | |
---|
305 | var attachFont = function(object){ |
---|
306 | // summary: deduces a font style from a node. |
---|
307 | // object: dojox.gfx.Shape: an VML shape |
---|
308 | var fontStyle = object.fontStyle = lang.clone(g.defaultFont), |
---|
309 | c = object.rawNode.childNodes, i = 0; |
---|
310 | for(; i < c.length && c[i].tagName == "textpath"; ++i); |
---|
311 | if(i >= c.length){ |
---|
312 | object.fontStyle = null; |
---|
313 | return; |
---|
314 | } |
---|
315 | var s = c[i].style; |
---|
316 | fontStyle.style = s.fontstyle; |
---|
317 | fontStyle.variant = s.fontvariant; |
---|
318 | fontStyle.weight = s.fontweight; |
---|
319 | fontStyle.size = s.fontsize; |
---|
320 | fontStyle.family = s.fontfamily; |
---|
321 | }; |
---|
322 | |
---|
323 | var attachTextTransform = function(object) { |
---|
324 | // summary: deduces a transformation matrix from a node. |
---|
325 | // object: dojox.gfx.Shape: an VML shape |
---|
326 | attachTransform(object); |
---|
327 | var matrix = object.matrix, fs = object.fontStyle; |
---|
328 | // see comments in _getRealMatrix() |
---|
329 | if(matrix && fs){ |
---|
330 | object.matrix = m.multiply(matrix, {dy: g.normalizedLength(fs.size) * 0.35}); |
---|
331 | } |
---|
332 | }; |
---|
333 | |
---|
334 | var attachPath = function(object){ |
---|
335 | // summary: builds a path shape from a Node. |
---|
336 | // object: dojox.gfx.Shape: an VML shape |
---|
337 | var shape = object.shape = lang.clone(g.defaultPath), |
---|
338 | p = object.rawNode.path.v.match(g.pathVmlRegExp), |
---|
339 | t = [], skip = false, map = pathLib._pathVmlToSvgMap; |
---|
340 | for(var i = 0; i < p.length; ++p){ |
---|
341 | var s = p[i]; |
---|
342 | if(s in map) { |
---|
343 | skip = false; |
---|
344 | t.push(map[s]); |
---|
345 | } else if(!skip){ |
---|
346 | var n = parseInt(s); |
---|
347 | if(isNaN(n)){ |
---|
348 | skip = true; |
---|
349 | }else{ |
---|
350 | t.push(n); |
---|
351 | } |
---|
352 | } |
---|
353 | } |
---|
354 | var l = t.length; |
---|
355 | if(l >= 4 && t[l - 1] == "" && t[l - 2] == 0 && t[l - 3] == 0 && t[l - 4] == "l"){ |
---|
356 | t.splice(l - 4, 4); |
---|
357 | } |
---|
358 | if(l){ |
---|
359 | shape.path = t.join(" "); |
---|
360 | } |
---|
361 | }; |
---|
362 | |
---|
363 | return vml; //return augmented vml api |
---|
364 | }); |
---|