1 /* 2 * Copyright (C) 2008, 2009 Mihai Şucan 3 * 4 * This file is part of PaintWeb. 5 * 6 * PaintWeb is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * PaintWeb is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with PaintWeb. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * $URL: http://code.google.com/p/paintweb $ 20 * $Date: 2009-07-29 20:34:06 +0300 $ 21 */ 22 23 /** 24 * @author <a lang="ro" href="http://www.robodesign.ro/mihai">Mihai Şucan</a> 25 * @fileOverview Holds the eraser tool implementation. 26 */ 27 28 /** 29 * @class The eraser tool. 30 * 31 * @param {PaintWeb} app Reference to the main paint application object. 32 */ 33 pwlib.tools.eraser = function (app) { 34 var _self = this, 35 bufferContext = app.buffer.context, 36 clearInterval = app.win.clearInterval, 37 config = app.config, 38 history = app.history.pos, 39 image = app.image, 40 layerContext = app.layer.context, 41 mouse = app.mouse, 42 setInterval = app.win.setInterval; 43 44 /** 45 * The interval ID used for running the erasing operation every few 46 * milliseconds. 47 * 48 * @private 49 * @see PaintWeb.config.toolDrawDelay 50 */ 51 var timer = null; 52 53 /** 54 * Holds the points needed to be drawn. Each point is added by the 55 * <code>mousemove</code> event handler. 56 * 57 * @private 58 * @type Array 59 */ 60 var points = []; 61 62 /** 63 * Holds the starting point on the <var>x</var> axis of the image, for the 64 * current drawing operation. 65 * 66 * @private 67 * @type Number 68 */ 69 var x0 = 0; 70 71 /** 72 * Holds the starting point on the <var>y</var> axis of the image, for the 73 * current drawing operation. 74 * 75 * @private 76 * @type Number 77 */ 78 var y0 = 0; 79 80 var globalOp_ = null, 81 lineWidth_ = null; 82 83 /** 84 * The tool deactivation event handler. This function clears timers, clears 85 * the canvas and allows shadows to be rendered again. 86 */ 87 this.deactivate = function () { 88 if (timer) { 89 clearInterval(timer); 90 timer = null; 91 } 92 93 if (mouse.buttonDown) { 94 if (globalOp_) { 95 layerContext.globalCompositeOperation = globalOp_; 96 } 97 if (lineWidth_) { 98 layerContext.lineWidth = lineWidth_; 99 } 100 101 app.historyGoto(history.pos); 102 } 103 104 points = []; 105 106 // Allow Canvas shadows. 107 app.shadowAllow(); 108 }; 109 110 /** 111 * The tool activation event handler. This is run after the tool construction 112 * and after the deactivation of the previous tool. This function simply 113 * disallows the rendering of shadows. 114 */ 115 this.activate = function () { 116 // Do not allow Canvas shadows. 117 app.shadowDisallow(); 118 }; 119 120 /** 121 * Initialize the drawing operation. 122 */ 123 this.mousedown = function () { 124 globalOp_ = layerContext.globalCompositeOperation; 125 lineWidth_ = layerContext.lineWidth; 126 127 layerContext.globalCompositeOperation = 'destination-out'; 128 layerContext.lineWidth = bufferContext.lineWidth; 129 130 x0 = mouse.x; 131 y0 = mouse.y; 132 133 points = []; 134 if (!timer) { 135 timer = setInterval(_self.draw, config.toolDrawDelay); 136 } 137 138 return true; 139 }; 140 141 /** 142 * Save the mouse coordinates in the array. 143 */ 144 this.mousemove = function () { 145 if (mouse.buttonDown) { 146 points.push(mouse.x, mouse.y); 147 } 148 }; 149 150 /** 151 * Draw the points in the stack. This function is called every few 152 * milliseconds. 153 * 154 * @see PaintWeb.config.toolDrawDelay 155 */ 156 this.draw = function () { 157 var i = 0, n = points.length; 158 if (!n) { 159 return; 160 } 161 162 layerContext.beginPath(); 163 layerContext.moveTo(x0, y0); 164 165 while (i < n) { 166 x0 = points[i++]; 167 y0 = points[i++]; 168 layerContext.lineTo(x0, y0); 169 } 170 171 layerContext.stroke(); 172 layerContext.closePath(); 173 174 points = []; 175 }; 176 177 /** 178 * End the drawing operation, once the user releases the mouse button. 179 */ 180 this.mouseup = function () { 181 if (mouse.x == x0 && mouse.y == y0) { 182 points.push(x0+1, y0+1); 183 } 184 185 if (timer) { 186 clearInterval(timer); 187 timer = null; 188 } 189 _self.draw(); 190 191 layerContext.globalCompositeOperation = globalOp_; 192 layerContext.lineWidth = lineWidth_; 193 194 app.historyAdd(); 195 196 return true; 197 }; 198 199 /** 200 * Allows the user to press <kbd>Escape</kbd> to cancel the drawing operation. 201 * 202 * @param {Event} ev The DOM Event object. 203 * 204 * @returns {Boolean} True if the drawing operation was cancelled, or false if 205 * not. 206 */ 207 this.keydown = function (ev) { 208 if (!mouse.buttonDown || ev.kid_ != 'Escape') { 209 return false; 210 } 211 212 if (timer) { 213 clearInterval(timer); 214 timer = null; 215 } 216 217 layerContext.globalCompositeOperation = globalOp_; 218 layerContext.lineWidth = lineWidth_; 219 220 mouse.buttonDown = false; 221 points = []; 222 223 app.historyGoto(history.pos); 224 225 return true; 226 }; 227 }; 228 229 // vim:set spell spl=en fo=wan1croqlt tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix: 230 231 232