2ElmRuntime.Render.Collage = function() {
5var Render = ElmRuntime.use(ElmRuntime.Render.Element);
6var Matrix = Elm.Matrix2D({});
7var Utils = ElmRuntime.use(ElmRuntime.Render.Utils);
8var newElement = Utils.newElement,
9 extract = Utils.extract, fromList = Utils.fromList,
10 fromString = Utils.fromString, addTransform = Utils.addTransform;
12function trace(ctx, path) {
13 var points = fromList(path);
14 var i = points.length - 1;
16 ctx.moveTo(points[i]._0, points[i]._1);
17 while (i--) { ctx.lineTo(points[i]._0, points[i]._1); }
19 i = points.length - 1;
20 ctx.lineTo(points[i]._0, points[i]._1);
24function line(ctx,style,path) {
25 style.dashing.ctor === 'Nil' ? trace(ctx, path) : customLineHelp(ctx, style, path);
30function customLineHelp(ctx, style, path) {
31 var points = fromList(path);
32 if (path.closed) points.push(points[0]);
33 var pattern = fromList(style.dashing);
34 var i = points.length - 1;
36 var x0 = points[i]._0, y0 = points[i]._1;
37 var x1=0, y1=0, dx=0, dy=0, remaining=0, nx=0, ny=0;
38 var pindex = 0, plen = pattern.length;
39 var draw = true, segmentLength = pattern[0];
42 x1 = points[i]._0; y1 = points[i]._1;
43 dx = x1 - x0; dy = y1 - y0;
44 remaining = Math.sqrt(dx * dx + dy * dy);
45 while (segmentLength <= remaining) {
46 x0 += dx * segmentLength / remaining;
47 y0 += dy * segmentLength / remaining;
48 ctx[draw ? 'lineTo' : 'moveTo'](x0, y0);
49 // update starting position
50 dx = x1 - x0; dy = y1 - y0;
51 remaining = Math.sqrt(dx * dx + dy * dy);
54 pindex = (pindex + 1) % plen;
55 segmentLength = pattern[pindex];
58 ctx[draw ? 'lineTo' : 'moveTo'](x1, y1);
59 segmentLength -= remaining;
65function drawLine(ctx, style, path) {
66 ctx.lineWidth = style.width;
67 var cap = style.cap.ctor;
68 ctx.lineCap = cap === 'Flat' ? 'butt' :
69 cap === 'Round' ? 'round' : 'square';
70 var join = style.join.ctor;
71 ctx.lineJoin = join === 'Smooth' ? 'round' :
72 join === 'Sharp' ? 'miter' : 'bevel';
73 ctx.miterLimit = style.join._0 || 10;
74 ctx.strokeStyle = extract(style.color);
75 return line(ctx, style, path);
78function texture(redo, ctx, src) {
79 var img = new Image();
80 img.src = fromString(src);
82 return ctx.createPattern(img, 'repeat');
85function gradient(ctx, grad) {
88 if (grad.ctor === 'Linear') {
89 var p0 = grad._0, p1 = grad._1;
90 g = ctx.createLinearGradient(p0._0, -p0._1, p1._0, -p1._1);
91 stops = fromList(grad._2);
93 var p0 = grad._0, p2 = grad._2;
94 g = ctx.createRadialGradient(p0._0, -p0._1, grad._1, p2._0, -p2._1, grad._3);
95 stops = fromList(grad._4);
97 var len = stops.length;
98 for (var i = 0; i < len; ++i) {
100 g.addColorStop(stop._0, extract(stop._1));
105function drawShape(redo, ctx, style, path) {
107 var sty = style.ctor;
109 sty === 'Solid' ? extract(style._0) :
110 sty === 'Texture' ? texture(redo, ctx, style._0) : gradient(ctx, style._0);
115function drawImage(redo, ctx, form) {
116 var img = new Image();
118 img.src = fromString(form._3);
132 ctx.drawImage(img, srcX, srcY, srcW, srcH, destX, destY, destW, destH);
135function renderForm(redo, ctx, form) {
137 var x = form.x, y = form.y, theta = form.theta, scale = form.scale;
138 if (x !== 0 || y !== 0) ctx.translate(x, y);
139 if (theta !== 0) ctx.rotate(theta);
140 if (scale !== 1) ctx.scale(scale,scale);
141 if (form.alpha !== 1) ctx.globalAlpha = ctx.globalAlpha * form.alpha;
145 case 'FPath' : drawLine(ctx, f._0, f._1); break;
146 case 'FImage': drawImage(redo, ctx, f); break;
148 if (f._0.ctor === 'Left') {
150 drawLine(ctx, f._0._0, f._1);
152 drawShape(redo, ctx, f._0._0, f._1);
159function formToMatrix(form) {
160 var scale = form.scale;
161 var matrix = A6( Matrix.matrix, scale, 0, 0, scale, form.x, form.y );
163 var theta = form.theta
165 matrix = A2( Matrix.multiply, matrix, Matrix.rotation(theta) );
170function makeTransform(w, h, form, matrices) {
171 var props = form.form._0.props;
172 var m = A6( Matrix.matrix, 1, 0, 0, 1,
174 (h - props.height)/2 );
175 var len = matrices.length;
176 for (var i = 0; i < len; ++i) { m = A2( Matrix.multiply, m, matrices[i] ); }
177 m = A2( Matrix.multiply, m, formToMatrix(form) );
179 return 'matrix(' + m[0] + ',' + m[3] + ',' +
180 (-m[1]) + ',' + (-m[4]) + ',' +
181 m[2] + ',' + m[5] + ')';
184function stepperHelp(list) {
185 var arr = fromList(list);
187 function peekNext() {
188 return i < arr.length ? arr[i].form.ctor : '';
190 // assumes that there is a next element
196 return { peekNext:peekNext, next:next };
199function stepper(forms) {
200 var ps = [stepperHelp(forms)];
203 function peekNext() {
206 for (var i = 0; i < len; ++i ) {
207 if (formType = ps[i].peekNext()) return formType;
211 // assumes that there is a next element
213 while (!ps[0].peekNext()) {
217 if (ctx) { ctx.restore(); }
219 var out = ps[0].next();
221 if (f.ctor === 'FGroup') {
222 ps.unshift(stepperHelp(f._1));
223 var m = A2(Matrix.multiply, f._0, formToMatrix(out));
225 ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
228 var alpha = (alphas[0] || 1) * out.alpha;
229 alphas.unshift(alpha);
230 ctx.globalAlpha = alpha;
234 function transforms() { return matrices; }
235 function alpha() { return alphas[0] || 1; }
236 return { peekNext:peekNext, next:next, transforms:transforms, alpha:alpha };
239function makeCanvas(w,h) {
240 var canvas = newElement('canvas');
241 canvas.style.width = w + 'px';
242 canvas.style.height = h + 'px';
243 canvas.style.display = "block";
244 canvas.style.position = "absolute";
250function render(model) {
251 var div = newElement('div');
252 update(div, model, model);
256function updateTracker(w,h,div) {
257 var kids = div.childNodes;
259 function transform(transforms, ctx) {
260 ctx.translate(w/2, h/2);
262 var len = transforms.length;
263 for (var i = 0; i < len; ++i) {
264 var m = transforms[i];
266 ctx.transform(m[0], m[3], m[1], m[4], m[2], m[5]);
270 function getContext(transforms) {
271 while (i < kids.length) {
273 if (node.getContext) {
276 node.style.width = w + 'px';
277 node.style.height = h + 'px';
279 return transform(transforms, node.getContext('2d'));
281 div.removeChild(node);
283 var canvas = makeCanvas(w,h);
284 div.appendChild(canvas);
285 // we have added a new node, so we must step our position
287 return transform(transforms, canvas.getContext('2d'));
289 function element(matrices, alpha, form) {
290 var container = kids[i];
291 if (!container || container.getContext) {
292 container = newElement('div');
293 container.style.overflow = 'hidden';
294 container.style.position = 'absolute';
295 addTransform(container.style, 'scaleY(-1)');
298 kid ? div.insertBefore(container, kid)
299 : div.appendChild(container);
301 // we have added a new node, so we must step our position
304 container.style.width = w + 'px';
305 container.style.height = h + 'px';
306 container.style.opacity = alpha * form.alpha;
308 var elem = form.form._0;
309 var node = container.firstChild;
311 Render.update(node, node.oldElement, elem);
312 node = container.firstChild;
314 node = Render.render(elem);
315 container.appendChild(node);
317 node.oldElement = elem;
318 addTransform(node.style, makeTransform(w, h, form, matrices));
320 function clearRest() {
321 while (i < kids.length) {
322 div.removeChild(kids[i]);
325 return { getContext:getContext, element:element, clearRest:clearRest };
329function update(div, _, model) {
332 div.style.width = w + 'px';
333 div.style.height = h + 'px';
334 if (model.forms.ctor === 'Nil') {
335 while (div.hasChildNodes()) {
336 div.removeChild(div.lastChild);
339 var stpr = stepper(model.forms);
340 var tracker = updateTracker(w,h,div);
344 while (formType = stpr.peekNext()) {
345 if (ctx === null && formType !== 'FElement') {
346 ctx = tracker.getContext(stpr.transforms());
347 ctx.globalAlpha = stpr.alpha();
349 var form = stpr.next(ctx);
350 if (formType === 'FElement') {
351 tracker.element(stpr.transforms(), stpr.alpha(), form);
353 } else if (formType !== 'FGroup') {
354 renderForm(function() { update(div, model, model); }, ctx, form);
361return { render:render, update:update };
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list