asciiblaster- draw irc art in your web browser |
git clone git://git.acid.vegas/asciiblaster.git |
Log | Files | Refs | Archive | README |
colorcode.js (15325B)
1 !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.colorcode=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ 2 var colorcode = {}; 3 module.exports = colorcode; 4 colorcode.to_json = require('./src/to_json'); 5 colorcode.from_json = require('./src/from_json'); 6 colorcode.style = require('./src/style'); 7 colorcode.to_canvas = require('./src/canvas'); 8 colorcode.color = require('./src/color'); 9 colorcode.font = require('./src/font'); 10 11 },{"./src/canvas":2,"./src/color":3,"./src/font":4,"./src/from_json":8,"./src/style":9,"./src/to_json":10}],2:[function(require,module,exports){ 12 var to_json = require('./to_json'); 13 var fontload = require('./font').load; 14 var style = require('./style'); 15 var color = require('./color'); 16 17 // node-canvas 18 var Canvas = require('canvas'); 19 if (typeof Image === "undefined") Image = Canvas.Image; 20 21 var make_canvas = function(){ 22 if (typeof document === "undefined" && typeof Canvas !== "undefined") 23 return new Canvas(); 24 else 25 return document.createElement("canvas"); 26 } 27 28 var canvas_tmp; 29 30 var render_colorcode = function(json, canvas, font, opts){ 31 32 var cw = font.char_w 33 , ch = font.char_h 34 , ctx = canvas.getContext('2d') 35 , canvas_tmp = canvas_tmp || make_canvas() 36 , ctx_tmp = canvas_tmp.getContext("2d") 37 38 var palette = color.palettes[opts.palette || style.palette]; 39 var bg = opts.bg || style.bg; 40 41 canvas_tmp.width = cw; 42 canvas_tmp.height = ch; 43 44 canvas.width = json.w * cw; 45 canvas.height = json.h * ch; 46 47 // pre fill entire canvas with bg color 48 // is this a good optimization? 49 if (bg === color.transparent_index){ 50 // already cleared when resized above 51 // canvas.clearRect(0,0, canvas.width,canvas.height); 52 } else { 53 ctx.fillStyle = palette[bg]; 54 ctx.fillRect(0,0, canvas.width,canvas.height); 55 } 56 57 for (var l=0; l<json.lines.length; l++){ 58 var line = json.lines[l]; 59 for (var c=0; c<line.length; c++){ 60 var char = line[c]; 61 var x = c * cw 62 var y = l * ch 63 64 // draw bg for this char if not already filled 65 if (char.bg !== bg) { 66 if (char.bg === color.transparent_index) { 67 ctx.clearRect(x, y, cw, ch) 68 } else { 69 ctx.fillStyle = palette[char.bg] 70 ctx.fillRect(x, y, cw, ch); 71 } 72 } 73 74 if (font.is_char_blank(char.value)) continue; 75 76 // draw char in fg 77 var fg = palette[char.fg] 78 if (fg !== color.transparent){ 79 ctx_tmp.globalCompositeOperation = 'source-over' 80 ctx_tmp.fillStyle = fg 81 ctx_tmp.fillRect(0,0,cw,ch) 82 ctx_tmp.globalCompositeOperation = 'destination-in' 83 font.render_char(font, char.value, ctx_tmp, 0, 0, char) 84 ctx.drawImage(canvas_tmp, x, y) 85 } else { // transparent foreground punches out bg 86 ctx.globalCompositeOperation = 'destination-out' 87 font.render_char(font, char.value, ctx, x, y, char) 88 ctx.globalCompositeOperation = 'source-over' 89 } 90 91 } 92 } 93 94 if (opts.done) opts.done(canvas) 95 96 97 } 98 99 var to_canvas = function(string_or_json, opts){ 100 opts = opts || {}; 101 102 if (typeof string_or_json === 'string') 103 string_or_json = to_json(string_or_json, opts); 104 105 var canvas = opts.canvas || make_canvas(); 106 var font_name = opts.font || style.font; 107 108 fontload(font_name, function(font){ 109 render_colorcode(string_or_json, canvas, font, opts) 110 }); 111 112 return canvas; 113 } 114 115 module.exports = to_canvas; 116 117 },{"./color":3,"./font":4,"./style":9,"./to_json":10,"canvas":11}],3:[function(require,module,exports){ 118 var style = require('./style'); 119 120 var color = {}; 121 module.exports = color; 122 123 style.palette = 'mirc'; 124 125 color.transparent_index = 99; 126 color.transparent = 'rgba(0,0,0,0)'; 127 var ps = color.palettes = {}; 128 129 ps.mirc = [ 130 'rgb(255,255,255)' 131 ,'rgb(0,0,0)' 132 ,'rgb(0,0,127)' 133 ,'rgb(0,147,0)' 134 ,'rgb(255,0,0)' 135 ,'rgb(127,0,0)' 136 ,'rgb(156,0,156)' 137 ,'rgb(252,127,0)' 138 ,'rgb(255,255,0)' 139 ,'rgb(0,252,0)' 140 ,'rgb(0,147,147)' 141 ,'rgb(0,255,255)' 142 ,'rgb(0,0,252)' 143 ,'rgb(255,0,255)' 144 ,'rgb(127,127,127)' 145 ,'rgb(210,210,210)' 146 ]; 147 148 ps.winxp = [ 149 'rgb(255,255,255)' 150 ,'rgb(0,0,0)' 151 ,'rgb(0,0,128)' 152 ,'rgb(0,128,0)' 153 ,'rgb(255,0,0)' 154 ,'rgb(128,0,0)' 155 ,'rgb(128,0,128)' 156 ,'rgb(255,128,0)' 157 ,'rgb(255,255,0)' 158 ,'rgb(0,255,0)' 159 ,'rgb(0,128,128)' 160 ,'rgb(0,255,255)' 161 ,'rgb(0,0,255)' 162 ,'rgb(255,0,255)' 163 ,'rgb(128,128,128)' 164 ,'rgb(192,192,192)' 165 ]; 166 167 ps.vga = [ 168 'rgb(255,255,255)' 169 ,'rgb(0,0,0)' 170 ,'rgb(0,0,170)' 171 ,'rgb(0,170,0)' 172 ,'rgb(255,85,85)' 173 ,'rgb(170,0,0)' 174 ,'rgb(170,0,170)' 175 ,'rgb(170,85,0)' 176 ,'rgb(255,255,85)' 177 ,'rgb(85,255,85)' 178 ,'rgb(0,170,170)' 179 ,'rgb(85,255,255)' 180 ,'rgb(85,85,255)' 181 ,'rgb(255,85,255)' 182 ,'rgb(85,85,85)' 183 ,'rgb(170,170,170)' 184 ]; 185 186 ps.c64 = [ 187 'rgb(255,255,255)' 188 ,'rgb(0,0,0)' 189 ,'rgb(69,32,170)' 190 ,'rgb(101,170,69)' 191 ,'rgb(138,101,32)' 192 ,'rgb(138,69,32)' 193 ,'rgb(138,69,170)' 194 ,'rgb(101,69,0)' 195 ,'rgb(207,207,101)' 196 ,'rgb(170,239,138)' 197 ,'rgb(138,138,138)' 198 ,'rgb(101,170,207)' 199 ,'rgb(138,101,223)' 200 ,'rgb(207,138,101)' 201 ,'rgb(69,69,69)' 202 ,'rgb(170,170,170)' 203 ]; 204 205 ps.appleii = [ 206 'rgb(255,255,255)' 207 ,'rgb(0,0,0)' 208 ,'rgb(64,53,121)' 209 ,'rgb(64,75,7)' 210 ,'rgb(191,180,248)' 211 ,'rgb(109,41,64)' 212 ,'rgb(218,60,241)' 213 ,'rgb(218,104,15)' 214 ,'rgb(191,202,134)' 215 ,'rgb(38,195,16)' 216 ,'rgb(19,87,64)' 217 ,'rgb(146,214,191)' 218 ,'rgb(37,151,240)' 219 ,'rgb(236,168,191)' 220 ,'rgb(128,128,128)' 221 ,'rgb(128,128,128)' 222 ]; 223 224 225 },{"./style":9}],4:[function(require,module,exports){ 226 var __dirname="/src";var style = require('./style'); 227 // node-canvas 228 var Canvas = require('canvas'); 229 if (typeof Image === "undefined") Image = Canvas.Image; 230 231 var font = {}; 232 module.exports = font; 233 234 // hack for loading fonts in node... todo, fix this 235 font.img_path = ""; 236 if (typeof document === "undefined") font.img_path = __dirname + "/../examples/web/" 237 238 239 font.list = {}; 240 241 var fsexps = require('./font/fixedsys'); 242 var cp437s = require('./font/cp437'); 243 for (f in fsexps) font.list[fsexps[f].name] = fsexps[f]; 244 for (f in cp437s) font.list[cp437s[f].name] = cp437s[f]; 245 246 style.font = 'fixedsys_8x16'; 247 248 var err_font_load = function(){ 249 console.log("couldn't load font") 250 } 251 252 253 font.load = function(font_name, callback_fn){ 254 if (!(font_name in font.list)) { return;} // todo error 255 256 var f = font.list[font_name] 257 258 if (f.loaded) { 259 callback_fn(f); 260 } else { 261 f.sheet = new Image(); 262 f.sheet.crossOrigin = 'anonymous' 263 // node-canvas doesn't have addEventListener :( 264 f.sheet.onload = function(){ 265 f.loaded = true 266 callback_fn(f); 267 } 268 f.sheet.src = font.img_path + f.sheet_url 269 270 } 271 } 272 273 274 },{"./font/cp437":5,"./font/fixedsys":6,"./style":9,"canvas":11}],5:[function(require,module,exports){ 275 var cp437s = [[8,8],[8,12],[8,14],[8,16],[10,10],[10,16],[12,12],[16,16]] 276 var fonts = {}; 277 module.exports = fonts; 278 279 // utf8 -> cp437 function by sheetjs 280 // edited from https://github.com/SheetJS/js-codepage/blob/master/bits/437.js 281 var cp437 = (function(){ var d = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ", D = [], e = {}; for(var i=0;i!=d.length;++i) { if(d.charCodeAt(i) !== 0xFFFD) e[d[i]] = i; D[i] = d.charAt(i); } return {"enc": e, "dec": D }; })(); 282 283 var render_char = function(font, char_value, ctx, ctx_x, ctx_y){ 284 char_value = cp437.enc[String.fromCharCode(char_value)] | 0; 285 var sheet_x = (char_value % font.sheet_w_in_chars) * font.char_w 286 var sheet_y = ((char_value / font.sheet_w_in_chars) |0) * font.char_h 287 ctx.drawImage(font.sheet, 288 sheet_x|0, sheet_y|0, font.char_w, font.char_h, 289 ctx_x|0, ctx_y|0, font.char_w, font.char_h) 290 291 } 292 293 for (var i=0, wh; wh=cp437s[i]; i++){ 294 var font = {}; 295 font.is_char_blank = require('../fontutil').is_char_blank; 296 font.render_char = render_char; 297 font.name = 'cp437_' + wh[0] + 'x' + wh[1]; 298 font.sheet_url = './img/' + font.name + '.png' 299 font.sheet_w_in_chars = 16; 300 font.char_w = wh[0] 301 font.char_h = wh[1] 302 fonts[font.name] = font; 303 } 304 305 306 307 // window.cp437 = cp437; 308 309 },{"../fontutil":7}],6:[function(require,module,exports){ 310 var fsexps = [[8,16,0],[8,15,1],[8,8,5]] 311 var fonts = {}; 312 module.exports = fonts; 313 314 var render_char = function(font, char_value, ctx, ctx_x, ctx_y, char){ 315 var sheet_x = 0, sheet_y = 3; 316 if (char_value >= 0x20 && char_value <= 0x7e){ // ascii 317 sheet_x = (char_value - 0x20) * font.char_w_sheet 318 if (char.i){ // italic 319 sheet_y = 1 * font.char_h_sheet + 3 320 } 321 } else if (char_value >= 0x80 && char_value <= 0xff){ // latin-1 322 sheet_x = (char_value - 0x80) * font.char_w_sheet; 323 sheet_y = 2 * font.char_h_sheet + 3 324 } else if (char_value >= 0x0100 && char_value <= 0x017f){ // latin a 325 sheet_x = (char_value - 0x0100) * font.char_w_sheet; 326 sheet_y = 3 * font.char_h_sheet + 3 327 } else if (char_value >= 0x0180 && char_value <= 0x024f){ // latin b 328 sheet_x = (char_value - 0x0180) * font.char_w_sheet; 329 sheet_y = 4 * font.char_h_sheet + 3 330 } else if (char_value >= 0x2500 && char_value <= 0x25ff){ // geom 331 sheet_x = (char_value - 0x2500) * font.char_w_sheet; 332 sheet_y = 5 * font.char_h_sheet + 3 333 } else if (char_value >= 0x2600 && char_value <= 0x26ff){ // emoji 334 sheet_x = (char_value - 0x2600) * font.char_w_sheet; 335 sheet_y = 6 * font.char_h_sheet + 3 336 } 337 338 // var sheet_x = (char_value % font.sheet_w_in_chars) * font.char_w 339 // var sheet_y = ((char_value / font.sheet_w_in_chars) |0) * font.char_h + 3 340 ctx.drawImage(font.sheet, 341 sheet_x|0, (sheet_y|0) + font.y_adj, font.char_w, font.char_h, 342 ctx_x|0, ctx_y|0, font.char_w, font.char_h) 343 344 } 345 346 for (var i=0, wh; wh=fsexps[i]; i++){ 347 var font = { 348 name: 'fixedsys_' + wh[0] + 'x' + wh[1], 349 sheet_url: './img/fsex-simple.png', 350 sheet_w_in_chars: 128, 351 char_w_sheet: 8, 352 char_h_sheet: 16, 353 char_w: wh[0], 354 char_h: wh[1], 355 y_adj: wh[2], 356 is_char_blank: require('../fontutil').is_char_blank, 357 render_char: render_char 358 } 359 fonts[font.name] = font 360 } 361 },{"../fontutil":7}],7:[function(require,module,exports){ 362 var util = {}; 363 module.exports = util; 364 365 util.is_char_blank = function(char_value){ 366 if (char_value === 32) return true; 367 } 368 369 util.render_char = function(font, char_value, ctx, ctx_x, ctx_y){ 370 var sheet_x = (char_value % font.sheet_w_in_chars) * font.char_w 371 var sheet_y = ((char_value / font.sheet_w_in_chars) |0) * font.char_h 372 ctx.drawImage(font.sheet, 373 sheet_x|0, sheet_y|0, font.char_w, font.char_h, 374 ctx_x|0, ctx_y|0, font.char_w, font.char_h) 375 376 } 377 378 379 },{}],8:[function(require,module,exports){ 380 var char_color = '\x03'; 381 382 var make_colorcode_fgbg = function(fg, bg){ 383 // pad numbers: this prevents irc parsing confusion 384 // when the character after the colorcode is a number 385 if (fg < 10) fg = "0" + fg; 386 if (bg < 10) bg = "0" + bg; 387 return char_color + fg + "," + bg 388 } 389 390 var colorcode_from_json = function(json, opts){ 391 var out = ""; 392 for (var li=0, line; line=json.lines[li]; li++){ 393 for (var ci=0, char; char=line[ci]; ci++){ 394 out += make_colorcode_fgbg(char.fg, char.bg) 395 out += String.fromCharCode(char.value) 396 } 397 out += "\n"; 398 } 399 return out; 400 } 401 402 403 module.exports = colorcode_from_json; 404 405 },{}],9:[function(require,module,exports){ 406 // default settings for fonts, colors, etc 407 var style = {}; 408 module.exports = style; 409 410 },{}],10:[function(require,module,exports){ 411 var char_color = '\x03'; 412 var regexp_color = /(^[\d]{1,2})?(?:,([\d]{1,2}))?/; 413 414 var style_chars = { 415 '\x02': 'bold', 416 '\x1d': 'italic', 417 '\x1f': 'underline', 418 '\x0f': 'reset', 419 '\x16': 'inverse' 420 }; 421 422 var Style = function(style){ 423 this.b = style.b; 424 this.i = style.i; 425 this.u = style.u; 426 this.fg = style.fg; 427 this.bg = style.bg; 428 }; 429 430 var style_fns = {}; 431 432 style_fns.bold = function(style){ style.b = !style.b }; 433 434 style_fns.italic = function(style){ style.i = !style.i }; 435 436 style_fns.underline = function(style){ style.u = !style.u }; 437 438 style_fns.inverse = function(style){ 439 var tmp = style.fg; 440 style.fg = style.bg; 441 style.bg = tmp; 442 }; 443 444 style_fns.reset = function(style, base_style){ 445 style.b = base_style.b; 446 style.i = base_style.i; 447 style.u = base_style.u; 448 style.fg = base_style.fg; 449 style.bg = base_style.bg; 450 }; 451 452 var colorcode_to_json = function(string, opts){ 453 // looks like its already converted 454 if (typeof string === 'object' && 455 'lines' in string && 456 'w' in string && 457 'h' in string) 458 return string; 459 460 461 opts = opts || {}; 462 var d = colorcode_to_json.defaults; 463 464 var base_style = { 465 b: "b" in opts ? opts.b : d.b, 466 i: "i" in opts ? opts.i : d.i, 467 u: "u" in opts ? opts.u : d.u, 468 fg: "fg" in opts ? opts.fg : d.fg, 469 bg: "bg" in opts ? opts.bg : d.bg 470 }; 471 472 var lines_in = string.split(/\r?\n/); 473 var lines_out = []; 474 var w = 0, h = 0; 475 476 for (var i=0; i<lines_in.length; i++){ 477 var line = lines_in[i]; 478 if (line.length === 0) continue; // skip blank lines 479 var json_line = line_to_json(line, base_style); 480 if (w < json_line.length) w = json_line.length; 481 lines_out.push(json_line); 482 h++; 483 } 484 485 return {w:w, h:h, lines:lines_out}; 486 }; 487 488 colorcode_to_json.defaults = { 489 b: false 490 , i: false 491 , u: false 492 , fg: 1 493 , bg: 99 494 }; 495 496 var line_to_json = function(line, base_style){ 497 var out = []; 498 var pos = -1; 499 var len = line.length -1; 500 var char; 501 var style = new Style(base_style); 502 503 while (pos < len){ pos++; 504 505 char = line[pos]; 506 507 // next char is a styling char 508 if (char in style_chars){ 509 style_fns[style_chars[char]](style, base_style); 510 continue; 511 } 512 513 // next char is a color styling char, with possible color nums after 514 if (char === char_color){ 515 var matches = line.substr(pos+1,5).match(regexp_color); 516 517 // \x03 without color code is a soft style reset 518 if (matches[1] === undefined && matches[2] === undefined) { 519 style.fg = base_style.fg; 520 style.bg = base_style.bg; 521 continue; 522 } 523 524 if (matches[1] !== undefined) 525 style.fg = Number(matches[1]); 526 527 if (matches[2] !== undefined) 528 style.bg = Number(matches[2]); 529 530 pos += matches[0].length; 531 continue; 532 533 } 534 535 // otherwise, next char is treated as normal content 536 var data = new Style(style); 537 //data.value = char; 538 data.value = char.charCodeAt(0); 539 540 out.push(data); 541 } 542 return out; 543 }; 544 545 module.exports = colorcode_to_json; 546 547 },{}],11:[function(require,module,exports){ 548 549 },{}]},{},[1]) 550 (1) 551 });