From 6a16ad9c408fb84dd27c618312f3111563ca2ad5 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 9 Dec 2014 01:40:49 -0500 Subject: blitting functions --- js/lex.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'js/lex.js') diff --git a/js/lex.js b/js/lex.js index 1dc07a0..62144b6 100644 --- a/js/lex.js +++ b/js/lex.js @@ -10,12 +10,14 @@ function Lex (x,y) { this.fg = colors.white this.bg = colors.black this.char = " " + this.opacity = 1 } Lex.prototype.build = function(){ this.span.className = this.css() this.span.innerHTML = this.html() } Lex.prototype.css = function(){ + if (this.opacity == 0) return "fabb" return "f" + letters[mod(this.fg,16)] + "b" + letters[mod(this.bg,16)] } Lex.prototype.html = function(){ @@ -52,16 +54,17 @@ Lex.prototype.clone = function (lex){ this.fg = lex.fg this.bg = lex.bg this.char = lex.char + this.opacity = lex.opacity this.build() } -Lex.prototype.erase = function (lex){ - if (lex.opacity == 0) return +Lex.prototype.erase = function (){ this.fg = colors.white this.bg = colors.black this.char = " " + this.opacity = 0 this.build() } -Lex.prototype.fill = function(fg,bg){ +Lex.prototype.fill = function(fg, bg){ this.fg = fg this.bg = bg this.opacity = 1 -- cgit v1.2.3-70-g09d2 From da3b3feedfe3a928dec6ac615579538a9ab5b582 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 9 Dec 2014 16:15:37 -0500 Subject: less-destructive resize; stub out selection --- js/lex.js | 2 +- js/matrix.js | 65 ++++++++++++++++++++++++++++++++++++++++++++---------- js/ui/brush.js | 26 ++++++++++------------ js/ui/canvas.js | 3 +-- js/ui/controls.js | 14 +++++++----- js/ui/keys.js | 7 +++++- js/ui/selection.js | 21 ++++++++++++++++++ 7 files changed, 102 insertions(+), 36 deletions(-) create mode 100644 js/ui/selection.js (limited to 'js/lex.js') diff --git a/js/lex.js b/js/lex.js index 62144b6..18ca4c5 100644 --- a/js/lex.js +++ b/js/lex.js @@ -93,7 +93,7 @@ Lex.prototype.blur = function(){ focused = null } Lex.prototype.demolish = function(){ - this.span.parentNode.removeChild(this.span) + if (this.span.parentNode) { this.span.parentNode.removeChild(this.span) } this.span = null } Lex.prototype.key = function(char, keyCode) { diff --git a/js/matrix.js b/js/matrix.js index fd4ee4f..79f3d9f 100644 --- a/js/matrix.js +++ b/js/matrix.js @@ -98,6 +98,59 @@ Matrix.prototype.getCell = function(x,y){ if (this.aa[y] && this.aa[y][x]) return this.aa[y][x] else return null } +Matrix.prototype.resize = function(w,h){ + var div, row, lex + var f = this.f, old_h = this.h, old_w = this.w + var rapper = this.rapper + w = max(w, 1) + h = max(h, 1) + if (h < old_h) { + for (var y = old_h; y > h; y--) { + row = this.aa.pop() + div = row[0].span.parentNode + row.forEach(function(lex, x){ + lex.demolish() + }) + div.parentNode.removeChild(div) + } + } + else if (h > old_h) { + for (var y = old_h; y < h; y++) { + div = document.createElement("div") + rapper.appendChild( div ) + this.aa[y] = new Array (w) + for (var x = 0; x < w; x++) { + lex = this.aa[y][x] = f(x,y) + div.appendChild(lex.span) + } + } + } + + if (w < old_w) { + this.aa.forEach(function(row, y){ + while (row.length > w) { + lex = row.pop() + lex.demolish() + } + }) + } + else if (w > old_w) { + this.aa.forEach(function(row, y){ + div = row[0].span.parentNode + for (var x = row.length; x < w; x++) { + lex = row[x] = f(x,y) + div.appendChild(lex.span) + } + }) + } + + this.w = w + this.h = h + this.bind && this.bind() +} + +// + Matrix.prototype.ascii = function () { var lines = this.aa.map(function(row, y){ var last, line = "" @@ -160,15 +213,3 @@ Matrix.prototype.irssi = function(){ } return '/exec -out printf "' + escaped_txt + '"\n' } -Matrix.prototype.expand = function(i){ - var w = this.w = clamp(this.w+i, 1, 9), h = this.h = clamp(this.h+i, 1, 9) - console.log(w,h) - controls.width.char = ""+w - controls.width.build() - controls.height.char = ""+h - controls.height.build() - this.rebuild() -} -Matrix.prototype.contract = function(i){ - this.expand(-i) -} diff --git a/js/ui/brush.js b/js/ui/brush.js index a055a97..c7cf583 100644 --- a/js/ui/brush.js +++ b/js/ui/brush.js @@ -7,20 +7,6 @@ var brush = (function(){ }) brush.modified = false - - brush.bind = function(){ - brush.forEach(function(lex, x, y){ - if (lex.bound) return - lex.bound = true - - lex.span.addEventListener('mousedown', function(e){ - e.preventDefault() - dragging = true - // lex.fill(lex.fg, lex.bg) - }) - - }) - } brush.bind = function(){ @@ -70,6 +56,18 @@ var brush = (function(){ }) } + brush.expand = function(i){ + var w = this.w = clamp(this.w+i, 1, 9), h = this.h = clamp(this.h+i, 1, 9) + controls.width.char = ""+w + controls.width.build() + controls.height.char = ""+h + controls.height.build() + this.rebuild() + } + brush.contract = function(i){ + this.expand(-i) + } + brush.fg = 0 brush.bg = 1 diff --git a/js/ui/canvas.js b/js/ui/canvas.js index d354c62..e36f1b5 100644 --- a/js/ui/canvas.js +++ b/js/ui/canvas.js @@ -2,6 +2,7 @@ var canvas = current_canvas = (function(){ var cols = 80 var rows = 24 + var last_point = [0,0] var exports = new Matrix (cols, rows, function(x,y){ var lex = new Lex (x,y) @@ -11,8 +12,6 @@ var canvas = current_canvas = (function(){ exports.bind = function(){ - var last_point = [0,0] - exports.forEach(function(lex, x, y){ if (lex.bound) return diff --git a/js/ui/controls.js b/js/ui/controls.js index d575725..aadd3c9 100644 --- a/js/ui/controls.js +++ b/js/ui/controls.js @@ -154,9 +154,10 @@ var controls = (function(){ } controls.canvas_width.char = ""+n controls.canvas_width.build() - canvas.w = n - canvas.rebuild() - canvas.build() + canvas.resize(n, canvas.h) + // canvas.w = n + // canvas.rebuild() + // canvas.build() }) controls.canvas_height.key = int_key(function(n, keyCode){ controls.canvas_height.read() @@ -165,9 +166,10 @@ var controls = (function(){ } controls.canvas_height.char = ""+n controls.canvas_height.build() - canvas.h = n - canvas.rebuild() - canvas.build() + canvas.resize(canvas.w, n) + // canvas.h = n + // canvas.rebuild() + // canvas.build() }) } diff --git a/js/ui/keys.js b/js/ui/keys.js index 7711e9d..d1badf6 100644 --- a/js/ui/keys.js +++ b/js/ui/keys.js @@ -74,7 +74,12 @@ var keys = (function(){ if (focused && char) { var y = focused.y, x = focused.x focused.key(char, e.keyCode) - current_canvas.focusLex(y + direction[0], focused.x + direction[1]) + if (! ('y' in focused && 'x' in focused) ) { + return + } + console.log(focused) + console.log(y, direction[0], x, direction[1]) + current_canvas.focusLex(y + direction[0], x + direction[1]) } }) } diff --git a/js/ui/selection.js b/js/ui/selection.js new file mode 100644 index 0000000..cbeb051 --- /dev/null +++ b/js/ui/selection.js @@ -0,0 +1,21 @@ +var selection = (function(){ + + var selection = new Matrix (1, 1, function(x,y){ + var lex = new Lex (x,y) + lex.build() + return lex + }) + + // in selection mode.. + // - we start by clicking the canvas. this positions the selection, and copies + // the character + // - then we drag down and to the right. this resizes the selection and pushes new + // rows and columns. each of these copies the character underneath. + // - on mouseup, the selection is locked. then.. + // - drag the selection to move it -- this "cuts" it and leaves a blank space on the canvas. + // - shift-drag the selection to copy it + + + return selection + +})() -- cgit v1.2.3-70-g09d2 From 6f151fef14c41ed1c4d65c2013224e0af37b7964 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 9 Dec 2014 17:13:38 -0500 Subject: non-destructive resize --- js/app.js | 8 -------- js/lex.js | 1 + js/ui/controls.js | 38 ++++++++++++++++++++++++++++---------- js/ui/keys.js | 7 ++----- 4 files changed, 31 insertions(+), 23 deletions(-) (limited to 'js/lex.js') diff --git a/js/app.js b/js/app.js index fd375cf..de399bc 100644 --- a/js/app.js +++ b/js/app.js @@ -49,12 +49,4 @@ function bind () { }) } - -function int_key (f) { - return function (key, keyCode) { - var n = parseInt(key) - ! isNaN(n) && f(n) - } -} - init() diff --git a/js/lex.js b/js/lex.js index 18ca4c5..2dc1dd5 100644 --- a/js/lex.js +++ b/js/lex.js @@ -91,6 +91,7 @@ Lex.prototype.focus = function(){ Lex.prototype.blur = function(){ this.span.classList.remove('focused') focused = null + this.onBlur && this.onBlur() } Lex.prototype.demolish = function(){ if (this.span.parentNode) { this.span.parentNode.removeChild(this.span) } diff --git a/js/ui/controls.js b/js/ui/controls.js index aadd3c9..e8c9abd 100644 --- a/js/ui/controls.js +++ b/js/ui/controls.js @@ -110,7 +110,12 @@ var controls = (function(){ // bind controls.bind = function(){ - [controls.width, controls.height, controls.canvas_width, controls.canvas_height].forEach(function(lex){ + [ + controls.width, + controls.height, + controls.canvas_width, + controls.canvas_height + ].forEach(function(lex){ lex.span.addEventListener('mousedown', function(e){ lex.focus() }) @@ -133,14 +138,14 @@ var controls = (function(){ }) controls.width.key = int_key(function(n, keyCode){ - controls.width.blur() + controls.width.blur() controls.width.char = ""+n controls.width.build() brush.w = n brush.rebuild() }) controls.height.key = int_key(function(n, keyCode){ - controls.height.blur() + controls.height.blur() controls.height.char = ""+n controls.height.build() brush.h = n @@ -154,11 +159,20 @@ var controls = (function(){ } controls.canvas_width.char = ""+n controls.canvas_width.build() - canvas.resize(n, canvas.h) - // canvas.w = n - // canvas.rebuild() - // canvas.build() }) + controls.canvas_width.onBlur = function(){ + var w = parseInt(controls.canvas_width.char) || 1 + controls.canvas_width.char = w+"" + controls.canvas_width.build() + canvas.resize(w, canvas.h) + } + controls.canvas_height.onBlur = function(){ + var h = parseInt(controls.canvas_height.char) || 1 + controls.canvas_height.char = h+"" + controls.canvas_height.build() + canvas.resize(canvas.w, h) + } + controls.canvas_height.key = int_key(function(n, keyCode){ controls.canvas_height.read() if (controls.canvas_height.char.length == 1) { @@ -167,11 +181,15 @@ var controls = (function(){ controls.canvas_height.char = ""+n controls.canvas_height.build() canvas.resize(canvas.w, n) - // canvas.h = n - // canvas.rebuild() - // canvas.build() }) } + function int_key (f) { + return function (key, keyCode) { + var n = parseInt(key) + ! isNaN(n) && f(n) + } + } + return controls })() \ No newline at end of file diff --git a/js/ui/keys.js b/js/ui/keys.js index d1badf6..0070dff 100644 --- a/js/ui/keys.js +++ b/js/ui/keys.js @@ -74,11 +74,8 @@ var keys = (function(){ if (focused && char) { var y = focused.y, x = focused.x focused.key(char, e.keyCode) - if (! ('y' in focused && 'x' in focused) ) { - return - } - console.log(focused) - console.log(y, direction[0], x, direction[1]) + if (! ('y' in focused && 'x' in focused) ) { return } + // console.log(y, direction[0], x, direction[1]) current_canvas.focusLex(y + direction[0], x + direction[1]) } }) -- cgit v1.2.3-70-g09d2 From a0b65f2e1a81b6fec30b4c1c2b2764c8dbcd64a9 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Fri, 12 Dec 2014 00:05:37 -0500 Subject: flood fill --- index.html | 1 + js/app.js | 2 +- js/draw.js | 43 +++++++++++++++++++++++++++++++++++++++++++ js/lex.js | 10 +++++++++- js/ui/brush.js | 2 ++ js/ui/canvas.js | 3 +++ js/ui/controls.js | 12 +++++++++++- 7 files changed, 70 insertions(+), 3 deletions(-) (limited to 'js/lex.js') diff --git a/index.html b/index.html index b45000f..2cdb580 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@ circle
text
select
+ fill

clear
grid
diff --git a/js/app.js b/js/app.js index 6c234c0..ab2c1ab 100644 --- a/js/app.js +++ b/js/app.js @@ -3,6 +3,7 @@ var dragging = false var drawing = false var erasing = false var selecting = false +var filling = false var focused var canvas, tools, palette, controls, brush, mode, current_tool, current_canvas @@ -28,7 +29,6 @@ function build () { brush.build() controls.grid.use() - controls.select.use() } function bind () { canvas.bind() diff --git a/js/draw.js b/js/draw.js index 8a12467..6bf55bd 100644 --- a/js/draw.js +++ b/js/draw.js @@ -51,6 +51,48 @@ var draw = (function(){ } }) } + + function fill (lex, x, y) { + var q = [ [x,y] ] + var target = canvas.aa[y][x].copy() + var n, w = 0, e = 0, j = 0 + var kk = 0 + // gets into a weird infinite loop if we don't break here.. :\ + if (target.eq(lex)) { return } + LOOP: while (q.length) { + n = q.shift() + if (canvas.aa[n[1]][n[0]].ne(target)) { + continue LOOP + } + w = e = n[0] + j = n[1] + WEST: while (w > 0) { + if (canvas.aa[j][w-1].eq(target)) { + w = w-1 + } + else { + break WEST + } + } + EAST: while (e < canvas.w-1) { + if (canvas.aa[j][e+1].eq(target)) { + e = e+1 + } + else { + break EAST + } + } + for (var i = w; i <= e; i++) { + canvas.aa[j][i].clone(lex) + if (j > 0 && canvas.aa[j-1][i].eq(target)) { + q.push([ i, j-1 ]) + } + if (j < canvas.h-1 && canvas.aa[j+1][i].eq(target)) { + q.push([ i, j+1 ]) + } + } + } + } var draw = {} draw.down = down @@ -58,6 +100,7 @@ var draw = (function(){ draw.stamp = stamp draw.line = line draw.point = point + draw.fill = fill return draw })() diff --git a/js/lex.js b/js/lex.js index 2dc1dd5..8c3b0f1 100644 --- a/js/lex.js +++ b/js/lex.js @@ -57,6 +57,11 @@ Lex.prototype.clone = function (lex){ this.opacity = lex.opacity this.build() } +Lex.prototype.copy = function () { + var lex = new Lex (0,0) + lex.clone(this) + return lex +} Lex.prototype.erase = function (){ this.fg = colors.white this.bg = colors.black @@ -71,7 +76,10 @@ Lex.prototype.fill = function(fg, bg){ this.build() } Lex.prototype.eq = function(lex){ - return lex && this.fg == lex.fg && this.bg == lex.fg && this.char == lex.char + return lex && this.fg == lex.fg && this.bg == lex.bg && this.char == lex.char +} +Lex.prototype.ne = function(lex){ + return ! this.eq(lex) } Lex.prototype.clear = function(){ this.bg = 1 diff --git a/js/ui/brush.js b/js/ui/brush.js index c7cf583..50f6e07 100644 --- a/js/ui/brush.js +++ b/js/ui/brush.js @@ -68,8 +68,10 @@ var brush = (function(){ this.expand(-i) } + brush.char = " " brush.fg = 0 brush.bg = 1 + brush.opacity = 1 return brush diff --git a/js/ui/canvas.js b/js/ui/canvas.js index c70b135..206cbee 100644 --- a/js/ui/canvas.js +++ b/js/ui/canvas.js @@ -29,6 +29,9 @@ var canvas = current_canvas = (function(){ else if (selecting) { selection.down(e, lex, point) } + else if (filling) { + draw.fill(brush, x, y) + } lex.focus() }) lex.span.addEventListener("mousemove", function(e){ diff --git a/js/ui/controls.js b/js/ui/controls.js index 293cd1d..bbf93cc 100644 --- a/js/ui/controls.js +++ b/js/ui/controls.js @@ -7,6 +7,7 @@ var controls = (function(){ brush.generate = controls.circle.generate brush.generate() drawing = true + filling = false selection.hide() brush.modified = false } @@ -30,6 +31,7 @@ var controls = (function(){ brush.generate() brush.modified = false drawing = true + filling = false selection.hide() } controls.square.generate = function(){ @@ -42,6 +44,7 @@ var controls = (function(){ brush.generate = controls.text.generate brush.generate() drawing = false + filling = false selection.hide() } controls.text.generate = function(){ @@ -50,9 +53,15 @@ var controls = (function(){ controls.select = new Tool (select_el) controls.select.use = function(){ drawing = false + filling = false selection.show() } - controls.text.generate = function(){ + + controls.fill = new Tool (fill_el) + controls.fill.use = function(){ + drawing = false + filling = true + selection.hide() } controls.clear = new Tool (clear_el) @@ -137,6 +146,7 @@ var controls = (function(){ controls.square, controls.circle, controls.text, + controls.fill, controls.select, controls.clear, controls.grid, -- cgit v1.2.3-70-g09d2