1describe('CanvasKit\'s Path Behavior', function() { 2 let container = document.createElement('div'); 3 document.body.appendChild(container); 4 const CANVAS_WIDTH = 600; 5 const CANVAS_HEIGHT = 600; 6 7 beforeEach(function() { 8 container.innerHTML = ` 9 <canvas width=600 height=600 id=test></canvas> 10 <canvas width=600 height=600 id=report></canvas>`; 11 }); 12 13 afterEach(function() { 14 container.innerHTML = ''; 15 }); 16 17 it('can draw a path', function(done) { 18 LoadCanvasKit.then(catchException(done, () => { 19 // This is taken from example.html 20 const surface = CanvasKit.MakeCanvasSurface('test'); 21 expect(surface).toBeTruthy('Could not make surface') 22 if (!surface) { 23 done(); 24 return; 25 } 26 const canvas = surface.getCanvas(); 27 const paint = new CanvasKit.SkPaint(); 28 paint.setStrokeWidth(1.0); 29 paint.setAntiAlias(true); 30 paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 31 paint.setStyle(CanvasKit.PaintStyle.Stroke); 32 33 const path = new CanvasKit.SkPath(); 34 path.moveTo(20, 5); 35 path.lineTo(30, 20); 36 path.lineTo(40, 10); 37 path.lineTo(50, 20); 38 path.lineTo(60, 0); 39 path.lineTo(20, 5); 40 41 path.moveTo(20, 80); 42 path.cubicTo(90, 10, 160, 150, 190, 10); 43 44 path.moveTo(36, 148); 45 path.quadTo(66, 188, 120, 136); 46 path.lineTo(36, 148); 47 48 path.moveTo(150, 180); 49 path.arcTo(150, 100, 50, 200, 20); 50 path.lineTo(160, 160); 51 52 path.moveTo(20, 120); 53 path.lineTo(20, 120); 54 55 path.transform([2, 0, 0, 56 0, 2, 0, 57 0, 0, 1 ]) 58 59 canvas.drawPath(path, paint); 60 61 let rrect = new CanvasKit.SkPath() 62 .addRoundRect(100, 10, 140, 62, 63 10, 4, true); 64 65 canvas.drawPath(rrect, paint); 66 rrect.delete(); 67 68 surface.flush(); 69 70 path.delete(); 71 paint.delete(); 72 73 reportSurface(surface, 'path_api_example', done); 74 })); 75 // See PathKit for more tests, since they share implementation 76 }); 77 78 it('can create a path from an SVG string', function(done) { 79 LoadCanvasKit.then(catchException(done, () => { 80 //.This is a parallelagram from 81 // https://upload.wikimedia.org/wikipedia/commons/e/e7/Simple_parallelogram.svg 82 let path = CanvasKit.MakePathFromSVGString('M 205,5 L 795,5 L 595,295 L 5,295 L 205,5 z'); 83 84 let cmds = path.toCmds(); 85 expect(cmds).toBeTruthy(); 86 // 1 move, 4 lines, 1 close 87 // each element in cmds is an array, with index 0 being the verb, and the rest being args 88 expect(cmds.length).toBe(6); 89 expect(cmds).toEqual([[CanvasKit.MOVE_VERB, 205, 5], 90 [CanvasKit.LINE_VERB, 795, 5], 91 [CanvasKit.LINE_VERB, 595, 295], 92 [CanvasKit.LINE_VERB, 5, 295], 93 [CanvasKit.LINE_VERB, 205, 5], 94 [CanvasKit.CLOSE_VERB]]); 95 path.delete(); 96 done(); 97 })); 98 }); 99 100 it('can create an SVG string from a path', function(done) { 101 LoadCanvasKit.then(catchException(done, () => { 102 let cmds = [[CanvasKit.MOVE_VERB, 205, 5], 103 [CanvasKit.LINE_VERB, 795, 5], 104 [CanvasKit.LINE_VERB, 595, 295], 105 [CanvasKit.LINE_VERB, 5, 295], 106 [CanvasKit.LINE_VERB, 205, 5], 107 [CanvasKit.CLOSE_VERB]]; 108 let path = CanvasKit.MakePathFromCmds(cmds); 109 110 let svgStr = path.toSVGString(); 111 // We output it in terse form, which is different than Wikipedia's version 112 expect(svgStr).toEqual('M205 5L795 5L595 295L5 295L205 5Z'); 113 path.delete(); 114 done(); 115 })); 116 }); 117 118 it('uses offset to transform the path with dx,dy', function(done) { 119 LoadCanvasKit.then(catchException(done, () => { 120 const surface = CanvasKit.MakeCanvasSurface('test'); 121 expect(surface).toBeTruthy('Could not make surface') 122 if (!surface) { 123 done(); 124 return; 125 } 126 const canvas = surface.getCanvas(); 127 const path = starPath(CanvasKit); 128 129 const paint = new CanvasKit.SkPaint(); 130 131 paint.setStyle(CanvasKit.PaintStyle.Stroke); 132 paint.setStrokeWidth(5.0); 133 paint.setAntiAlias(true); 134 paint.setColor(CanvasKit.BLACK); 135 136 canvas.clear(CanvasKit.WHITE); 137 138 canvas.drawPath(path, paint); 139 path.offset(80, 40); 140 canvas.drawPath(path, paint); 141 surface.flush(); 142 path.delete(); 143 paint.delete(); 144 145 reportSurface(surface, 'offset_path', done); 146 })); 147 }); 148 149 it('draws ovals', function(done) { 150 LoadCanvasKit.then(catchException(done, () => { 151 const surface = CanvasKit.MakeCanvasSurface('test'); 152 expect(surface).toBeTruthy('Could not make surface') 153 if (!surface) { 154 done(); 155 return; 156 } 157 const canvas = surface.getCanvas(); 158 const paint = new CanvasKit.SkPaint(); 159 160 paint.setStyle(CanvasKit.PaintStyle.Stroke); 161 paint.setStrokeWidth(5.0); 162 paint.setAntiAlias(true); 163 paint.setColor(CanvasKit.BLACK); 164 165 canvas.clear(CanvasKit.WHITE); 166 167 const path = new CanvasKit.SkPath(); 168 path.moveTo(5, 5); 169 path.lineTo(10, 120); 170 path.addOval(CanvasKit.LTRBRect(10, 20, 100, 200), false, 3); 171 path.lineTo(300, 300); 172 173 canvas.drawPath(path, paint); 174 surface.flush(); 175 path.delete(); 176 paint.delete(); 177 178 reportSurface(surface, 'oval_path', done); 179 })); 180 }); 181 182 it('draws arcTo in a multitude of ways', function(done) { 183 LoadCanvasKit.then(catchException(done, () => { 184 const surface = CanvasKit.MakeCanvasSurface('test'); 185 expect(surface).toBeTruthy('Could not make surface') 186 if (!surface) { 187 done(); 188 return; 189 } 190 const canvas = surface.getCanvas(); 191 const paint = new CanvasKit.SkPaint(); 192 193 paint.setStyle(CanvasKit.PaintStyle.Stroke); 194 paint.setStrokeWidth(5.0); 195 paint.setAntiAlias(true); 196 paint.setColor(CanvasKit.BLACK); 197 198 canvas.clear(CanvasKit.WHITE); 199 200 const path = new CanvasKit.SkPath(); 201 //path.moveTo(5, 5); 202 // takes 4, 5 or 7 args 203 // - 5 x1, y1, x2, y2, radius 204 path.arcTo(40, 0, 40, 40, 40); 205 // - 4 oval (as Rect), startAngle, sweepAngle, forceMoveTo 206 path.arcTo(CanvasKit.LTRBRect(90, 10, 120, 200), 30, 300, true); 207 // - 7 rx, ry, xAxisRotate, useSmallArc, isCCW, x, y 208 path.moveTo(5, 105); 209 path.arcTo(24, 24, 45, true, false, 82, 156); 210 211 canvas.drawPath(path, paint); 212 surface.flush(); 213 path.delete(); 214 paint.delete(); 215 216 reportSurface(surface, 'arcto_path', done); 217 })); 218 }); 219 220 it('can draw a path using relative functions', function(done) { 221 LoadCanvasKit.then(catchException(done, () => { 222 // This is taken from example.html 223 const surface = CanvasKit.MakeCanvasSurface('test'); 224 expect(surface).toBeTruthy('Could not make surface') 225 if (!surface) { 226 done(); 227 return; 228 } 229 const canvas = surface.getCanvas(); 230 const paint = new CanvasKit.SkPaint(); 231 paint.setStrokeWidth(1.0); 232 paint.setAntiAlias(true); 233 paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 234 paint.setStyle(CanvasKit.PaintStyle.Stroke); 235 236 const path = new CanvasKit.SkPath(); 237 path.rMoveTo(20, 5) 238 .rLineTo(10, 15) // 30, 20 239 .rLineTo(10, -5); // 40, 10 240 path.rLineTo(10, 10); // 50, 20 241 path.rLineTo(10, -20); // 60, 0 242 path.rLineTo(-40, 5); // 20, 5 243 244 path.moveTo(20, 80) 245 .rCubicTo(70, -70, 140, 70, 170, -70); // 90, 10, 160, 150, 190, 10 246 247 path.moveTo(36, 148) 248 .rQuadTo(30, 40, 84, -12) // 66, 188, 120, 136 249 .lineTo(36, 148); 250 251 path.moveTo(150, 180) 252 .rArcTo(24, 24, 45, true, false, -68, -24); // 82, 156 253 path.lineTo(160, 160); 254 255 canvas.drawPath(path, paint); 256 257 surface.flush(); 258 path.delete(); 259 paint.delete(); 260 261 reportSurface(surface, 'path_relative', done); 262 })); 263 }); 264 265 it('can measure a path', function(done) { 266 LoadCanvasKit.then(catchException(done, () => { 267 268 const path = new CanvasKit.SkPath(); 269 path.moveTo(10, 10) 270 .lineTo(40, 50); // should be length 50 because of the 3/4/5 triangle rule 271 272 path.moveTo(80, 0) 273 .lineTo(80, 10) 274 .lineTo(100, 5) 275 .lineTo(80, 0); 276 277 const meas = new CanvasKit.SkPathMeasure(path, false, 1); 278 expect(meas.getLength()).toBeCloseTo(50.0, 3); 279 const pt = meas.getPosTan(28.7); // arbitrary point 280 expect(pt[0]).toBeCloseTo(27.22, 3); // x 281 expect(pt[1]).toBeCloseTo(32.96, 3); // y 282 expect(pt[2]).toBeCloseTo(0.6, 3); // dy 283 expect(pt[3]).toBeCloseTo(0.8, 3); // dy 284 const subpath = meas.getSegment(20, 40, true); // make sure this doesn't crash 285 286 expect(meas.nextContour()).toBeTruthy(); 287 expect(meas.getLength()).toBeCloseTo(51.231, 3); 288 289 expect(meas.nextContour()).toBeFalsy(); 290 291 path.delete(); 292 done(); 293 })); 294 }); 295 296 it('can measure the contours of a path', function(done) { 297 LoadCanvasKit.then(catchException(done, () => { 298 299 const path = new CanvasKit.SkPath(); 300 path.moveTo(10, 10) 301 .lineTo(40, 50); // should be length 50 because of the 3/4/5 triangle rule 302 303 path.moveTo(80, 0) 304 .lineTo(80, 10) 305 .lineTo(100, 5) 306 .lineTo(80, 0); 307 308 const meas = new CanvasKit.SkContourMeasureIter(path, false, 1); 309 let cont = meas.next(); 310 expect(cont).toBeTruthy(); 311 312 expect(cont.length()).toBeCloseTo(50.0, 3); 313 const pt = cont.getPosTan(28.7); // arbitrary point 314 expect(pt[0]).toBeCloseTo(27.22, 3); // x 315 expect(pt[1]).toBeCloseTo(32.96, 3); // y 316 expect(pt[2]).toBeCloseTo(0.6, 3); // dy 317 expect(pt[3]).toBeCloseTo(0.8, 3); // dy 318 const subpath = cont.getSegment(20, 40, true); // make sure this doesn't crash 319 320 cont.delete(); 321 cont = meas.next(); 322 expect(cont).toBeTruthy() 323 expect(cont.length()).toBeCloseTo(51.231, 3); 324 325 cont.delete(); 326 expect(meas.next()).toBeFalsy(); 327 328 meas.delete(); 329 path.delete(); 330 done(); 331 })); 332 }); 333 334 it('can draw a polygon', function(done) { 335 LoadCanvasKit.then(catchException(done, () => { 336 // This is taken from example.html 337 const surface = CanvasKit.MakeCanvasSurface('test'); 338 expect(surface).toBeTruthy('Could not make surface') 339 if (!surface) { 340 done(); 341 return; 342 } 343 const canvas = surface.getCanvas(); 344 const paint = new CanvasKit.SkPaint(); 345 paint.setStrokeWidth(1.0); 346 paint.setAntiAlias(true); 347 paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 348 paint.setStyle(CanvasKit.PaintStyle.Stroke); 349 350 const points = [[5, 5], [30, 20], [55, 5], [55, 50], [30, 30], [5, 50]]; 351 352 const mPoints = CanvasKit.Malloc(Float32Array, 6 * 2); 353 mPoints.set([105, 105, 130, 120, 155, 105, 155, 150, 130, 130, 105, 150]); 354 355 const path = new CanvasKit.SkPath(); 356 path.addPoly(points, true) 357 .moveTo(100, 0) 358 .addPoly(mPoints, true); 359 360 canvas.drawPath(path, paint); 361 362 surface.flush(); 363 path.delete(); 364 paint.delete(); 365 366 reportSurface(surface, 'drawpoly_path', done); 367 })); 368 }); 369}); 370