1 // The increased timeout is especially needed with larger binaries 2 // like in the debug/gpu build 3 jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; 4 5 describe('CanvasKit\'s Path Behavior', function() { 6 // Note, don't try to print the CanvasKit object - it can cause Karma/Jasmine to lock up. 7 var CanvasKit = null; 8 const LoadCanvasKit = new Promise(function(resolve, reject) { 9 if (CanvasKit) { 10 resolve(); 11 } else { 12 CanvasKitInit({ 13 locateFile: (file) => '/canvaskit/'+file, 14 }).ready().then((_CanvasKit) => { 15 CanvasKit = _CanvasKit; 16 resolve(); 17 }); 18 } 19 }); 20 21 let container = document.createElement('div'); 22 document.body.appendChild(container); 23 const CANVAS_WIDTH = 600; 24 const CANVAS_HEIGHT = 600; 25 26 beforeEach(function() { 27 container.innerHTML = ` 28 <canvas width=600 height=600 id=test></canvas> 29 <canvas width=600 height=600 id=report></canvas>`; 30 }); 31 32 afterEach(function() { 33 container.innerHTML = ''; 34 }); 35 36 function reportSurface(surface, testname, done) { 37 // In docker, the webgl canvas is blank, but the surface has the pixel 38 // data. So, we copy it out and draw it to a normal canvas to take a picture. 39 // To be consistent across CPU and GPU, we just do it for all configurations 40 // (even though the CPU canvas shows up after flush just fine). 41 let pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); 42 pixels = new Uint8ClampedArray(pixels.buffer); 43 var imageData = new ImageData(pixels, CANVAS_WIDTH, CANVAS_HEIGHT); 44 45 let reportingCanvas = document.getElementById('report'); 46 reportingCanvas.getContext('2d').putImageData(imageData, 0, 0); 47 reportCanvas(reportingCanvas, testname).then(() => { 48 done(); 49 }).catch(reportError(done)); 50 } 51 52 it('can draw a path', function(done) { 53 LoadCanvasKit.then(catchException(done, () => { 54 // This is taken from example.html 55 const surface = CanvasKit.MakeCanvasSurface('test'); 56 expect(surface).toBeTruthy('Could not make surface') 57 if (!surface) { 58 done(); 59 return; 60 } 61 const canvas = surface.getCanvas(); 62 const paint = new CanvasKit.SkPaint(); 63 paint.setStrokeWidth(1.0); 64 paint.setAntiAlias(true); 65 paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 66 paint.setStyle(CanvasKit.PaintStyle.Stroke); 67 68 const path = new CanvasKit.SkPath(); 69 path.moveTo(20, 5); 70 path.lineTo(30, 20); 71 path.lineTo(40, 10); 72 path.lineTo(50, 20); 73 path.lineTo(60, 0); 74 path.lineTo(20, 5); 75 76 path.moveTo(20, 80); 77 path.cubicTo(90, 10, 160, 150, 190, 10); 78 79 path.moveTo(36, 148); 80 path.quadTo(66, 188, 120, 136); 81 path.lineTo(36, 148); 82 83 path.moveTo(150, 180); 84 path.arcTo(150, 100, 50, 200, 20); 85 path.lineTo(160, 160); 86 87 path.moveTo(20, 120); 88 path.lineTo(20, 120); 89 90 path.transform([2, 0, 0, 91 0, 2, 0, 92 0, 0, 1 ]) 93 94 canvas.drawPath(path, paint); 95 96 let rrect = new CanvasKit.SkPath() 97 .addRoundRect(100, 10, 140, 62, 98 10, 4, true); 99 100 canvas.drawPath(rrect, paint); 101 rrect.delete(); 102 103 surface.flush(); 104 105 path.delete(); 106 paint.delete(); 107 108 reportSurface(surface, 'path_api_example', done); 109 })); 110 // See PathKit for more tests, since they share implementation 111 }); 112 113 it('can draw directly to a canvas', function(done) { 114 LoadCanvasKit.then(catchException(done, () => { 115 // This is taken from example.html 116 const surface = CanvasKit.MakeCanvasSurface('test'); 117 expect(surface).toBeTruthy('Could not make surface') 118 if (!surface) { 119 done(); 120 return; 121 } 122 const canvas = surface.getCanvas(); 123 const paint = new CanvasKit.SkPaint(); 124 paint.setStrokeWidth(2.0); 125 paint.setAntiAlias(true); 126 paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 127 paint.setStyle(CanvasKit.PaintStyle.Stroke); 128 129 canvas.drawLine(3, 10, 30, 15, paint); 130 canvas.drawRoundRect(CanvasKit.LTRBRect(5, 35, 45, 80), 15, 10, paint); 131 132 canvas.drawOval(CanvasKit.LTRBRect(5, 35, 45, 80), paint); 133 134 canvas.drawArc(CanvasKit.LTRBRect(55, 35, 95, 80), 15, 270, true, paint); 135 136 const font = new CanvasKit.SkFont(null, 20); 137 canvas.drawText('this is ascii text', 5, 100, font, paint); 138 139 const blob = CanvasKit.SkTextBlob.MakeFromText('Unicode chars ', font); 140 canvas.drawTextBlob(blob, 5, 130, paint); 141 142 surface.flush(); 143 font.delete(); 144 blob.delete(); 145 paint.delete(); 146 147 reportSurface(surface, 'canvas_api_example', done); 148 })); 149 // See canvas2d for more API tests 150 }); 151 152 function starPath(CanvasKit, X=128, Y=128, R=116) { 153 let p = new CanvasKit.SkPath(); 154 p.moveTo(X + R, Y); 155 for (let i = 1; i < 8; i++) { 156 let a = 2.6927937 * i; 157 p.lineTo(X + R * Math.cos(a), Y + R * Math.sin(a)); 158 } 159 return p; 160 } 161 162 it('can apply an effect and draw text', function(done) { 163 LoadCanvasKit.then(catchException(done, () => { 164 const surface = CanvasKit.MakeCanvasSurface('test'); 165 expect(surface).toBeTruthy('Could not make surface') 166 if (!surface) { 167 done(); 168 return; 169 } 170 const canvas = surface.getCanvas(); 171 const path = starPath(CanvasKit); 172 173 const paint = new CanvasKit.SkPaint(); 174 175 const textPaint = new CanvasKit.SkPaint(); 176 textPaint.setColor(CanvasKit.Color(40, 0, 0, 1.0)); 177 textPaint.setAntiAlias(true); 178 179 const textFont = new CanvasKit.SkFont(null, 30); 180 181 const dpe = CanvasKit.MakeSkDashPathEffect([15, 5, 5, 10], 1); 182 183 paint.setPathEffect(dpe); 184 paint.setStyle(CanvasKit.PaintStyle.Stroke); 185 paint.setStrokeWidth(5.0); 186 paint.setAntiAlias(true); 187 paint.setColor(CanvasKit.Color(66, 129, 164, 1.0)); 188 189 canvas.clear(CanvasKit.Color(255, 255, 255, 1.0)); 190 191 canvas.drawPath(path, paint); 192 canvas.drawText('This is text', 10, 280, textFont, textPaint); 193 surface.flush(); 194 dpe.delete(); 195 path.delete(); 196 197 reportSurface(surface, 'effect_and_text_example', done); 198 })); 199 }); 200 201 it('can create a path from an SVG string', function(done) { 202 LoadCanvasKit.then(catchException(done, () => { 203 //.This is a parallelagram from 204 // https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg 205 let path = CanvasKit.MakePathFromSVGString('M 205,5 L 795,5 L 595,295 L 5,295 L 205,5 z'); 206 207 let cmds = path.toCmds(); 208 expect(cmds).toBeTruthy(); 209 // 1 move, 4 lines, 1 close 210 // each element in cmds is an array, with index 0 being the verb, and the rest being args 211 expect(cmds.length).toBe(6); 212 expect(cmds).toEqual([[CanvasKit.MOVE_VERB, 205, 5], 213 [CanvasKit.LINE_VERB, 795, 5], 214 [CanvasKit.LINE_VERB, 595, 295], 215 [CanvasKit.LINE_VERB, 5, 295], 216 [CanvasKit.LINE_VERB, 205, 5], 217 [CanvasKit.CLOSE_VERB]]); 218 path.delete(); 219 done(); 220 })); 221 }); 222 223 it('can create an SVG string from a path', function(done) { 224 LoadCanvasKit.then(catchException(done, () => { 225 let cmds = [[CanvasKit.MOVE_VERB, 205, 5], 226 [CanvasKit.LINE_VERB, 795, 5], 227 [CanvasKit.LINE_VERB, 595, 295], 228 [CanvasKit.LINE_VERB, 5, 295], 229 [CanvasKit.LINE_VERB, 205, 5], 230 [CanvasKit.CLOSE_VERB]]; 231 let path = CanvasKit.MakePathFromCmds(cmds); 232 233 let svgStr = path.toSVGString(); 234 // We output it in terse form, which is different than Wikipedia's version 235 expect(svgStr).toEqual('M205 5L795 5L595 295L5 295L205 5Z'); 236 path.delete(); 237 done(); 238 })); 239 }); 240 }); 241