Skip to content

Commit 125377c

Browse files
committed
implement small functionality, rendering using "half blocks"
Thanks for the idea @coreh!
1 parent e6d4dee commit 125377c

File tree

1 file changed

+85
-24
lines changed

1 file changed

+85
-24
lines changed

index.js

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ module.exports = term;
2323
function term (opts) {
2424
if (!opts) opts = {};
2525
var stream = opts.stream || process.stdout;
26-
var pixel = opts.pixel || ' ';
27-
var pixelHeight = 1;
28-
var pixelWidth = pixel.length;
26+
var small = !!opts.small;
27+
var pixelHeight = small ? 0.5 : 1;
28+
var pixelWidth = small ? 1 : 2;
2929

3030
// create <canvas> instance
3131
var canvas = new Canvas(stream.columns / pixelWidth, stream.rows / pixelHeight);
3232
canvas.render = render;
3333
canvas.stream = stream;
34-
canvas.pixel = pixel;
34+
canvas.small = small;
3535

3636
// cached "context"
3737
canvas.renderCtx = canvas.getContext('2d');
@@ -54,6 +54,9 @@ function term (opts) {
5454
function render () {
5555
var cursor = ansi(this.stream);
5656

57+
// retain calls in memory until `flush()` call
58+
cursor.buffer();
59+
5760
// erase everything on the screen
5861
cursor.eraseData(2);
5962

@@ -62,32 +65,90 @@ function render () {
6265

6366
// render the current <canvas> contents to the TTY
6467
var ctx = this.renderCtx;
68+
var small = this.small;
6569
var w = this.width;
6670
var h = this.height;
6771
var alphaThreshold = 0;
68-
var pixel = this.pixel;
6972

7073
var data = ctx.getImageData(0, 0, w, h).data;
71-
72-
for (var i = 0, l = data.length; i < l; i += 4) {
73-
74-
if ((i/4|0) % w === 0) {
75-
// beginning of the row
76-
cursor.bg.reset();
77-
cursor.write('\n');
74+
var r, g, b, alpha;
75+
var topBlank, bottomBlank;
76+
var i = 0;
77+
78+
for (var y = 0; y < h; y++) {
79+
80+
// beginning of the row
81+
cursor.bg.reset();
82+
cursor.write('\n');
83+
84+
for (var x = 0; x < w; x++) {
85+
86+
// in `small` mode, we have to render 2 rows at a time, where the top row
87+
// is the background color, and the bottom row is the foreground color
88+
i = ((y * w) + x) * 4;
89+
90+
// top row
91+
r = data[i];
92+
g = data[i+1];
93+
b = data[i+2];
94+
alpha = data[i+3];
95+
96+
if (alpha > alphaThreshold) {
97+
cursor.bg.rgb(r, g, b);
98+
topBlank = false;
99+
} else {
100+
cursor.bg.reset();
101+
topBlank = true;
102+
}
103+
104+
if (small) {
105+
// bottom row
106+
107+
// go to the next row
108+
i = (((y + 1) * w) + x) * 4;
109+
110+
r = data[i];
111+
g = data[i+1];
112+
b = data[i+2];
113+
alpha = data[i+3];
114+
115+
if (alpha > alphaThreshold) {
116+
cursor.fg.rgb(r, g, b);
117+
bottomBlank = false;
118+
} else {
119+
cursor.fg.reset();
120+
bottomBlank = true;
121+
}
122+
}
123+
124+
if (small && bottomBlank && !topBlank) {
125+
// swapping fg and bg for this pixel since we're gonna use a "top
126+
// half" instead of the usual "bottom half"
127+
i = ((y * w) + x) * 4;
128+
129+
// top row
130+
r = data[i];
131+
g = data[i+1];
132+
b = data[i+2];
133+
134+
cursor.bg.reset();
135+
cursor.fg.rgb(r, g, b);
136+
}
137+
138+
// write the pixel
139+
if (!small) {
140+
cursor.write(' ');
141+
} else if (topBlank && bottomBlank) {
142+
cursor.write(' ');
143+
} else if (bottomBlank) {
144+
cursor.write('▀');
145+
} else {
146+
cursor.write('▄');
147+
}
78148
}
79149

80-
var r = data[i];
81-
var g = data[i+1];
82-
var b = data[i+2];
83-
var alpha = data[i+3];
84-
85-
if (alpha > alphaThreshold) {
86-
cursor.bg.rgb(r, g, b);
87-
} else {
88-
cursor.bg.reset();
89-
}
90-
91-
cursor.write(pixel);
150+
if (small) y++;
92151
}
152+
153+
cursor.flush();
93154
}

0 commit comments

Comments
 (0)