scratch – Blame information for rev 94
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
84 | office | 1 | /* drawingboard.js v0.4.6 - https://github.com/Leimi/drawingboard.js |
2 | * Copyright (c) 2015 Emmanuel Pelletier |
||
3 | * Licensed MIT */ |
||
4 | (function() { |
||
5 | |||
6 | 'use strict'; |
||
7 | |||
8 | /** |
||
9 | * SimpleUndo is a very basic javascript undo/redo stack for managing histories of basically anything. |
||
10 | * |
||
11 | * options are: { |
||
12 | * * `provider` : required. a function to call on `save`, which should provide the current state of the historized object through the given "done" callback |
||
13 | * * `maxLength` : the maximum number of items in history |
||
14 | * * `opUpdate` : a function to call to notify of changes in history. Will be called on `save`, `undo`, `redo` and `clear` |
||
15 | * } |
||
16 | * |
||
17 | */ |
||
18 | var SimpleUndo = function(options) { |
||
19 | |||
20 | var settings = options ? options : {}; |
||
21 | var defaultOptions = { |
||
22 | provider: function() { |
||
23 | throw new Error("No provider!"); |
||
24 | }, |
||
25 | maxLength: 30, |
||
26 | onUpdate: function() {} |
||
27 | }; |
||
28 | |||
29 | this.provider = (typeof settings.provider != 'undefined') ? settings.provider : defaultOptions.provider; |
||
30 | this.maxLength = (typeof settings.maxLength != 'undefined') ? settings.maxLength : defaultOptions.maxLength; |
||
31 | this.onUpdate = (typeof settings.onUpdate != 'undefined') ? settings.onUpdate : defaultOptions.onUpdate; |
||
32 | |||
33 | this.initialItem = null; |
||
34 | this.clear(); |
||
35 | }; |
||
36 | |||
37 | function truncate (stack, limit) { |
||
38 | while (stack.length > limit) { |
||
39 | stack.shift(); |
||
40 | } |
||
41 | } |
||
42 | |||
43 | SimpleUndo.prototype.initialize = function(initialItem) { |
||
44 | this.stack[0] = initialItem; |
||
45 | this.initialItem = initialItem; |
||
46 | }; |
||
47 | |||
48 | |||
49 | SimpleUndo.prototype.clear = function() { |
||
50 | this.stack = [this.initialItem]; |
||
51 | this.position = 0; |
||
52 | this.onUpdate(); |
||
53 | }; |
||
54 | |||
55 | SimpleUndo.prototype.save = function() { |
||
56 | this.provider(function(current) { |
||
57 | truncate(this.stack, this.maxLength); |
||
58 | this.position = Math.min(this.position,this.stack.length - 1); |
||
59 | |||
60 | this.stack = this.stack.slice(0, this.position + 1); |
||
61 | this.stack.push(current); |
||
62 | this.position++; |
||
63 | this.onUpdate(); |
||
64 | }.bind(this)); |
||
65 | }; |
||
66 | |||
67 | SimpleUndo.prototype.undo = function(callback) { |
||
68 | if (this.canUndo()) { |
||
69 | var item = this.stack[--this.position]; |
||
70 | this.onUpdate(); |
||
71 | |||
72 | if (callback) { |
||
73 | callback(item); |
||
74 | } |
||
75 | } |
||
76 | }; |
||
77 | |||
78 | SimpleUndo.prototype.redo = function(callback) { |
||
79 | if (this.canRedo()) { |
||
80 | var item = this.stack[++this.position]; |
||
81 | this.onUpdate(); |
||
82 | |||
83 | if (callback) { |
||
84 | callback(item); |
||
85 | } |
||
86 | } |
||
87 | }; |
||
88 | |||
89 | SimpleUndo.prototype.canUndo = function() { |
||
90 | return this.position > 0; |
||
91 | }; |
||
92 | |||
93 | SimpleUndo.prototype.canRedo = function() { |
||
94 | return this.position < this.count(); |
||
95 | }; |
||
96 | |||
97 | SimpleUndo.prototype.count = function() { |
||
98 | return this.stack.length - 1; // -1 because of initial item |
||
99 | }; |
||
100 | |||
101 | |||
102 | |||
103 | |||
104 | |||
105 | //exports |
||
106 | // node module |
||
107 | if (typeof module != 'undefined') { |
||
108 | module.exports = SimpleUndo; |
||
109 | } |
||
110 | |||
111 | // browser global |
||
112 | if (typeof window != 'undefined') { |
||
113 | window.SimpleUndo = SimpleUndo; |
||
114 | } |
||
115 | |||
116 | })(); |
||
117 | window.DrawingBoard = typeof DrawingBoard !== "undefined" ? DrawingBoard : {}; |
||
118 | |||
119 | |||
120 | DrawingBoard.Utils = {}; |
||
121 | |||
122 | /*! |
||
123 | * Tim (lite) |
||
124 | * github.com/premasagar/tim |
||
125 | *//* |
||
126 | A tiny, secure JavaScript micro-templating script. |
||
127 | */ |
||
128 | DrawingBoard.Utils.tpl = (function(){ |
||
129 | "use strict"; |
||
130 | |||
131 | var start = "{{", |
||
132 | end = "}}", |
||
133 | path = "[a-z0-9_][\\.a-z0-9_]*", // e.g. config.person.name |
||
134 | pattern = new RegExp(start + "\\s*("+ path +")\\s*" + end, "gi"), |
||
135 | undef; |
||
136 | |||
137 | return function(template, data){ |
||
138 | // Merge data into the template string |
||
139 | return template.replace(pattern, function(tag, token){ |
||
140 | var path = token.split("."), |
||
141 | len = path.length, |
||
142 | lookup = data, |
||
143 | i = 0; |
||
144 | |||
145 | for (; i < len; i++){ |
||
146 | lookup = lookup[path[i]]; |
||
147 | |||
148 | // Property not found |
||
149 | if (lookup === undef){ |
||
150 | throw "tim: '" + path[i] + "' not found in " + tag; |
||
151 | } |
||
152 | |||
153 | // Return the required value |
||
154 | if (i === len - 1){ |
||
155 | return lookup; |
||
156 | } |
||
157 | } |
||
158 | }); |
||
159 | }; |
||
160 | }()); |
||
161 | |||
162 | /** |
||
163 | * https://github.com/jeromeetienne/microevent.js |
||
164 | * MicroEvent - to make any js object an event emitter (server or browser) |
||
165 | * |
||
166 | * - pure javascript - server compatible, browser compatible |
||
167 | * - dont rely on the browser doms |
||
168 | * - super simple - you get it immediatly, no mistery, no magic involved |
||
169 | * |
||
170 | * - create a MicroEventDebug with goodies to debug |
||
171 | * - make it safer to use |
||
172 | */ |
||
173 | DrawingBoard.Utils.MicroEvent = function(){}; |
||
174 | |||
175 | DrawingBoard.Utils.MicroEvent.prototype = { |
||
176 | bind : function(event, fct){ |
||
177 | this._events = this._events || {}; |
||
178 | this._events[event] = this._events[event] || []; |
||
179 | this._events[event].push(fct); |
||
180 | }, |
||
181 | unbind : function(event, fct){ |
||
182 | this._events = this._events || {}; |
||
183 | if( event in this._events === false ) return; |
||
184 | this._events[event].splice(this._events[event].indexOf(fct), 1); |
||
185 | }, |
||
186 | trigger : function(event /* , args... */){ |
||
187 | this._events = this._events || {}; |
||
188 | if( event in this._events === false ) return; |
||
189 | for(var i = 0; i < this._events[event].length; i++){ |
||
190 | this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); |
||
191 | } |
||
192 | } |
||
193 | }; |
||
194 | |||
195 | //I know. |
||
196 | DrawingBoard.Utils._boxBorderSize = function($el, withPadding, withMargin, direction) { |
||
197 | withPadding = !!withPadding || true; |
||
198 | withMargin = !!withMargin || false; |
||
199 | var width = 0, |
||
200 | props; |
||
201 | if (direction == "width") { |
||
202 | props = ['border-left-width', 'border-right-width']; |
||
203 | if (withPadding) props.push('padding-left', 'padding-right'); |
||
204 | if (withMargin) props.push('margin-left', 'margin-right'); |
||
205 | } else { |
||
206 | props = ['border-top-width', 'border-bottom-width']; |
||
207 | if (withPadding) props.push('padding-top', 'padding-bottom'); |
||
208 | if (withMargin) props.push('margin-top', 'margin-bottom'); |
||
209 | } |
||
210 | for (var i = props.length - 1; i >= 0; i--) |
||
211 | width += parseInt($el.css(props[i]).replace('px', ''), 10); |
||
212 | return width; |
||
213 | }; |
||
214 | |||
215 | DrawingBoard.Utils.boxBorderWidth = function($el, withPadding, withMargin) { |
||
216 | return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'width'); |
||
217 | }; |
||
218 | |||
219 | DrawingBoard.Utils.boxBorderHeight = function($el, withPadding, withMargin) { |
||
220 | return DrawingBoard.Utils._boxBorderSize($el, withPadding, withMargin, 'height'); |
||
221 | }; |
||
222 | |||
223 | DrawingBoard.Utils.isColor = function(string) { |
||
224 | if (!string || !string.length) return false; |
||
225 | return (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i).test(string) || $.inArray(string.substring(0, 3), ['rgb', 'hsl']) !== -1; |
||
226 | }; |
||
227 | |||
228 | /** |
||
229 | * Packs an RGB color into a single integer. |
||
230 | */ |
||
231 | DrawingBoard.Utils.RGBToInt = function(r, g, b) { |
||
232 | var c = 0; |
||
233 | c |= (r & 255) << 16; |
||
234 | c |= (g & 255) << 8; |
||
235 | c |= (b & 255); |
||
236 | return c; |
||
237 | }; |
||
238 | |||
239 | /** |
||
240 | * Returns informations on the pixel located at (x,y). |
||
241 | */ |
||
242 | DrawingBoard.Utils.pixelAt = function(image, x, y) { |
||
243 | var i = (y * image.width + x) * 4; |
||
244 | var c = DrawingBoard.Utils.RGBToInt( |
||
245 | image.data[i], |
||
246 | image.data[i + 1], |
||
247 | image.data[i + 2] |
||
248 | ); |
||
249 | |||
250 | return [ |
||
251 | i, // INDEX |
||
252 | x, // X |
||
253 | y, // Y |
||
254 | c // COLOR |
||
255 | ]; |
||
256 | }; |
||
257 | |||
258 | /** |
||
259 | * Compares two colors with the given tolerance (between 0 and 255). |
||
260 | */ |
||
261 | DrawingBoard.Utils.compareColors = function(a, b, tolerance) { |
||
262 | if (tolerance === 0) { |
||
263 | return (a === b); |
||
264 | } |
||
265 | |||
266 | var ra = (a >> 16) & 255, rb = (b >> 16) & 255, |
||
267 | ga = (a >> 8) & 255, gb = (b >> 8) & 255, |
||
268 | ba = a & 255, bb = b & 255; |
||
269 | |||
270 | return (Math.abs(ra - rb) <= tolerance) |
||
271 | && (Math.abs(ga - gb) <= tolerance) |
||
272 | && (Math.abs(ba - bb) <= tolerance); |
||
273 | }; |
||
274 | |||
275 | (function() { |
||
276 | var lastTime = 0; |
||
277 | var vendors = ['ms', 'moz', 'webkit', 'o']; |
||
278 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { |
||
279 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; |
||
280 | window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; |
||
281 | } |
||
282 | }()); |
||
283 | |||
284 | window.DrawingBoard = typeof DrawingBoard !== "undefined" ? DrawingBoard : {}; |
||
285 | |||
286 | /** |
||
287 | * pass the id of the html element to put the drawing board into |
||
288 | * and some options : { |
||
289 | * controls: array of controls to initialize with the drawingboard. 'Colors', 'Size', and 'Navigation' by default |
||
290 | * instead of simple strings, you can pass an object to define a control opts |
||
291 | * ie ['Color', { Navigation: { reset: false }}] |
||
292 | * controlsPosition: "top left" by default. Define where to put the controls: at the "top" or "bottom" of the canvas, aligned to "left"/"right"/"center" |
||
293 | * background: background of the drawing board. Give a hex color or an image url "#ffffff" (white) by default |
||
294 | * color: pencil color ("#000000" by default) |
||
295 | * size: pencil size (3 by default) |
||
296 | * webStorage: 'session', 'local' or false ('session' by default). store the current drawing in session or local storage and restore it when you come back |
||
297 | * droppable: true or false (false by default). If true, dropping an image on the canvas will include it and allow you to draw on it, |
||
298 | * errorMessage: html string to put in the board's element on browsers that don't support canvas. |
||
299 | * stretchImg: default behavior of image setting on the canvas: set to the canvas width/height or not? false by default |
||
300 | * } |
||
301 | */ |
||
302 | DrawingBoard.Board = function(id, opts) { |
||
303 | this.opts = this.mergeOptions(opts); |
||
304 | |||
305 | this.ev = new DrawingBoard.Utils.MicroEvent(); |
||
306 | |||
307 | this.id = id; |
||
308 | this.$el = $(document.getElementById(id)); |
||
309 | if (!this.$el.length) |
||
310 | return false; |
||
311 | |||
312 | var tpl = '<div class="drawing-board-canvas-wrapper"></canvas><canvas class="drawing-board-canvas"></canvas><div class="drawing-board-cursor drawing-board-utils-hidden"></div></div>'; |
||
313 | if (this.opts.controlsPosition.indexOf("bottom") > -1) tpl += '<div class="drawing-board-controls"></div>'; |
||
314 | else tpl = '<div class="drawing-board-controls"></div>' + tpl; |
||
315 | |||
316 | this.$el.addClass('drawing-board').append(tpl); |
||
317 | this.dom = { |
||
318 | $canvasWrapper: this.$el.find('.drawing-board-canvas-wrapper'), |
||
319 | $canvas: this.$el.find('.drawing-board-canvas'), |
||
320 | $cursor: this.$el.find('.drawing-board-cursor'), |
||
321 | $controls: this.$el.find('.drawing-board-controls') |
||
322 | }; |
||
323 | |||
324 | $.each(['left', 'right', 'center'], $.proxy(function(n, val) { |
||
325 | if (this.opts.controlsPosition.indexOf(val) > -1) { |
||
326 | this.dom.$controls.attr('data-align', val); |
||
327 | return false; |
||
328 | } |
||
329 | }, this)); |
||
330 | |||
331 | this.canvas = this.dom.$canvas.get(0); |
||
332 | this.ctx = this.canvas && this.canvas.getContext && this.canvas.getContext('2d') ? this.canvas.getContext('2d') : null; |
||
333 | this.color = this.opts.color; |
||
334 | |||
335 | if (!this.ctx) { |
||
336 | if (this.opts.errorMessage) |
||
337 | this.$el.html(this.opts.errorMessage); |
||
338 | return false; |
||
339 | } |
||
340 | |||
341 | this.storage = this._getStorage(); |
||
342 | |||
343 | this.initHistory(); |
||
344 | //init default board values before controls are added (mostly pencil color and size) |
||
345 | this.reset({ webStorage: false, history: false, background: false }); |
||
346 | //init controls (they will need the default board values to work like pencil color and size) |
||
347 | this.initControls(); |
||
348 | //set board's size after the controls div is added |
||
349 | this.resize(); |
||
350 | //reset the board to take all resized space |
||
351 | this.reset({ webStorage: false, history: false, background: true }); |
||
352 | this.restoreWebStorage(); |
||
353 | this.initDropEvents(); |
||
354 | this.initDrawEvents(); |
||
355 | }; |
||
356 | |||
357 | |||
358 | |||
359 | DrawingBoard.Board.defaultOpts = { |
||
360 | controls: ['Color', 'DrawingMode', 'Size', 'Navigation'], |
||
361 | controlsPosition: "top left", |
||
362 | color: "#000000", |
||
363 | size: 1, |
||
364 | background: "#fff", |
||
365 | eraserColor: "background", |
||
366 | fillTolerance: 100, |
||
367 | fillHack: true, //try to prevent issues with anti-aliasing with a little hack by default |
||
368 | webStorage: 'session', |
||
369 | droppable: false, |
||
370 | enlargeYourContainer: false, |
||
371 | errorMessage: "<p>It seems you use an obsolete browser. <a href=\"http://browsehappy.com/\" target=\"_blank\">Update it</a> to start drawing.</p>", |
||
372 | stretchImg: false //when setting the canvas img, strech the image at the whole canvas size when this opt is true |
||
373 | }; |
||
374 | |||
375 | |||
376 | |||
377 | DrawingBoard.Board.prototype = { |
||
378 | |||
379 | mergeOptions: function(opts) { |
||
380 | opts = $.extend({}, DrawingBoard.Board.defaultOpts, opts); |
||
381 | if (!opts.background && opts.eraserColor === "background") |
||
382 | opts.eraserColor = "transparent"; |
||
383 | return opts; |
||
384 | }, |
||
385 | |||
386 | /** |
||
387 | * Canvas reset/resize methods: put back the canvas to its default values |
||
388 | * |
||
389 | * depending on options, can set color, size, background back to default values |
||
390 | * and store the reseted canvas in webstorage and history queue |
||
391 | * |
||
392 | * resize values depend on the `enlargeYourContainer` option |
||
393 | */ |
||
394 | |||
395 | reset: function(opts) { |
||
396 | opts = $.extend({ |
||
397 | color: this.opts.color, |
||
398 | size: this.opts.size, |
||
399 | webStorage: true, |
||
400 | history: true, |
||
401 | background: false |
||
402 | }, opts); |
||
403 | |||
404 | this.setMode('pencil'); |
||
405 | |||
406 | if (opts.background) { |
||
407 | this.resetBackground(this.opts.background, $.proxy(function() { |
||
408 | if (opts.history) this.saveHistory(); |
||
409 | }, this)); |
||
410 | } |
||
411 | |||
412 | if (opts.color) this.setColor(opts.color); |
||
413 | if (opts.size) this.ctx.lineWidth = opts.size; |
||
414 | |||
415 | this.ctx.lineCap = "round"; |
||
416 | this.ctx.lineJoin = "round"; |
||
417 | // this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.width); |
||
418 | |||
419 | if (opts.webStorage) this.saveWebStorage(); |
||
420 | |||
421 | // if opts.background we already dealt with the history |
||
422 | if (opts.history && !opts.background) this.saveHistory(); |
||
423 | |||
424 | this.blankCanvas = this.getImg(); |
||
425 | |||
426 | this.ev.trigger('board:reset', opts); |
||
427 | }, |
||
428 | |||
429 | resetBackground: function(background, callback) { |
||
430 | background = background || this.opts.background; |
||
431 | |||
432 | var bgIsColor = DrawingBoard.Utils.isColor(background); |
||
433 | var prevMode = this.getMode(); |
||
434 | this.setMode('pencil'); |
||
435 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); |
||
436 | if (bgIsColor) { |
||
437 | this.ctx.fillStyle = background; |
||
438 | this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); |
||
439 | this.history.initialize(this.getImg()); |
||
440 | if (callback) callback(); |
||
441 | } else if (background) |
||
442 | this.setImg(background, { |
||
443 | callback: $.proxy(function() { |
||
444 | this.history.initialize(this.getImg()); |
||
445 | if (callback) callback(); |
||
446 | }, this) |
||
447 | }); |
||
448 | this.setMode(prevMode); |
||
449 | }, |
||
450 | |||
451 | resize: function() { |
||
452 | this.dom.$controls.toggleClass('drawing-board-controls-hidden', (!this.controls || !this.controls.length)); |
||
453 | |||
454 | var canvasWidth, canvasHeight; |
||
455 | var widths = [ |
||
456 | this.$el.width(), |
||
457 | DrawingBoard.Utils.boxBorderWidth(this.$el), |
||
458 | DrawingBoard.Utils.boxBorderWidth(this.dom.$canvasWrapper, true, true) |
||
459 | ]; |
||
460 | var heights = [ |
||
461 | this.$el.height(), |
||
462 | DrawingBoard.Utils.boxBorderHeight(this.$el), |
||
463 | this.dom.$controls.height(), |
||
464 | DrawingBoard.Utils.boxBorderHeight(this.dom.$controls, false, true), |
||
465 | DrawingBoard.Utils.boxBorderHeight(this.dom.$canvasWrapper, true, true) |
||
466 | ]; |
||
467 | var that = this; |
||
468 | var sum = function(values, multiplier) { //make the sum of all array values |
||
469 | multiplier = multiplier || 1; |
||
470 | var res = values[0]; |
||
471 | for (var i = 1; i < values.length; i++) { |
||
472 | res = res + (values[i]*multiplier); |
||
473 | } |
||
474 | return res; |
||
475 | }; |
||
476 | var sub = function(values) { return sum(values, -1); }; //substract all array values from the first one |
||
477 | |||
478 | if (this.opts.enlargeYourContainer) { |
||
479 | canvasWidth = this.$el.width(); |
||
480 | canvasHeight = this.$el.height(); |
||
481 | |||
482 | this.$el.width( sum(widths) ); |
||
483 | this.$el.height( sum(heights) ); |
||
484 | } else { |
||
485 | canvasWidth = sub(widths); |
||
486 | canvasHeight = sub(heights); |
||
487 | } |
||
488 | |||
489 | this.dom.$canvasWrapper.css('width', canvasWidth + 'px'); |
||
490 | this.dom.$canvasWrapper.css('height', canvasHeight + 'px'); |
||
491 | |||
492 | this.dom.$canvas.css('width', canvasWidth + 'px'); |
||
493 | this.dom.$canvas.css('height', canvasHeight + 'px'); |
||
494 | |||
495 | this.canvas.width = canvasWidth; |
||
496 | this.canvas.height = canvasHeight; |
||
497 | }, |
||
498 | |||
499 | |||
500 | |||
501 | /** |
||
502 | * Controls: |
||
503 | * the drawing board can has various UI elements to control it. |
||
504 | * one control is represented by a class in the namespace DrawingBoard.Control |
||
505 | * it must have a $el property (jQuery object), representing the html element to append on the drawing board at initialization. |
||
506 | * |
||
507 | */ |
||
508 | |||
509 | initControls: function() { |
||
510 | this.controls = []; |
||
511 | if (!this.opts.controls.length || !DrawingBoard.Control) return false; |
||
512 | for (var i = 0; i < this.opts.controls.length; i++) { |
||
513 | var c = null; |
||
514 | if (typeof this.opts.controls[i] == "string") |
||
515 | c = new window['DrawingBoard']['Control'][this.opts.controls[i]](this); |
||
516 | else if (typeof this.opts.controls[i] == "object") { |
||
517 | for (var controlName in this.opts.controls[i]) break; |
||
518 | c = new window['DrawingBoard']['Control'][controlName](this, this.opts.controls[i][controlName]); |
||
519 | } |
||
520 | if (c) { |
||
521 | this.addControl(c); |
||
522 | } |
||
523 | } |
||
524 | }, |
||
525 | |||
526 | //add a new control or an existing one at the position you want in the UI |
||
527 | //to add a totally new control, you can pass a string with the js class as 1st parameter and control options as 2nd ie "addControl('Navigation', { reset: false }" |
||
528 | //the last parameter (2nd or 3rd depending on the situation) is always the position you want to place the control at |
||
529 | addControl: function(control, optsOrPos, pos) { |
||
530 | if (typeof control !== "string" && (typeof control !== "object" || !control instanceof DrawingBoard.Control)) |
||
531 | return false; |
||
532 | |||
533 | var opts = typeof optsOrPos == "object" ? optsOrPos : {}; |
||
534 | pos = pos ? pos*1 : (typeof optsOrPos == "number" ? optsOrPos : null); |
||
535 | |||
536 | if (typeof control == "string") |
||
537 | control = new window['DrawingBoard']['Control'][control](this, opts); |
||
538 | |||
539 | if (pos) |
||
540 | this.dom.$controls.children().eq(pos).before(control.$el); |
||
541 | else |
||
542 | this.dom.$controls.append(control.$el); |
||
543 | |||
544 | if (!this.controls) |
||
545 | this.controls = []; |
||
546 | this.controls.push(control); |
||
547 | this.dom.$controls.removeClass('drawing-board-controls-hidden'); |
||
548 | }, |
||
549 | |||
550 | |||
551 | |||
552 | /** |
||
553 | * History methods: undo and redo drawed lines |
||
554 | */ |
||
555 | |||
556 | initHistory: function() { |
||
557 | this.history = new SimpleUndo({ |
||
558 | maxLength: 30, |
||
559 | provider: $.proxy(function(done) { |
||
560 | done(this.getImg()); |
||
561 | }, this), |
||
562 | onUpdate: $.proxy(function() { |
||
563 | this.ev.trigger('historyNavigation'); |
||
564 | }, this) |
||
565 | }); |
||
566 | }, |
||
567 | |||
568 | saveHistory: function() { |
||
569 | this.history.save(); |
||
570 | }, |
||
571 | |||
572 | restoreHistory: function(image) { |
||
573 | this.setImg(image, { |
||
574 | callback: $.proxy(function() { |
||
575 | this.saveWebStorage(); |
||
576 | }, this) |
||
577 | }); |
||
578 | }, |
||
579 | |||
580 | goBackInHistory: function() { |
||
581 | this.history.undo($.proxy(this.restoreHistory, this)); |
||
582 | }, |
||
583 | |||
584 | goForthInHistory: function() { |
||
585 | this.history.redo($.proxy(this.restoreHistory, this)); |
||
586 | }, |
||
587 | |||
588 | /** |
||
589 | * Image methods: you can directly put an image on the canvas, get it in base64 data url or start a download |
||
590 | */ |
||
591 | |||
592 | setImg: function(src, opts) { |
||
593 | opts = $.extend({ |
||
594 | stretch: this.opts.stretchImg, |
||
595 | callback: null |
||
596 | }, opts); |
||
597 | |||
598 | var ctx = this.ctx; |
||
599 | var img = new Image(); |
||
600 | var oldGCO = ctx.globalCompositeOperation; |
||
601 | img.onload = function() { |
||
602 | ctx.globalCompositeOperation = "source-over"; |
||
603 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
||
604 | |||
605 | if (opts.stretch) { |
||
606 | ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height); |
||
607 | } else { |
||
608 | ctx.drawImage(img, 0, 0); |
||
609 | } |
||
610 | |||
611 | ctx.globalCompositeOperation = oldGCO; |
||
612 | |||
613 | if (opts.callback) { |
||
614 | opts.callback(); |
||
615 | } |
||
616 | }; |
||
617 | img.src = src; |
||
618 | }, |
||
619 | |||
620 | getImg: function() { |
||
621 | return this.canvas.toDataURL("image/png"); |
||
622 | }, |
||
623 | |||
624 | downloadImg: function() { |
||
625 | var img = this.getImg(); |
||
626 | img = img.replace("image/png", "image/octet-stream"); |
||
627 | window.location.href = img; |
||
628 | }, |
||
629 | |||
630 | |||
631 | |||
632 | /** |
||
633 | * WebStorage handling : save and restore to local or session storage |
||
634 | */ |
||
635 | |||
636 | saveWebStorage: function() { |
||
637 | if (window[this.storage]) { |
||
638 | window[this.storage].setItem('drawing-board-' + this.id, this.getImg()); |
||
639 | this.ev.trigger('board:save' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1), this.getImg()); |
||
640 | } |
||
641 | }, |
||
642 | |||
643 | restoreWebStorage: function() { |
||
644 | if (window[this.storage] && window[this.storage].getItem('drawing-board-' + this.id) !== null) { |
||
645 | this.setImg(window[this.storage].getItem('drawing-board-' + this.id)); |
||
646 | this.ev.trigger('board:restore' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1), window[this.storage].getItem('drawing-board-' + this.id)); |
||
647 | } |
||
648 | }, |
||
649 | |||
650 | clearWebStorage: function() { |
||
651 | if (window[this.storage] && window[this.storage].getItem('drawing-board-' + this.id) !== null) { |
||
652 | window[this.storage].removeItem('drawing-board-' + this.id); |
||
653 | this.ev.trigger('board:clear' + this.storage.charAt(0).toUpperCase() + this.storage.slice(1)); |
||
654 | } |
||
655 | }, |
||
656 | |||
657 | _getStorage: function() { |
||
658 | if (!this.opts.webStorage || !(this.opts.webStorage === 'session' || this.opts.webStorage === 'local')) return false; |
||
659 | return this.opts.webStorage + 'Storage'; |
||
660 | }, |
||
661 | |||
662 | |||
663 | |||
664 | /** |
||
665 | * Drop an image on the canvas to draw on it |
||
666 | */ |
||
667 | |||
668 | initDropEvents: function() { |
||
669 | if (!this.opts.droppable) |
||
670 | return false; |
||
671 | |||
672 | this.dom.$canvas.on('dragover dragenter drop', function(e) { |
||
673 | e.stopPropagation(); |
||
674 | e.preventDefault(); |
||
675 | }); |
||
676 | |||
677 | this.dom.$canvas.on('drop', $.proxy(this._onCanvasDrop, this)); |
||
678 | }, |
||
679 | |||
680 | _onCanvasDrop: function(e) { |
||
681 | e = e.originalEvent ? e.originalEvent : e; |
||
682 | var files = e.dataTransfer.files; |
||
683 | if (!files || !files.length || files[0].type.indexOf('image') == -1 || !window.FileReader) |
||
684 | return false; |
||
685 | var fr = new FileReader(); |
||
686 | fr.readAsDataURL(files[0]); |
||
687 | fr.onload = $.proxy(function(ev) { |
||
688 | this.setImg(ev.target.result, { |
||
689 | callback: $.proxy(function() { |
||
690 | this.saveHistory(); |
||
691 | }, this) |
||
692 | }); |
||
693 | this.ev.trigger('board:imageDropped', ev.target.result); |
||
694 | this.ev.trigger('board:userAction'); |
||
695 | }, this); |
||
696 | }, |
||
697 | |||
698 | |||
699 | |||
700 | /** |
||
701 | * set and get current drawing mode |
||
702 | * |
||
703 | * possible modes are "pencil" (draw normally), "eraser" (draw transparent, like, erase, you know), "filler" (paint can) |
||
704 | */ |
||
705 | |||
706 | setMode: function(newMode, silent) { |
||
707 | silent = silent || false; |
||
708 | newMode = newMode || 'pencil'; |
||
709 | |||
710 | this.ev.unbind('board:startDrawing', $.proxy(this.fill, this)); |
||
711 | |||
712 | if (this.opts.eraserColor === "transparent") |
||
713 | this.ctx.globalCompositeOperation = newMode === "eraser" ? "destination-out" : "source-over"; |
||
714 | else { |
||
715 | if (newMode === "eraser") { |
||
716 | if (this.opts.eraserColor === "background" && DrawingBoard.Utils.isColor(this.opts.background)) |
||
717 | this.ctx.strokeStyle = this.opts.background; |
||
718 | else if (DrawingBoard.Utils.isColor(this.opts.eraserColor)) |
||
719 | this.ctx.strokeStyle = this.opts.eraserColor; |
||
720 | } else if (!this.mode || this.mode === "eraser") { |
||
721 | this.ctx.strokeStyle = this.color; |
||
722 | } |
||
723 | |||
724 | if (newMode === "filler") |
||
725 | this.ev.bind('board:startDrawing', $.proxy(this.fill, this)); |
||
726 | } |
||
727 | this.mode = newMode; |
||
728 | if (!silent) |
||
729 | this.ev.trigger('board:mode', this.mode); |
||
730 | }, |
||
731 | |||
732 | getMode: function() { |
||
733 | return this.mode || "pencil"; |
||
734 | }, |
||
735 | |||
736 | setColor: function(color) { |
||
737 | var that = this; |
||
738 | color = color || this.color; |
||
739 | if (!DrawingBoard.Utils.isColor(color)) |
||
740 | return false; |
||
741 | this.color = color; |
||
742 | if (this.opts.eraserColor !== "transparent" && this.mode === "eraser") { |
||
743 | var setStrokeStyle = function(mode) { |
||
744 | if (mode !== "eraser") |
||
745 | that.strokeStyle = that.color; |
||
746 | that.ev.unbind('board:mode', setStrokeStyle); |
||
747 | }; |
||
748 | this.ev.bind('board:mode', setStrokeStyle); |
||
749 | } else |
||
750 | this.ctx.strokeStyle = this.color; |
||
751 | }, |
||
752 | |||
753 | /** |
||
754 | * Fills an area with the current stroke color. |
||
755 | */ |
||
756 | fill: function(e) { |
||
757 | if (this.getImg() === this.blankCanvas) { |
||
758 | this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); |
||
759 | this.ctx.fillStyle = this.color; |
||
760 | this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); |
||
761 | return; |
||
762 | } |
||
763 | |||
764 | var img = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height); |
||
765 | |||
766 | // constants identifying pixels components |
||
767 | var INDEX = 0, X = 1, Y = 2, COLOR = 3; |
||
768 | |||
769 | // target color components |
||
770 | var stroke = this.ctx.strokeStyle; |
||
771 | var r = parseInt(stroke.substr(1, 2), 16); |
||
772 | var g = parseInt(stroke.substr(3, 2), 16); |
||
773 | var b = parseInt(stroke.substr(5, 2), 16); |
||
774 | |||
775 | // starting point |
||
776 | var start = DrawingBoard.Utils.pixelAt(img, parseInt(e.coords.x, 10), parseInt(e.coords.y, 10)); |
||
777 | var startColor = start[COLOR]; |
||
778 | var tolerance = this.opts.fillTolerance; |
||
779 | var useHack = this.opts.fillHack; //see https://github.com/Leimi/drawingboard.js/pull/38 |
||
780 | |||
781 | // no need to continue if starting and target colors are the same |
||
782 | if (DrawingBoard.Utils.compareColors(startColor, DrawingBoard.Utils.RGBToInt(r, g, b), tolerance)) |
||
783 | return; |
||
784 | |||
785 | // pixels to evaluate |
||
786 | var queue = [start]; |
||
787 | |||
788 | // loop vars |
||
789 | var pixel, x, y; |
||
790 | var maxX = img.width - 1; |
||
791 | var maxY = img.height - 1; |
||
792 | |||
793 | function updatePixelColor(pixel) { |
||
794 | img.data[pixel[INDEX]] = r; |
||
795 | img.data[pixel[INDEX] + 1] = g; |
||
796 | img.data[pixel[INDEX] + 2] = b; |
||
797 | } |
||
798 | |||
799 | while ((pixel = queue.pop())) { |
||
800 | if (useHack) |
||
801 | updatePixelColor(pixel); |
||
802 | |||
803 | if (DrawingBoard.Utils.compareColors(pixel[COLOR], startColor, tolerance)) { |
||
804 | if (!useHack) |
||
805 | updatePixelColor(pixel); |
||
806 | if (pixel[X] > 0) // west |
||
807 | queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X] - 1, pixel[Y])); |
||
808 | if (pixel[X] < maxX) // east |
||
809 | queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X] + 1, pixel[Y])); |
||
810 | if (pixel[Y] > 0) // north |
||
811 | queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X], pixel[Y] - 1)); |
||
812 | if (pixel[Y] < maxY) // south |
||
813 | queue.push(DrawingBoard.Utils.pixelAt(img, pixel[X], pixel[Y] + 1)); |
||
814 | } |
||
815 | } |
||
816 | |||
817 | this.ctx.putImageData(img, 0, 0); |
||
818 | }, |
||
819 | |||
820 | |||
821 | /** |
||
822 | * Drawing handling, with mouse or touch |
||
823 | */ |
||
824 | |||
825 | initDrawEvents: function() { |
||
826 | this.isDrawing = false; |
||
827 | this.isMouseHovering = false; |
||
828 | this.coords = {}; |
||
829 | this.coords.old = this.coords.current = this.coords.oldMid = { x: 0, y: 0 }; |
||
830 | |||
831 | this.dom.$canvas.on('mousedown touchstart', $.proxy(function(e) { |
||
832 | this._onInputStart(e, this._getInputCoords(e) ); |
||
833 | }, this)); |
||
834 | |||
835 | this.dom.$canvas.on('mousemove touchmove', $.proxy(function(e) { |
||
836 | this._onInputMove(e, this._getInputCoords(e) ); |
||
837 | }, this)); |
||
838 | |||
839 | this.dom.$canvas.on('mousemove', $.proxy(function(e) { |
||
840 | |||
841 | }, this)); |
||
842 | |||
843 | this.dom.$canvas.on('mouseup touchend', $.proxy(function(e) { |
||
844 | this._onInputStop(e, this._getInputCoords(e) ); |
||
845 | }, this)); |
||
846 | |||
847 | this.dom.$canvas.on('mouseover', $.proxy(function(e) { |
||
848 | this._onMouseOver(e, this._getInputCoords(e) ); |
||
849 | }, this)); |
||
850 | |||
851 | this.dom.$canvas.on('mouseout', $.proxy(function(e) { |
||
852 | this._onMouseOut(e, this._getInputCoords(e) ); |
||
853 | |||
854 | }, this)); |
||
855 | |||
856 | $('body').on('mouseup touchend', $.proxy(function(e) { |
||
857 | this.isDrawing = false; |
||
858 | }, this)); |
||
859 | |||
860 | if (window.requestAnimationFrame) requestAnimationFrame( $.proxy(this.draw, this) ); |
||
861 | }, |
||
862 | |||
863 | draw: function() { |
||
864 | //if the pencil size is big (>10), the small crosshair makes a friend: a circle of the size of the pencil |
||
865 | //todo: have the circle works on every browser - it currently should be added only when CSS pointer-events are supported |
||
866 | //we assume that if requestAnimationFrame is supported, pointer-events is too, but this is terribad. |
||
867 | if (window.requestAnimationFrame && this.ctx.lineWidth > 10 && this.isMouseHovering) { |
||
868 | this.dom.$cursor.css({ width: this.ctx.lineWidth + 'px', height: this.ctx.lineWidth + 'px' }); |
||
869 | var transform = DrawingBoard.Utils.tpl("translateX({{x}}px) translateY({{y}}px)", { x: this.coords.current.x-(this.ctx.lineWidth/2), y: this.coords.current.y-(this.ctx.lineWidth/2) }); |
||
870 | this.dom.$cursor.css({ 'transform': transform, '-webkit-transform': transform, '-ms-transform': transform }); |
||
871 | this.dom.$cursor.removeClass('drawing-board-utils-hidden'); |
||
872 | } else { |
||
873 | this.dom.$cursor.addClass('drawing-board-utils-hidden'); |
||
874 | } |
||
875 | |||
876 | if (this.isDrawing) { |
||
877 | var currentMid = this._getMidInputCoords(this.coords.current); |
||
878 | this.ctx.beginPath(); |
||
879 | this.ctx.moveTo(currentMid.x, currentMid.y); |
||
880 | this.ctx.quadraticCurveTo(this.coords.old.x, this.coords.old.y, this.coords.oldMid.x, this.coords.oldMid.y); |
||
881 | this.ctx.stroke(); |
||
882 | |||
883 | this.coords.old = this.coords.current; |
||
884 | this.coords.oldMid = currentMid; |
||
885 | } |
||
886 | |||
887 | if (window.requestAnimationFrame) requestAnimationFrame( $.proxy(function() { this.draw(); }, this) ); |
||
888 | }, |
||
889 | |||
890 | _onInputStart: function(e, coords) { |
||
891 | this.coords.current = this.coords.old = coords; |
||
892 | this.coords.oldMid = this._getMidInputCoords(coords); |
||
893 | this.isDrawing = true; |
||
894 | |||
895 | if (!window.requestAnimationFrame) this.draw(); |
||
896 | |||
897 | this.ev.trigger('board:startDrawing', {e: e, coords: coords}); |
||
898 | e.stopPropagation(); |
||
899 | e.preventDefault(); |
||
900 | }, |
||
901 | |||
902 | _onInputMove: function(e, coords) { |
||
903 | this.coords.current = coords; |
||
904 | this.ev.trigger('board:drawing', {e: e, coords: coords}); |
||
905 | |||
906 | if (!window.requestAnimationFrame) this.draw(); |
||
907 | |||
908 | e.stopPropagation(); |
||
909 | e.preventDefault(); |
||
910 | }, |
||
911 | |||
912 | _onInputStop: function(e, coords) { |
||
913 | if (this.isDrawing && (!e.touches || e.touches.length === 0)) { |
||
914 | this.isDrawing = false; |
||
915 | |||
916 | this.saveWebStorage(); |
||
917 | this.saveHistory(); |
||
918 | |||
919 | this.ev.trigger('board:stopDrawing', {e: e, coords: coords}); |
||
920 | this.ev.trigger('board:userAction'); |
||
921 | e.stopPropagation(); |
||
922 | e.preventDefault(); |
||
923 | } |
||
924 | }, |
||
925 | |||
926 | _onMouseOver: function(e, coords) { |
||
927 | this.isMouseHovering = true; |
||
928 | this.coords.old = this._getInputCoords(e); |
||
929 | this.coords.oldMid = this._getMidInputCoords(this.coords.old); |
||
930 | |||
931 | this.ev.trigger('board:mouseOver', {e: e, coords: coords}); |
||
932 | }, |
||
933 | |||
934 | _onMouseOut: function(e, coords) { |
||
935 | this.isMouseHovering = false; |
||
936 | |||
937 | this.ev.trigger('board:mouseOut', {e: e, coords: coords}); |
||
938 | }, |
||
939 | |||
940 | _getInputCoords: function(e) { |
||
941 | e = e.originalEvent ? e.originalEvent : e; |
||
942 | var |
||
943 | rect = this.canvas.getBoundingClientRect(), |
||
944 | width = this.dom.$canvas.width(), |
||
945 | height = this.dom.$canvas.height() |
||
946 | ; |
||
947 | var x, y; |
||
948 | if (e.touches && e.touches.length == 1) { |
||
949 | x = e.touches[0].pageX; |
||
950 | y = e.touches[0].pageY; |
||
951 | } else { |
||
952 | x = e.pageX; |
||
953 | y = e.pageY; |
||
954 | } |
||
955 | x = x - this.dom.$canvas.offset().left; |
||
956 | y = y - this.dom.$canvas.offset().top; |
||
957 | x *= (width / rect.width); |
||
958 | y *= (height / rect.height); |
||
959 | return { |
||
960 | x: x, |
||
961 | y: y |
||
962 | }; |
||
963 | }, |
||
964 | |||
965 | _getMidInputCoords: function(coords) { |
||
966 | return { |
||
967 | x: this.coords.old.x + coords.x>>1, |
||
968 | y: this.coords.old.y + coords.y>>1 |
||
969 | }; |
||
970 | } |
||
971 | }; |
||
972 | |||
973 | DrawingBoard.Control = function(drawingBoard, opts) { |
||
974 | this.board = drawingBoard; |
||
975 | this.opts = $.extend({}, this.defaults, opts); |
||
976 | |||
977 | this.$el = $(document.createElement('div')).addClass('drawing-board-control'); |
||
978 | if (this.name) |
||
979 | this.$el.addClass('drawing-board-control-' + this.name); |
||
980 | |||
981 | this.board.ev.bind('board:reset', $.proxy(this.onBoardReset, this)); |
||
982 | |||
983 | this.initialize.apply(this, arguments); |
||
984 | return this; |
||
985 | }; |
||
986 | |||
987 | DrawingBoard.Control.prototype = { |
||
988 | |||
989 | name: '', |
||
990 | |||
991 | defaults: {}, |
||
992 | |||
993 | initialize: function() { |
||
994 | |||
995 | }, |
||
996 | |||
997 | addToBoard: function() { |
||
998 | this.board.addControl(this); |
||
999 | }, |
||
1000 | |||
1001 | onBoardReset: function(opts) { |
||
1002 | |||
1003 | } |
||
1004 | |||
1005 | }; |
||
1006 | |||
1007 | //extend directly taken from backbone.js |
||
1008 | DrawingBoard.Control.extend = function(protoProps, staticProps) { |
||
1009 | var parent = this; |
||
1010 | var child; |
||
1011 | if (protoProps && protoProps.hasOwnProperty('constructor')) { |
||
1012 | child = protoProps.constructor; |
||
1013 | } else { |
||
1014 | child = function(){ return parent.apply(this, arguments); }; |
||
1015 | } |
||
1016 | $.extend(child, parent, staticProps); |
||
1017 | var Surrogate = function(){ this.constructor = child; }; |
||
1018 | Surrogate.prototype = parent.prototype; |
||
1019 | child.prototype = new Surrogate(); |
||
1020 | if (protoProps) $.extend(child.prototype, protoProps); |
||
1021 | child.__super__ = parent.prototype; |
||
1022 | return child; |
||
1023 | }; |
||
1024 | DrawingBoard.Control.Color = DrawingBoard.Control.extend({ |
||
1025 | name: 'colors', |
||
1026 | |||
1027 | initialize: function() { |
||
1028 | this.initTemplate(); |
||
1029 | |||
1030 | var that = this; |
||
1031 | this.$el.on('click', '.drawing-board-control-colors-picker', function(e) { |
||
1032 | var color = $(this).attr('data-color'); |
||
1033 | that.board.setColor(color); |
||
1034 | that.$el.find('.drawing-board-control-colors-current') |
||
1035 | .css('background-color', color) |
||
1036 | .attr('data-color', color); |
||
1037 | |||
1038 | that.board.ev.trigger('color:changed', color); |
||
1039 | that.$el.find('.drawing-board-control-colors-rainbows').addClass('drawing-board-utils-hidden'); |
||
1040 | |||
1041 | e.preventDefault(); |
||
1042 | }); |
||
1043 | |||
1044 | this.$el.on('click', '.drawing-board-control-colors-current', function(e) { |
||
1045 | that.$el.find('.drawing-board-control-colors-rainbows').toggleClass('drawing-board-utils-hidden'); |
||
1046 | e.preventDefault(); |
||
1047 | }); |
||
1048 | |||
1049 | $('body').on('click', function(e) { |
||
1050 | var $target = $(e.target); |
||
1051 | var $relatedButton = $target.hasClass('drawing-board-control-colors-current') ? $target : $target.closest('.drawing-board-control-colors-current'); |
||
1052 | var $myButton = that.$el.find('.drawing-board-control-colors-current'); |
||
1053 | var $popup = that.$el.find('.drawing-board-control-colors-rainbows'); |
||
1054 | if ( (!$relatedButton.length || $relatedButton.get(0) !== $myButton.get(0)) && !$popup.hasClass('drawing-board-utils-hidden') ) |
||
1055 | $popup.addClass('drawing-board-utils-hidden'); |
||
1056 | }); |
||
1057 | }, |
||
1058 | |||
1059 | initTemplate: function() { |
||
1060 | var tpl = '<div class="drawing-board-control-inner">' + |
||
1061 | '<div class="drawing-board-control-colors-current" style="background-color: {{color}}" data-color="{{color}}"></div>' + |
||
1062 | '<div class="drawing-board-control-colors-rainbows">{{rainbows}}</div>' + |
||
1063 | '</div>'; |
||
1064 | var oneColorTpl = '<div class="drawing-board-control-colors-picker" data-color="{{color}}" style="background-color: {{color}}"></div>'; |
||
1065 | var rainbows = ''; |
||
1066 | $.each([0.75, 0.5, 0.25], $.proxy(function(key, val) { |
||
1067 | var i = 0; |
||
1068 | var additionalColor = null; |
||
1069 | rainbows += '<div class="drawing-board-control-colors-rainbow">'; |
||
1070 | if (val == 0.25) additionalColor = this._rgba(0, 0, 0, 1); |
||
1071 | if (val == 0.5) additionalColor = this._rgba(150, 150, 150, 1); |
||
1072 | if (val == 0.75) additionalColor = this._rgba(255, 255, 255, 1); |
||
1073 | rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: additionalColor.toString() }); |
||
1074 | while (i <= 330) { |
||
1075 | rainbows += DrawingBoard.Utils.tpl(oneColorTpl, {color: this._hsl2Rgba(this._hsl(i-60, 1, val)).toString() }); |
||
1076 | i+=30; |
||
1077 | } |
||
1078 | rainbows += '</div>'; |
||
1079 | }, this)); |
||
1080 | |||
1081 | this.$el.append( $( DrawingBoard.Utils.tpl(tpl, {color: this.board.color, rainbows: rainbows }) ) ); |
||
1082 | this.$el.find('.drawing-board-control-colors-rainbows').addClass('drawing-board-utils-hidden'); |
||
1083 | }, |
||
1084 | |||
1085 | onBoardReset: function(opts) { |
||
1086 | this.board.setColor(this.$el.find('.drawing-board-control-colors-current').attr('data-color')); |
||
1087 | }, |
||
1088 | |||
1089 | _rgba: function(r, g, b, a) { |
||
1090 | return { r: r, g: g, b: b, a: a, toString: function() { return "rgba(" + r +", " + g + ", " + b + ", " + a + ")"; } }; |
||
1091 | }, |
||
1092 | |||
1093 | _hsl: function(h, s, l) { |
||
1094 | return { h: h, s: s, l: l, toString: function() { return "hsl(" + h +", " + s*100 + "%, " + l*100 + "%)"; } }; |
||
1095 | }, |
||
1096 | |||
1097 | _hex2Rgba: function(hex) { |
||
1098 | var num = parseInt(hex.substring(1), 16); |
||
1099 | return this._rgba(num >> 16, num >> 8 & 255, num & 255, 1); |
||
1100 | }, |
||
1101 | |||
1102 | //conversion function (modified a bit) taken from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript |
||
1103 | _hsl2Rgba: function(hsl) { |
||
1104 | var h = hsl.h/360, s = hsl.s, l = hsl.l, r, g, b; |
||
1105 | function hue2rgb(p, q, t) { |
||
1106 | if(t < 0) t += 1;> |
||
1107 | < 0) t += 1; if(t > 1) t -= 1;> |
||
1108 | < 0) t += 1; if(t < 1/6) return p + (q - p) * 6 * t;>> |
||
1109 | < 0) t += 1;< 1/ if(t < 1/2) return q;>> |
||
1110 | < 0) t += 1;< 1/ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;>>> |
||
1111 | < 0) t += 1;< 1/< 2/ return p;>>> |
||
1112 | < 0) t += 1;< 1/< 2/ }>>> |
||
1113 | < 0) t += 1;< 1/< 2/ if (s === 0) {>>> |
||
1114 | < 0) t += 1;< 1/< 2/ r = g = b = l; // achromatic>>> |
||
1115 | < 0) t += 1;< 1/< 2/ } else {>>> |
||
1116 | < 0) t += 1;< 1/< 2/ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1117 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q;>>>> |
||
1118 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; r = Math.floor( (hue2rgb(p, q, h + 1/3)) * 255);>>>> |
||
1119 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; g = Math.floor( (hue2rgb(p, q, h)) * 255);>>>> |
||
1120 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; b = Math.floor( (hue2rgb(p, q, h - 1/3)) * 255);>>>> |
||
1121 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; }>>>> |
||
1122 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; return this._rgba(r, g, b, 1);>>>> |
||
1123 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; }>>>> |
||
1124 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;});>>>> |
||
1125 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;DrawingBoard.Control.DrawingMode = DrawingBoard.Control.extend({>>>> |
||
1126 | |||
1127 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; name: 'drawingmode',>>>> |
||
1128 | |||
1129 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; defaults: {>>>> |
||
1130 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; pencil: true,>>>> |
||
1131 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; eraser: true,>>>> |
||
1132 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; filler: true>>>> |
||
1133 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; },>>>> |
||
1134 | |||
1135 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; initialize: function() {>>>> |
||
1136 | |||
1137 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; this.prevMode = this.board.getMode();>>>> |
||
1138 | |||
1139 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; $.each(["pencil", "eraser", "filler"], $.proxy(function(k, value) {>>>> |
||
1140 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; if (this.opts[value]) {>>>> |
||
1141 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; this.$el.append('button>');>>>> |
||
1142 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1143 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1144 | |||
1145 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1146 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1147 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1148 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1149 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1150 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1151 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1152 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1153 | |||
1154 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1155 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1156 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1157 | |||
1158 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1159 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1160 | |||
1161 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1162 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1163 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1164 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1165 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1166 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1167 | |||
1168 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1169 | |||
1170 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1171 | |||
1172 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1173 | |||
1174 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1175 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1176 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1177 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1178 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1179 | |||
1180 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1181 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1182 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1183 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s;>>>> |
||
1184 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1185 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1186 | |||
1187 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1188 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1189 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1190 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1191 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1192 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1193 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1194 | |||
1195 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1196 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1197 | |||
1198 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1199 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1200 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1201 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1202 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1203 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1204 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1205 | |||
1206 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1207 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1208 | |||
1209 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1210 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1211 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1212 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1213 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1214 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1215 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1216 | |||
1217 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1218 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1219 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1220 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1221 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1222 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1223 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1224 | |||
1225 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1226 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1227 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1228 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1229 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1230 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1231 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1232 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1233 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1234 | |||
1235 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1236 | |||
1237 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1238 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1239 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1240 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1241 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1242 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1243 | |||
1244 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1245 | |||
1246 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1247 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1248 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1249 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1250 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1251 | |||
1252 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1253 | |||
1254 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1255 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1256 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1257 | |||
1258 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1259 | |||
1260 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1261 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1262 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1263 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1264 | |||
1265 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1266 | |||
1267 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1268 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1269 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1270 | |||
1271 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1272 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1273 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1274 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1275 | |||
1276 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1277 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1278 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1279 | |||
1280 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1281 | |||
1282 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1283 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1284 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1285 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1286 | |||
1287 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1288 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1289 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1290 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1291 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1292 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1293 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1294 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1295 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1296 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1297 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1298 | |||
1299 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1300 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1301 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1302 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1303 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1304 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1305 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1306 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1307 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1308 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1309 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1310 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1311 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1312 | |||
1313 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1314 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1315 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1316 | |||
1317 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1318 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1319 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1320 | |||
1321 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1322 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1323 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1324 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1325 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1326 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1327 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1328 | |||
1329 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1330 | |||
1331 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1332 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1333 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1334 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1335 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1336 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1337 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1338 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1339 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1340 | |||
1341 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1342 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1343 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1344 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1345 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1346 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1347 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1348 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1349 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1350 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1351 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1352 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1353 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1354 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1355 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1356 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1357 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1358 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1359 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1360 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1361 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1362 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1363 | |||
1364 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1365 | |||
1366 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1367 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1368 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1369 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1370 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1371 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1372 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |
||
1373 | |||
1374 | < 0) t += 1;< 1/< 2/< 0.5 ? l * (1 + s) : l + s - l * s; |