|
|
|
@ -4,28 +4,28 @@ import Base64 from '../core/base64.js';
|
|
|
|
|
import Display from '../core/display.js';
|
|
|
|
|
|
|
|
|
|
describe('Display/Canvas Helper', function () {
|
|
|
|
|
const checked_data = new Uint8Array([
|
|
|
|
|
const checkedData = new Uint8Array([
|
|
|
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
|
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
|
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
|
|
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const basic_data = new Uint8Array([0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0xff, 0xff, 0xff, 255]);
|
|
|
|
|
const basicData = new Uint8Array([0xff, 0x00, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0xff, 0xff, 0xff, 255]);
|
|
|
|
|
|
|
|
|
|
function make_image_canvas(input_data) {
|
|
|
|
|
function makeImageCanvas(inputData) {
|
|
|
|
|
const canvas = document.createElement('canvas');
|
|
|
|
|
canvas.width = 4;
|
|
|
|
|
canvas.height = 4;
|
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
|
const data = ctx.createImageData(4, 4);
|
|
|
|
|
for (let i = 0; i < checked_data.length; i++) { data.data[i] = input_data[i]; }
|
|
|
|
|
for (let i = 0; i < checkedData.length; i++) { data.data[i] = inputData[i]; }
|
|
|
|
|
ctx.putImageData(data, 0, 0);
|
|
|
|
|
return canvas;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function make_image_png(input_data) {
|
|
|
|
|
const canvas = make_image_canvas(input_data);
|
|
|
|
|
function makeImagePng(inputData) {
|
|
|
|
|
const canvas = makeImageCanvas(inputData);
|
|
|
|
|
const url = canvas.toDataURL();
|
|
|
|
|
const data = url.split(",")[1];
|
|
|
|
|
return Base64.decode(data);
|
|
|
|
@ -44,11 +44,11 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
it('should take viewport location into consideration when drawing images', function () {
|
|
|
|
|
display.resize(4, 4);
|
|
|
|
|
display.viewportChangeSize(2, 2);
|
|
|
|
|
display.drawImage(make_image_canvas(basic_data), 1, 1);
|
|
|
|
|
display.drawImage(makeImageCanvas(basicData), 1, 1);
|
|
|
|
|
display.flip();
|
|
|
|
|
|
|
|
|
|
const expected = new Uint8Array(16);
|
|
|
|
|
for (let i = 0; i < 8; i++) { expected[i] = basic_data[i]; }
|
|
|
|
|
for (let i = 0; i < 8; i++) { expected[i] = basicData[i]; }
|
|
|
|
|
for (let i = 8; i < 16; i++) { expected[i] = 0; }
|
|
|
|
|
expect(display).to.have.displayed(expected);
|
|
|
|
|
});
|
|
|
|
@ -123,8 +123,8 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
|
|
|
|
|
it('should change the size of the logical canvas', function () {
|
|
|
|
|
display.resize(5, 7);
|
|
|
|
|
expect(display._fb_width).to.equal(5);
|
|
|
|
|
expect(display._fb_height).to.equal(7);
|
|
|
|
|
expect(display._fbWidth).to.equal(5);
|
|
|
|
|
expect(display._fbHeight).to.equal(7);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should keep the framebuffer data', function () {
|
|
|
|
@ -275,7 +275,7 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.flip();
|
|
|
|
|
display.fillRect(0, 0, 4, 4, [0, 0xff, 0]);
|
|
|
|
|
const expected = [];
|
|
|
|
|
for (let i = 0; i < 4 * display._fb_width * display._fb_height; i += 4) {
|
|
|
|
|
for (let i = 0; i < 4 * display._fbWidth * display._fbHeight; i += 4) {
|
|
|
|
|
expected[i] = 0xff;
|
|
|
|
|
expected[i+1] = expected[i+2] = 0;
|
|
|
|
|
expected[i+3] = 0xff;
|
|
|
|
@ -288,7 +288,7 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.fillRect(0, 0, 2, 2, [0xff, 0, 0]);
|
|
|
|
|
display.fillRect(2, 2, 2, 2, [0xff, 0, 0]);
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should support copying an portion of the canvas via #copyImage', function () {
|
|
|
|
@ -296,14 +296,14 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.fillRect(0, 0, 2, 2, [0xff, 0, 0x00]);
|
|
|
|
|
display.copyImage(0, 0, 2, 2, 2, 2);
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should support drawing images via #imageRect', function (done) {
|
|
|
|
|
display.imageRect(0, 0, 4, 4, "image/png", make_image_png(checked_data));
|
|
|
|
|
display.imageRect(0, 0, 4, 4, "image/png", makeImagePng(checkedData));
|
|
|
|
|
display.flip();
|
|
|
|
|
display.onflush = () => {
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
done();
|
|
|
|
|
};
|
|
|
|
|
display.flush();
|
|
|
|
@ -315,12 +315,12 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.subTile(2, 2, 2, 2, [0xff, 0, 0]);
|
|
|
|
|
display.finishTile();
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// We have a special cache for 16x16 tiles that we need to test
|
|
|
|
|
it('should support drawing a 16x16 tile', function () {
|
|
|
|
|
const large_checked_data = new Uint8Array(16*16*4);
|
|
|
|
|
const largeCheckedData = new Uint8Array(16*16*4);
|
|
|
|
|
display.resize(16, 16);
|
|
|
|
|
|
|
|
|
|
for (let y = 0;y < 16;y++) {
|
|
|
|
@ -328,11 +328,11 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
let pixel;
|
|
|
|
|
if ((x < 4) && (y < 4)) {
|
|
|
|
|
// NB: of course IE11 doesn't support #slice on ArrayBufferViews...
|
|
|
|
|
pixel = Array.prototype.slice.call(checked_data, (y*4+x)*4, (y*4+x+1)*4);
|
|
|
|
|
pixel = Array.prototype.slice.call(checkedData, (y*4+x)*4, (y*4+x+1)*4);
|
|
|
|
|
} else {
|
|
|
|
|
pixel = [0, 0xff, 0, 255];
|
|
|
|
|
}
|
|
|
|
|
large_checked_data.set(pixel, (y*16+x)*4);
|
|
|
|
|
largeCheckedData.set(pixel, (y*16+x)*4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -341,39 +341,39 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.subTile(2, 2, 2, 2, [0xff, 0, 0]);
|
|
|
|
|
display.finishTile();
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(large_checked_data);
|
|
|
|
|
expect(display).to.have.displayed(largeCheckedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should support drawing BGRX blit images with true color via #blitImage', function () {
|
|
|
|
|
const data = [];
|
|
|
|
|
for (let i = 0; i < 16; i++) {
|
|
|
|
|
data[i * 4] = checked_data[i * 4 + 2];
|
|
|
|
|
data[i * 4 + 1] = checked_data[i * 4 + 1];
|
|
|
|
|
data[i * 4 + 2] = checked_data[i * 4];
|
|
|
|
|
data[i * 4 + 3] = checked_data[i * 4 + 3];
|
|
|
|
|
data[i * 4] = checkedData[i * 4 + 2];
|
|
|
|
|
data[i * 4 + 1] = checkedData[i * 4 + 1];
|
|
|
|
|
data[i * 4 + 2] = checkedData[i * 4];
|
|
|
|
|
data[i * 4 + 3] = checkedData[i * 4 + 3];
|
|
|
|
|
}
|
|
|
|
|
display.blitImage(0, 0, 4, 4, data, 0);
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should support drawing RGB blit images with true color via #blitRgbImage', function () {
|
|
|
|
|
const data = [];
|
|
|
|
|
for (let i = 0; i < 16; i++) {
|
|
|
|
|
data[i * 3] = checked_data[i * 4];
|
|
|
|
|
data[i * 3 + 1] = checked_data[i * 4 + 1];
|
|
|
|
|
data[i * 3 + 2] = checked_data[i * 4 + 2];
|
|
|
|
|
data[i * 3] = checkedData[i * 4];
|
|
|
|
|
data[i * 3 + 1] = checkedData[i * 4 + 1];
|
|
|
|
|
data[i * 3 + 2] = checkedData[i * 4 + 2];
|
|
|
|
|
}
|
|
|
|
|
display.blitRgbImage(0, 0, 4, 4, data, 0);
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should support drawing an image object via #drawImage', function () {
|
|
|
|
|
const img = make_image_canvas(checked_data);
|
|
|
|
|
const img = makeImageCanvas(checkedData);
|
|
|
|
|
display.drawImage(img, 0, 0);
|
|
|
|
|
display.flip();
|
|
|
|
|
expect(display).to.have.displayed(checked_data);
|
|
|
|
|
expect(display).to.have.displayed(checkedData);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -382,18 +382,18 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
beforeEach(function () {
|
|
|
|
|
display = new Display(document.createElement('canvas'));
|
|
|
|
|
display.resize(4, 4);
|
|
|
|
|
sinon.spy(display, '_scan_renderQ');
|
|
|
|
|
sinon.spy(display, '_scanRenderQ');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should try to process an item when it is pushed on, if nothing else is on the queue', function () {
|
|
|
|
|
display._renderQ_push({ type: 'noop' }); // does nothing
|
|
|
|
|
expect(display._scan_renderQ).to.have.been.calledOnce;
|
|
|
|
|
display._renderQPush({ type: 'noop' }); // does nothing
|
|
|
|
|
expect(display._scanRenderQ).to.have.been.calledOnce;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should not try to process an item when it is pushed on if we are waiting for other items', function () {
|
|
|
|
|
display._renderQ.length = 2;
|
|
|
|
|
display._renderQ_push({ type: 'noop' });
|
|
|
|
|
expect(display._scan_renderQ).to.not.have.been.called;
|
|
|
|
|
display._renderQPush({ type: 'noop' });
|
|
|
|
|
expect(display._scanRenderQ).to.not.have.been.called;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should wait until an image is loaded to attempt to draw it and the rest of the queue', function () {
|
|
|
|
@ -403,13 +403,13 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.drawImage = sinon.spy();
|
|
|
|
|
display.fillRect = sinon.spy();
|
|
|
|
|
|
|
|
|
|
display._scan_renderQ();
|
|
|
|
|
display._scanRenderQ();
|
|
|
|
|
expect(display.drawImage).to.not.have.been.called;
|
|
|
|
|
expect(display.fillRect).to.not.have.been.called;
|
|
|
|
|
expect(img.addEventListener).to.have.been.calledOnce;
|
|
|
|
|
|
|
|
|
|
display._renderQ[0].img.complete = true;
|
|
|
|
|
display._scan_renderQ();
|
|
|
|
|
display._scanRenderQ();
|
|
|
|
|
expect(display.drawImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.fillRect).to.have.been.calledOnce;
|
|
|
|
|
expect(img.addEventListener).to.have.been.calledOnce;
|
|
|
|
@ -422,7 +422,7 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display.drawImage = sinon.spy();
|
|
|
|
|
display.fillRect = sinon.spy();
|
|
|
|
|
|
|
|
|
|
display._scan_renderQ();
|
|
|
|
|
display._scanRenderQ();
|
|
|
|
|
expect(display.drawImage).to.not.have.been.called;
|
|
|
|
|
expect(display.fillRect).to.not.have.been.called;
|
|
|
|
|
expect(img.addEventListener).to.have.been.calledOnce;
|
|
|
|
@ -430,7 +430,7 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
display._renderQ[0].img.complete = true;
|
|
|
|
|
display._renderQ[0].img.width = 4;
|
|
|
|
|
display._renderQ[0].img.height = 4;
|
|
|
|
|
display._scan_renderQ();
|
|
|
|
|
display._scanRenderQ();
|
|
|
|
|
expect(display.drawImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.fillRect).to.have.been.calledOnce;
|
|
|
|
|
expect(img.addEventListener).to.have.been.calledOnce;
|
|
|
|
@ -446,35 +446,35 @@ describe('Display/Canvas Helper', function () {
|
|
|
|
|
|
|
|
|
|
it('should draw a blit image on type "blit"', function () {
|
|
|
|
|
display.blitImage = sinon.spy();
|
|
|
|
|
display._renderQ_push({ type: 'blit', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] });
|
|
|
|
|
display._renderQPush({ type: 'blit', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] });
|
|
|
|
|
expect(display.blitImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.blitImage).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9], 0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should draw a blit RGB image on type "blitRgb"', function () {
|
|
|
|
|
display.blitRgbImage = sinon.spy();
|
|
|
|
|
display._renderQ_push({ type: 'blitRgb', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] });
|
|
|
|
|
display._renderQPush({ type: 'blitRgb', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] });
|
|
|
|
|
expect(display.blitRgbImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.blitRgbImage).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9], 0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should copy a region on type "copy"', function () {
|
|
|
|
|
display.copyImage = sinon.spy();
|
|
|
|
|
display._renderQ_push({ type: 'copy', x: 3, y: 4, width: 5, height: 6, old_x: 7, old_y: 8 });
|
|
|
|
|
display._renderQPush({ type: 'copy', x: 3, y: 4, width: 5, height: 6, oldX: 7, oldY: 8 });
|
|
|
|
|
expect(display.copyImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.copyImage).to.have.been.calledWith(7, 8, 3, 4, 5, 6);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should fill a rect with a given color on type "fill"', function () {
|
|
|
|
|
display.fillRect = sinon.spy();
|
|
|
|
|
display._renderQ_push({ type: 'fill', x: 3, y: 4, width: 5, height: 6, color: [7, 8, 9]});
|
|
|
|
|
display._renderQPush({ type: 'fill', x: 3, y: 4, width: 5, height: 6, color: [7, 8, 9]});
|
|
|
|
|
expect(display.fillRect).to.have.been.calledOnce;
|
|
|
|
|
expect(display.fillRect).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should draw an image from an image object on type "img" (if complete)', function () {
|
|
|
|
|
display.drawImage = sinon.spy();
|
|
|
|
|
display._renderQ_push({ type: 'img', x: 3, y: 4, img: { complete: true } });
|
|
|
|
|
display._renderQPush({ type: 'img', x: 3, y: 4, img: { complete: true } });
|
|
|
|
|
expect(display.drawImage).to.have.been.calledOnce;
|
|
|
|
|
expect(display.drawImage).to.have.been.calledWith({ complete: true }, 3, 4);
|
|
|
|
|
});
|
|
|
|
|