| // The increased timeout is especially needed with larger binaries |
| // like in the debug/gpu build |
| jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; |
| |
| describe('CanvasKit\'s Path Behavior', function() { |
| // Note, don't try to print the CanvasKit object - it can cause Karma/Jasmine to lock up. |
| var CanvasKit = null; |
| const LoadCanvasKit = new Promise(function(resolve, reject) { |
| if (CanvasKit) { |
| resolve(); |
| } else { |
| CanvasKitInit({ |
| locateFile: (file) => '/canvaskit/'+file, |
| }).ready().then((_CanvasKit) => { |
| CanvasKit = _CanvasKit; |
| resolve(); |
| }); |
| } |
| }); |
| |
| let container = document.createElement('div'); |
| document.body.appendChild(container); |
| const CANVAS_WIDTH = 600; |
| const CANVAS_HEIGHT = 600; |
| |
| beforeEach(function() { |
| container.innerHTML = ` |
| <canvas width=600 height=600 id=test></canvas> |
| <canvas width=600 height=600 id=report></canvas>`; |
| }); |
| |
| afterEach(function() { |
| container.innerHTML = ''; |
| }); |
| |
| function reportSurface(surface, testname, done) { |
| // In docker, the webgl canvas is blank, but the surface has the pixel |
| // data. So, we copy it out and draw it to a normal canvas to take a picture. |
| // To be consistent across CPU and GPU, we just do it for all configurations |
| // (even though the CPU canvas shows up after flush just fine). |
| let pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); |
| pixels = new Uint8ClampedArray(pixels.buffer); |
| var imageData = new ImageData(pixels, CANVAS_WIDTH, CANVAS_HEIGHT); |
| |
| let reportingCanvas = document.getElementById('report'); |
| reportingCanvas.getContext('2d').putImageData(imageData, 0, 0); |
| reportCanvas(reportingCanvas, testname).then(() => { |
| done(); |
| }).catch(reportError(done)); |
| } |
| |
| it('can draw a path', function(done) { |
| LoadCanvasKit.then(catchException(done, () => { |
| // This is taken from example.html |
| const surface = CanvasKit.MakeCanvasSurface('test'); |
| expect(surface).toBeTruthy('Could not make surface') |
| if (!surface) { |
| done(); |
| return; |
| } |
| const canvas = surface.getCanvas(); |
| const paint = new CanvasKit.SkPaint(); |
| paint.setStrokeWidth(1.0); |
| paint.setAntiAlias(true); |
| paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); |
| paint.setStyle(CanvasKit.PaintStyle.Stroke); |
| |
| const path = new CanvasKit.SkPath(); |
| 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.cubicTo(90, 10, 160, 150, 190, 10); |
| |
| path.moveTo(36, 148); |
| path.quadTo(66, 188, 120, 136); |
| path.lineTo(36, 148); |
| |
| path.moveTo(150, 180); |
| path.arcTo(150, 100, 50, 200, 20); |
| path.lineTo(160, 160); |
| |
| path.moveTo(20, 120); |
| path.lineTo(20, 120); |
| |
| path.transform([2, 0, 0, |
| 0, 2, 0, |
| 0, 0, 1 ]) |
| |
| canvas.drawPath(path, paint); |
| |
| let rrect = new CanvasKit.SkPath() |
| .addRoundRect(100, 10, 140, 62, |
| 10, 4, true); |
| |
| canvas.drawPath(rrect, paint); |
| rrect.delete(); |
| |
| surface.flush(); |
| |
| path.delete(); |
| paint.delete(); |
| |
| reportSurface(surface, 'path_api_example', done); |
| })); |
| // See PathKit for more tests, since they share implementation |
| }); |
| |
| it('can draw directly to a canvas', function(done) { |
| LoadCanvasKit.then(catchException(done, () => { |
| // This is taken from example.html |
| const surface = CanvasKit.MakeCanvasSurface('test'); |
| expect(surface).toBeTruthy('Could not make surface') |
| if (!surface) { |
| done(); |
| return; |
| } |
| const canvas = surface.getCanvas(); |
| const paint = new CanvasKit.SkPaint(); |
| paint.setStrokeWidth(2.0); |
| paint.setAntiAlias(true); |
| paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); |
| paint.setStyle(CanvasKit.PaintStyle.Stroke); |
| |
| canvas.drawLine(3, 10, 30, 15, paint); |
| canvas.drawRoundRect(CanvasKit.LTRBRect(5, 35, 45, 80), 15, 10, paint); |
| |
| canvas.drawOval(CanvasKit.LTRBRect(5, 35, 45, 80), paint); |
| |
| canvas.drawArc(CanvasKit.LTRBRect(55, 35, 95, 80), 15, 270, true, paint); |
| |
| const font = new CanvasKit.SkFont(null, 20); |
| canvas.drawText('this is ascii text', 5, 100, font, paint); |
| |
| const blob = CanvasKit.SkTextBlob.MakeFromText('Unicode chars 💩 é É ص', font); |
| canvas.drawTextBlob(blob, 5, 130, paint); |
| |
| surface.flush(); |
| font.delete(); |
| blob.delete(); |
| paint.delete(); |
| |
| reportSurface(surface, 'canvas_api_example', done); |
| })); |
| // See canvas2d for more API tests |
| }); |
| |
| function starPath(CanvasKit, X=128, Y=128, R=116) { |
| let p = new CanvasKit.SkPath(); |
| p.moveTo(X + R, Y); |
| for (let i = 1; i < 8; i++) { |
| let a = 2.6927937 * i; |
| p.lineTo(X + R * Math.cos(a), Y + R * Math.sin(a)); |
| } |
| return p; |
| } |
| |
| it('can apply an effect and draw text', function(done) { |
| LoadCanvasKit.then(catchException(done, () => { |
| const surface = CanvasKit.MakeCanvasSurface('test'); |
| expect(surface).toBeTruthy('Could not make surface') |
| if (!surface) { |
| done(); |
| return; |
| } |
| const canvas = surface.getCanvas(); |
| const path = starPath(CanvasKit); |
| |
| const paint = new CanvasKit.SkPaint(); |
| |
| const textPaint = new CanvasKit.SkPaint(); |
| textPaint.setColor(CanvasKit.Color(40, 0, 0, 1.0)); |
| textPaint.setAntiAlias(true); |
| |
| const textFont = new CanvasKit.SkFont(null, 30); |
| |
| const dpe = CanvasKit.MakeSkDashPathEffect([15, 5, 5, 10], 1); |
| |
| paint.setPathEffect(dpe); |
| paint.setStyle(CanvasKit.PaintStyle.Stroke); |
| paint.setStrokeWidth(5.0); |
| paint.setAntiAlias(true); |
| paint.setColor(CanvasKit.Color(66, 129, 164, 1.0)); |
| |
| canvas.clear(CanvasKit.Color(255, 255, 255, 1.0)); |
| |
| canvas.drawPath(path, paint); |
| canvas.drawText('This is text', 10, 280, textFont, textPaint); |
| surface.flush(); |
| dpe.delete(); |
| path.delete(); |
| |
| reportSurface(surface, 'effect_and_text_example', done); |
| })); |
| }); |
| |
| it('can create a path from an SVG string', function(done) { |
| LoadCanvasKit.then(catchException(done, () => { |
| //.This is a parallelagram from |
| // https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg |
| let path = CanvasKit.MakePathFromSVGString('M 205,5 L 795,5 L 595,295 L 5,295 L 205,5 z'); |
| |
| let cmds = path.toCmds(); |
| expect(cmds).toBeTruthy(); |
| // 1 move, 4 lines, 1 close |
| // each element in cmds is an array, with index 0 being the verb, and the rest being args |
| expect(cmds.length).toBe(6); |
| expect(cmds).toEqual([[CanvasKit.MOVE_VERB, 205, 5], |
| [CanvasKit.LINE_VERB, 795, 5], |
| [CanvasKit.LINE_VERB, 595, 295], |
| [CanvasKit.LINE_VERB, 5, 295], |
| [CanvasKit.LINE_VERB, 205, 5], |
| [CanvasKit.CLOSE_VERB]]); |
| path.delete(); |
| done(); |
| })); |
| }); |
| |
| it('can create an SVG string from a path', function(done) { |
| LoadCanvasKit.then(catchException(done, () => { |
| let cmds = [[CanvasKit.MOVE_VERB, 205, 5], |
| [CanvasKit.LINE_VERB, 795, 5], |
| [CanvasKit.LINE_VERB, 595, 295], |
| [CanvasKit.LINE_VERB, 5, 295], |
| [CanvasKit.LINE_VERB, 205, 5], |
| [CanvasKit.CLOSE_VERB]]; |
| let path = CanvasKit.MakePathFromCmds(cmds); |
| |
| let svgStr = path.toSVGString(); |
| // We output it in terse form, which is different than Wikipedia's version |
| expect(svgStr).toEqual('M205 5L795 5L595 295L5 295L205 5Z'); |
| path.delete(); |
| done(); |
| })); |
| }); |
| }); |