OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Command queue is the only way to modify images. | 6 * Command queue is the only way to modify images. |
7 * Supports undo/redo. | 7 * Supports undo/redo. |
8 * Command execution is asynchronous (callback-based). | 8 * Command execution is asynchronous (callback-based). |
9 * | 9 * |
10 * @param {!Document} document Document to create canvases in. | 10 * @param {!Document} document Document to create canvases in. |
11 * @param {!HTMLCanvasElement} canvas The canvas with the original image. | 11 * @param {!HTMLCanvasElement|!HTMLImageElement} image |
12 * The canvas with the original image. | |
yawano
2016/01/20 06:23:09
small nit: please use the line until the end. i.e.
ryoh
2016/01/21 03:19:55
Done.
| |
12 * @param {function(function())} saveFunction Function to save the image. | 13 * @param {function(function())} saveFunction Function to save the image. |
13 * @constructor | 14 * @constructor |
14 * @struct | 15 * @struct |
15 */ | 16 */ |
16 function CommandQueue(document, canvas, saveFunction) { | 17 function CommandQueue(document, image, saveFunction) { |
17 this.document_ = document; | 18 this.document_ = document; |
18 this.undo_ = []; | 19 this.undo_ = []; |
19 this.redo_ = []; | 20 this.redo_ = []; |
20 this.subscribers_ = []; | 21 this.subscribers_ = []; |
21 this.currentImage_ = canvas; | 22 this.currentImage_ = image; |
22 | 23 |
23 // Current image may be null or not-null but with width = height = 0. | 24 // Current image may be null or not-null but with width = height = 0. |
24 // Copying an image with zero dimensions causes js errors. | 25 // Copying an image with zero dimensions causes js errors. |
25 if (this.currentImage_) { | 26 if (this.currentImage_) { |
26 this.baselineImage_ = document.createElement('canvas'); | 27 this.baselineImage_ = document.createElement('canvas'); |
27 this.baselineImage_.width = this.currentImage_.width; | 28 this.baselineImage_.width = this.currentImage_.width; |
28 this.baselineImage_.height = this.currentImage_.height; | 29 this.baselineImage_.height = this.currentImage_.height; |
29 if (this.currentImage_.width > 0 && this.currentImage_.height > 0) { | 30 if (this.currentImage_.width > 0 && this.currentImage_.height > 0) { |
30 var context = this.baselineImage_.getContext('2d'); | 31 var context = this.baselineImage_.getContext('2d'); |
31 context.drawImage(this.currentImage_, 0, 0); | 32 context.drawImage(this.currentImage_, 0, 0); |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 return 'Command ' + this.name_; | 290 return 'Command ' + this.name_; |
290 }; | 291 }; |
291 | 292 |
292 /** | 293 /** |
293 * Execute the command and visualize its results. | 294 * Execute the command and visualize its results. |
294 * | 295 * |
295 * The two actions are combined into one method because sometimes it is nice | 296 * The two actions are combined into one method because sometimes it is nice |
296 * to be able to show partial results for slower operations. | 297 * to be able to show partial results for slower operations. |
297 * | 298 * |
298 * @param {!Document} document Document on which to execute command. | 299 * @param {!Document} document Document on which to execute command. |
299 * @param {!HTMLCanvasElement} srcCanvas Canvas to execute on. | 300 * @param {!HTMLCanvasElement|!HTMLImageElement} srcImage Image to execute on. |
300 * @param {function(HTMLCanvasElement, number=)} callback Callback to call on | 301 * @param {function(HTMLCanvasElement, number=)} callback Callback to call on |
301 * completion. | 302 * completion. |
302 * @param {!Object} uiContext Context to work in. | 303 * @param {!Object} uiContext Context to work in. |
303 */ | 304 */ |
304 Command.prototype.execute = function(document, srcCanvas, callback, uiContext) { | 305 Command.prototype.execute = function(document, srcImage, callback, uiContext) { |
305 console.error('Command.prototype.execute not implemented'); | 306 console.error('Command.prototype.execute not implemented'); |
306 }; | 307 }; |
307 | 308 |
308 /** | 309 /** |
309 * Visualize reversion of the operation. | 310 * Visualize reversion of the operation. |
310 * | 311 * |
311 * @param {!HTMLCanvasElement} canvas Image data to use. | 312 * @param {!HTMLCanvasElement} canvas Image data to use. |
312 * @param {!ImageView} imageView ImageView to revert. | 313 * @param {!ImageView} imageView ImageView to revert. |
313 * @return {number} Animation duration in ms. | 314 * @return {number} Animation duration in ms. |
314 */ | 315 */ |
315 Command.prototype.revertView = function(canvas, imageView) { | 316 Command.prototype.revertView = function(canvas, imageView) { |
316 imageView.replace(canvas); | 317 imageView.replace(canvas); |
317 return 0; | 318 return 0; |
318 }; | 319 }; |
319 | 320 |
320 /** | 321 /** |
321 * Creates canvas to render on. | 322 * Creates canvas to render on. |
322 * | 323 * |
323 * @param {!Document} document Document to create canvas in. | 324 * @param {!Document} document Document to create canvas in. |
324 * @param {!HTMLCanvasElement} srcCanvas to copy optional dimensions from. | 325 * @param {!HTMLCanvasElement|!HTMLImageElement} srcImage |
326 * to copy optional dimensions from. | |
325 * @param {number=} opt_width new canvas width. | 327 * @param {number=} opt_width new canvas width. |
326 * @param {number=} opt_height new canvas height. | 328 * @param {number=} opt_height new canvas height. |
327 * @return {!HTMLCanvasElement} Newly created canvas. | 329 * @return {!HTMLCanvasElement} Newly created canvas. |
328 * @private | 330 * @private |
329 */ | 331 */ |
330 Command.prototype.createCanvas_ = function( | 332 Command.prototype.createCanvas_ = function( |
331 document, srcCanvas, opt_width, opt_height) { | 333 document, srcImage, opt_width, opt_height) { |
332 var result = assertInstanceof(document.createElement('canvas'), | 334 var result = assertInstanceof(document.createElement('canvas'), |
333 HTMLCanvasElement); | 335 HTMLCanvasElement); |
334 result.width = opt_width || srcCanvas.width; | 336 result.width = opt_width || srcImage.width; |
335 result.height = opt_height || srcCanvas.height; | 337 result.height = opt_height || srcImage.height; |
336 return result; | 338 return result; |
337 }; | 339 }; |
338 | 340 |
339 | 341 |
340 /** | 342 /** |
341 * Rotate command | 343 * Rotate command |
342 * @param {number} rotate90 Rotation angle in 90 degree increments (signed). | 344 * @param {number} rotate90 Rotation angle in 90 degree increments (signed). |
343 * @constructor | 345 * @constructor |
344 * @extends {Command} | 346 * @extends {Command} |
345 * @struct | 347 * @struct |
346 */ | 348 */ |
347 Command.Rotate = function(rotate90) { | 349 Command.Rotate = function(rotate90) { |
348 Command.call(this, 'rotate(' + rotate90 * 90 + 'deg)'); | 350 Command.call(this, 'rotate(' + rotate90 * 90 + 'deg)'); |
349 this.rotate90_ = rotate90; | 351 this.rotate90_ = rotate90; |
350 }; | 352 }; |
351 | 353 |
352 Command.Rotate.prototype = { __proto__: Command.prototype }; | 354 Command.Rotate.prototype = { __proto__: Command.prototype }; |
353 | 355 |
354 /** @override */ | 356 /** @override */ |
355 Command.Rotate.prototype.execute = function( | 357 Command.Rotate.prototype.execute = function( |
356 document, srcCanvas, callback, uiContext) { | 358 document, srcImage, callback, uiContext) { |
357 var result = this.createCanvas_( | 359 var result = this.createCanvas_( |
358 document, | 360 document, |
359 srcCanvas, | 361 srcImage, |
360 (this.rotate90_ & 1) ? srcCanvas.height : srcCanvas.width, | 362 (this.rotate90_ & 1) ? srcImage.height : srcImage.width, |
361 (this.rotate90_ & 1) ? srcCanvas.width : srcCanvas.height); | 363 (this.rotate90_ & 1) ? srcImage.width : srcImage.height); |
362 ImageUtil.drawImageTransformed( | 364 ImageUtil.drawImageTransformed( |
363 result, srcCanvas, 1, 1, this.rotate90_ * Math.PI / 2); | 365 result, srcImage, 1, 1, this.rotate90_ * Math.PI / 2); |
364 var delay; | 366 var delay; |
365 if (uiContext.imageView) { | 367 if (uiContext.imageView) { |
366 delay = uiContext.imageView.replaceAndAnimate(result, null, this.rotate90_); | 368 delay = uiContext.imageView.replaceAndAnimate(result, null, this.rotate90_); |
367 } | 369 } |
368 setTimeout(callback, 0, result, delay); | 370 setTimeout(callback, 0, result, delay); |
369 }; | 371 }; |
370 | 372 |
371 /** @override */ | 373 /** @override */ |
372 Command.Rotate.prototype.revertView = function(canvas, imageView) { | 374 Command.Rotate.prototype.revertView = function(canvas, imageView) { |
373 return imageView.replaceAndAnimate(canvas, null, -this.rotate90_); | 375 return imageView.replaceAndAnimate(canvas, null, -this.rotate90_); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 Command.Filter = function(name, filter, message) { | 425 Command.Filter = function(name, filter, message) { |
424 Command.call(this, name); | 426 Command.call(this, name); |
425 this.filter_ = filter; | 427 this.filter_ = filter; |
426 this.message_ = message; | 428 this.message_ = message; |
427 }; | 429 }; |
428 | 430 |
429 Command.Filter.prototype = { __proto__: Command.prototype }; | 431 Command.Filter.prototype = { __proto__: Command.prototype }; |
430 | 432 |
431 /** @override */ | 433 /** @override */ |
432 Command.Filter.prototype.execute = function( | 434 Command.Filter.prototype.execute = function( |
433 document, srcCanvas, callback, uiContext) { | 435 document, srcImage, callback, uiContext) { |
434 var result = this.createCanvas_(document, srcCanvas); | 436 var result = this.createCanvas_(document, srcImage); |
435 var self = this; | 437 var self = this; |
436 var previousRow = 0; | 438 var previousRow = 0; |
437 | 439 |
438 function onProgressVisible(updatedRow, rowCount) { | 440 function onProgressVisible(updatedRow, rowCount) { |
439 if (updatedRow == rowCount) { | 441 if (updatedRow == rowCount) { |
440 uiContext.imageView.replace(result); | 442 uiContext.imageView.replace(result); |
441 if (self.message_) | 443 if (self.message_) |
442 uiContext.prompt.show(self.message_, 2000); | 444 uiContext.prompt.show(self.message_, 2000); |
443 callback(result); | 445 callback(result); |
444 } else { | 446 } else { |
(...skipping 13 matching lines...) Expand all Loading... | |
458 previousRow = updatedRow; | 460 previousRow = updatedRow; |
459 } | 461 } |
460 } | 462 } |
461 | 463 |
462 function onProgressInvisible(updatedRow, rowCount) { | 464 function onProgressInvisible(updatedRow, rowCount) { |
463 if (updatedRow == rowCount) { | 465 if (updatedRow == rowCount) { |
464 callback(result); | 466 callback(result); |
465 } | 467 } |
466 } | 468 } |
467 | 469 |
468 filter.applyByStrips(result, srcCanvas, this.filter_, | 470 filter.applyByStrips(result, srcImage, this.filter_, |
469 uiContext.imageView ? onProgressVisible : onProgressInvisible); | 471 uiContext.imageView ? onProgressVisible : onProgressInvisible); |
470 }; | 472 }; |
OLD | NEW |