@@ -2,10 +2,11 @@
22ElmRuntime.Render.Collage = function() {
33'use strict';
44
5+var Render = ElmRuntime.use(ElmRuntime.Render.Element);
56var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
67var newElement = Utils.newElement, addTo = Utils.addTo,
78 extract = Utils.extract, fromList = Utils.fromList,
8− fromString = Utils.fromString;
9+ fromString = Utils.fromString, addTransform = Utils.addTransform;
910
1011function trace(ctx, path) {
1112 var points = fromList(path);
@@ -129,9 +130,9 @@ function renderForms(redo, ctx, forms) {
129130}
130131
131132function collageForms(w,h,forms) {
132− var canvas = Render.newElement('canvas');
133− w = ~~w;
134− h = ~~h;
133+ var canvas = newElement('canvas');
134+ w = w|0;
135+ h = h|0;
135136 canvas.style.width = w + 'px';
136137 canvas.style.height = h + 'px';
137138 canvas.style.display = "block";
@@ -143,183 +144,27 @@ function collageForms(w,h,forms) {
143144 renderForms(redo,ctx,w,h,forms);
144145 return canvas;
145146 }
146− canvas.innerHTML = "Your browser does not support the canvas element.";
147+ canvas.innerHTML = "Your browser does not support canvas.";
147148 return canvas;
148149}
149150
150−function applyTransforms(theta,scale,x,y,w,h,e) {
151− var t = "translate(" + (x - w / 2) + "px,"+ (y - h / 2) + "px)";
152− var r = theta === (~~theta) ? "" : "rotate(" + theta*360 + "deg)";
153− var s = scale === 1 ? "" : "scale(" + scale + "," + scale + ")";
154− var transforms = t + " " + s + " " + r;
155− e.style.transform = transforms;
156− e.style.msTransform = transforms;
157− e.style.MozTransform = transforms;
158− e.style.webkitTransform = transforms;
159− e.style.OTransform = transforms;
151+function collageElement(w, h, m, elem) {
152+ var e = Render.render(elem);
153+ var matrix = 'matrix(' + m[0] + ',' + m[3] + ',' + m[1] + ',' +
154+ m[4] + ',' + m[2] + ',' + m[5] + ')';
155+ addTransform(e.style, matrix);
156+ var div = newElement('div');
157+ addTo(div,e);
158+ div.style.width = (w|0) + "px";
159+ div.style.height = (h|0) + "px";
160+ div.style.overflow = "hidden";
161+ return div;
160162}
161163
162−function collageElement(w,h,theta,scale,x,y,elem) {
163− var e = Render.render(elem);
164− applyTransforms(theta,scale,x,y,elem[3],elem[4],e);
165− var div = Render.newElement('div');
166− Render.addTo(div,e);
167− div.style.width = (~~w) + "px";
168− div.style.height = (~~h) + "px";
169− div.style.overflow = "hidden";
170− return div;
164+function render(model) {
165+ return collageForms(model.w, model.h, model.forms);
171166}
172167
173−function collage(w,h,formss) {
174− if (formss.length === 0) { return collageForms(w,h,[]); }
175− var elems = new Array(formss.length);
176− for (var i = formss.length; i--; ) {
177− var f = formss[i];
178− if (typeof f[0] === "string") {
179− elems[i] = collageElement(w,h,f[1],f[2],f[3][1],f[3][2],f[4][1]);
180− } else {
181− elems[i] = collageForms(w,h,f);
182− }
183− }
184− if (formss.length === 1) { return elems[0]; }
185− return Render.flowWith(Render.goIn,function(x){return x},elems);
186−}
187−
188−function updateFormSet(node,currSet,nextSet) {
189− if (Value.eq(nextSet,currSet)) return;
190− var w = node.style.width.slice(0,-2) - 0;
191− var h = node.style.height.slice(0,-2) - 0;
192− if (typeof nextSet[0] === "object") {
193− if (typeof currSet[0] === "object") {
194− if (node.getContext) {
195− var ctx = node.getContext('2d');
196− function redo() { renderForms(this,ctx,w,h,nextSet); }
197− return renderForms(redo,ctx,w,h,nextSet);
198− }
199− }
200− var newNode = collageForms(w,h,nextSet);
201− newNode.style.position = 'absolute';
202− return node.parentNode.replaceChild(newNode,node);
203− }
204− node.style.width = (~~w) + "px";
205− node.style.height = (~~h) + "px";
206− var f = nextSet;
207− var next = nextSet[4][1];
208− Render.update(node.firstChild, currSet[4][1], next);
209− applyTransforms(f[1],f[2],f[3][1],f[3][2],next[3],next[4],node.firstChild);
210−}
211−
212−// assumes that the form sets are the same length.
213−function updateCollage(node,currs,nexts) {
214− if (nexts.length === 1) {
215− return updateFormSet(node,currs[0],nexts[0]);
216− }
217− var kids = node.childNodes;
218− var len = kids.length;
219− for (var i = len; i--; ) {
220− updateFormSet(kids[len-i-1], currs[i], nexts[i]);
221− }
222−}
223−
224−function style(clr,n,list) {
225− return ["Tuple2",
226− '<span style="font-size:100%;color:' + clr + ';">' + n + '</span>',
227− list];
228−}
229−
230−function insideForm(point) { return function(form) {
231− if (!inBoundsOf(point[1],point[2],form)) return false;
232− var hw, hh;
233− switch (form[4][0]) {
234− case "FShape": return insideShape(point,form[1],form[2],form[3],form[4][3][1]);
235− case "FLine": return false;
236− case "FImage":
237− hw = form[4][1] / 2;
238− hh = form[4][2] / 2;
239− break;
240− case "FElement":
241− hw = form[4][1][3] / 2;
242− hh = form[4][1][4] / 2;
243− break;
244− }
245− return insideShape(point,form[1],form[2],form[3],
246− [ [null, hw, hh],
247− [null,-hw, hh],
248− [null,-hw,-hh],
249− [null, hw,-hh],
250− [null, hw, hh] ]);
251− };
252−}
253−
254−function inBoundsOf(px,py,form) {
255− if (form.length < 6) {
256− var fx = form[3][1], fy = form[3][2];
257− var radiusSquared = 0;
258− var scale = form[2];
259− switch (form[4][0]) {
260− case "FShape":
261− var points = form[4][3][1];
262− for (var i = points.length; --i; ) {
263− var p = points[i];
264− radiusSquared = Math.max(radiusSquared, p[1]*p[1] + p[2]*p[2]);
265− }
266− radiusSquared *= scale * scale;
267− break;
268− case "FLine":
269− break;
270− case "FImage":
271− var x = scale * form[4][1] / 2;
272− var y = scale * form[4][2] / 2;
273− radiusSquared = x*x + y*y;
274− break;
275− case "FElement":
276− var x = scale * form[4][1][3] / 2;
277− var y = scale * form[4][1][4] / 2;
278− radiusSquared = x*x + y*y;
279− break;
280− }
281− form.push(function(px,py) {
282− var dx = px - fx;
283− var dy = py - fy;
284− return dx*dx + dy*dy < radiusSquared + 1;
285− });
286− }
287− return form[5](px,py);
288−}
289−
290−function insideShape(point,theta,scale,pos,points) {
291− var counter = 0;
292− var list = ["Nil"];
293− var p1,p2;
294−
295− var x = (point[1] - pos[1]) / scale;
296− var y = (point[2] - pos[2]) / scale;
297− if (theta !== 0) {
298− var t = -2 * Math.PI * theta;
299− var nx = x * Math.cos(t) - y * Math.sin(t);
300− y = x * Math.sin(t) + y * Math.cos(t);
301− x = nx;
302− }
303−
304− if (points.length === 0) { return false; }
305− p1 = points[0];
306− for (var i = points.length - 1; i--; ) {
307− p2 = points[i];
308− var p1x = p1[1], p1y = p1[2], p2x = p2[1], p2y = p2[2];
309−
310− if (p1y < p2y) {var ymin=p1y, ymax=p2y;} else {var ymin=p2y, ymax=p1y;}
311− if (p1x < p2x) {var xmin=p1x, xmax=p2x;} else {var xmin=p2x, xmax=p1x;}
312−
313− if (ymin < y && y <= ymax && x <= xmax) {
314− if (x <= xmin || x <= ((y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x)) {
315− ++counter;
316− }
317− }
318− p1 = p2;
319− }
320− return (counter % 2) === 1;
321−}
322−
323−return {collage:collage, updateCollage:updateCollage, insideForm:insideForm};
168+return { render:render };
324169
325170};