You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
7.0 KiB
194 lines
7.0 KiB
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
|
|
|
|
describe('PathKit\'s Path2D API', function() {
|
|
// Note, don't try to print the PathKit object - it can cause Karma/Jasmine to lock up.
|
|
var PathKit = null;
|
|
const LoadPathKit = new Promise(function(resolve, reject) {
|
|
if (PathKit) {
|
|
resolve();
|
|
} else {
|
|
PathKitInit({
|
|
locateFile: (file) => '/pathkit/'+file,
|
|
}).ready().then((_PathKit) => {
|
|
PathKit = _PathKit;
|
|
resolve();
|
|
});
|
|
}
|
|
});
|
|
|
|
it('can do everything in the Path2D API w/o crashing', function(done) {
|
|
LoadPathKit.then(catchException(done, () => {
|
|
// This is taken from example.html
|
|
let path = PathKit.NewPath();
|
|
|
|
path.moveTo(20, 5);
|
|
path.lineTo(30, 20);
|
|
path.lineTo(40, 10);
|
|
path.lineTo(50, 20);
|
|
path.lineTo(60, 0);
|
|
path.lineTo(20, 5);
|
|
|
|
path.moveTo(20, 80);
|
|
path.bezierCurveTo(90, 10, 160, 150, 190, 10);
|
|
|
|
path.moveTo(36, 148);
|
|
path.quadraticCurveTo(66, 188, 120, 136);
|
|
path.lineTo(36, 148);
|
|
|
|
path.rect(5, 170, 20, 20);
|
|
|
|
path.moveTo(150, 180);
|
|
path.arcTo(150, 100, 50, 200, 20);
|
|
path.lineTo(160, 160);
|
|
|
|
path.moveTo(20, 120);
|
|
path.arc(20, 120, 18, 0, 1.75 * Math.PI);
|
|
path.lineTo(20, 120);
|
|
|
|
let secondPath = PathKit.NewPath();
|
|
secondPath.ellipse(130, 25, 30, 10, -1*Math.PI/8, Math.PI/6, 1.5*Math.PI, false);
|
|
|
|
path.addPath(secondPath);
|
|
|
|
let m = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
|
|
m.a = 1; m.b = 0;
|
|
m.c = 0; m.d = 1;
|
|
m.e = 0; m.f = 20.5;
|
|
|
|
path.addPath(secondPath, m);
|
|
|
|
let canvas = document.createElement('canvas');
|
|
let canvasCtx = canvas.getContext('2d');
|
|
// Set canvas size and make it a bit bigger to zoom in on the lines
|
|
standardizedCanvasSize(canvasCtx);
|
|
canvasCtx.scale(3.0, 3.0);
|
|
canvasCtx.fillStyle = 'blue';
|
|
canvasCtx.stroke(path.toPath2D());
|
|
|
|
let svgPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
svgPath.setAttribute('stroke', 'black');
|
|
svgPath.setAttribute('fill', 'rgba(255,255,255,0.0)');
|
|
svgPath.setAttribute('transform', 'scale(3.0, 3.0)');
|
|
svgPath.setAttribute('d', path.toSVGString());
|
|
|
|
let newSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
newSVG.appendChild(svgPath);
|
|
newSVG.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
newSVG.setAttribute('width', 600);
|
|
newSVG.setAttribute('height', 600);
|
|
|
|
path.delete();
|
|
secondPath.delete();
|
|
|
|
reportCanvas(canvas, 'path2D_api_example').then(() => {
|
|
reportSVG(newSVG, 'path2D_api_example').then(() => {
|
|
done();
|
|
}).catch(reportError(done));
|
|
}).catch(reportError(done));
|
|
}));
|
|
});
|
|
|
|
it('can chain by returning the same object', function(done) {
|
|
LoadPathKit.then(catchException(done, () => {
|
|
let path = PathKit.NewPath();
|
|
|
|
let p1 = path.moveTo(20, 5)
|
|
.lineTo(30, 20)
|
|
.quadTo(66, 188, 120, 136)
|
|
.close();
|
|
|
|
// these should be the same object
|
|
expect(path === p1).toBe(true);
|
|
p1.delete();
|
|
try {
|
|
// This should throw an exception because
|
|
// the underlying path was already deleted.
|
|
path.delete();
|
|
expect('should not have gotten here').toBe(false);
|
|
} catch (e) {
|
|
// all is well
|
|
}
|
|
done();
|
|
}));
|
|
});
|
|
|
|
it('does not leak path objects when chaining', function(done) {
|
|
LoadPathKit.then(catchException(done, () => {
|
|
// By default, we have 16 MB of memory assigned to our PathKit
|
|
// library. This can be configured by -S TOTAL_MEMORY=NN
|
|
// and defaults to 16MB (we likely don't need to touch this).
|
|
// If there's a leak in here, we should OOM pretty quick.
|
|
// Testing showed around 50k is enough to see one if we leak a path,
|
|
// so run 250k times just to be safe.
|
|
for(let i = 0; i < 250000; i++) {
|
|
let path = PathKit.NewPath()
|
|
.moveTo(20, 5)
|
|
.lineTo(30, 20)
|
|
.quadTo(66, 188, 120, 136)
|
|
.close();
|
|
path.delete();
|
|
}
|
|
done();
|
|
}));
|
|
});
|
|
|
|
function drawTriangle() {
|
|
let path = PathKit.NewPath();
|
|
path.moveTo(0, 0);
|
|
path.lineTo(10, 0);
|
|
path.lineTo(10, 10);
|
|
path.close();
|
|
return path;
|
|
}
|
|
|
|
it('has multiple overloads of addPath', function(done) {
|
|
LoadPathKit.then(catchException(done, () => {
|
|
let basePath = PathKit.NewPath();
|
|
let otherPath = drawTriangle();
|
|
// These add path call can be chained.
|
|
// add it unchanged
|
|
basePath.addPath(otherPath)
|
|
// providing the 6 params of an SVG matrix to make it appear 20.5 px down
|
|
.addPath(otherPath, 1, 0, 0, 1, 0, 20.5)
|
|
// provide the full 9 matrix params to make it appear 30 px to the right
|
|
// and be 3 times as big.
|
|
.addPath(otherPath, 3, 0, 30,
|
|
0, 3, 0,
|
|
0, 0, 1);
|
|
|
|
reportPath(basePath, 'add_path_3x', done);
|
|
basePath.delete();
|
|
otherPath.delete();
|
|
}));
|
|
});
|
|
|
|
it('approximates arcs (conics) with quads', function(done) {
|
|
LoadPathKit.then(catchException(done, () => {
|
|
let path = PathKit.NewPath();
|
|
path.moveTo(50, 120);
|
|
path.arc(50, 120, 45, 0, 1.75 * Math.PI);
|
|
path.lineTo(50, 120);
|
|
|
|
let canvas = document.createElement('canvas');
|
|
let canvasCtx = canvas.getContext('2d');
|
|
standardizedCanvasSize(canvasCtx);
|
|
// The and.callThrough is important to make it actually
|
|
// draw the quadratics
|
|
spyOn(canvasCtx, 'quadraticCurveTo').and.callThrough();
|
|
|
|
canvasCtx.beginPath();
|
|
path.toCanvas(canvasCtx);
|
|
canvasCtx.stroke();
|
|
// No need to check the whole path, as that's more what the
|
|
// gold correctness tests are for (can account for changes we make
|
|
// to the approximation algorithms).
|
|
expect(canvasCtx.quadraticCurveTo).toHaveBeenCalled();
|
|
path.delete();
|
|
reportCanvas(canvas, 'conics_quads_approx').then(() => {
|
|
done();
|
|
}).catch(reportError(done));
|
|
}));
|
|
});
|
|
|
|
});
|