cleanup. improve BCE. remove old code.

This commit is contained in:
Christopher Jeffrey 2013-07-21 23:53:10 -05:00
parent 00e680d413
commit 346e39b723
3 changed files with 207 additions and 121 deletions

View File

@ -62,6 +62,86 @@ exports.matchColor = function(hex) {
return exports._cache[hex] = li; return exports._cache[hex] = li;
}; };
exports.matchColor_ = function(r1, g1, b1) {
if (typeof r1 === 'string' && g1 == null) {
var hex = r1;
if (hex[0] !== '#') {
return hex;
}
if (hex.length === 4) {
hex = hex[0]
+ hex[1] + hex[1]
+ hex[2] + hex[2]
+ hex[3] + hex[3];
}
hex = exports.HexToRGB(hex);
r1 = hex[0], g1 = hex[1], b1 = hex[2];
}
var hash = r1 + '.' + g1 + '.' + b1;
if (exports._cache[hash] != null) {
return exports._cache[hash];
}
var ldiff = Infinity
, li = -1
, i = 0
, c
, r2
, g2
, b2
, diff;
for (; i < exports.vcolors.length; i++) {
c = exports.vcolors[i];
r2 = c[0];
g2 = c[1];
b2 = c[2];
if (r1 === r2 && g1 === g2 && b1 === b2) {
diff = 0;
} else {
// diff = colorDistance3d(r1, g1, b1, r2, g2, b2);
diff = colorDistance3dWeight(r1, g1, b1, r2, g2, b2);
// diff = colorDistance3dWeightSqrt(r1, g1, b1, r2, g2, b2);
}
if (diff === 0) {
li = i;
break;
}
if (diff < ldiff) {
ldiff = diff;
li = i;
}
}
return exports._cache[hash] = li;
};
exports.RGBToHex = function(r, g, b) {
if (Array.isArray(r)) b = r[2], g = r[1], r = r[0];
function hex(n) {
n = n.toString(16);
if (n.length < 2) n = '0' + n;
return n;
}
return '#' + hex(r) + hex(g) + hex(b);
};
exports.hexToRGB = function(hex) {
var col = parseInt(hex.substring(1), 16)
, r = (col >> 16) & 0xff
, g = (col >> 8) & 0xff
, b = col & 0xff;
return [r, g, b];
};
// As it happens, comparing how similar two colors are is really hard. Here is // As it happens, comparing how similar two colors are is really hard. Here is
// one of the simplest solutions, which doesn't require conversion to another // one of the simplest solutions, which doesn't require conversion to another
// color space, posted on stackoverflow. Maybe someone better at math can // color space, posted on stackoverflow. Maybe someone better at math can

View File

@ -1155,7 +1155,7 @@ Program.prototype._parseChar = function(text, attr) {
this.x = 0; this.x = 0;
} else { } else {
this.x++; this.x++;
if (this.x >= this.width) { if (this.x >= this.cols) {
this._wrapCursor(); this._wrapCursor();
} }
} }
@ -1318,7 +1318,7 @@ Program.prototype.return = function() {
Program.prototype.nel = Program.prototype.nel =
Program.prototype.newline = Program.prototype.newline =
Program.prototype.feed = function() { Program.prototype.feed = function() {
if (this.tput && this.tput.bools.eat_newline_glitch && this.x >= this.width) { if (this.tput && this.tput.bools.eat_newline_glitch && this.x >= this.cols) {
return; return;
} }
this.x = 0; this.x = 0;
@ -1383,7 +1383,8 @@ Program.prototype.tabSet = function() {
// ESC 7 Save Cursor (DECSC). // ESC 7 Save Cursor (DECSC).
Program.prototype.sc = Program.prototype.sc =
Program.prototype.saveCursor = function() { Program.prototype.saveCursor = function(key) {
if (key) return this.lsaveCursor(key);
this.savedX = this.x || 0; this.savedX = this.x || 0;
this.savedY = this.y || 0; this.savedY = this.y || 0;
if (this.tput) return this.put.sc(); if (this.tput) return this.put.sc();
@ -1392,13 +1393,40 @@ Program.prototype.saveCursor = function() {
// ESC 8 Restore Cursor (DECRC). // ESC 8 Restore Cursor (DECRC).
Program.prototype.rc = Program.prototype.rc =
Program.prototype.restoreCursor = function() { Program.prototype.restoreCursor = function(key, hide) {
if (key) return this.lrestoreCursor(key, hide);
this.x = this.savedX || 0; this.x = this.savedX || 0;
this.y = this.savedY || 0; this.y = this.savedY || 0;
if (this.tput) return this.put.rc(); if (this.tput) return this.put.rc();
return this.esc('8'); return this.esc('8');
}; };
// Save Cursor Locally
Program.prototype.lsaveCursor = function(key) {
var key = key || 'local';
this._saved = this._saved || {};
this._saved[key] = this._saved[key] || {};
this._saved[key].x = this.x;
this._saved[key].y = this.y;
this._saved[key].hidden = this.cursorHidden;
};
// Restore Cursor Locally
Program.prototype.lrestoreCursor = function(key, hide) {
var key = key || 'local', pos;
if (!this._saved || !this._saved[key]) return;
pos = this._saved[key];
delete this._saved[key];
this.cup(pos.y, pos.x);
if (hide && pos.hidden !== this.cursorHidden) {
if (pos.hidden) {
this.hideCursor();
} else {
this.showCursor();
}
}
};
// ESC # 3 DEC line height/width // ESC # 3 DEC line height/width
Program.prototype.lineHeight = function() { Program.prototype.lineHeight = function() {
return this.esc('#'); return this.esc('#');

View File

@ -826,17 +826,17 @@ Screen.prototype.draw = function(start, end) {
, attr , attr
, fg , fg
, bg , bg
, flags , flags;
, acs
, bc; var clr
, neq
, xx;
var lx = -1 var lx = -1
, ly = -1 , ly = -1
, o; , o;
var bcx = -1 var acs;
, bcy = -1
, bca = -1;
// var cx = this.program.x // var cx = this.program.x
// , cy = this.program.y // , cy = this.program.y
@ -844,7 +844,8 @@ Screen.prototype.draw = function(start, end) {
// //
// if (!ch) this.program.hideCursor(); // if (!ch) this.program.hideCursor();
this.program.saveCursor(); // this.program.sc('draw');
this.program.sc();
for (y = start; y <= end; y++) { for (y = start; y <= end; y++) {
line = this.lines[y]; line = this.lines[y];
@ -861,63 +862,75 @@ Screen.prototype.draw = function(start, end) {
data = line[x][0]; data = line[x][0];
ch = line[x][1]; ch = line[x][1];
// Take advantage of xterm's back_color_erase // Take advantage of xterm's back_color_erase feature by using a
// feature by using a lookahead. // lookahead. Stop spitting out so many damn spaces. NOTE: Is checking
if (this.tput.bools.back_color_erase && ch === ' ' && line[x + 1]) { // the bg for non BCE terminals worth the overhead?
var ne = false if (ch === ' '
, cl = true; && ((this.tput && this.tput.bools.back_color_erase)
|| (data & 0x1ff) === (this.dattr & 0x1ff))
&& ((data >> 18) & 8) === ((this.dattr >> 18) & 8)) {
clr = true;
neq = false;
for (var xi = x; xi < this.cols; xi++) { for (xx = x; xx < this.cols; xx++) {
if (line[xi][0] !== data || line[xi][1] !== ' ') { if (line[xx][0] !== data || line[xx][1] !== ' ') {
cl = false; clr = false;
break; break;
} }
if (line[xi][0] !== o[xi][0] || line[xi][1] !== o[xi][1]) { if (line[xx][0] !== o[xx][0] || line[xx][1] !== o[xx][1]) {
ne = true; neq = true;
} }
} }
if (cl && ne) { if (clr && neq) {
if (data !== attr) { if (data !== attr) {
out += this.codeAttr(data); out += this.codeAttr(data);
attr = data; attr = data;
} }
out += this.tput.el(0); out += this.tput.el(0);
for (var xi = x; xi < this.cols; xi++) { for (xx = x; xx < this.cols; xx++) {
o[xi][0] = data; o[xx][0] = data;
o[xi][1] = ' '; o[xx][1] = ' ';
} }
break; break;
} }
// comment the break in the first xi loop above for this to work. // If there's more than 10 spaces, use EL regardless
// if (!ne) { // and start over drawing the rest of line. Might
// not be worth it.
// if (!clr && neq && (xx - x) > 10) {
// if (data !== attr) {
// out += this.codeAttr(data);
// attr = data;
// }
// out += this.tput.el(0) + this.tput.cuf(xx - x);
// clr = xx; // tmp
// for (xx = x; xx < this.cols; xx++) {
// o[xx][0] = data;
// o[xx][1] = ' ';
// }
// x = clr - 1;
// continue;
// }
// Skip to the next line if the
// rest of the line is already drawn.
// Comment the break in the first
// xx loop above for this to work.
// Which carries less overhead?
// OR use another for loop:
// for (xx = x; xx < this.cols; xx++) {
// if (line[xx][0] !== o[xx][0] || line[xx][1] !== o[xx][1]) {
// neq = true;
// break;
// }
// }
// if (!neq) {
// attr = data; // attr = data;
// break; // break;
// } // }
} }
// Take advantage of xterm's back_color_erase feature.
// Stop spitting out so many damn spaces.
if (0) if (this.tput.bools.back_color_erase) {
if (ch === ' ' && (bca === -1 || bca === data)) {
if (bcy === -1) {
bcx = x;
bcy = y;
bca = data;
}
//ch = '';
} else if (bcy !== -1) {
// If it's more than ten spaces, just EL and jump forward.
// Might break things since it could alter the output buffer.
// out += x - bcx > 10
// ? this.tput.el(0) + this.tput.cuf(x - bcx)
// : Array((x - bcx) + 1).join(' ');
out += Array((x - bcx) + 1).join(' ');
bcx = -1, bcy = -1, bca = -1;
}
}
// Optimize by comparing the real output // Optimize by comparing the real output
// buffer to the pending output buffer. // buffer to the pending output buffer.
if (data === o[x][0] && ch === o[x][1]) { if (data === o[x][0] && ch === o[x][1]) {
@ -1013,7 +1026,6 @@ Screen.prototype.draw = function(start, end) {
} }
} }
/*
// Attempt to use ACS for supported characters. // Attempt to use ACS for supported characters.
// This is not ideal, but it's how ncurses works. // This is not ideal, but it's how ncurses works.
// There are a lot of terminals that support ACS // There are a lot of terminals that support ACS
@ -1028,13 +1040,22 @@ Screen.prototype.draw = function(start, end) {
// Maybe remove !this.tput.unicode check, however, // Maybe remove !this.tput.unicode check, however,
// this seems to be the way ncurses does it. // this seems to be the way ncurses does it.
if (this.tput) { if (this.tput) {
if (this.tput.strings.enter_alt_charset_mode if (this.tput.strings.enter_alt_charset_mode) {
&& this.tput.acscr[ch] if (!this.tput.brokenACS || !this.tput.unicode) {
&& (!this.tput.brokenACS || !this.tput.unicode)) { if (this.tput.acscr[ch]) {
ch = this.tput.smacs() if (acs) {
+ this.tput.acscr[ch] ch = this.tput.acscr[ch];
+ this.tput.rmacs(); } else {
} else if (!this.tput.strings.enter_alt_charset_mode) { ch = this.tput.smacs()
+ this.tput.acscr[ch]
acs = true;
}
} else if (acs) {
ch = this.tput.rmacs() + ch;
acs = false;
}
}
} else {
// U8 is not consistently correct. Some terminfo's // U8 is not consistently correct. Some terminfo's
// terminals that do not declare it may actually // terminals that do not declare it may actually
// support utf8 (e.g. urxvt), but if the terminal // support utf8 (e.g. urxvt), but if the terminal
@ -1042,61 +1063,22 @@ Screen.prototype.draw = function(start, end) {
// are it does not support UTF8. This is probably // are it does not support UTF8. This is probably
// the "safest" way to do this. Should fix things // the "safest" way to do this. Should fix things
// like sun-color. // like sun-color.
// if (this.program.term('sun') && ch > '~') {
// if (this.tput.numbers.U8 !== 1 && ch > '~') {
if (this.tput.numbers.U8 !== 1 && this.utoa[ch]) { if (this.tput.numbers.U8 !== 1 && this.utoa[ch]) {
ch = this.tput.utoa[ch] || '?'; ch = this.tput.utoa[ch] || '?';
} }
} }
// } else if (this.program.term('sun') && ch > '~') {
// } else if (this.tput.numbers.U8 !== 1 && ch > '~') {
// // If this terminal doesn't explicitly support UTF8,
// // replace unicode characters with ugly shitty ones.
// ch = this.tput.utoa[ch] || '?';
// }
} }
*/
if (this.tput.strings.enter_alt_charset_mode) {
if (!this.tput.brokenACS || !this.tput.unicode) {
if (this.tput.acscr[ch]) {
if (acs) {
ch = this.tput.acscr[ch];
} else {
ch = this.tput.smacs()
+ this.tput.acscr[ch]
acs = true;
}
} else if (acs) {
ch = this.tput.rmacs() + ch;
acs = false;
}
}
} else {
// if (this.program.term('sun') && ch > '~') {
// if (this.tput.numbers.U8 !== 1 && ch > '~') {
if (this.tput.numbers.U8 !== 1 && this.utoa[ch]) {
ch = this.tput.utoa[ch] || '?';
}
}
if (0) if (bcy !== -1) ch = '';
out += ch; out += ch;
attr = data; attr = data;
} }
if (0) if (bcy !== -1) {
out += this.tput.el(0);
bcx = -1, bcy = -1, bca = -1;
}
if (attr !== this.dattr) { if (attr !== this.dattr) {
out += '\x1b[m'; out += '\x1b[m';
} }
//if (this.tput.bools.back_color_erase && out && lx === -1) {
// out = this._replaceSpaces(out);
//}
if (this.tput) { if (this.tput) {
if (out) this.program.write(this.tput.cup(y, 0) + out); if (out) this.program.write(this.tput.cup(y, 0) + out);
} else { } else {
@ -1107,28 +1089,8 @@ Screen.prototype.draw = function(start, end) {
// this.program.cup(cy, cx); // this.program.cup(cy, cx);
// if (ch) this.program.hideCursor(); // if (ch) this.program.hideCursor();
this.program.restoreCursor(); // this.program.rc('draw', true);
}; this.program.rc();
Screen.prototype._replaceSpaces = function(out) {
if (!this._sr) this._sr = this._spaceReplacer.bind(this);
return out.replace(/ {5,}/g, this._sr);
};
Screen.prototype._spaceReplacer = function(ch) {
return this.tput.el(0) + this.tput.cuf(ch.length);
};
Screen.prototype._replaceSpaces = function(out) {
if (!this._sr) this._sr = this._spaceReplacer.bind(this);
// / +(?=(?:\x1b\[m)?(?:\x1b\[[\d;]*H|$))/g,
return out.replace(
/ {5,}(?=(?:\x1b\[[\d;]*m)*(?:\x1b\[[\d;]*H|$))/g,
this._sr);
};
Screen.prototype._spaceReplacer = function(ch) {
return this.tput.el(0);
}; };
Screen.prototype._reduceColor = function(col) { Screen.prototype._reduceColor = function(col) {
@ -1196,15 +1158,31 @@ Screen.prototype.attrCode = function(code, cur) {
case 28: case 28:
flags &= ~16; flags &= ~16;
break; break;
case 100: // default fg/bg
bg = 0x1ff;
fg = 0x1ff;
break;
default: // color default: // color
if (c === 48 && code[i+1] === '5') { if (c === 48 && +code[i+1] === 5) {
i += 2; i += 2;
bg = +code[i]; bg = +code[i];
break; break;
} else if (c === 38 && code[i+1] === '5') { } else if (c === 48 && +code[i+1] === 2) {
i += 2;
bg = colors.matchColor(
colors.RGBToHex(+code[i], +code[i+1], +code[i+2]));
i += 2;
break;
} else if (c === 38 && +code[i+1] === 5) {
i += 2; i += 2;
fg = +code[i]; fg = +code[i];
break; break;
} else if (c === 38 && +code[i+1] === 2) {
i += 2;
fg = colors.matchColor(
colors.RGBToHex(+code[i], +code[i+1], +code[i+2]));
i += 2;
break;
} }
if (c >= 40 && c <= 47) { if (c >= 40 && c <= 47) {
bg = c - 40; bg = c - 40;