jsbasic/hires.js
2023-01-04 19:34:48 -08:00

121 lines
2.8 KiB
JavaScript

//
// High Resolution Graphics (HiRes) Emulation
//
// This variation does not rely on a canvas element with the same dimensions
// as the pixel buffer; instead, it paints pixels on the canvas using rectangles.
// This works even if the underlying canvas implementation does not support
// scaling (e.g. fallbacks for IE using VML or Flash)
// Usage:
//
// var hires = new HiRes( element, width, height )
// hires.clear( [color_index] )
// hires.setColor( color_index )
// hires.plot( x, y )
// hires.plot_to( x, x )
// hires.getPixel( x, x ) // for "HSCRN"
// hires.show( bool )
// { width: w, height: h } = hires.getScreenSize()
function HiRes(element, width, height) {
var COLORS, // Apple II to HTML color table
last_x = 0,
last_y = 0,
pixels = [],
color = 0,
context = element.getContext("2d");
pixels.length = width * height;
// From: Apple ][ Colors at MROB
// https://mrob.com/pub/xapple2/colors.html
COLORS = [
'#000000', // 0 = Black 1
'#14f53c', // 1 = Green
'#ff44fd', // 2 = Purple
'#ffffff', // 3 = White 1
'#000000', // 4 = Black 2
'#ff6a3c', // 5 = Orange
'#14cffd', // 6 = Medium Blue
'#ffffff' // 7 = White 2
];
this.clear = function(opt_color) {
var i;
context.clearRect(0, 0, element.width, element.height);
pixels = [];
pixels.length = width * height;
if (arguments.length >= 1) {
context.fillStyle = COLORS[opt_color];
context.fillRect(0, 0, element.width, element.height);
for (i = 0; i < pixels.length; i += 1) {
pixels[i] = opt_color;
}
}
};
this.setColor = function(newColor) {
color = Math.floor(newColor) % COLORS.length;
};
function drawPixel(x, y) {
var sx = element.width / width,
sy = element.height / height;
context.fillRect((x * sx)|0, (y * sy)|0, sx|0, sy|0);
pixels[x + y * width] = color;
}
this.plot = function(x, y) {
context.fillStyle = COLORS[color];
drawPixel(x, y);
last_x = x;
last_y = y;
};
this.plot_to = function(x, y) {
var x0 = last_x, y0 = last_y, x1 = x, y1 = y,
dx = Math.abs(x1 - x0),
dy = Math.abs(y1 - y0),
sx = (x0 < x1) ? 1 : -1,
sy = (y0 < y1) ? 1 : -1,
err = dx - dy,
e2;
last_x = x;
last_y = y;
for (;;) {
this.plot(x0, y0);
if (x0 === x1 && y0 === y1) { return; }
e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x0 += sx;
}
if (e2 < dx) {
err += dx;
y0 += sy;
}
}
};
this.getPixel = function(x, y) {
return pixels[y * width + x] >>> 0;
};
this.getScreenSize = function() {
return { width: width, height: height };
};
this.show = function(state) {
element.style.visibility = state ? "visible" : "hidden";
};
}