idraw/packages/util/__tests__/lib/context.test.ts

624 lines
22 KiB
TypeScript

import Context from './../../src/lib/context';
import { deepClone } from './../../src/index'
import { getData } from './data';
describe('@idraw/board: src/lib/context', () => {
const options = {
width: 600,
height: 400,
contextWidth: 1000,
contextHeight: 900,
devicePixelRatio: 2
}
test('Context', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const data = getData();
ctx.clearRect(0, 0, opts.contextWidth, opts.contextHeight);
ctx.setFillStyle('#ffffff');
ctx.fillRect(0, 0, opts.contextWidth, opts.contextHeight);
data.elements.forEach(ele => {
ctx.setFillStyle(ele.desc.color);
ctx.fillRect(ele.x, ele.y, ele.w, ele.h);
});
// @ts-ignore;
const calls = ctx2d.__getDrawCalls();
expect(calls).toMatchSnapshot();
});
test('Context.getSize', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
expect(ctx.getSize()).toStrictEqual(opts);
})
test('Context.resetSize', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const newOpts = {
width: 601,
height: 401,
contextWidth: 1001,
contextHeight: 901,
devicePixelRatio: 3,
}
const ctx = new Context(ctx2d, opts);
ctx.resetSize(newOpts);
expect(ctx.getSize()).toStrictEqual(newOpts);
});
test('Context.calcDeviceNum', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const num = 100;
expect(ctx.calcDeviceNum(num)).toStrictEqual(opts.devicePixelRatio * num);
});
test('Context.calcScreenNum', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const num = 100;
expect(ctx.calcScreenNum(num)).toStrictEqual(num / opts.devicePixelRatio);
});
test('Context.setTransform', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const transform = {
scale: 2,
scrollX: 100,
scrollY: -200,
};
ctx.setTransform(deepClone(transform))
expect(ctx.getTransform()).toStrictEqual(deepClone(transform));
});
test('Context.getTransform', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
expect(ctx.getTransform()).toStrictEqual({
scale: 1,
scrollX: 0,
scrollY: 0,
});
});
test('Context.setFillStyle', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const color = '#f0f0f0';
ctx.setFillStyle(color);
ctx.fillRect(0, 0, opts.contextWidth, opts.contextHeight);
expect(ctx2d.fillStyle).toStrictEqual(color);
});
test('Context.fill', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
expect(calls).toMatchSnapshot();
});
test('Context.arc', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.arc(70, 80, 50, 0, Math.PI * 2, true);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.rect', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.rect(10, 20, 100, 200);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.fillRect', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.fillRect(10, 20, 80, 100);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
// expect(calls).toStrictEqual([
// {
// type: 'fillRect',
// transform: [ 1, 0, 0, 1, 0, 0 ],
// props: { x: 0, y: 0, width: 2000, height: 1800 }
// }
// ]);
});
test('Context.clearRect', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.clearRect(0, 0, opts.contextWidth, opts.contextHeight);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.beginPath', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.beginPath();
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.closePath', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.closePath();
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.lineTo', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.lineTo(10, 20);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.moveTo', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.moveTo(10, 20);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.arcTo', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.arcTo(50, 50, 100, 100, Math.PI * 2);
ctx.fill();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.setLineWidth', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const lineWidth = 12;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.setLineWidth(lineWidth);
expect(ctx2d.lineWidth).toStrictEqual(lineWidth * opts.devicePixelRatio);
});
test('Context.setLineDash', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const lineDash = [10, 20];
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.setLineDash(lineDash);
// @ts-ignore
// const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
// expect(calls).toMatchSnapshot();
expect(ctx2d.getLineDash()).toStrictEqual(lineDash.map(n => n * opts.devicePixelRatio));
});
test('Context.setStrokeStyle', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const color = '#f0f0f0';
ctx.setStrokeStyle(color);
ctx.fillRect(0, 0, opts.contextWidth, opts.contextHeight);
expect(ctx2d.strokeStyle).toStrictEqual(color);
});
// TODO
test('Context.isPointInPath', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
// const lineDash = [10, 20];
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const x = 50;
const y = 50;
const w = 50;
const h = 50;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + w, y);
ctx.lineTo(x + w, y + h);
ctx.lineTo(x, y + h);
ctx.lineTo(x, y);
ctx.closePath();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
expect(ctx.isPointInPath(51, 51))
.toStrictEqual(ctx2d.isPointInPath(60 * opts.devicePixelRatio, 60 * opts.devicePixelRatio));
});
// TODO
test('Context.isPointInPathWithoutScroll', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
// const lineDash = [10, 20];
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.setTransform({
scale: 2,
scrollX: 10,
scrollY: 10,
})
ctx.beginPath();
ctx.rect(50, 50, 100, 100);
ctx.closePath();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
expect(ctx.isPointInPathWithoutScroll(51, 51))
.toStrictEqual(
ctx2d.isPointInPath(
60 * opts.devicePixelRatio,
60 * opts.devicePixelRatio
)
);
});
test('Context.setStrokeStyle', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const color = '#f0f0f0';
ctx.setStrokeStyle(color);
expect(ctx2d.strokeStyle).toStrictEqual(color);
});
test('Context.stroke', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.rect(10, 20, 100, 200);
ctx.stroke();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.translate', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const x = 50;
const y = 60;
ctx.translate(x, y);
ctx.rect(10, 20, 100, 200);
ctx.stroke();
ctx.translate(-x, -y);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
expect(calls).toMatchSnapshot();
});
test('Context.rotate', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const radian = Math.PI / 6;
ctx.rotate(radian);
ctx.rect(10, 20, 100, 200);
ctx.stroke();
ctx.rotate(-radian);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.drawImage', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const img = new Image();
const dx = 11;
const dy = 12;
const dw = 51;
const dh = 52;
const sx = 61;
const sy = 62;
const sw = 101
const sh = 102;
ctx.drawImage(img, dx, dy);
ctx.drawImage(img, dx, dy, dw, dh);
ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.createPattern', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const img = new Image();
const pattern = ctx.createPattern(img, 'repeat') as CanvasPattern;
ctx.setFillStyle(pattern);
ctx.fillRect(0, 0, 300, 300);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(ctx2d.fillStyle).toStrictEqual(pattern);
expect(calls).toMatchSnapshot();
});
test('Context.measureText', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.setFont({ fontSize: 20 });
const size = ctx.measureText('Hello World!');
expect(size.width).toStrictEqual(12);
});
test('Context.setTextAlign', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const textAlign = 'center';
ctx.setTextAlign(textAlign);
ctx.fillRect(0, 0, opts.contextWidth, opts.contextHeight);
expect(ctx2d.textAlign).toStrictEqual(textAlign);
});
test('Context.fillText', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.fillText('Hello world', 50, 100);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.setFont', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const fontSize = 22;
const fontFamily = 'Hello';
const fontWeight = 'bold';
ctx.setFont({
fontSize, fontFamily, fontWeight
});
// console.log('ctx2d.font =', ctx2d.font);
expect(ctx2d.font).toStrictEqual([fontWeight, (fontSize * opts.devicePixelRatio) + 'px', fontFamily].join(' '))
});
test('Context.setTextBaseline', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const textBaseline = 'bottom';
ctx.setTextBaseline(textBaseline);
expect(ctx2d.textBaseline).toStrictEqual(textBaseline)
});
test('Context.setGlobalAlpha', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const globalAlpha = 0.45;
ctx.setGlobalAlpha(globalAlpha);
expect(ctx2d.globalAlpha).toStrictEqual(globalAlpha)
});
test('Context.save', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.save();
ctx.setFillStyle('#f0f0f0');
ctx.fillRect(10, 10, 100, 100);
ctx.restore();
ctx.fillRect(150, 75, 100, 100);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.restore', async () => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
ctx.save();
ctx.setFillStyle('#f0f0f0');
ctx.fillRect(10, 10, 100, 100);
ctx.restore();
ctx.fillRect(150, 75, 100, 100);
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
test('Context.scale', async() => {
const opts = deepClone(options);
const canvas = document.createElement('canvas');
canvas.width = opts.contextWidth;
canvas.height = opts.contextHeight;
const ctx2d: CanvasRenderingContext2D = canvas.getContext('2d') as CanvasRenderingContext2D;
const ctx = new Context(ctx2d, opts);
const scaleX = 2;
const scaleY = 3;
ctx.scale(scaleX, scaleY);
ctx.rect(10, 20, 100, 200);
ctx.stroke();
// @ts-ignore
const calls = ctx2d.__getDrawCalls();
// console.log('calls =', JSON.stringify(calls, null, 2));
expect(calls).toMatchSnapshot();
});
})