Created
January 24, 2014 15:43
-
-
Save jennschiffer/8599766 to your computer and use it in GitHub Desktop.
christopher clay's canvaspaint r1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CanvasPaint r1 | |
// by Christopher Clay <[email protected]> | |
// | |
// The code in this file is dedicated to the Public Domain | |
// http://creativecommons.org/licenses/publicdomain/ | |
// | |
//some global vars | |
var canvas, c, canvastemp, ctemp, canvassel, csel, canvasundo, cundo, wsp, imgd, co, check; | |
var iface = { dragging:false, resizing:false, status:null, xy:null, txy:null } | |
var prefs = { pretty:false, controlpoints:false } | |
window.onload = function() { | |
wsp = document.getElementById('workspace'); | |
//set up canvas | |
canvas = document.getElementById('canvas'); | |
if(canvas.getContext) { | |
c = canvas.getContext("2d"); | |
iface.status = document.getElementById('status').firstChild; | |
iface.xy = document.getElementById('xy').firstChild; | |
iface.txy = document.getElementById('txy').firstChild; | |
//set up defaults | |
c.tool = new tool.pencil(); | |
c.lineWidth = 1; | |
c.strokeStyle = '#000'; | |
c.fillStyle = '#FFF'; | |
c.tertStyle = '#DDD'; | |
c.strokeFill = 1; //outline shapes | |
prefs.pretty = document.getElementById('pretty').checked; | |
prefs.controlpoints = document.getElementById('controlpoints').checked; | |
c.fillRect(0, 0, canvas.width, canvas.height); //fill with background color (=not transparent) | |
//alert(getPixel(0, 0)); | |
//set up overlay canvas (for preview when drawing lines, rects etc) | |
canvastemp = document.getElementById("canvastemp"); | |
ctemp = canvastemp.getContext("2d"); | |
//set up selection canvas (invisible, used for selections) | |
canvassel = document.getElementById("canvassel"); | |
csel = canvassel.getContext("2d"); | |
//set up undo canvas (invisible) | |
canvasundo = document.getElementById("canvasundo"); | |
cundo = canvasundo.getContext("2d"); | |
//draw title bar gradient | |
gradientcanvas = document.getElementById('gradient'); | |
if(gradientcanvas.getContext){ | |
var g = gradientcanvas.getContext('2d'); | |
grad = g.createLinearGradient(0, 0, 200, 15); | |
grad.addColorStop(0, '#036'); | |
grad.addColorStop(1, '#ACF'); | |
g.fillStyle = grad; | |
g.fillRect(0, 0, 300, 17); | |
} | |
//set up events | |
window.onmouseup = bodyUp; | |
window.onmousemove = bodyMove; | |
window.onkeydown = shortcuts; | |
canvas.onmousedown = canvastemp.onmousedown = c_down; | |
canvas.onmousemove = canvastemp.onmousemove = c_move; | |
canvas.onmouseout = canvastemp.onmouseout = c_out; | |
canvas.onmouseup = canvastemp.onmouseup = c_up; | |
if(document.location.search) { | |
paint.open(document.location.search.substring(1)); | |
} | |
} else { //go away, IE! | |
document.getElementById('overlaybg').style.display = 'block'; | |
document.getElementById('overlay').style.display = 'block'; | |
} | |
} | |
function shortcuts(e) { | |
if(e.keyCode == 46) { //delete | |
if(c.tool.name == 'select' && c.tool.status > 0) { //del selection | |
c.tool.del(); | |
} | |
} else if(e.ctrlKey || e.metaKey) { | |
var letter = String.fromCharCode(e.keyCode); | |
switch(letter) { | |
case 'A': | |
sel_all(); | |
break; | |
case 'C': | |
copy(); | |
break; | |
case 'V': | |
paste(); | |
break; | |
case 'X': | |
cut(); | |
break; | |
case 'Z': | |
undo(); | |
break; | |
} | |
} | |
return false; | |
} | |
function sel_all() { | |
selTool(document.getElementById('select')); | |
c.tool.all(); | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
function sel_cancel() { | |
if(c.tool.status == 2) { c.drawImage(canvassel, Math.floor(ctemp.start.x), Math.floor(ctemp.start.y)); } | |
if(c.tool.status != 4) { canvastemp.style.display='none'; } | |
} | |
function copy() { | |
if(c.tool.name == 'select' && c.tool.status > 0) { //copy selection | |
c.tool.copy(); | |
} | |
} | |
function cut() { | |
if(c.tool.name == 'select' && c.tool.status > 0) { //cut selection | |
c.tool.copy(); | |
c.tool.del(); | |
} | |
} | |
function paste() { | |
//todo only if something on canvassel | |
selTool(document.getElementById('select')); | |
c.tool.paste(); | |
} | |
function undo() { | |
if(c.tool.name == 'select') { //reset all info about current selection | |
activateTempCanvas(); | |
canvastemp.style.display='none'; | |
c.tool.status = 0; | |
} | |
undoLoad(); | |
} | |
function getxy(e, o) { | |
//gets mouse position relative to object o | |
if(c) { | |
var bo = getpos(o); | |
var x = e.clientX - bo.x + wsp.scrollLeft; //correct for canvas position, workspace scroll offset | |
var y = e.clientY - bo.y + wsp.scrollTop; | |
x += document.documentElement.scrollLeft; //correct for window scroll offset | |
y += document.documentElement.scrollTop; | |
x = (c.zoom) ? x/c.zoom : x; //correct for zoom | |
y = (c.zoom) ? y/c.zoom : y; | |
return { x: x-.5, y: y-.5 }; //-.5 prevents antialiasing of stroke lines | |
} | |
} | |
function getpos(o) { | |
//gets position of object o | |
var bo, x, y, b; x = y = 0; | |
if(document.getBoxObjectFor) { //moz | |
bo = document.getBoxObjectFor(o); | |
x = bo.x; y = bo.y; | |
} else if (o.getBoundingClientRect) { //ie (??) | |
bo = o.getBoundingClientRect(); | |
x = bo.left; y = bo.top; | |
} else { //opera, safari etc | |
while(o && o.nodeName != 'BODY') { | |
x += o.offsetLeft; | |
y += o.offsetTop; | |
b = parseInt(document.defaultView.getComputedStyle(o,null).getPropertyValue('border-width')); | |
if(b > 0) { x += b; y +=b; } | |
o = o.offsetParent; | |
} | |
} | |
return { x:x, y:y } | |
} | |
function zoomTo(level) { | |
//changes zoom level (by css-sizing canvas) | |
var lastzoom = c.zoom; | |
if(lastzoom) { //to diff zoom level: scale back first | |
canvas.style.width=canvastemp.style.width=canvas.offsetWidth/c.zoom+'px'; | |
canvas.style.height=canvastemp.style.height=canvas.offsetHeight/c.zoom+'px'; | |
c.zoom=null; | |
//todo: fix scrollbars | |
} | |
if(lastzoom != level && level > 1) { | |
c.zoom=level; | |
canvas.style.width=canvastemp.style.width=level*canvas.offsetWidth+'px'; | |
canvas.style.height=canvastemp.style.height=level*canvas.offsetHeight+'px'; | |
} | |
//todo: move resize indicator | |
} | |
var tool = { | |
_shapes: function() { | |
this.down = this._down = function() { | |
undoSave(); | |
activateTempCanvas(); | |
this.start = { x:m.x, y:m.y } | |
this.status = 1; | |
c.beginPath(); | |
} | |
this._move = function() { | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
iface.txy.innerHTML = Math.round(m.x-this.start.x)+'x'+Math.round(m.y-this.start.y); | |
} | |
this._up = function() { | |
canvastemp.style.display='none'; | |
this.status = 0; | |
iface.txy.innerHTML = ' '; | |
} | |
}, | |
_brushes: function() { | |
this.down = function() { | |
this.last = null; | |
this.cp = null; | |
this.lastcp = null; | |
this.disconnected = null; | |
c.beginPath(); | |
undoSave(); | |
this.sstart = this.last = { x:m.x, y:m.y } //extra s in sstart to not affect status bar display | |
this.status = 1; | |
} | |
this.move = function(e) { | |
if(this.disconnected) { //re-entering canvas: dont draw a line | |
iface.status.innerHTML = 'reentering'; | |
this.disconnected = null; | |
this.last = { x:m.x, y:m.y } | |
} else { //draw connecting line | |
this.draw(); | |
} | |
c.moveTo(m.x, m.y); | |
} | |
this.up = function() { | |
if(this.sstart && this.sstart.x == m.x && this.sstart.y == m.y) { | |
drawDot(m.x, m.y, c.lineWidth, c.strokeStyle); | |
} | |
this.sstart = null; | |
this.status = 0; | |
} | |
this.draw = function() { | |
if(prefs.pretty) { | |
//calculate control point | |
this.cp = { x:m.x, y:m.y } //default: no bezier | |
var deltax = Math.abs(m.x-this.last.x); | |
var deltay = Math.abs(m.y-this.last.y); | |
if(this.last && (deltax+deltay > 10)) { //long line | |
//had no control point last time: use last vertex | |
var lx = (this.lastcp) ? this.lastcp.x : this.last.x; //should be last2x? | |
var ly = (this.lastcp) ? this.lastcp.y : this.last.y; | |
var delta2x = this.last.x-lx; var delta2y = this.last.y-ly; | |
this.cp = { x:lx+delta2x*1.4, y:ly+delta2y*1.4 } | |
} | |
this.lastcp = { x:this.cp.x, y:this.cp.y } | |
c.bezierCurveTo(this.cp.x, this.cp.y, m.x, m.y, m.x, m.y); //make pretty curve, first two params =control pt | |
c.stroke(); | |
c.beginPath(); | |
if(prefs.controlpoints) { | |
if(!(this.cp.x==m.x && this.cp.y==m.y)) { drawDot(this.cp.x, this.cp.y, 3, 'blue'); } | |
drawDot(this.last.x, this.last.y, 3, 'red'); | |
} | |
} else { //unpretty | |
c.lineTo(m.x, m.y); | |
c.stroke(); | |
c.beginPath(); | |
if(prefs.controlpoints) { | |
drawDot(m.x, m.y, 3, 'red'); | |
} | |
} | |
this.last = { x:m.x, y:m.y } | |
} | |
}, | |
pencil: function() { | |
this.name = 'pencil'; | |
this.status = 0; | |
this.inherit = tool._brushes; this.inherit(); | |
c.lineCap = 'butt'; | |
c.lineWidth = 1; | |
}, | |
brush: function() { | |
this.name = 'brush'; | |
this.status = 0; | |
this.inherit = tool._brushes; this.inherit(); | |
}, | |
eraser: function() { | |
this.name = 'eraser'; | |
this.status = 0; | |
this.inherit = tool._brushes; this.inherit(); | |
c.lineCap = 'square'; | |
c.lineWidth = 7; | |
c.lastStrokeStyle = c.strokeStyle; | |
c.strokeStyle = c.fillStyle; //'#FFF'; //selCol('#FFF'); | |
}, | |
line: function() { | |
this.name = 'line'; | |
this.status = 0; | |
this.inherit = tool._shapes; this.inherit(); | |
c.lineCap = 'round'; | |
c.lineWidth = 1; | |
this.move = function(e) { | |
this._move(); | |
drawLine(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
} | |
this.up = function(e) { | |
this._up(); | |
drawLine(this.start.x, this.start.y, m.x, m.y, e.shiftKey, c); | |
} | |
}, | |
rectangle: function() { | |
this.name = 'rectangle'; | |
this.status = 0; | |
this.inherit = tool._shapes; this.inherit(); | |
this.move = function(e) { | |
this._move(); | |
drawRectangle(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
} | |
this.up = function(e) { | |
this._up(); | |
drawRectangle(this.start.x, this.start.y, m.x, m.y, e.shiftKey, c); | |
} | |
}, | |
ellipse: function() { | |
this.name = 'ellipse'; | |
this.status = 0; | |
this.inherit = tool._shapes; this.inherit(); | |
this.down = function(e) { | |
this._down(); | |
this.lastLineWidth = c.lineWidth; | |
if(c.strokeFill == 3) { c.lineWidth+=1.1; ctemp.lineWidth+=1.1; } //hm | |
} | |
this.move = function(e) { | |
this._move(); | |
drawEllipse(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
} | |
this.up = function(e) { | |
this._up(); | |
drawEllipse(this.start.x, this.start.y, m.x, m.y, e.shiftKey, c); | |
if(c.strokeFill == 3) { c.lineWidth = this.lastLineWidth; ctemp.lineWidth = this.lastLineWidth; } | |
} | |
}, | |
rounded: function() { | |
this.name = 'rounded'; | |
this.status = 0; | |
this.inherit = tool._shapes; this.inherit(); | |
this.move = function(e) { | |
this._move(); | |
drawRounded(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
} | |
this.up = function(e) { | |
this._up(); | |
drawRounded(this.start.x, this.start.y, m.x, m.y, e.shiftKey, c); | |
} | |
}, | |
curve: function() { | |
this.name = 'curve'; | |
this.status = 0; | |
c.lineCap = 'round'; | |
c.lineWidth = 1; | |
this.down = function() { | |
if(this.status==0) { //starting | |
undoSave(); | |
activateTempCanvas(); | |
this.start = { x:m.x, y:m.y } | |
this.end = null; | |
this.bezier1 = null; | |
this.status = 5; | |
c.beginPath(); | |
} else if(this.status==4 || this.status==2) { //continuing | |
this.status--; | |
} | |
} | |
this.move = function(e) { | |
if(this.status==5) { | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
drawLine(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
ctemp.stroke(); | |
iface.txy.innerHTML = Math.round(m.x-this.start.x)+'x'+Math.round(m.y-this.start.y); | |
} else if(this.status == 3 || this.status == 1) { | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
ctemp.moveTo(this.start.x, this.start.y); | |
var b1x = (this.bezier1) ? this.bezier1.x : m.x; | |
var b1y = (this.bezier1) ? this.bezier1.y : m.y; | |
var b2x = (this.bezier1) ? m.x : this.end.x; | |
var b2y = (this.bezier1) ? m.y : this.end.y; | |
ctemp.bezierCurveTo(b1x, b1y, b2x, b2y, this.end.x, this.end.y); | |
ctemp.stroke(); | |
iface.txy.innerHTML = Math.round(this.end.x-this.start.x)+'x'+Math.round(this.end.y-this.start.y); | |
} | |
} | |
this.up = function() { | |
if(this.status==5) { //setting endpoint // && source.id != 'body' | |
this.end = { x:m.x, y:m.y } | |
this.status = 4; | |
} else if(this.status==3) { //setting bezier1 && source.id != 'body' | |
this.bezier1 = { x:m.x, y:m.y } | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
ctemp.moveTo(this.start.x, this.start.y); | |
ctemp.bezierCurveTo(m.x, m.y, this.end.x, this.end.y, this.end.x, this.end.y); | |
ctemp.stroke(); | |
this.status = 2; | |
} else if(this.status==1) { //setting bezier2 && source.id != 'body' | |
canvastemp.style.display='none'; | |
c.moveTo(this.start.x, this.start.y); | |
c.bezierCurveTo(this.bezier1.x, this.bezier1.y, m.x, m.y, this.end.x, this.end.y); | |
c.stroke(); | |
this.status = 0; | |
iface.txy.innerHTML = ' '; | |
} | |
} | |
}, | |
polygon: function() { | |
this.name = 'polygon'; | |
this.status = 0; | |
this.points = new Array(); | |
this.down = function() { | |
if(this.status==0) { //starting poly | |
undoSave(); | |
activateTempCanvas(); | |
this.start = { x:m.x, y:m.y } | |
this.last = null; | |
this.status = 3; | |
this.points = new Array(); | |
c.beginPath(); | |
} else if(this.status==1) { //adding points | |
this.status = 2; | |
} | |
} | |
this.move = function(e) { | |
if(this.status == 3) { //first polyline | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
drawLine(this.start.x, this.start.y, m.x, m.y, e.shiftKey, ctemp); | |
} else if(this.status == 2) { // next polyline | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
drawLine(this.last.x, this.last.y, m.x, m.y, e.shiftKey, ctemp); | |
} | |
iface.txy.innerHTML = Math.round(m.x-this.start.x)+'x'+Math.round(m.y-this.start.y); | |
} | |
this.up = function(e) { | |
if(Math.abs(m.x-this.start.x) < 4 && Math.abs(m.y-this.start.y) < 4) { //closing | |
this.close(); | |
} else { | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
var fromx = (this.status==2) ? this.last.x : this.start.x; | |
var fromy = (this.status==2) ? this.last.y : this.start.y; | |
var end = drawLine(fromx, fromy, m.x, m.y, e.shiftKey, c); //TODO cant drawline on c yet...3rd canvas?? | |
this.last = { x:m.x, y:m.y }; | |
this.points[this.points.length] = { x:m.x, y:m.y }; | |
this.status = 1; | |
} | |
trg.stroke(); | |
} | |
this.close = function() { | |
if(this.last.x) { // not just started | |
c.beginPath(); | |
c.moveTo(this.start.x, this.start.y); | |
for(var i=0; i<this.points.length; i++) { | |
c.lineTo(this.points[i].x, this.points[i].y); | |
} | |
c.lineTo(this.last.x, this.last.y); | |
c.lineTo(this.start.x, this.start.y); | |
if(c.strokeFill == 2 || c.strokeFill == 3) { c.fill(); } | |
if(c.strokeFill == 1 || c.strokeFill == 3) { c.stroke(); } | |
c.fill(); | |
} else { | |
//iface.txy.innerHTML = 'aborted'; | |
} | |
canvastemp.style.display='none'; | |
this.status = 0; | |
} | |
}, | |
airbrush: function() { | |
this.name = 'airbrush'; | |
this.status = 0; | |
c.lineCap = 'square'; | |
this.down = function() { | |
undoSave(); | |
this.drawing = setInterval('c.tool.draw()', 50); | |
this.last = { x:m.x, y:m.y } | |
this.lineCap = 'square'; | |
this.status = 1; | |
} | |
this.move = function(e) { | |
this.last = { x:m.x, y:m.y } | |
} | |
this.up = function(e) { | |
clearInterval(this.drawing); | |
this.status = 0; | |
} | |
this.draw = function() { | |
//iface.txy.innerHTML = this.last.x+'/'+this.last.y; | |
c.save(); | |
c.beginPath(); | |
c.arc(this.last.x, this.last.y, c.lineWidth*4, 0, Math.PI*2, true); | |
c.clip(); | |
for(var i=c.lineWidth*15; i>0; i--) { | |
var rndx = c.tool.last.x + Math.round(Math.random()*(c.lineWidth*8)-(c.lineWidth*4)); | |
var rndy = c.tool.last.y + Math.round(Math.random()*(c.lineWidth*8)-(c.lineWidth*4)); | |
drawDot(rndx, rndy, 1, c.strokeStyle); | |
} | |
c.restore(); | |
} | |
}, | |
zoom: function() { | |
this.name = 'zoom'; | |
this.status = 0; | |
//c.lastTool = c.tool.name; | |
this.down = function() { | |
zoomTo(c.selectedzoom); | |
} | |
this.move = function() { } | |
this.up = function() { } | |
}, | |
picker: function() { | |
this.name = 'picker'; | |
this.status = 0; | |
this.down = function(e) { | |
csel.drawImage(canvas, m.x, m.y, 1, 1, 0, 0, canvassel.width, canvassel.height); | |
var pat = c.createPattern(canvassel, 'repeat'); | |
selCol2(pat, e); | |
//selTool(document.getElementById(c.lastTool)); | |
} | |
this.move = function() { } | |
this.up = function() { } | |
}, | |
floodfill: function() { | |
this.name = 'floodfill'; | |
this.status = 0; | |
this.down = function(e) { | |
undoSave(); | |
//var imgd = c.getImageData(0, 0, canvas.width, canvas.height); | |
var x = Math.round(m.x); | |
var y = Math.round(m.y); | |
var oldColor = getPixel(x, y); | |
if(!oldColor) { alert('Sorry, your browser doesn\'t support flood fill.'); return false; } | |
if(oldColor == c.strokeStyle) { return; } | |
iface.status.innerHTML = 'Filling... please wait.'; | |
iface.xy.innerHTML = oldColor; | |
var stack = [{x:x, y:y}]; | |
//var n = 0; | |
while(popped = stack.pop()) { | |
//n++; | |
//iface.txy.innerHTML = 'while'+n; | |
var x = popped.x; | |
var y1 = popped.y; | |
while(getPixel(x, y1) == oldColor && y1 >= 0) { y1--; } | |
y1++; | |
var spanLeft = false; | |
var spanRight = false; | |
while(getPixel(x, y1) == oldColor && y1 < canvas.height) { | |
//iface.xy.innerHTML = x+'/'+y1; | |
if(window.opera) { | |
co.setPixel(x, y1, c.strokeStyle); | |
} else { | |
//c.beginPath(); | |
c.fillStyle = c.strokeStyle; | |
c.fillRect(x, y1, 1, 1); | |
//drawDot(x, y1, 1, c.strokeStyle, c); | |
//document.getElementById('info').innerHTML += '<br />'+x+'/'+y1; | |
} | |
if(!spanLeft && x > 0 && getPixel(x-1, y1) == oldColor) { | |
//break; | |
stack.push({x:x-1, y:y1}); | |
spanLeft = true; | |
} else if(spanLeft && x > 0 && getPixel(x-1, y1) != oldColor) { | |
spanRight = false; | |
} else if(spanRight && x <= 0) { spanRight = false; } | |
if(!spanRight && x < canvas.width-1 && getPixel(x+1, y1) == oldColor) { | |
//break; | |
stack.push({x:x+1, y:y1}); | |
spanRight = true; | |
} else if(spanRight && x < canvas.width-1 && getPixel(x+1, y1) != oldColor) { | |
spanRight = false; | |
} else if(spanRight && x >= canvas.width) { spanRight = false; } | |
y1++; | |
} | |
} | |
if(window.opera) { | |
co.lockCanvasUpdates(false); | |
co.updateCanvas(); | |
} | |
//document.getElementById('info').innerHTML = check; | |
iface.status.innerHTML = 'Finished filling.'; | |
} | |
this.move = function() { } | |
this.up = function() { } | |
}, | |
select: function() { | |
this.name = 'select'; | |
this.status = 0; | |
//c.lastTool = c.tool.name; | |
c.lineWidth = 1; | |
var dashed = new Image(); | |
dashed.src = 'icons/dashed2.gif'; | |
c.lastStrokeStyle = c.strokeStyle; | |
c.strokeStyle = c.createPattern(dashed, 'repeat'); | |
c.strokeFill = 1; | |
c.beginPath(); | |
this.down = function(e) { | |
if(this.status==0) { //starting select | |
var dashed = new Image(); //doing this here instead of in selTool to ignore user changing color | |
dashed.src = 'icons/dashed2.gif'; | |
c.strokeStyle = c.createPattern(dashed, 'repeat'); | |
activateTempCanvas(); | |
this.start = { x:m.x, y:m.y } | |
this.status = 4; | |
} else if(this.status==3 || this.status==2) { //moving selection | |
if(intersects(m, this.start, this.dimension)) { | |
this.offset = { x:m.x-this.start.x, y:m.y-this.start.y } | |
if(this.status == 3 && !e.ctrlKey && !e.shiftKey) { //when first moving (and not in stamp mode), clear original pos and paint on tempcanvas | |
undoSave(); | |
var pos = { x:m.x-this.offset.x, y:m.y-this.offset.y } | |
drawRectangle(pos.x-1, pos.y-1, pos.x+this.dimension.x, pos.y+this.dimension.y, null, ctemp); | |
ctemp.drawImage(canvassel, Math.floor(pos.x), Math.floor(pos.y)); | |
c.fillRect(this.start.x-.5, this.start.y-.5, this.dimension.x, this.dimension.y); | |
} | |
this.status = 1; | |
} else { //starting new selection | |
if(this.status < 3) { //actually draw last moved selection to canvas TODO also do this when switching tools | |
c.drawImage(canvassel, Math.floor(this.start.x), Math.floor(this.start.y)); | |
} | |
activateTempCanvas(); | |
this.start = { x:m.x, y:m.y } | |
this.status = 4; | |
} | |
} | |
} | |
this.move = function(e) { | |
if(this.status==4) { //selecting | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
var constrained = { x:constrain(m.x, 0, canvas.width), y:constrain(m.y, 0, canvas.height-5) } | |
drawRectangle(this.start.x-1, this.start.y-1, constrained.x, constrained.y, null, ctemp); | |
iface.txy.innerHTML = Math.round(constrained.x-this.start.x)+'x'+Math.round(constrained.y-this.start.y); | |
} else if(this.status==1) { //moving selection | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
var pos = { x:m.x-this.offset.x, y:m.y-this.offset.y } | |
drawRectangle(pos.x-1, pos.y-1, pos.x+this.dimension.x, pos.y+this.dimension.y, null, ctemp); | |
ctemp.drawImage(canvassel, Math.floor(pos.x), Math.floor(pos.y)); | |
if(e.shiftKey) { //dupli mode | |
c.drawImage(canvassel, Math.floor(pos.x), Math.floor(pos.y)); | |
} | |
} else if(this.start) { | |
if(c.tool.status == 1 || (c.tool.dimension && intersects(m, c.tool.start, c.tool.dimension))) { | |
canvastemp.style.cursor = 'move'; | |
} else { | |
canvastemp.style.cursor = ''; | |
} | |
} | |
} | |
this.up = function(e) { | |
if(this.status == 4) { //finished selecting | |
this.status = 3; | |
this.dimension = { x:constrain(m.x, 0, canvas.width)-this.start.x, | |
y:constrain(m.y, 0, canvas.height)-this.start.y } | |
if(this.dimension.x == 0 && this.dimension.y == 0) { //nothing selected, abort | |
this.status = 0; | |
canvastemp.style.display='none'; | |
csel.clearRect(0, 0, canvassel.width, canvassel.height); | |
} else { //save on selection canvas | |
csel.clearRect(0, 0, canvassel.width, canvassel.height); | |
if(this.dimension.x < 0) { this.start.x = this.start.x + this.dimension.x; this.dimension.x *= -1; } //correct for selections not drawn from top left | |
if(this.dimension.y < 0) { this.start.y = this.start.y + this.dimension.y; this.dimension.y *= -1; } | |
//todo check for >max | |
csel.drawImage(canvas, Math.floor(this.start.x), Math.floor(this.start.y), this.dimension.x, this.dimension.y, 0, 0, this.dimension.x, this.dimension.y); | |
csel.dimension = this.dimension; | |
} | |
iface.txy.innerHTML = ' '; | |
} else if(this.status == 1) { //finished moving selection | |
this.status = 2; | |
this.start = { x:m.x-this.offset.x, y:m.y-this.offset.y } | |
if(e.ctrlKey) { //stamp mode | |
c.drawImage(canvassel, Math.floor(this.start.x), Math.floor(this.start.y)); | |
} | |
} | |
} | |
this.del = function() { | |
undoSave(); | |
c.fillRect(this.start.x-.5, this.start.y-.5, this.dimension.x, this.dimension.y); | |
activateTempCanvas(); | |
canvastemp.style.display = 'none'; | |
this.status = 0; | |
} | |
this.all = function() { | |
csel.clearRect(0, 0, canvassel.width, canvassel.height); | |
csel.drawImage(canvas, 0, 0); | |
activateTempCanvas(); | |
this.start = { x:0.5, y:0.5 } | |
this.dimension = { x:canvas.width, y:canvas.height } | |
ctemp.strokeRect(0.5, 0.5, canvas.width-1, canvas.height-1); | |
this.status = 3; | |
} | |
this.copy = function() { | |
csel.drawImage(canvas, Math.floor(this.start.x), Math.floor(this.start.y), this.dimension.x, this.dimension.y, 0, 0, this.dimension.x, this.dimension.y); | |
csel.dimension = this.dimension; | |
} | |
this.paste = function() { | |
activateTempCanvas(); | |
ctemp.drawImage(canvassel, 0, 0); | |
this.status = 3; | |
this.start = { x:.5, y:.5 } | |
this.dimension = csel.dimension; | |
ctemp.strokeRect(this.start.x-.5, this.start.y-.5, this.dimension.x+.5, this.dimension.y+.5); | |
} | |
} | |
} | |
function getPixel(x, y) { | |
if(imgd || c.getImageData) { | |
//if(!imgd) { | |
// imgd = c.getImageData(0, 0, canvas.width, canvas.height); | |
// alert('getting img data'); | |
// } | |
//var pos = (y*canvas.width+x)*4; | |
//if(imgd.data[pos]) { | |
// var col = 'rgb('+imgd.data[pos]+', '+imgd.data[pos+1]+', '+imgd.data[pos+2]+')'; //rgba: ', '+imgd.data[pos+3]+')'; | |
// check += '<br />'+x+'/'+y+': '+col; | |
// //drawDot(x, y, 1, 'red', c); | |
// return col; | |
//} else { | |
return false; | |
//} | |
} else if (window.opera) { | |
if(!co) { co = canvas.getContext('opera-2dgame'); } | |
col = co.getPixel(x, y); | |
//check += '<br />'+x+'/'+y+': '+col; | |
return col; | |
} else { | |
return false; | |
} | |
} | |
function c_down(e) { | |
//handles mousedown on the canvas depending on tool selected | |
var source = e.currentTarget; | |
m = getxy(e, canvas); | |
if(c.tool.name != 'select' && c.tool.name != 'eraser' && c.tool.name != 'picker') { //no color switching for these | |
if(e.ctrlKey) { //ctrl: switch tert & stroke | |
var temp = c.tertStyle; | |
c.tertStyle = c.strokeStyle; | |
c.strokeStyle = temp; | |
} | |
if(e.button == 2 && c.tool.name != 'eraser') { //right: switch stroke & fill | |
var temp = c.strokeStyle; | |
c.strokeStyle = c.fillStyle; | |
c.fillStyle = temp; | |
} | |
} | |
c.tool.down(e); | |
c.moveTo(m.x, m.y); //? | |
//iface.status.innerHTML = 'c_down: '+m.x+'/'+m.y+' - status:'+c.tool.status+' - source:'+source.id+' - tool:'+c.tool.name; | |
return false; | |
} | |
function c_up(e) { | |
//handles mouseup on the canvas depending on tool selected | |
m = getxy(e, canvas); | |
e.stopPropagation(); | |
if(iface.dragging || iface.resizing || c.resizing) { bodyUp(e); } //but not if dragging | |
c.tool.up(e); | |
if(c.tool.name != 'select' && c.tool.name != 'eraser' && c.tool.name != 'picker') { //no color switching for these | |
if(e.button == 2 && c.tool.name != 'eraser') { //right: switch stroke & fill back | |
var temp = c.fillStyle; | |
c.fillStyle = c.strokeStyle; | |
c.strokeStyle = temp; | |
} | |
if(e.ctrlKey) { | |
var temp = c.strokeStyle; | |
c.strokeStyle = c.tertStyle; | |
c.tertStyle = temp; | |
} | |
} | |
//iface.status.innerHTML = 'c_up - status: '+c.tool.status; | |
return false; | |
} | |
function c_move(e) { | |
m = getxy(e, canvas); | |
e.stopPropagation(); | |
if(iface.dragging || iface.resizing || c.resizing) { bodyMove(e); } //don't stop propagation if dragging | |
if(c.tool.status > 0) { | |
c.tool.move(e); | |
} | |
if(c.tool.start && c.tool.status > 0) { | |
iface.xy.innerHTML = Math.round(c.tool.start.x)+', '+Math.round(c.tool.start.y); | |
} else { | |
iface.xy.innerHTML = Math.round(m.x)+', '+Math.round(m.y); | |
} | |
return false; | |
} | |
function c_out(e) { | |
//var source = e.currentTarget; | |
if(c && (c.tool.name=='pencil' || c.tool.name=='eraser' || c.tool.name=='brush') && c.tool.status==1) { | |
c.tool.disconnected = 1; | |
m = getxy(e, canvas); | |
c.tool.draw(); | |
//iface.status.innerHTML = 'c_out: '+m.x+'/'+m.y+' '+c.fillStyle; | |
} | |
iface.xy.innerHTML = ' '; | |
} | |
function activateTempCanvas() { | |
//resets and shows overlay canvas | |
if(m) { ctemp.moveTo(m.x, m.y); } //copy context from main | |
ctemp.lineCap = c.lineCap; | |
ctemp.lineWidth = c.lineWidth; | |
ctemp.strokeStyle = c.strokeStyle; | |
ctemp.fillStyle = c.fillStyle; | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); //clear | |
canvastemp.style.display='block'; //show | |
} | |
function undoSave() { | |
//sets an undo point | |
//cundo.clearRect(0, 0, canvas.width, canvas.height); //this doesn't help with the bg.. | |
if(imgd) { imgd = null; } | |
if(canvas.width != canvasundo.width || canvas.height != canvasundo.height) { | |
canvasundo.width = canvas.width; | |
canvasundo.height = canvas.height; | |
} | |
cundo.drawImage(canvas, 0, 0); | |
} | |
function undoLoad() { | |
//reverts to last undo point | |
if(canvas.width != canvasundo.width || canvas.height != canvasundo.height) { | |
clipResize(canvasundo.width, canvasundo.height); | |
} | |
//ctemp.clearRect(0, 0, canvas.width, canvas.height); | |
ctemp.drawImage(canvas, 0, 0); | |
//c.clearRect(0, 0, canvas.width, canvas.height); | |
c.drawImage(canvasundo, 0, 0); | |
//cundo.clearRect(0, 0, canvas.width, canvas.height); | |
cundo.drawImage(canvastemp, 0, 0); | |
} | |
function windowDrag(e) { | |
iface.dragging = true; | |
var win = wsp.parentNode.parentNode.parentNode; | |
var pos = getpos(win); | |
c.start = { x:e.clientX-pos.x+1, y:e.clientY-pos.y+1 }; | |
} | |
function windowResize(e, o) { | |
iface.resizing = true; | |
var pos = getpos(o); | |
c.start = { x:o.offsetWidth+3-(e.clientX-pos.x), y:o.offsetHeight+3-(e.clientY-pos.y) }; | |
e.stopPropagation(); | |
document.body.style.cursor = 'nw-resize'; | |
} | |
function canvasResize(e) { | |
c.resizing = true; | |
document.body.style.cursor = 'nw-resize'; | |
canvastemp.lastCursor = canvastemp.style.cursor; | |
canvastemp.style.cursor = 'nw-resize'; | |
activateTempCanvas(); | |
var dotted = new Image(); dotted.src = 'icons/dotted.gif'; | |
ctemp.strokeStyle = ctemp.createPattern(dotted, 'repeat'); | |
} | |
function clipResize(w, h) { | |
//resizes all the canvases by clipping/extending, moves resize handle | |
undoSave(); | |
cundo.fillStyle = c.fillStyle; //save | |
canvas.width = canvastemp.width = canvassel.width = w; | |
canvas.height = canvastemp.height = canvassel.height = h; | |
canvas.style.width = canvastemp.style.width = w+'px'; | |
canvas.style.height = canvastemp.style.height = h+'px'; | |
var cresizer = document.getElementById('canvasresize'); | |
cresizer.style.left = w+cresizer.offsetWidth+'px'; cresizer.style.top = h+cresizer.offsetHeight+'px'; | |
c.fillStyle = cundo.fillStyle; //restore | |
c.fillRect(0, 0, canvas.width, canvas.height); //so that if expanding it's filled with bg col | |
c.drawImage(canvasundo, 0, 0); | |
} | |
function bodyMove(e) { | |
//lets the user move outside the canvas while drawing shapes and lines | |
if(c.tool.status > 0) { c_move(e); } | |
if(c.resizing) { | |
m = getxy(e, document.body); | |
var win = wsp.parentNode.parentNode.parentNode; | |
ctemp.clearRect(0, 0, canvastemp.width, canvastemp.height); | |
ctemp.strokeRect(0, 0, m.x, m.y); //dotted line | |
} else if(iface.dragging) { | |
m = getxy(e, document.body); | |
var win = wsp.parentNode.parentNode.parentNode; | |
win.style.left = e.clientX-c.start.x+'px'; | |
win.style.top = e.clientY-c.start.y+'px'; | |
} else if(iface.resizing) { | |
m = getxy(e, document.body); | |
var win = wsp.parentNode.parentNode.parentNode; | |
win.style.width = e.clientX-win.offsetLeft+c.start.x+3+'px'; | |
win.style.height = e.clientY-win.offsetTop+c.start.y+3+'px'; | |
//todo prevent selecting statusbar text.. how? | |
} | |
} | |
function bodyUp(e) { | |
//stops drawing even if mouseup happened outside canvas | |
//closes menus if clicking somewhere else | |
if(c.resizing) { | |
c.resizing = false; document.body.style.cursor = 'auto'; canvastemp.style.cursor = canvastemp.lastCursor; | |
m = getxy(e, wsp); | |
clipResize(m.x-3, m.y-3); | |
} | |
if(iface.dragging) { iface.dragging = false; } | |
if(iface.resizing) { iface.resizing = false; document.body.style.cursor = 'auto'; } | |
if(c.tool.name == 'select') { //cancel selection or finalize selection move | |
sel_cancel(); | |
} | |
if(c && c.tool.name != 'polygon' && c.tool.status > 0) { | |
c_up(e); | |
} | |
if(document.getElementById('menubar').className=='open') { | |
document.getElementById('menubar').className=''; | |
e.stopPropagation(); | |
} | |
} | |
function drawDot(x, y, size, col, trg) { | |
x = Math.floor(x)+1; //prevent antialiasing of 1px dots | |
y = Math.floor(y)+1; | |
if(x>0 && y>0) { | |
if(!trg) { trg = c; } | |
if(col || size) { var lastcol = trg.fillStyle; var lastsize = trg.lineWidth; } | |
if(col) { trg.fillStyle = col; } | |
if(size) { trg.lineWidth = size; } | |
if(trg.lineCap == 'round') { | |
trg.arc(x, y, trg.lineWidth/2, 0, (Math.PI/180)*360, false); | |
trg.fill(); | |
} else { | |
var dotoffset = (trg.lineWidth > 1) ? trg.lineWidth/2 : trg.lineWidth; | |
trg.fillRect((x-dotoffset), (y-dotoffset), trg.lineWidth, trg.lineWidth); | |
} | |
if(col || size) { trg.fillStyle = lastcol; trg.lineWidth = lastsize; } | |
} | |
} | |
function drawLine(x1, y1, x2, y2, mod, trg) { | |
if(trg.lineWidth % 2 == 0) { x1 = Math.floor(x1); y1 = Math.floor(y1); x2 = Math.floor(x2); y2 = Math.floor(y2); } //no antialiasing | |
trg.beginPath(); | |
trg.moveTo(x1, y1); | |
if(mod) { | |
var dx = Math.abs(x2-x1); | |
var dy = Math.abs(y2-y1); | |
var dd = Math.abs(dx-dy); | |
if(dx > 0 && dy > 0 && dx != dy) { | |
if(dd < dx && dd < dy) { //diagonal | |
if(dx < dy) { | |
y2 = y1+(((y2-y1)/dy)*dx); | |
} else { | |
x2 = x1+(((x2-x1)/dx)*dy); | |
} | |
} else if(dx < dy) { | |
x2 = x1; | |
} else if(dy < dx) { | |
y2 = y1; | |
} | |
} | |
} | |
trg.lineTo(x2, y2); | |
trg.stroke(); | |
trg.beginPath(); | |
return { x:x2, y:y2 } | |
} | |
function drawEllipse(x1, y1, x2, y2, mod, trg) { | |
//bounding box. this maybe isn't the best idea? | |
var dx = Math.abs(x2-x1); | |
var dy = Math.abs(y2-y1); | |
if(mod && !(dx==dy)) { //shift held down: constrain | |
if(dx < dy) { | |
x2 = x1+(((x2-x1)/dx)*dy); | |
} else { | |
y2 = y1+(((y2-y1)/dy)*dx); | |
} | |
} | |
var KAPPA = 4 * ((Math.sqrt(2) -1) / 3); | |
var rx = (x2-x1)/2; | |
var ry = (y2-y1)/2; | |
var cx = x1+rx; | |
var cy = y1+ry; | |
trg.beginPath(); | |
trg.moveTo(cx, cy - ry); | |
trg.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy); | |
trg.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry); | |
trg.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy); | |
trg.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry); | |
if(c.strokeFill == 1 || c.strokeFill == 3) { trg.stroke(); } | |
if(c.strokeFill == 2 || c.strokeFill == 3) { trg.fill(); } | |
} | |
function drawRectangle(x1, y1, x2, y2, mod, trg) { | |
var dx = Math.abs(x2-x1); | |
var dy = Math.abs(y2-y1); | |
if(mod && dx != dy) { //shift held down: constrain | |
if(dx < dy) { | |
y2 = y1+(((y2-y1)/dy)*dx); | |
} else { | |
x2 = x1+(((x2-x1)/dx)*dy); | |
} | |
} | |
if(c.strokeFill == 2 || trg.lineWidth % 2 == 0) { //no antialiasing | |
x1 = Math.floor(x1); y1 = Math.floor(y1); x2 = Math.floor(x2); y2 = Math.floor(y2); | |
} | |
trg.rect(x1, y1, (x2-x1), (y2-y1)); | |
if(c.strokeFill == 2 || c.strokeFill == 3) { trg.fill(); } | |
if(c.strokeFill == 1 || c.strokeFill == 3) { trg.stroke(); } | |
} | |
function drawRounded(x1, y1, x2, y2, mod, trg) { | |
var dx = Math.abs(x2-x1); | |
var dy = Math.abs(y2-y1); | |
if(mod && dx != dy) { //shift held down: constrain | |
if(dx < dy) { | |
y2 = y1+(((y2-y1)/dy)*dx); | |
dy = dx; | |
} else { | |
x2 = x1+(((x2-x1)/dx)*dy); | |
dx = dy; | |
} | |
} | |
var dmin = (dx < dy) ? dx : dy; | |
var cornersize = (dmin/2 >= 15) ? 15 : dmin/2; | |
var xdir = (x2 > x1) ? cornersize : -1*cornersize; | |
var ydir = (y2 > y1) ? cornersize : -1*cornersize; | |
drawRounded2(trg, x1, x2, y1, y2, xdir, ydir); | |
if(c.strokeFill == 2 || c.strokeFill == 3) { trg.fill(); } | |
if(c.strokeFill == 1 || c.strokeFill == 3) { trg.stroke(); } | |
} | |
function drawRounded2(trg, x1, x2, y1, y2, xdir, ydir) { | |
trg.beginPath(); | |
trg.moveTo(x1, y1+ydir); | |
trg.quadraticCurveTo(x1, y1, x1+xdir, y1); | |
trg.lineTo(x2-xdir, y1); | |
trg.quadraticCurveTo(x2, y1, x2, y1+ydir); | |
trg.lineTo(x2, y2-ydir); | |
trg.quadraticCurveTo(x2, y2, x2-xdir, y2); | |
trg.lineTo(x1+xdir, y2); | |
trg.quadraticCurveTo(x1, y2, x1, y2-ydir); | |
trg.closePath(); | |
} | |
function constrain(n, min, max) { | |
if(n > max) return max; | |
if(n < min) return min; | |
return n; | |
} | |
function intersects(m, start, dim) { | |
//checks if m(x,y) is between start(x,y) and start+dim(x,y) | |
if( m.x >= start.x && m.y >= start.y && | |
m.x <= (start.x+dim.x) && m.y <= (start.y+dim.y)) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
function selCol(o, e, context) { | |
//context because silly safari doesnt capture right click, apparently.. thus oncontextmenu | |
// alert(typeof(o)); | |
col = (typeof(o) == 'string') ? o : o.style.backgroundColor; | |
selCol2(col, e, context); | |
// if(e) e.preventDefault(); | |
} | |
function selCol2(col, e, context) { | |
if(e && e.ctrlKey) { //tertiary | |
var whichcanvas = document.getElementById('currcoltert'); | |
c.tertStyle = col; | |
} else if(context == 1 || (e && e.button == 2)) { //right | |
var whichcanvas = document.getElementById('currcolback'); | |
c.fillStyle = col; | |
ctemp.fillStyle=col; | |
if(c.tool.name=='eraser') { c.strokeStyle = col; } | |
} else { | |
var whichcanvas = document.getElementById('currcolfore'); | |
c.strokeStyle=col; | |
ctemp.strokeStyle=col; | |
if(c.lastStrokeStyle) { c.lastStrokeStyle = col; } //allows color changing during select/eraser | |
} | |
if(whichcanvas) { | |
whichcontext = whichcanvas.getContext('2d'); | |
whichcontext.fillStyle = col; | |
whichcontext.fillRect(0, 0, whichcanvas.width, whichcanvas.height); | |
} | |
if(e) e.preventDefault(); | |
} | |
function selTool(o) { | |
c.tool.status = 0; | |
canvastemp.style.display='none'; | |
var newtool = o.id; | |
iface.status.innerHTML=newtool; | |
document.getElementById('workspace').className = newtool; | |
//button highlighting | |
var toolbarbtns = document.getElementById('buttons').getElementsByTagName('li'); | |
for(var i=0; i<toolbarbtns.length;i++) { | |
if(toolbarbtns[i].className == 'sel') { toolbarbtns[i].className=''; } | |
} | |
o.className = 'sel'; | |
//reset color (after eraser and select) | |
if(c.lastStrokeStyle) { selCol(c.lastStrokeStyle); c.lastStrokeStyle = null } | |
if(c.tool.name == 'polygon') { c.tool.close(); } | |
c.lastTool = c.tool.name; | |
c.tool = new tool[newtool](); | |
var newtool = shareSettingsPanels(c.tool.name); | |
//settings panel switching | |
var settingpanels = document.getElementById('settings').getElementsByTagName('div'); | |
for(var i=0; i<settingpanels.length;i++) { | |
if(settingpanels[i].style.display == 'block') { settingpanels[i].style.display='none'; } | |
} | |
if(document.getElementById(newtool+'-settings')) { | |
document.getElementById(newtool+'-settings').style.display = 'block'; | |
if(newtool != 'zoom') { //cause this would switch back | |
var settingbtns = document.getElementById(newtool+'-settings').childNodes; | |
for(var i=0; i<settingbtns.length;i++) { //reapply last selection | |
if(settingbtns[i].className == 'sel') { settingbtns[i].onclick(); } | |
} | |
} | |
} | |
} | |
function selSetting(o, sett) { | |
c.tool.status = 0; | |
canvastemp.style.display='none'; | |
var newtool = shareSettingsPanels(c.tool.name); | |
if(document.getElementById(newtool+'-settings')) { | |
var settingbtns = document.getElementById(newtool+'-settings').childNodes; | |
for(var i=0; i<settingbtns.length;i++) { | |
if(settingbtns[i].className == 'sel') { settingbtns[i].className=''; } | |
} | |
o.className = 'sel'; | |
eval(sett); | |
} | |
if(c.tool.name=='zoom') { //switch back | |
selTool(document.getElementById(c.lastTool)); | |
} | |
} | |
function shareSettingsPanels(tool) { | |
if(tool=='select' || tool=='text') { return 'select'; } | |
if(tool=='line' || tool=='curve') { return 'line'; } | |
if(tool=='rectangle' || tool=='polygon'|| tool=='ellipse' || tool=='rounded') { return 'shape'; } | |
if(tool=='ffselect' || tool=='select'|| tool=='text') { return 'trans'; } | |
return tool; | |
} | |
function buttonReset(o) { | |
iface.status.innerHTML=' '; | |
if(o.className=='down') { o.className=''; } //todo why isn't this working | |
} | |
function buttonDown(e, o) { | |
if(e.button != 2 && o.className != 'sel') { o.className='down'; } //not on rightclick | |
} | |
function save(onserver) { | |
if(canvas.toDataURL) { | |
var dataurl = canvas.toDataURL(); | |
if(onserver == true) { | |
saveonline(dataurl); | |
} else { | |
overlay('Please right-click/save-as to save your drawing. <a href="#" onclick="overlay_hide()">close</a><br /><img src="'+dataurl+'" title="Please right-click/save-as" />'); | |
} | |
} else { | |
alert('Sorry, your browser does not implement the toDataURL() method required to save images.'); | |
} | |
} | |
function saveonline(dataurl) { | |
var req = null; | |
iface.status.innerHTML="Saving to server..."; | |
if (window.XMLHttpRequest) { | |
req = new XMLHttpRequest(); | |
//if (req.overrideMimeType) { req.overrideMimeType('text/xml'); } | |
} else { | |
return; | |
} | |
req.onreadystatechange = function() { | |
if(req.readyState == 4) { | |
if(req.status == 200) { | |
var response = req.responseText; | |
overlay('Your image has been saved as <input size="50" value="http://sigilmaster.com/sigils/'+response+'"> <a href="#" onclick="overlay_hide()">close</a><br /><img src="http://sigilmaster.com/sigils/'+response+'" />'); | |
} else { | |
iface.status.innerHTML="Post error code " + req.status + " " + req.statusText; | |
} | |
} | |
}; | |
req.open("POST", "save.php", true); | |
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); | |
req.send('u='+dataurl); | |
} | |
function overlay(content) { | |
var obg = document.getElementById('overlaybg'); | |
obg.style.display='block'; | |
var o = document.getElementById('overlay'); | |
o.innerHTML = content; | |
o.style.display = 'block'; | |
} | |
function overlay_hide() { | |
var o = document.getElementById('overlay'); | |
o.innerHTML = ''; | |
o.style.display = 'none'; | |
document.getElementById('overlaybg').style.display = 'none'; | |
} | |
function menuOpen(e, o) { | |
iface.txy.innerHTML = o.parentNode.className; //todo remove after fixing menu bug | |
o.parentNode.className = (o.parentNode.className != 'open') ? 'open' : ''; | |
e.stopPropagation(); | |
} | |
var paint = { | |
open: function(url) { | |
if(url.indexOf('.') == -1) { url += '.png' } | |
if(url.indexOf('://') == -1) { url = 'http://sigilmaster.com/'+url; } | |
var src = (url.indexOf('http://sigilmaster.com/') > -1) ? url.replace('http://sigilmaster.com', '') : 'open.php?u='+url; | |
var img = document.createElement('img'); | |
img.src = src; | |
img.style.visibility='none'; | |
iface.status.innerHTML = 'Opening '+src+'...'; | |
img.onload = function() { | |
clipResize(this.width, this.height); | |
c.drawImage(this, 0, 0); | |
iface.status.innerHTML = 'Opened '+url+'.'; | |
} | |
img.onerror = function() { | |
alert('Error opening '+this.src); | |
iface.status.innerHTML = ''; | |
} | |
} | |
} | |
// 1337, dude. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment