1*c8dee2aaSAndroid Build Coastguard Workerconst onlytests = []; 2*c8dee2aaSAndroid Build Coastguard Workerconst tests = []; 3*c8dee2aaSAndroid Build Coastguard Worker// In all tests, the canvas is 600 by 600 px. 4*c8dee2aaSAndroid Build Coastguard Worker// tests should NOT call ctx.surface.flush() 5*c8dee2aaSAndroid Build Coastguard Worker// flush is done by benchmark.js 6*c8dee2aaSAndroid Build Coastguard Worker 7*c8dee2aaSAndroid Build Coastguard Workerfunction randomColorTwo(CanvasKit, i, j) { 8*c8dee2aaSAndroid Build Coastguard Worker c = [1, 1, 1, 1]; 9*c8dee2aaSAndroid Build Coastguard Worker c[i] = Math.random(); 10*c8dee2aaSAndroid Build Coastguard Worker c[j] = Math.random(); 11*c8dee2aaSAndroid Build Coastguard Worker return CanvasKit.Color4f(...c); 12*c8dee2aaSAndroid Build Coastguard Worker} 13*c8dee2aaSAndroid Build Coastguard Worker 14*c8dee2aaSAndroid Build Coastguard Workerfunction randomColor(CanvasKit) { 15*c8dee2aaSAndroid Build Coastguard Worker return CanvasKit.Color4f(Math.random(), Math.random(), Math.random(), Math.random()); 16*c8dee2aaSAndroid Build Coastguard Worker} 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard Workerfunction starPath(CanvasKit, X=128, Y=128, R=116) { 19*c8dee2aaSAndroid Build Coastguard Worker const p = new CanvasKit.Path(); 20*c8dee2aaSAndroid Build Coastguard Worker p.moveTo(X + R, Y); 21*c8dee2aaSAndroid Build Coastguard Worker for (let i = 1; i < 8; i++) { 22*c8dee2aaSAndroid Build Coastguard Worker let a = 2.6927937 * i; 23*c8dee2aaSAndroid Build Coastguard Worker p.lineTo(X + R * Math.cos(a), Y + R * Math.sin(a)); 24*c8dee2aaSAndroid Build Coastguard Worker } 25*c8dee2aaSAndroid Build Coastguard Worker p.close(); 26*c8dee2aaSAndroid Build Coastguard Worker return p; 27*c8dee2aaSAndroid Build Coastguard Worker} 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Workertests.push({ 30*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw 10K colored rect clips', 31*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 32*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 33*c8dee2aaSAndroid Build Coastguard Worker }, 34*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 35*c8dee2aaSAndroid Build Coastguard Worker // Draw a lot of colored squares. 36*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 37*c8dee2aaSAndroid Build Coastguard Worker const x = Math.random()*550; 38*c8dee2aaSAndroid Build Coastguard Worker const y = Math.random()*550; 39*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.save(); 40*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.clipRect(CanvasKit.LTRBRect(x, y, x+50, y+50), 41*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.ClipOp.Intersect, false); 42*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawColor(randomColorTwo(CanvasKit, 0, 1), CanvasKit.BlendMode.SrcOver); 43*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.restore(); 44*c8dee2aaSAndroid Build Coastguard Worker } 45*c8dee2aaSAndroid Build Coastguard Worker }, 46*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 47*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawColor', 48*c8dee2aaSAndroid Build Coastguard Worker}); 49*c8dee2aaSAndroid Build Coastguard Worker 50*c8dee2aaSAndroid Build Coastguard Workertests.push({ 51*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw 10K colored ellipses', 52*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 53*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 56*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 57*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 58*c8dee2aaSAndroid Build Coastguard Worker }, 59*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 60*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 61*c8dee2aaSAndroid Build Coastguard Worker const x = Math.random()*550; 62*c8dee2aaSAndroid Build Coastguard Worker const y = Math.random()*550; 63*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColorTwo(CanvasKit, 1, 2)); 64*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawOval(CanvasKit.LTRBRect(x, y, x+50, y+50), ctx.paint); 65*c8dee2aaSAndroid Build Coastguard Worker } 66*c8dee2aaSAndroid Build Coastguard Worker }, 67*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 68*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 69*c8dee2aaSAndroid Build Coastguard Worker }, 70*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawOval', 71*c8dee2aaSAndroid Build Coastguard Worker}); 72*c8dee2aaSAndroid Build Coastguard Worker 73*c8dee2aaSAndroid Build Coastguard Workertests.push({ 74*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw 10K colored roundRects', 75*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 76*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 77*c8dee2aaSAndroid Build Coastguard Worker 78*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 79*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 80*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 81*c8dee2aaSAndroid Build Coastguard Worker }, 82*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 83*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 84*c8dee2aaSAndroid Build Coastguard Worker const x = Math.random()*550; 85*c8dee2aaSAndroid Build Coastguard Worker const y = Math.random()*550; 86*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColorTwo(CanvasKit, 0, 2)); 87*c8dee2aaSAndroid Build Coastguard Worker const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(x, y, x+50, y+50), 10, 10,); 88*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawRRect(rr, ctx.paint); 89*c8dee2aaSAndroid Build Coastguard Worker } 90*c8dee2aaSAndroid Build Coastguard Worker }, 91*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 92*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 93*c8dee2aaSAndroid Build Coastguard Worker }, 94*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawRRect', 95*c8dee2aaSAndroid Build Coastguard Worker}); 96*c8dee2aaSAndroid Build Coastguard Worker 97*c8dee2aaSAndroid Build Coastguard Workertests.push({ 98*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw 10K colored rects', 99*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 100*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 103*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 104*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 105*c8dee2aaSAndroid Build Coastguard Worker }, 106*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 107*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 108*c8dee2aaSAndroid Build Coastguard Worker const x = Math.random()*550; 109*c8dee2aaSAndroid Build Coastguard Worker const y = Math.random()*550; 110*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColorTwo(CanvasKit, 1, 2)); 111*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawRect(CanvasKit.LTRBRect(x, y, x+50, y+50), ctx.paint); 112*c8dee2aaSAndroid Build Coastguard Worker } 113*c8dee2aaSAndroid Build Coastguard Worker }, 114*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 115*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 116*c8dee2aaSAndroid Build Coastguard Worker }, 117*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawRect', 118*c8dee2aaSAndroid Build Coastguard Worker}); 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Workertests.push({ 121*c8dee2aaSAndroid Build Coastguard Worker description: "Draw 10K colored rects with malloc'd rect", 122*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 123*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 126*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 127*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 128*c8dee2aaSAndroid Build Coastguard Worker ctx.rect = CanvasKit.Malloc(Float32Array, 4); 129*c8dee2aaSAndroid Build Coastguard Worker }, 130*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 131*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 132*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColorTwo(CanvasKit, 1, 2)); 133*c8dee2aaSAndroid Build Coastguard Worker const ta = ctx.rect.toTypedArray(); 134*c8dee2aaSAndroid Build Coastguard Worker ta[0] = Math.random()*550; // x 135*c8dee2aaSAndroid Build Coastguard Worker ta[1] = Math.random()*550; // y 136*c8dee2aaSAndroid Build Coastguard Worker ta[2] = ta[0] + 50; 137*c8dee2aaSAndroid Build Coastguard Worker ta[3] = ta[1] + 50; 138*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawRect(ta, ctx.paint); 139*c8dee2aaSAndroid Build Coastguard Worker } 140*c8dee2aaSAndroid Build Coastguard Worker }, 141*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 142*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 143*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Free(ctx.rect); 144*c8dee2aaSAndroid Build Coastguard Worker }, 145*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawRect_malloc', 146*c8dee2aaSAndroid Build Coastguard Worker}); 147*c8dee2aaSAndroid Build Coastguard Worker 148*c8dee2aaSAndroid Build Coastguard Workertests.push({ 149*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw 10K colored rects using 4 float API', 150*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 151*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 154*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 155*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 156*c8dee2aaSAndroid Build Coastguard Worker }, 157*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 158*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<10000; i++) { 159*c8dee2aaSAndroid Build Coastguard Worker const x = Math.random()*550; 160*c8dee2aaSAndroid Build Coastguard Worker const y = Math.random()*550; 161*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColorTwo(CanvasKit, 1, 2)); 162*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawRect4f(x, y, x+50, y+50, ctx.paint); 163*c8dee2aaSAndroid Build Coastguard Worker } 164*c8dee2aaSAndroid Build Coastguard Worker }, 165*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 166*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 167*c8dee2aaSAndroid Build Coastguard Worker }, 168*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawRect4f', 169*c8dee2aaSAndroid Build Coastguard Worker}); 170*c8dee2aaSAndroid Build Coastguard Worker 171*c8dee2aaSAndroid Build Coastguard Workertests.push({ 172*c8dee2aaSAndroid Build Coastguard Worker description: 'Compute tonal colors', 173*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) {}, 174*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 175*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 10; i++) { 176*c8dee2aaSAndroid Build Coastguard Worker const input = { 177*c8dee2aaSAndroid Build Coastguard Worker ambient: randomColor(CanvasKit), 178*c8dee2aaSAndroid Build Coastguard Worker spot: randomColor(CanvasKit), 179*c8dee2aaSAndroid Build Coastguard Worker }; 180*c8dee2aaSAndroid Build Coastguard Worker const out = CanvasKit.computeTonalColors(input); 181*c8dee2aaSAndroid Build Coastguard Worker if (out.spot[2] > 10 || out.ambient[3] > 10) { 182*c8dee2aaSAndroid Build Coastguard Worker // Something to make sure v8 can't optimize away the return value 183*c8dee2aaSAndroid Build Coastguard Worker throw 'not possible'; 184*c8dee2aaSAndroid Build Coastguard Worker } 185*c8dee2aaSAndroid Build Coastguard Worker } 186*c8dee2aaSAndroid Build Coastguard Worker }, 187*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 188*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'computeTonalColors', 189*c8dee2aaSAndroid Build Coastguard Worker}); 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Workertests.push({ 192*c8dee2aaSAndroid Build Coastguard Worker description: 'Get and set the color to a paint', 193*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 194*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 195*c8dee2aaSAndroid Build Coastguard Worker }, 196*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 197*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 10; i++) { 198*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(randomColor(CanvasKit)); 199*c8dee2aaSAndroid Build Coastguard Worker const color = ctx.paint.getColor(); 200*c8dee2aaSAndroid Build Coastguard Worker if (color[3] > 4) { 201*c8dee2aaSAndroid Build Coastguard Worker // Something to make sure v8 can't optimize away the return value 202*c8dee2aaSAndroid Build Coastguard Worker throw 'not possible'; 203*c8dee2aaSAndroid Build Coastguard Worker } 204*c8dee2aaSAndroid Build Coastguard Worker } 205*c8dee2aaSAndroid Build Coastguard Worker }, 206*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 207*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 208*c8dee2aaSAndroid Build Coastguard Worker }, 209*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'paint_setColor_getColor', 210*c8dee2aaSAndroid Build Coastguard Worker}); 211*c8dee2aaSAndroid Build Coastguard Worker 212*c8dee2aaSAndroid Build Coastguard Workertests.push({ 213*c8dee2aaSAndroid Build Coastguard Worker description: 'Set the color to a paint by components', 214*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 215*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 216*c8dee2aaSAndroid Build Coastguard Worker }, 217*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 218*c8dee2aaSAndroid Build Coastguard Worker const r = Math.random(); 219*c8dee2aaSAndroid Build Coastguard Worker const g = Math.random(); 220*c8dee2aaSAndroid Build Coastguard Worker const b = Math.random(); 221*c8dee2aaSAndroid Build Coastguard Worker const a = Math.random(); 222*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 10000; i++) { 223*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColorComponents(r, g, b, a); 224*c8dee2aaSAndroid Build Coastguard Worker } 225*c8dee2aaSAndroid Build Coastguard Worker }, 226*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 227*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 228*c8dee2aaSAndroid Build Coastguard Worker }, 229*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'paint_setColorComponents', 230*c8dee2aaSAndroid Build Coastguard Worker}); 231*c8dee2aaSAndroid Build Coastguard Worker 232*c8dee2aaSAndroid Build Coastguard Workertests.push({ 233*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw a shadow with tonal colors', 234*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 235*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 236*c8dee2aaSAndroid Build Coastguard Worker 237*c8dee2aaSAndroid Build Coastguard Worker ctx.input = { 238*c8dee2aaSAndroid Build Coastguard Worker ambient: CanvasKit.Color4f(0.2, 0.1, 0.3, 0.5), 239*c8dee2aaSAndroid Build Coastguard Worker spot: CanvasKit.Color4f(0.8, 0.8, 0.9, 0.9), 240*c8dee2aaSAndroid Build Coastguard Worker }; 241*c8dee2aaSAndroid Build Coastguard Worker ctx.lightRadius = 30; 242*c8dee2aaSAndroid Build Coastguard Worker ctx.flags = 0; 243*c8dee2aaSAndroid Build Coastguard Worker ctx.lightPos = [250,150,300]; 244*c8dee2aaSAndroid Build Coastguard Worker ctx.zPlaneParams = [0,0,1]; 245*c8dee2aaSAndroid Build Coastguard Worker ctx.path = starPath(CanvasKit); 246*c8dee2aaSAndroid Build Coastguard Worker }, 247*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 248*c8dee2aaSAndroid Build Coastguard Worker const out = CanvasKit.computeTonalColors(ctx.input); 249*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawShadow(ctx.path, ctx.zPlaneParams, ctx.lightPos, ctx.lightRadius, 250*c8dee2aaSAndroid Build Coastguard Worker out.ambient, out.spot, ctx.flags); 251*c8dee2aaSAndroid Build Coastguard Worker }, 252*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 253*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawShadow', 254*c8dee2aaSAndroid Build Coastguard Worker}); 255*c8dee2aaSAndroid Build Coastguard Worker 256*c8dee2aaSAndroid Build Coastguard Workertests.push({ 257*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw a gradient with an array of 10K colors', 258*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 259*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 260*c8dee2aaSAndroid Build Coastguard Worker }, 261*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 262*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.clear(CanvasKit.WHITE); 263*c8dee2aaSAndroid Build Coastguard Worker 264*c8dee2aaSAndroid Build Coastguard Worker const num = 10000; 265*c8dee2aaSAndroid Build Coastguard Worker colors = Array(num); 266*c8dee2aaSAndroid Build Coastguard Worker positions = Array(num); 267*c8dee2aaSAndroid Build Coastguard Worker // Create an array of colors spaced evenly along the 0..1 range of positions. 268*c8dee2aaSAndroid Build Coastguard Worker for (let i=0; i<num; i++) { 269*c8dee2aaSAndroid Build Coastguard Worker colors[i] = randomColorTwo(CanvasKit, 2, 3); 270*c8dee2aaSAndroid Build Coastguard Worker positions[i] = i/num; 271*c8dee2aaSAndroid Build Coastguard Worker } 272*c8dee2aaSAndroid Build Coastguard Worker // make a gradient from those colors 273*c8dee2aaSAndroid Build Coastguard Worker const shader = CanvasKit.Shader.MakeRadialGradient( 274*c8dee2aaSAndroid Build Coastguard Worker [300, 300], 50, // center, radius 275*c8dee2aaSAndroid Build Coastguard Worker colors, positions, 276*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Mirror, 277*c8dee2aaSAndroid Build Coastguard Worker ); 278*c8dee2aaSAndroid Build Coastguard Worker // Fill the canvas using the gradient shader. 279*c8dee2aaSAndroid Build Coastguard Worker const paint = new CanvasKit.Paint(); 280*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(CanvasKit.PaintStyle.Fill); 281*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(shader); 282*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawPaint(paint); 283*c8dee2aaSAndroid Build Coastguard Worker 284*c8dee2aaSAndroid Build Coastguard Worker shader.delete(); 285*c8dee2aaSAndroid Build Coastguard Worker paint.delete(); 286*c8dee2aaSAndroid Build Coastguard Worker }, 287*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 288*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawHugeGradient', 289*c8dee2aaSAndroid Build Coastguard Worker}); 290*c8dee2aaSAndroid Build Coastguard Worker 291*c8dee2aaSAndroid Build Coastguard Workertests.push({ 292*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw a png image', 293*c8dee2aaSAndroid Build Coastguard Worker setup: async function(CanvasKit, ctx) { 294*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 295*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 296*c8dee2aaSAndroid Build Coastguard Worker ctx.img = CanvasKit.MakeImageFromEncoded(ctx.files['test_512x512.png']); 297*c8dee2aaSAndroid Build Coastguard Worker ctx.frame = 0; 298*c8dee2aaSAndroid Build Coastguard Worker }, 299*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 300*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.clear(CanvasKit.WHITE); 301*c8dee2aaSAndroid Build Coastguard Worker // Make the image to move so you can see visually that the test is running. 302*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawImage(ctx.img, ctx.frame, ctx.frame, ctx.paint); 303*c8dee2aaSAndroid Build Coastguard Worker ctx.frame++; 304*c8dee2aaSAndroid Build Coastguard Worker }, 305*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 306*c8dee2aaSAndroid Build Coastguard Worker ctx.img.delete(); 307*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 308*c8dee2aaSAndroid Build Coastguard Worker }, 309*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawPngImage', 310*c8dee2aaSAndroid Build Coastguard Worker}); 311*c8dee2aaSAndroid Build Coastguard Worker 312*c8dee2aaSAndroid Build Coastguard Worker 313*c8dee2aaSAndroid Build Coastguard Workerfunction htmlImageElementToDataURL(htmlImageElement) { 314*c8dee2aaSAndroid Build Coastguard Worker const canvas = document.createElement('canvas'); 315*c8dee2aaSAndroid Build Coastguard Worker canvas.height = htmlImageElement.height; 316*c8dee2aaSAndroid Build Coastguard Worker canvas.width = htmlImageElement.width; 317*c8dee2aaSAndroid Build Coastguard Worker const ctx = canvas.getContext('2d') 318*c8dee2aaSAndroid Build Coastguard Worker ctx.drawImage(htmlImageElement, 0, 0); 319*c8dee2aaSAndroid Build Coastguard Worker return canvas.toDataURL(); 320*c8dee2aaSAndroid Build Coastguard Worker} 321*c8dee2aaSAndroid Build Coastguard Worker 322*c8dee2aaSAndroid Build Coastguard Worker// This for loop generates two perf cases for each test image. One uses browser APIs 323*c8dee2aaSAndroid Build Coastguard Worker// to decode an image, and the other uses codecs included in the CanvasKit wasm to decode an 324*c8dee2aaSAndroid Build Coastguard Worker// image. wasm codec Image decoding is faster (50 microseconds vs 20000 microseconds), but 325*c8dee2aaSAndroid Build Coastguard Worker// including codecs in wasm increases the size of the CanvasKit wasm binary. 326*c8dee2aaSAndroid Build Coastguard Workerfor (const testImageFilename of ['test_64x64.png', 'test_512x512.png', 'test_1500x959.jpg']) { 327*c8dee2aaSAndroid Build Coastguard Worker const htmlImageElement = new Image(); 328*c8dee2aaSAndroid Build Coastguard Worker htmlImageElementLoadPromise = new Promise((resolve) => 329*c8dee2aaSAndroid Build Coastguard Worker htmlImageElement.addEventListener('load', resolve)); 330*c8dee2aaSAndroid Build Coastguard Worker // Create a data url of the image so that load and decode time can be measured 331*c8dee2aaSAndroid Build Coastguard Worker // while ignoring the time of getting the image from disk / the network. 332*c8dee2aaSAndroid Build Coastguard Worker imageDataURLPromise = htmlImageElementLoadPromise.then(() => 333*c8dee2aaSAndroid Build Coastguard Worker htmlImageElementToDataURL(htmlImageElement)); 334*c8dee2aaSAndroid Build Coastguard Worker htmlImageElement.src = `/static/assets/${testImageFilename}`; 335*c8dee2aaSAndroid Build Coastguard Worker 336*c8dee2aaSAndroid Build Coastguard Worker tests.push({ 337*c8dee2aaSAndroid Build Coastguard Worker description: 'Decode an image using HTMLImageElement and Canvas2D', 338*c8dee2aaSAndroid Build Coastguard Worker setup: async function(CanvasKit, ctx) { 339*c8dee2aaSAndroid Build Coastguard Worker ctx.imageDataURL = await imageDataURLPromise; 340*c8dee2aaSAndroid Build Coastguard Worker }, 341*c8dee2aaSAndroid Build Coastguard Worker test: async function(CanvasKit, ctx) { 342*c8dee2aaSAndroid Build Coastguard Worker const image = new Image(); 343*c8dee2aaSAndroid Build Coastguard Worker // Testing showed that waiting for the load event is faster than waiting for 344*c8dee2aaSAndroid Build Coastguard Worker // image.decode(). 345*c8dee2aaSAndroid Build Coastguard Worker // Despite the name, both of them would decode the image, it was loaded in setup. 346*c8dee2aaSAndroid Build Coastguard Worker // HTMLImageElement.decode() reference: 347*c8dee2aaSAndroid Build Coastguard Worker // https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decode 348*c8dee2aaSAndroid Build Coastguard Worker const promise = new Promise((resolve) => image.addEventListener('load', resolve)); 349*c8dee2aaSAndroid Build Coastguard Worker image.src = ctx.imageDataURL; 350*c8dee2aaSAndroid Build Coastguard Worker await promise; 351*c8dee2aaSAndroid Build Coastguard Worker const img = await CanvasKit.MakeImageFromCanvasImageSource(image); 352*c8dee2aaSAndroid Build Coastguard Worker img.delete(); 353*c8dee2aaSAndroid Build Coastguard Worker }, 354*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 355*c8dee2aaSAndroid Build Coastguard Worker perfKey: `canvas_${testImageFilename}_HTMLImageElementDecoding`, 356*c8dee2aaSAndroid Build Coastguard Worker }); 357*c8dee2aaSAndroid Build Coastguard Worker 358*c8dee2aaSAndroid Build Coastguard Worker tests.push({ 359*c8dee2aaSAndroid Build Coastguard Worker description: 'Decode an image using codecs in wasm', 360*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) {}, 361*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 362*c8dee2aaSAndroid Build Coastguard Worker const img = CanvasKit.MakeImageFromEncoded(ctx.files[testImageFilename]); 363*c8dee2aaSAndroid Build Coastguard Worker img.delete(); 364*c8dee2aaSAndroid Build Coastguard Worker }, 365*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 366*c8dee2aaSAndroid Build Coastguard Worker perfKey: '`canvas_${testImageFilename}_wasmImageDecoding`', 367*c8dee2aaSAndroid Build Coastguard Worker }); 368*c8dee2aaSAndroid Build Coastguard Worker} 369*c8dee2aaSAndroid Build Coastguard Worker 370*c8dee2aaSAndroid Build Coastguard Worker// 3x3 matrix ops 371*c8dee2aaSAndroid Build Coastguard Workertests.push({ 372*c8dee2aaSAndroid Build Coastguard Worker description: 'Multiply 3x3 matrices together', 373*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 374*c8dee2aaSAndroid Build Coastguard Worker ctx.first = CanvasKit.Matrix.rotated(Math.PI/2, 10, 20); 375*c8dee2aaSAndroid Build Coastguard Worker ctx.second = CanvasKit.Matrix.scaled(1, 2, 3, 4); 376*c8dee2aaSAndroid Build Coastguard Worker }, 377*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 378*c8dee2aaSAndroid Build Coastguard Worker ctx.result = CanvasKit.Matrix.multiply(ctx.first, ctx.second); 379*c8dee2aaSAndroid Build Coastguard Worker if (ctx.result.length === 18) { 380*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 381*c8dee2aaSAndroid Build Coastguard Worker } 382*c8dee2aaSAndroid Build Coastguard Worker }, 383*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 384*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skmatrix_multiply', 385*c8dee2aaSAndroid Build Coastguard Worker}); 386*c8dee2aaSAndroid Build Coastguard Worker 387*c8dee2aaSAndroid Build Coastguard Workertests.push({ 388*c8dee2aaSAndroid Build Coastguard Worker description: 'Transform a point using a matrix (mapPoint)', 389*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 390*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.Matrix.multiply( 391*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.rotated(Math.PI/2, 10, 20), 392*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(1, 2, 3, 4), 393*c8dee2aaSAndroid Build Coastguard Worker ); // make an arbitrary, but interesting matrix 394*c8dee2aaSAndroid Build Coastguard Worker }, 395*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 396*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 30; i++) { 397*c8dee2aaSAndroid Build Coastguard Worker const pt = CanvasKit.Matrix.mapPoints(ctx.matr, [i, i]); 398*c8dee2aaSAndroid Build Coastguard Worker if (pt.length === 18) { 399*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep pt from being optimized away'; 400*c8dee2aaSAndroid Build Coastguard Worker } 401*c8dee2aaSAndroid Build Coastguard Worker } 402*c8dee2aaSAndroid Build Coastguard Worker }, 403*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 404*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skmatrix_transformPoint', 405*c8dee2aaSAndroid Build Coastguard Worker}); 406*c8dee2aaSAndroid Build Coastguard Worker 407*c8dee2aaSAndroid Build Coastguard Workertests.push({ 408*c8dee2aaSAndroid Build Coastguard Worker description: 'Invert a 3x3 matrix', 409*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 410*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.Matrix.multiply( 411*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.rotated(Math.PI/2, 10, 20), 412*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(1, 2, 3, 4), 413*c8dee2aaSAndroid Build Coastguard Worker ); 414*c8dee2aaSAndroid Build Coastguard Worker }, 415*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 416*c8dee2aaSAndroid Build Coastguard Worker ctx.result = CanvasKit.Matrix.invert(ctx.matr); 417*c8dee2aaSAndroid Build Coastguard Worker if (ctx.result.length === 18) { 418*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 419*c8dee2aaSAndroid Build Coastguard Worker } 420*c8dee2aaSAndroid Build Coastguard Worker }, 421*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 422*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skmatrix_invert', 423*c8dee2aaSAndroid Build Coastguard Worker}); 424*c8dee2aaSAndroid Build Coastguard Worker 425*c8dee2aaSAndroid Build Coastguard Workertests.push({ 426*c8dee2aaSAndroid Build Coastguard Worker description: 'Create a shader from a 3x3 matrix', 427*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 428*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.Matrix.multiply( 429*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.rotated(Math.PI/2, 10, 20), 430*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(1, 2, 3, 4), 431*c8dee2aaSAndroid Build Coastguard Worker ); 432*c8dee2aaSAndroid Build Coastguard Worker }, 433*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 434*c8dee2aaSAndroid Build Coastguard Worker const shader = CanvasKit.Shader.MakeSweepGradient( 435*c8dee2aaSAndroid Build Coastguard Worker 100, 100, 436*c8dee2aaSAndroid Build Coastguard Worker [CanvasKit.GREEN, CanvasKit.BLUE], 437*c8dee2aaSAndroid Build Coastguard Worker [0.0, 1.0], 438*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Clamp, 439*c8dee2aaSAndroid Build Coastguard Worker ctx.matr); 440*c8dee2aaSAndroid Build Coastguard Worker shader.delete(); 441*c8dee2aaSAndroid Build Coastguard Worker }, 442*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 443*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skmatrix_makeShader', 444*c8dee2aaSAndroid Build Coastguard Worker}); 445*c8dee2aaSAndroid Build Coastguard Worker 446*c8dee2aaSAndroid Build Coastguard Workertests.push({ 447*c8dee2aaSAndroid Build Coastguard Worker description: 'Concat 3x3 matrix on a canvas', 448*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 449*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = new CanvasKit.Canvas(); 450*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.Matrix.multiply( 451*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.rotated(Math.PI/2, 10, 20), 452*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.Matrix.scaled(1, 2, 3, 4), 453*c8dee2aaSAndroid Build Coastguard Worker ); 454*c8dee2aaSAndroid Build Coastguard Worker }, 455*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 456*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.concat(ctx.matr); 457*c8dee2aaSAndroid Build Coastguard Worker }, 458*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 459*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.delete(); 460*c8dee2aaSAndroid Build Coastguard Worker }, 461*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skmatrix_concat', 462*c8dee2aaSAndroid Build Coastguard Worker}); 463*c8dee2aaSAndroid Build Coastguard Worker 464*c8dee2aaSAndroid Build Coastguard Worker// 4x4 matrix operations 465*c8dee2aaSAndroid Build Coastguard Workertests.push({ 466*c8dee2aaSAndroid Build Coastguard Worker description: 'Multiply 4x4 matrices together', 467*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 468*c8dee2aaSAndroid Build Coastguard Worker ctx.first = CanvasKit.M44.rotated([10, 20, 30], Math.PI/2); 469*c8dee2aaSAndroid Build Coastguard Worker ctx.second = CanvasKit.M44.scaled([1, 2, 3]); 470*c8dee2aaSAndroid Build Coastguard Worker }, 471*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 472*c8dee2aaSAndroid Build Coastguard Worker ctx.result = CanvasKit.M44.multiply(ctx.first, ctx.second); 473*c8dee2aaSAndroid Build Coastguard Worker if (ctx.result.length === 18) { 474*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 475*c8dee2aaSAndroid Build Coastguard Worker } 476*c8dee2aaSAndroid Build Coastguard Worker }, 477*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 478*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skm44_multiply', 479*c8dee2aaSAndroid Build Coastguard Worker}); 480*c8dee2aaSAndroid Build Coastguard Worker 481*c8dee2aaSAndroid Build Coastguard Workertests.push({ 482*c8dee2aaSAndroid Build Coastguard Worker description: 'Invert a 4x4 matrix', 483*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 484*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.M44.multiply( 485*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.M44.rotated([10, 20, 30], Math.PI/2), 486*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.M44.scaled([1, 2, 3]), 487*c8dee2aaSAndroid Build Coastguard Worker ); 488*c8dee2aaSAndroid Build Coastguard Worker }, 489*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 490*c8dee2aaSAndroid Build Coastguard Worker const result = CanvasKit.M44.invert(ctx.matr); 491*c8dee2aaSAndroid Build Coastguard Worker if (result.length === 18) { 492*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 493*c8dee2aaSAndroid Build Coastguard Worker } 494*c8dee2aaSAndroid Build Coastguard Worker }, 495*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 496*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skm44_invert', 497*c8dee2aaSAndroid Build Coastguard Worker}); 498*c8dee2aaSAndroid Build Coastguard Worker 499*c8dee2aaSAndroid Build Coastguard Workertests.push({ 500*c8dee2aaSAndroid Build Coastguard Worker description: 'Concat 4x4 matrix on a canvas', 501*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 502*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = new CanvasKit.Canvas(); 503*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = CanvasKit.M44.multiply( 504*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.M44.rotated([10, 20, 30], Math.PI/2), 505*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.M44.scaled([1, 2, 3]), 506*c8dee2aaSAndroid Build Coastguard Worker ); 507*c8dee2aaSAndroid Build Coastguard Worker }, 508*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 509*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.concat(ctx.matr); 510*c8dee2aaSAndroid Build Coastguard Worker }, 511*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 512*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.delete(); 513*c8dee2aaSAndroid Build Coastguard Worker }, 514*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'skm44_concat', 515*c8dee2aaSAndroid Build Coastguard Worker}); 516*c8dee2aaSAndroid Build Coastguard Worker 517*c8dee2aaSAndroid Build Coastguard Worker// DOMMatrix operations 518*c8dee2aaSAndroid Build Coastguard Workertests.push({ 519*c8dee2aaSAndroid Build Coastguard Worker description: 'Multiply DOM matrices together', 520*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 521*c8dee2aaSAndroid Build Coastguard Worker ctx.first = new DOMMatrix().translate(10, 20).rotate(90).translate(-10, -20); 522*c8dee2aaSAndroid Build Coastguard Worker ctx.second = new DOMMatrix().translate(3, 4).scale(1, 2).translate(-3, -4); 523*c8dee2aaSAndroid Build Coastguard Worker }, 524*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 525*c8dee2aaSAndroid Build Coastguard Worker const result = ctx.first.multiply(ctx.second); 526*c8dee2aaSAndroid Build Coastguard Worker if (result.length === 18) { 527*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 528*c8dee2aaSAndroid Build Coastguard Worker } 529*c8dee2aaSAndroid Build Coastguard Worker }, 530*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 531*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'dommatrix_multiply', 532*c8dee2aaSAndroid Build Coastguard Worker}); 533*c8dee2aaSAndroid Build Coastguard Worker 534*c8dee2aaSAndroid Build Coastguard Workertests.push({ 535*c8dee2aaSAndroid Build Coastguard Worker description: 'Transform a point using a matrix (transformPoint)', 536*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 537*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = new DOMMatrix().translate(10, 20).rotate(90).translate(-10, -20) 538*c8dee2aaSAndroid Build Coastguard Worker .multiply(new DOMMatrix().translate(3, 4).scale(1, 2).translate(-3, -4)); 539*c8dee2aaSAndroid Build Coastguard Worker 540*c8dee2aaSAndroid Build Coastguard Worker ctx.reusablePt = new DOMPoint(0, 0) 541*c8dee2aaSAndroid Build Coastguard Worker }, 542*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 543*c8dee2aaSAndroid Build Coastguard Worker for (let i = 0; i < 30; i++) { 544*c8dee2aaSAndroid Build Coastguard Worker ctx.reusablePt.X = i; ctx.reusablePt.Y = i; 545*c8dee2aaSAndroid Build Coastguard Worker const pt = ctx.matr.transformPoint(ctx.reusablePt); 546*c8dee2aaSAndroid Build Coastguard Worker if (pt.length === 18) { 547*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep pt from being optimized away'; 548*c8dee2aaSAndroid Build Coastguard Worker } 549*c8dee2aaSAndroid Build Coastguard Worker } 550*c8dee2aaSAndroid Build Coastguard Worker }, 551*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 552*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'dommatrix_transformPoint', 553*c8dee2aaSAndroid Build Coastguard Worker}); 554*c8dee2aaSAndroid Build Coastguard Worker 555*c8dee2aaSAndroid Build Coastguard Workertests.push({ 556*c8dee2aaSAndroid Build Coastguard Worker description: 'Invert a DOM matrix', 557*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 558*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = new DOMMatrix().translate(10, 20).rotate(90).translate(-10, -20) 559*c8dee2aaSAndroid Build Coastguard Worker .multiply(new DOMMatrix().translate(3, 4).scale(1, 2).translate(-3, -4)); 560*c8dee2aaSAndroid Build Coastguard Worker }, 561*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 562*c8dee2aaSAndroid Build Coastguard Worker const inverted = ctx.matr.inverse(); 563*c8dee2aaSAndroid Build Coastguard Worker if (inverted.length === 18) { 564*c8dee2aaSAndroid Build Coastguard Worker throw 'this is here to keep the result from being optimized away'; 565*c8dee2aaSAndroid Build Coastguard Worker } 566*c8dee2aaSAndroid Build Coastguard Worker }, 567*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 568*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'dommatrix_invert', 569*c8dee2aaSAndroid Build Coastguard Worker}); 570*c8dee2aaSAndroid Build Coastguard Worker 571*c8dee2aaSAndroid Build Coastguard Workertests.push({ 572*c8dee2aaSAndroid Build Coastguard Worker description: 'make a shader from a DOMMatrix', 573*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 574*c8dee2aaSAndroid Build Coastguard Worker ctx.matr = new DOMMatrix().translate(10, 20).rotate(90).translate(-10, -20) 575*c8dee2aaSAndroid Build Coastguard Worker .multiply(new DOMMatrix().translate(3, 4).scale(1, 2).translate(-3, -4)); 576*c8dee2aaSAndroid Build Coastguard Worker }, 577*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 578*c8dee2aaSAndroid Build Coastguard Worker const shader = CanvasKit.Shader.MakeSweepGradient( 579*c8dee2aaSAndroid Build Coastguard Worker 100, 100, 580*c8dee2aaSAndroid Build Coastguard Worker [CanvasKit.GREEN, CanvasKit.BLUE], 581*c8dee2aaSAndroid Build Coastguard Worker [0.0, 1.0], 582*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.TileMode.Clamp, 583*c8dee2aaSAndroid Build Coastguard Worker ctx.matr); 584*c8dee2aaSAndroid Build Coastguard Worker shader.delete(); 585*c8dee2aaSAndroid Build Coastguard Worker }, 586*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) {}, 587*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'dommatrix_makeShader', 588*c8dee2aaSAndroid Build Coastguard Worker}); 589*c8dee2aaSAndroid Build Coastguard Worker 590*c8dee2aaSAndroid Build Coastguard Worker// Tests the layout and drawing of a paragraph with hundreds of words. 591*c8dee2aaSAndroid Build Coastguard Worker// In the second variant, the colors change every frame 592*c8dee2aaSAndroid Build Coastguard Worker// In the third variant, the font size cycles between three sizes. 593*c8dee2aaSAndroid Build Coastguard Worker// In the fourth variant, the layout width changes. 594*c8dee2aaSAndroid Build Coastguard Worker// in the fifth variant, all of those properties change at the same time. 595*c8dee2aaSAndroid Build Coastguard Workerfor (const variant of ['static', 'color_changing', 'size_changing', 'layout_changing', 'everything']) { 596*c8dee2aaSAndroid Build Coastguard Worker tests.push({ 597*c8dee2aaSAndroid Build Coastguard Worker description: `Layout and draw a ${variant} paragraph`, 598*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 599*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 600*c8dee2aaSAndroid Build Coastguard Worker ctx.fontMgr = CanvasKit.FontMgr.FromData([ctx.files['Roboto-Regular.ttf']]); 601*c8dee2aaSAndroid Build Coastguard Worker ctx.paraStyle = new CanvasKit.ParagraphStyle({ 602*c8dee2aaSAndroid Build Coastguard Worker textStyle: { 603*c8dee2aaSAndroid Build Coastguard Worker color: CanvasKit.WHITE, 604*c8dee2aaSAndroid Build Coastguard Worker fontFamilies: ['Roboto'], 605*c8dee2aaSAndroid Build Coastguard Worker fontSize: 11, 606*c8dee2aaSAndroid Build Coastguard Worker }, 607*c8dee2aaSAndroid Build Coastguard Worker textAlign: CanvasKit.TextAlign.Left, 608*c8dee2aaSAndroid Build Coastguard Worker }); 609*c8dee2aaSAndroid Build Coastguard Worker ctx.frame = 0; 610*c8dee2aaSAndroid Build Coastguard Worker ctx.text = "annap sap sa ladipidapidi rapadip sam dim dap dim dap do raka dip da da badip badip badipidipidipadisuten din dab do ".repeat(40); 611*c8dee2aaSAndroid Build Coastguard Worker }, 612*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 613*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.clear(CanvasKit.BLACK); 614*c8dee2aaSAndroid Build Coastguard Worker const builder = CanvasKit.ParagraphBuilder.Make(ctx.paraStyle, ctx.fontMgr); 615*c8dee2aaSAndroid Build Coastguard Worker let pos = 0; 616*c8dee2aaSAndroid Build Coastguard Worker let color = CanvasKit.WHITE; 617*c8dee2aaSAndroid Build Coastguard Worker while (pos < ctx.text.length) { 618*c8dee2aaSAndroid Build Coastguard Worker let size = 11; 619*c8dee2aaSAndroid Build Coastguard Worker if (variant === 'size_changing' || variant === 'everything') { 620*c8dee2aaSAndroid Build Coastguard Worker // the bigger this modulo, the more work it takes to fill the glyph cache 621*c8dee2aaSAndroid Build Coastguard Worker size += ctx.frame % 4; 622*c8dee2aaSAndroid Build Coastguard Worker } 623*c8dee2aaSAndroid Build Coastguard Worker if (variant === 'color_changing' || variant === 'everything') { 624*c8dee2aaSAndroid Build Coastguard Worker color = randomColorTwo(CanvasKit, 0, 1); 625*c8dee2aaSAndroid Build Coastguard Worker } 626*c8dee2aaSAndroid Build Coastguard Worker builder.pushStyle(CanvasKit.TextStyle({ 627*c8dee2aaSAndroid Build Coastguard Worker color: color, 628*c8dee2aaSAndroid Build Coastguard Worker fontFamilies: ['Roboto'], 629*c8dee2aaSAndroid Build Coastguard Worker fontSize: size, 630*c8dee2aaSAndroid Build Coastguard Worker fontStyle: { 631*c8dee2aaSAndroid Build Coastguard Worker weight: CanvasKit.FontWeight.Bold, 632*c8dee2aaSAndroid Build Coastguard Worker }, 633*c8dee2aaSAndroid Build Coastguard Worker })); 634*c8dee2aaSAndroid Build Coastguard Worker const len = Math.floor(Math.random()*5+2); 635*c8dee2aaSAndroid Build Coastguard Worker builder.addText(ctx.text.slice(pos, pos+len)); 636*c8dee2aaSAndroid Build Coastguard Worker builder.pop(); 637*c8dee2aaSAndroid Build Coastguard Worker pos += len; 638*c8dee2aaSAndroid Build Coastguard Worker } 639*c8dee2aaSAndroid Build Coastguard Worker const paragraph = builder.build(); 640*c8dee2aaSAndroid Build Coastguard Worker let w = 0; 641*c8dee2aaSAndroid Build Coastguard Worker const base_width = 520; 642*c8dee2aaSAndroid Build Coastguard Worker const varying_width_modulo = 70; 643*c8dee2aaSAndroid Build Coastguard Worker if (variant === 'layout_changing' || variant === 'everything') { 644*c8dee2aaSAndroid Build Coastguard Worker w = ctx.frame % varying_width_modulo; 645*c8dee2aaSAndroid Build Coastguard Worker } 646*c8dee2aaSAndroid Build Coastguard Worker paragraph.layout(base_width + w); // width in pixels to use when wrapping text 647*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawParagraph(paragraph, 10, 10); 648*c8dee2aaSAndroid Build Coastguard Worker 649*c8dee2aaSAndroid Build Coastguard Worker ctx.frame++; 650*c8dee2aaSAndroid Build Coastguard Worker builder.delete(); 651*c8dee2aaSAndroid Build Coastguard Worker paragraph.delete(); 652*c8dee2aaSAndroid Build Coastguard Worker }, 653*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 654*c8dee2aaSAndroid Build Coastguard Worker ctx.fontMgr.delete(); 655*c8dee2aaSAndroid Build Coastguard Worker }, 656*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_drawParagraph_'+variant, 657*c8dee2aaSAndroid Build Coastguard Worker }); 658*c8dee2aaSAndroid Build Coastguard Worker} 659*c8dee2aaSAndroid Build Coastguard Worker 660*c8dee2aaSAndroid Build Coastguard Workertests.push({ 661*c8dee2aaSAndroid Build Coastguard Worker description: 'Draw a path with a blur mask', 662*c8dee2aaSAndroid Build Coastguard Worker setup: function(CanvasKit, ctx) { 663*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas = ctx.surface.getCanvas(); 664*c8dee2aaSAndroid Build Coastguard Worker ctx.paint = new CanvasKit.Paint(); 665*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setAntiAlias(true); 666*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setStyle(CanvasKit.PaintStyle.Fill); 667*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setColor(CanvasKit.Color4f(0.1, 0.7, 0.0, 1.0)); 668*c8dee2aaSAndroid Build Coastguard Worker ctx.path = starPath(CanvasKit); 669*c8dee2aaSAndroid Build Coastguard Worker ctx.frame = 0; 670*c8dee2aaSAndroid Build Coastguard Worker }, 671*c8dee2aaSAndroid Build Coastguard Worker test: function(CanvasKit, ctx) { 672*c8dee2aaSAndroid Build Coastguard Worker const sigma = 0.1 + (ctx.frame/10); 673*c8dee2aaSAndroid Build Coastguard Worker const blurMask = CanvasKit.MaskFilter.MakeBlur( 674*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.BlurStyle.Normal, sigma, true); 675*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.setMaskFilter(blurMask); 676*c8dee2aaSAndroid Build Coastguard Worker ctx.canvas.drawPath(ctx.path, ctx.paint); 677*c8dee2aaSAndroid Build Coastguard Worker blurMask.delete(); 678*c8dee2aaSAndroid Build Coastguard Worker ctx.frame++; 679*c8dee2aaSAndroid Build Coastguard Worker }, 680*c8dee2aaSAndroid Build Coastguard Worker teardown: function(CanvasKit, ctx) { 681*c8dee2aaSAndroid Build Coastguard Worker ctx.paint.delete(); 682*c8dee2aaSAndroid Build Coastguard Worker ctx.path.delete(); 683*c8dee2aaSAndroid Build Coastguard Worker }, 684*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'canvas_blur_mask_filter', 685*c8dee2aaSAndroid Build Coastguard Worker}); 686*c8dee2aaSAndroid Build Coastguard Worker 687*c8dee2aaSAndroid Build Coastguard Workerfor (const variant of ['ttf', 'woff', 'woff2']) { 688*c8dee2aaSAndroid Build Coastguard Worker tests.push({ 689*c8dee2aaSAndroid Build Coastguard Worker description: `Get glyphIDs from a ${variant} font`, 690*c8dee2aaSAndroid Build Coastguard Worker setup: function (CanvasKit, ctx) { 691*c8dee2aaSAndroid Build Coastguard Worker const robotoData = ctx.files['Roboto-Regular.' + variant]; 692*c8dee2aaSAndroid Build Coastguard Worker ctx.robotoFace = CanvasKit.Typeface.MakeTypefaceFromData(robotoData); 693*c8dee2aaSAndroid Build Coastguard Worker if (!ctx.robotoFace) { 694*c8dee2aaSAndroid Build Coastguard Worker throw 'could not load ' + variant; 695*c8dee2aaSAndroid Build Coastguard Worker } 696*c8dee2aaSAndroid Build Coastguard Worker ctx.robotoFont = new CanvasKit.Font(ctx.robotoFace, 20); 697*c8dee2aaSAndroid Build Coastguard Worker ctx.testGlyphID = 1; 698*c8dee2aaSAndroid Build Coastguard Worker }, 699*c8dee2aaSAndroid Build Coastguard Worker test: function (CanvasKit, ctx) { 700*c8dee2aaSAndroid Build Coastguard Worker // We get one glyph ID at a time to force cache misses and require Skia to 701*c8dee2aaSAndroid Build Coastguard Worker // perhaps re-access the font. See skbug.com/12112 for example. 702*c8dee2aaSAndroid Build Coastguard Worker const output = new Uint16Array(1); 703*c8dee2aaSAndroid Build Coastguard Worker for (let i = ctx.testGlyphID; i < ctx.testGlyphID+100; i++) { 704*c8dee2aaSAndroid Build Coastguard Worker ctx.robotoFont.getGlyphIDs(String.fromCodePoint(i), 1, output); 705*c8dee2aaSAndroid Build Coastguard Worker } 706*c8dee2aaSAndroid Build Coastguard Worker ctx.testGlyphID += 100; 707*c8dee2aaSAndroid Build Coastguard Worker }, 708*c8dee2aaSAndroid Build Coastguard Worker teardown: function (CanvasKit, ctx) { 709*c8dee2aaSAndroid Build Coastguard Worker ctx.robotoFace.delete(); 710*c8dee2aaSAndroid Build Coastguard Worker ctx.robotoFont.delete(); 711*c8dee2aaSAndroid Build Coastguard Worker }, 712*c8dee2aaSAndroid Build Coastguard Worker perfKey: 'font_getGlyphIDs_' + variant, 713*c8dee2aaSAndroid Build Coastguard Worker }); 714*c8dee2aaSAndroid Build Coastguard Worker} 715