1cb93a386Sopenharmony_ci<!DOCTYPE html> 2cb93a386Sopenharmony_ci<title>CanvasKit (Skia via Web Assembly)</title> 3cb93a386Sopenharmony_ci<meta charset="utf-8" /> 4cb93a386Sopenharmony_ci<meta http-equiv="X-UA-Compatible" content="IE=edge"> 5cb93a386Sopenharmony_ci<meta name="viewport" content="width=device-width, initial-scale=1.0"> 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci<style> 8cb93a386Sopenharmony_ci canvas, img { 9cb93a386Sopenharmony_ci border: 1px dashed #AAA; 10cb93a386Sopenharmony_ci } 11cb93a386Sopenharmony_ci #api5_c, #api6_c { 12cb93a386Sopenharmony_ci width: 300px; 13cb93a386Sopenharmony_ci height: 300px; 14cb93a386Sopenharmony_ci } 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci</style> 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci<h2>Drop in replacement for HTML Canvas (e.g. node.js)</h2> 19cb93a386Sopenharmony_ci<img id=api1 width=300 height=300> 20cb93a386Sopenharmony_ci<canvas id=api1_c width=300 height=300></canvas> 21cb93a386Sopenharmony_ci<img id=api2 width=300 height=300> 22cb93a386Sopenharmony_ci<canvas id=api2_c width=300 height=300></canvas> 23cb93a386Sopenharmony_ci<img id=api3 width=300 height=300> 24cb93a386Sopenharmony_ci<canvas id=api3_c width=300 height=300></canvas> 25cb93a386Sopenharmony_ci<img id=api4 width=300 height=300> 26cb93a386Sopenharmony_ci<canvas id=api4_c width=300 height=300></canvas> 27cb93a386Sopenharmony_ci<img id=api5 width=300 height=300> 28cb93a386Sopenharmony_ci<canvas id=api5_c width=300 height=300></canvas> 29cb93a386Sopenharmony_ci<img id=api6 width=300 height=300> 30cb93a386Sopenharmony_ci<canvas id=api6_c width=300 height=300></canvas> 31cb93a386Sopenharmony_ci<img id=api7 width=300 height=300> 32cb93a386Sopenharmony_ci<canvas id=api7_c width=300 height=300></canvas> 33cb93a386Sopenharmony_ci<img id=api8 width=300 height=300> 34cb93a386Sopenharmony_ci<canvas id=api8_c width=300 height=300></canvas> 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ci<h2> CanvasKit expands the functionality of a stock HTML canvas</h2> 37cb93a386Sopenharmony_ci<canvas id=vertex1 width=300 height=300></canvas> 38cb93a386Sopenharmony_ci<canvas id=gradient1 width=300 height=300></canvas> 39cb93a386Sopenharmony_ci<canvas id=patheffect width=300 height=300></canvas> 40cb93a386Sopenharmony_ci<canvas id=paths width=200 height=200></canvas> 41cb93a386Sopenharmony_ci<canvas id=pathperson width=300 height=300></canvas> 42cb93a386Sopenharmony_ci<canvas id=ink width=300 height=300></canvas> 43cb93a386Sopenharmony_ci<canvas id=surfaces width=300 height=300></canvas> 44cb93a386Sopenharmony_ci<canvas id=atlas width=300 height=300></canvas> 45cb93a386Sopenharmony_ci<canvas id=decode width=300 height=300></canvas> 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci<h2> CanvasKit can allow for text measurement/placement (e.g. breaking, kerning)</h2> 48cb93a386Sopenharmony_ci<canvas id=textonpath width=300 height=300></canvas> 49cb93a386Sopenharmony_ci<canvas id=drawGlyphs width=300 height=300></canvas> 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci<h2> Interactive drawPatch</h2> 52cb93a386Sopenharmony_ci<canvas id=interdrawpatch width=512 height=512></canvas> 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci<script type="text/javascript" src="/build/canvaskit.js"></script> 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci<script type="text/javascript" charset="utf-8"> 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci var CanvasKit = null; 59cb93a386Sopenharmony_ci var cdn = 'https://storage.googleapis.com/skia-cdn/misc/'; 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci const ckLoaded = CanvasKitInit({locateFile: (file) => '/build/'+file}); 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ci const loadRoboto = fetch(cdn + 'Roboto-Regular.ttf').then((response) => response.arrayBuffer()); 64cb93a386Sopenharmony_ci const loadNotoSerif = fetch(cdn + 'NotoSerif-Regular.ttf').then((response) => response.arrayBuffer()); 65cb93a386Sopenharmony_ci const loadTestImage = fetch(cdn + 'test.png').then((response) => response.arrayBuffer()); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci // Examples which only require canvaskit 68cb93a386Sopenharmony_ci ckLoaded.then((CK) => { 69cb93a386Sopenharmony_ci CanvasKit = CK; 70cb93a386Sopenharmony_ci PathExample(CanvasKit); 71cb93a386Sopenharmony_ci InkExample(CanvasKit); 72cb93a386Sopenharmony_ci PathPersonExample(CanvasKit); 73cb93a386Sopenharmony_ci VertexAPI1(CanvasKit); 74cb93a386Sopenharmony_ci GradiantAPI1(CanvasKit); 75cb93a386Sopenharmony_ci TextOnPathAPI1(CanvasKit); 76cb93a386Sopenharmony_ci DrawGlyphsAPI1(CanvasKit); 77cb93a386Sopenharmony_ci SurfaceAPI1(CanvasKit); 78cb93a386Sopenharmony_ci CanvasAPI1(CanvasKit); 79cb93a386Sopenharmony_ci CanvasAPI2(CanvasKit); 80cb93a386Sopenharmony_ci CanvasAPI3(CanvasKit); 81cb93a386Sopenharmony_ci CanvasAPI4(CanvasKit); 82cb93a386Sopenharmony_ci CanvasAPI5(CanvasKit); 83cb93a386Sopenharmony_ci CanvasAPI6(CanvasKit); 84cb93a386Sopenharmony_ci CanvasAPI7(CanvasKit); 85cb93a386Sopenharmony_ci CanvasAPI8(CanvasKit); 86cb93a386Sopenharmony_ci InteractivePatch(CanvasKit); 87cb93a386Sopenharmony_ci }); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci // Examples requiring external resources 90cb93a386Sopenharmony_ci Promise.all([ckLoaded, loadRoboto]).then((results) => {DrawingExample(...results)}); 91cb93a386Sopenharmony_ci Promise.all([ckLoaded, loadTestImage]).then((results) => {AtlasAPI1(...results)}); 92cb93a386Sopenharmony_ci Promise.all([ckLoaded, loadTestImage]).then((results) => {DecodeAPI(...results)}); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci function DrawingExample(CanvasKit, robotoData) { 95cb93a386Sopenharmony_ci if (!robotoData || !CanvasKit) { 96cb93a386Sopenharmony_ci return; 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('patheffect'); 99cb93a386Sopenharmony_ci if (!surface) { 100cb93a386Sopenharmony_ci console.error('Could not make surface'); 101cb93a386Sopenharmony_ci return; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 105cb93a386Sopenharmony_ci const roboto = CanvasKit.Typeface.MakeFreeTypeFaceFromData(robotoData); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci const textPaint = new CanvasKit.Paint(); 108cb93a386Sopenharmony_ci textPaint.setColor(CanvasKit.RED); 109cb93a386Sopenharmony_ci textPaint.setAntiAlias(true); 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci const textFont = new CanvasKit.Font(roboto, 30); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci let i = 0; 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci let X = 128; 116cb93a386Sopenharmony_ci let Y = 128; 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci function drawFrame(canvas) { 119cb93a386Sopenharmony_ci const path = starPath(CanvasKit, X, Y); 120cb93a386Sopenharmony_ci // Some animations see performance improvements by marking their 121cb93a386Sopenharmony_ci // paths as volatile. 122cb93a386Sopenharmony_ci path.setIsVolatile(true); 123cb93a386Sopenharmony_ci const dpe = CanvasKit.PathEffect.MakeDash([15, 5, 5, 10], i/5); 124cb93a386Sopenharmony_ci i++; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci paint.setPathEffect(dpe); 127cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Stroke); 128cb93a386Sopenharmony_ci paint.setStrokeWidth(5.0 + -3 * Math.cos(i/30)); 129cb93a386Sopenharmony_ci paint.setAntiAlias(true); 130cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(66, 129, 164, 1.0)); 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_ci canvas.clear(CanvasKit.TRANSPARENT); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci canvas.drawPath(path, paint); 135cb93a386Sopenharmony_ci canvas.drawText('Try Clicking!', 10, 280, textPaint, textFont); 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci dpe.delete(); 138cb93a386Sopenharmony_ci path.delete(); 139cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci // Make animation interactive 144cb93a386Sopenharmony_ci let interact = (e) => { 145cb93a386Sopenharmony_ci if (!e.pressure) { 146cb93a386Sopenharmony_ci return; 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci X = e.offsetX; 149cb93a386Sopenharmony_ci Y = e.offsetY; 150cb93a386Sopenharmony_ci }; 151cb93a386Sopenharmony_ci document.getElementById('patheffect').addEventListener('pointermove', interact); 152cb93a386Sopenharmony_ci document.getElementById('patheffect').addEventListener('pointerdown', interact); 153cb93a386Sopenharmony_ci preventScrolling(document.getElementById('patheffect')); 154cb93a386Sopenharmony_ci // A client would need to delete this if it didn't go on for ever. 155cb93a386Sopenharmony_ci // paint.delete(); 156cb93a386Sopenharmony_ci // textPaint.delete(); 157cb93a386Sopenharmony_ci // textFont.delete(); 158cb93a386Sopenharmony_ci } 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci function InteractivePatch(CanvasKit) { 161cb93a386Sopenharmony_ci const ELEM = 'interdrawpatch'; 162cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface(ELEM); 163cb93a386Sopenharmony_ci if (!surface) { 164cb93a386Sopenharmony_ci console.error('Could not make surface'); 165cb93a386Sopenharmony_ci return; 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ci let live_corner, live_index; 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 171cb93a386Sopenharmony_ci const pts_paint = new CanvasKit.Paint(); 172cb93a386Sopenharmony_ci pts_paint.setStyle(CanvasKit.PaintStyle.Stroke); 173cb93a386Sopenharmony_ci pts_paint.setStrokeWidth(9); 174cb93a386Sopenharmony_ci pts_paint.setStrokeCap(CanvasKit.StrokeCap.Round); 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci const line_paint = new CanvasKit.Paint(); 177cb93a386Sopenharmony_ci line_paint.setStyle(CanvasKit.PaintStyle.Stroke); 178cb93a386Sopenharmony_ci line_paint.setStrokeWidth(2); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci const colors = [CanvasKit.RED, CanvasKit.BLUE, CanvasKit.YELLOW, CanvasKit.CYAN]; 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci const patch = [ 183cb93a386Sopenharmony_ci [ 10,170, 10, 10, 170, 10], // prev_vector, point, next_vector 184cb93a386Sopenharmony_ci [340, 10, 500, 10, 500,170], 185cb93a386Sopenharmony_ci [500,340, 500,500, 340,500], 186cb93a386Sopenharmony_ci [170,500, 10,500, 10,340], 187cb93a386Sopenharmony_ci ]; 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci function get_corner(corner, index) { 190cb93a386Sopenharmony_ci return [corner[index*2+0], corner[index*2+1]]; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci function push_xy(array, xy) { 194cb93a386Sopenharmony_ci array.push(xy[0], xy[1]); 195cb93a386Sopenharmony_ci } 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_ci function patch_to_cubics(patch) { 198cb93a386Sopenharmony_ci const array = []; 199cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[0],1)); 200cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[0],2)); 201cb93a386Sopenharmony_ci for (let i = 1; i < 4; ++i) { 202cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[i],0)); 203cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[i],1)); 204cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[i],2)); 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci push_xy(array, get_corner(patch[0],0)); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci return array; 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci 211cb93a386Sopenharmony_ci function drawFrame(canvas) { 212cb93a386Sopenharmony_ci const cubics = patch_to_cubics(patch); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci canvas.drawColor(CanvasKit.WHITE); 215cb93a386Sopenharmony_ci canvas.drawPatch(cubics, colors, null, null, paint); 216cb93a386Sopenharmony_ci if (live_corner) { 217cb93a386Sopenharmony_ci canvas.drawPoints(CanvasKit.PointMode.Polygon, live_corner, line_paint); 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci canvas.drawPoints(CanvasKit.PointMode.Points, cubics, pts_paint); 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci function length2(x, y) { 227cb93a386Sopenharmony_ci return x*x + y*y; 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci function hit_test(x,y, x1,y1) { 230cb93a386Sopenharmony_ci return length2(x-x1, y-y1) <= 10*10; 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci function pointer_up(e) { 233cb93a386Sopenharmony_ci live_corner = null; 234cb93a386Sopenharmony_ci live_index = null; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci function pointer_down(e) { 238cb93a386Sopenharmony_ci live_corner = null; 239cb93a386Sopenharmony_ci live_index = null; 240cb93a386Sopenharmony_ci for (p of patch) { 241cb93a386Sopenharmony_ci for (let i = 0; i < 6; i += 2) { 242cb93a386Sopenharmony_ci if (hit_test(p[i], p[i+1], e.offsetX, e.offsetY)) { 243cb93a386Sopenharmony_ci live_corner = p; 244cb93a386Sopenharmony_ci live_index = i; 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci } 247cb93a386Sopenharmony_ci } 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci function pointer_move(e) { 251cb93a386Sopenharmony_ci if (e.pressure && live_corner) { 252cb93a386Sopenharmony_ci if (live_index == 2) { 253cb93a386Sopenharmony_ci // corner 254cb93a386Sopenharmony_ci const dx = e.offsetX - live_corner[2]; 255cb93a386Sopenharmony_ci const dy = e.offsetY - live_corner[3]; 256cb93a386Sopenharmony_ci for (let i = 0; i < 3; ++i) { 257cb93a386Sopenharmony_ci live_corner[i*2+0] += dx; 258cb93a386Sopenharmony_ci live_corner[i*2+1] += dy; 259cb93a386Sopenharmony_ci } 260cb93a386Sopenharmony_ci } else { 261cb93a386Sopenharmony_ci // control-point 262cb93a386Sopenharmony_ci live_corner[live_index+0] = e.offsetX; 263cb93a386Sopenharmony_ci live_corner[live_index+1] = e.offsetY; 264cb93a386Sopenharmony_ci } 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci } 267cb93a386Sopenharmony_ci document.getElementById(ELEM).addEventListener('pointermove', pointer_move); 268cb93a386Sopenharmony_ci document.getElementById(ELEM).addEventListener('pointerdown', pointer_down); 269cb93a386Sopenharmony_ci document.getElementById(ELEM).addEventListener('pointerup', pointer_up); 270cb93a386Sopenharmony_ci preventScrolling(document.getElementById(ELEM)); 271cb93a386Sopenharmony_ci } 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_ci function PathPersonExample(CanvasKit) { 274cb93a386Sopenharmony_ci const surface = CanvasKit.MakeSWCanvasSurface('pathperson'); 275cb93a386Sopenharmony_ci if (!surface) { 276cb93a386Sopenharmony_ci console.error('Could not make surface'); 277cb93a386Sopenharmony_ci return; 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci function drawFrame(canvas) { 281cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 282cb93a386Sopenharmony_ci paint.setStrokeWidth(1.0); 283cb93a386Sopenharmony_ci paint.setAntiAlias(true); 284cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 285cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Stroke); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci const path = new CanvasKit.Path(); 288cb93a386Sopenharmony_ci path.moveTo(10, 10); 289cb93a386Sopenharmony_ci path.lineTo(100, 10); 290cb93a386Sopenharmony_ci path.moveTo(10, 10); 291cb93a386Sopenharmony_ci path.lineTo(10, 200); 292cb93a386Sopenharmony_ci path.moveTo(10, 100); 293cb93a386Sopenharmony_ci path.lineTo(100,100); 294cb93a386Sopenharmony_ci path.moveTo(10, 200); 295cb93a386Sopenharmony_ci path.lineTo(100, 200); 296cb93a386Sopenharmony_ci 297cb93a386Sopenharmony_ci canvas.drawPath(path, paint); 298cb93a386Sopenharmony_ci path.delete(); 299cb93a386Sopenharmony_ci paint.delete(); 300cb93a386Sopenharmony_ci } 301cb93a386Sopenharmony_ci // Intentionally just draw frame once 302cb93a386Sopenharmony_ci surface.drawOnce(drawFrame); 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci 305cb93a386Sopenharmony_ci function PathExample(CanvasKit) { 306cb93a386Sopenharmony_ci const surface = CanvasKit.MakeSWCanvasSurface('paths'); 307cb93a386Sopenharmony_ci if (!surface) { 308cb93a386Sopenharmony_ci console.error('Could not make surface'); 309cb93a386Sopenharmony_ci return; 310cb93a386Sopenharmony_ci } 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci function drawFrame(canvas) { 313cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 314cb93a386Sopenharmony_ci paint.setStrokeWidth(1.0); 315cb93a386Sopenharmony_ci paint.setAntiAlias(true); 316cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 317cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Stroke); 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci const path = new CanvasKit.Path(); 320cb93a386Sopenharmony_ci path.moveTo(20, 5); 321cb93a386Sopenharmony_ci path.lineTo(30, 20); 322cb93a386Sopenharmony_ci path.lineTo(40, 10); 323cb93a386Sopenharmony_ci path.lineTo(50, 20); 324cb93a386Sopenharmony_ci path.lineTo(60, 0); 325cb93a386Sopenharmony_ci path.lineTo(20, 5); 326cb93a386Sopenharmony_ci 327cb93a386Sopenharmony_ci path.moveTo(20, 80); 328cb93a386Sopenharmony_ci path.cubicTo(90, 10, 160, 150, 190, 10); 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci path.moveTo(36, 148); 331cb93a386Sopenharmony_ci path.quadTo(66, 188, 120, 136); 332cb93a386Sopenharmony_ci path.lineTo(36, 148); 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_ci path.moveTo(150, 180); 335cb93a386Sopenharmony_ci path.arcToTangent(150, 100, 50, 200, 20); 336cb93a386Sopenharmony_ci path.lineTo(160, 160); 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ci path.moveTo(20, 120); 339cb93a386Sopenharmony_ci path.lineTo(20, 120); 340cb93a386Sopenharmony_ci 341cb93a386Sopenharmony_ci canvas.drawPath(path, paint); 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci const rrect = CanvasKit.RRectXY([100, 10, 140, 62], 10, 4); 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci const rrectPath = new CanvasKit.Path().addRRect(rrect, true); 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ci canvas.drawPath(rrectPath, paint); 348cb93a386Sopenharmony_ci 349cb93a386Sopenharmony_ci rrectPath.delete(); 350cb93a386Sopenharmony_ci path.delete(); 351cb93a386Sopenharmony_ci paint.delete(); 352cb93a386Sopenharmony_ci } 353cb93a386Sopenharmony_ci // Intentionally just draw frame once 354cb93a386Sopenharmony_ci surface.drawOnce(drawFrame); 355cb93a386Sopenharmony_ci } 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci function preventScrolling(canvas) { 358cb93a386Sopenharmony_ci canvas.addEventListener('touchmove', (e) => { 359cb93a386Sopenharmony_ci // Prevents touch events in the canvas from scrolling the canvas. 360cb93a386Sopenharmony_ci e.preventDefault(); 361cb93a386Sopenharmony_ci e.stopPropagation(); 362cb93a386Sopenharmony_ci }); 363cb93a386Sopenharmony_ci } 364cb93a386Sopenharmony_ci 365cb93a386Sopenharmony_ci function InkExample(CanvasKit) { 366cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('ink'); 367cb93a386Sopenharmony_ci if (!surface) { 368cb93a386Sopenharmony_ci console.error('Could not make surface'); 369cb93a386Sopenharmony_ci return; 370cb93a386Sopenharmony_ci } 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci let paint = new CanvasKit.Paint(); 373cb93a386Sopenharmony_ci paint.setAntiAlias(true); 374cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(0, 0, 0, 1.0)); 375cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Stroke); 376cb93a386Sopenharmony_ci paint.setStrokeWidth(4.0); 377cb93a386Sopenharmony_ci paint.setPathEffect(CanvasKit.PathEffect.MakeCorner(50)); 378cb93a386Sopenharmony_ci 379cb93a386Sopenharmony_ci // Draw I N K 380cb93a386Sopenharmony_ci let path = new CanvasKit.Path(); 381cb93a386Sopenharmony_ci path.moveTo(80, 30); 382cb93a386Sopenharmony_ci path.lineTo(80, 80); 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci path.moveTo(100, 80); 385cb93a386Sopenharmony_ci path.lineTo(100, 15); 386cb93a386Sopenharmony_ci path.lineTo(130, 95); 387cb93a386Sopenharmony_ci path.lineTo(130, 30); 388cb93a386Sopenharmony_ci 389cb93a386Sopenharmony_ci path.moveTo(150, 30); 390cb93a386Sopenharmony_ci path.lineTo(150, 80); 391cb93a386Sopenharmony_ci path.moveTo(170, 30); 392cb93a386Sopenharmony_ci path.lineTo(150, 55); 393cb93a386Sopenharmony_ci path.lineTo(170, 80); 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci let paths = [path]; 396cb93a386Sopenharmony_ci let paints = [paint]; 397cb93a386Sopenharmony_ci 398cb93a386Sopenharmony_ci function drawFrame(canvas) { 399cb93a386Sopenharmony_ci canvas.clear(CanvasKit.Color(255, 255, 255, 1.0)); 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci for (let i = 0; i < paints.length && i < paths.length; i++) { 402cb93a386Sopenharmony_ci canvas.drawPath(paths[i], paints[i]); 403cb93a386Sopenharmony_ci } 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 406cb93a386Sopenharmony_ci } 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci let hold = false; 409cb93a386Sopenharmony_ci let interact = (e) => { 410cb93a386Sopenharmony_ci let type = e.type; 411cb93a386Sopenharmony_ci if (type === 'lostpointercapture' || type === 'pointerup' || !e.pressure ) { 412cb93a386Sopenharmony_ci hold = false; 413cb93a386Sopenharmony_ci return; 414cb93a386Sopenharmony_ci } 415cb93a386Sopenharmony_ci if (hold) { 416cb93a386Sopenharmony_ci path.lineTo(e.offsetX, e.offsetY); 417cb93a386Sopenharmony_ci } else { 418cb93a386Sopenharmony_ci paint = paint.copy(); 419cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(Math.random() * 255, Math.random() * 255, Math.random() * 255, Math.random() + .2)); 420cb93a386Sopenharmony_ci paints.push(paint); 421cb93a386Sopenharmony_ci path = new CanvasKit.Path(); 422cb93a386Sopenharmony_ci paths.push(path); 423cb93a386Sopenharmony_ci path.moveTo(e.offsetX, e.offsetY); 424cb93a386Sopenharmony_ci } 425cb93a386Sopenharmony_ci hold = true; 426cb93a386Sopenharmony_ci }; 427cb93a386Sopenharmony_ci document.getElementById('ink').addEventListener('pointermove', interact); 428cb93a386Sopenharmony_ci document.getElementById('ink').addEventListener('pointerdown', interact); 429cb93a386Sopenharmony_ci document.getElementById('ink').addEventListener('lostpointercapture', interact); 430cb93a386Sopenharmony_ci document.getElementById('ink').addEventListener('pointerup', interact); 431cb93a386Sopenharmony_ci preventScrolling(document.getElementById('ink')); 432cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 433cb93a386Sopenharmony_ci } 434cb93a386Sopenharmony_ci 435cb93a386Sopenharmony_ci function starPath(CanvasKit, X=128, Y=128, R=116) { 436cb93a386Sopenharmony_ci let p = new CanvasKit.Path(); 437cb93a386Sopenharmony_ci p.moveTo(X + R, Y); 438cb93a386Sopenharmony_ci for (let i = 1; i < 8; i++) { 439cb93a386Sopenharmony_ci let a = 2.6927937 * i; 440cb93a386Sopenharmony_ci p.lineTo(X + R * Math.cos(a), Y + R * Math.sin(a)); 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci return p; 443cb93a386Sopenharmony_ci } 444cb93a386Sopenharmony_ci 445cb93a386Sopenharmony_ci function CanvasAPI1(CanvasKit) { 446cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 447cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api1_c'); 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_ci let skPromise = fetch(cdn + 'test.png') 450cb93a386Sopenharmony_ci // if clients want to use a Blob, they are responsible 451cb93a386Sopenharmony_ci // for reading it themselves. 452cb93a386Sopenharmony_ci .then((response) => response.arrayBuffer()) 453cb93a386Sopenharmony_ci .then((buffer) => { 454cb93a386Sopenharmony_ci skcanvas._img = skcanvas.decodeImage(buffer); 455cb93a386Sopenharmony_ci }); 456cb93a386Sopenharmony_ci let realPromise = fetch(cdn + 'test.png') 457cb93a386Sopenharmony_ci .then((response) => response.blob()) 458cb93a386Sopenharmony_ci .then((blob) => createImageBitmap(blob)) 459cb93a386Sopenharmony_ci .then((bitmap) => { 460cb93a386Sopenharmony_ci realCanvas._img = bitmap; 461cb93a386Sopenharmony_ci }); 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_ci let realFontLoaded = new FontFace('Bungee', 'url(/tests/assets/Bungee-Regular.ttf)', { 464cb93a386Sopenharmony_ci 'family': 'Bungee', 465cb93a386Sopenharmony_ci 'style': 'normal', 466cb93a386Sopenharmony_ci 'weight': '400', 467cb93a386Sopenharmony_ci }).load().then((font) => { 468cb93a386Sopenharmony_ci document.fonts.add(font); 469cb93a386Sopenharmony_ci }); 470cb93a386Sopenharmony_ci 471cb93a386Sopenharmony_ci let skFontLoaded = fetch('/tests/assets/Bungee-Regular.ttf').then( 472cb93a386Sopenharmony_ci (response) => response.arrayBuffer()).then( 473cb93a386Sopenharmony_ci (buffer) => { 474cb93a386Sopenharmony_ci // loadFont is synchronous 475cb93a386Sopenharmony_ci skcanvas.loadFont(buffer, { 476cb93a386Sopenharmony_ci 'family': 'Bungee', 477cb93a386Sopenharmony_ci 'style': 'normal', 478cb93a386Sopenharmony_ci 'weight': '400', 479cb93a386Sopenharmony_ci }); 480cb93a386Sopenharmony_ci }); 481cb93a386Sopenharmony_ci 482cb93a386Sopenharmony_ci Promise.all([realPromise, skPromise, realFontLoaded, skFontLoaded]).then(() => { 483cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 484cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 485cb93a386Sopenharmony_ci ctx.fillStyle = '#EEE'; 486cb93a386Sopenharmony_ci ctx.fillRect(0, 0, 300, 300); 487cb93a386Sopenharmony_ci ctx.fillStyle = 'black'; 488cb93a386Sopenharmony_ci ctx.font = '26px Bungee'; 489cb93a386Sopenharmony_ci ctx.rotate(.1); 490cb93a386Sopenharmony_ci ctx.fillText('Awesome ', 25, 100); 491cb93a386Sopenharmony_ci ctx.strokeText('Groovy!', 200, 100); 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_ci // Draw line under Awesome 494cb93a386Sopenharmony_ci ctx.strokeStyle = 'rgba(125,0,0,0.5)'; 495cb93a386Sopenharmony_ci ctx.beginPath(); 496cb93a386Sopenharmony_ci ctx.lineWidth = 6; 497cb93a386Sopenharmony_ci ctx.moveTo(25, 105); 498cb93a386Sopenharmony_ci ctx.lineTo(200, 105); 499cb93a386Sopenharmony_ci ctx.stroke(); 500cb93a386Sopenharmony_ci 501cb93a386Sopenharmony_ci // squished vertically 502cb93a386Sopenharmony_ci ctx.globalAlpha = 0.7; 503cb93a386Sopenharmony_ci ctx.imageSmoothingQuality = 'medium'; 504cb93a386Sopenharmony_ci ctx.drawImage(canvas._img, 150, 150, 150, 100); 505cb93a386Sopenharmony_ci ctx.rotate(-.2); 506cb93a386Sopenharmony_ci ctx.imageSmoothingEnabled = false; 507cb93a386Sopenharmony_ci ctx.drawImage(canvas._img, 100, 150, 400, 350, 10, 200, 150, 100); 508cb93a386Sopenharmony_ci 509cb93a386Sopenharmony_ci let idata = ctx.getImageData(80, 220, 40, 45); 510cb93a386Sopenharmony_ci ctx.putImageData(idata, 250, 10); 511cb93a386Sopenharmony_ci ctx.putImageData(idata, 200, 10, 20, 10, 20, 30); 512cb93a386Sopenharmony_ci ctx.resetTransform(); 513cb93a386Sopenharmony_ci ctx.strokeStyle = 'black'; 514cb93a386Sopenharmony_ci ctx.lineWidth = 1; 515cb93a386Sopenharmony_ci ctx.strokeRect(200, 10, 40, 45); 516cb93a386Sopenharmony_ci 517cb93a386Sopenharmony_ci idata = ctx.createImageData(10, 20); 518cb93a386Sopenharmony_ci ctx.putImageData(idata, 10, 10); 519cb93a386Sopenharmony_ci } 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_ci document.getElementById('api1').src = skcanvas.toDataURL(); 522cb93a386Sopenharmony_ci skcanvas.dispose(); 523cb93a386Sopenharmony_ci }); 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_ci } 526cb93a386Sopenharmony_ci 527cb93a386Sopenharmony_ci function CanvasAPI2(CanvasKit) { 528cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 529cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api2_c'); 530cb93a386Sopenharmony_ci realCanvas.width = 300; 531cb93a386Sopenharmony_ci realCanvas.height = 300; 532cb93a386Sopenharmony_ci 533cb93a386Sopenharmony_ci // svg data for a clock 534cb93a386Sopenharmony_ci skcanvas._path = skcanvas.makePath2D('M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z'); 535cb93a386Sopenharmony_ci realCanvas._path = new Path2D('M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z'); 536cb93a386Sopenharmony_ci 537cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 538cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 539cb93a386Sopenharmony_ci ctx.scale(1.5, 1.5); 540cb93a386Sopenharmony_ci ctx.moveTo(20, 5); 541cb93a386Sopenharmony_ci ctx.lineTo(30, 20); 542cb93a386Sopenharmony_ci ctx.lineTo(40, 10); 543cb93a386Sopenharmony_ci ctx.lineTo(50, 20); 544cb93a386Sopenharmony_ci ctx.lineTo(60, 0); 545cb93a386Sopenharmony_ci ctx.lineTo(20, 5); 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_ci ctx.moveTo(20, 80); 548cb93a386Sopenharmony_ci ctx.bezierCurveTo(90, 10, 160, 150, 190, 10); 549cb93a386Sopenharmony_ci 550cb93a386Sopenharmony_ci ctx.moveTo(36, 148); 551cb93a386Sopenharmony_ci ctx.quadraticCurveTo(66, 188, 120, 136); 552cb93a386Sopenharmony_ci ctx.lineTo(36, 148); 553cb93a386Sopenharmony_ci 554cb93a386Sopenharmony_ci ctx.rect(5, 170, 20, 25); 555cb93a386Sopenharmony_ci 556cb93a386Sopenharmony_ci ctx.moveTo(150, 180); 557cb93a386Sopenharmony_ci ctx.arcTo(150, 100, 50, 200, 20); 558cb93a386Sopenharmony_ci ctx.lineTo(160, 160); 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_ci ctx.moveTo(20, 120); 561cb93a386Sopenharmony_ci ctx.arc(20, 120, 18, 0, 1.75 * Math.PI); 562cb93a386Sopenharmony_ci ctx.lineTo(20, 120); 563cb93a386Sopenharmony_ci 564cb93a386Sopenharmony_ci ctx.moveTo(150, 5); 565cb93a386Sopenharmony_ci ctx.ellipse(130, 25, 30, 10, -1*Math.PI/8, Math.PI/6, 1.5*Math.PI); 566cb93a386Sopenharmony_ci 567cb93a386Sopenharmony_ci ctx.lineWidth = 4/3; 568cb93a386Sopenharmony_ci ctx.stroke(); 569cb93a386Sopenharmony_ci 570cb93a386Sopenharmony_ci // make a clock 571cb93a386Sopenharmony_ci ctx.stroke(canvas._path); 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_ci // Test edgecases and draw direction 574cb93a386Sopenharmony_ci ctx.beginPath(); 575cb93a386Sopenharmony_ci ctx.arc(50, 100, 10, Math.PI, -Math.PI/2); 576cb93a386Sopenharmony_ci ctx.stroke(); 577cb93a386Sopenharmony_ci ctx.beginPath(); 578cb93a386Sopenharmony_ci ctx.arc(75, 100, 10, Math.PI, -Math.PI/2, true); 579cb93a386Sopenharmony_ci ctx.stroke(); 580cb93a386Sopenharmony_ci ctx.beginPath(); 581cb93a386Sopenharmony_ci ctx.arc(100, 100, 10, Math.PI, 100.1 * Math.PI, true); 582cb93a386Sopenharmony_ci ctx.stroke(); 583cb93a386Sopenharmony_ci ctx.beginPath(); 584cb93a386Sopenharmony_ci ctx.arc(125, 100, 10, Math.PI, 100.1 * Math.PI, false); 585cb93a386Sopenharmony_ci ctx.stroke(); 586cb93a386Sopenharmony_ci ctx.beginPath(); 587cb93a386Sopenharmony_ci ctx.ellipse(155, 100, 10, 15, Math.PI/8, 100.1 * Math.PI, Math.PI, true); 588cb93a386Sopenharmony_ci ctx.stroke(); 589cb93a386Sopenharmony_ci ctx.beginPath(); 590cb93a386Sopenharmony_ci ctx.ellipse(180, 100, 10, 15, Math.PI/8, Math.PI, 100.1 * Math.PI, true); 591cb93a386Sopenharmony_ci ctx.stroke(); 592cb93a386Sopenharmony_ci } 593cb93a386Sopenharmony_ci document.getElementById('api2').src = skcanvas.toDataURL(); 594cb93a386Sopenharmony_ci skcanvas.dispose(); 595cb93a386Sopenharmony_ci } 596cb93a386Sopenharmony_ci 597cb93a386Sopenharmony_ci function CanvasAPI3(CanvasKit) { 598cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 599cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api3_c'); 600cb93a386Sopenharmony_ci realCanvas.width = 300; 601cb93a386Sopenharmony_ci realCanvas.height = 300; 602cb93a386Sopenharmony_ci 603cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 604cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 605cb93a386Sopenharmony_ci ctx.rect(10, 10, 20, 20); 606cb93a386Sopenharmony_ci 607cb93a386Sopenharmony_ci ctx.scale(2.0, 4.0); 608cb93a386Sopenharmony_ci ctx.rect(30, 10, 20, 20); 609cb93a386Sopenharmony_ci ctx.resetTransform(); 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_ci ctx.rotate(Math.PI / 3); 612cb93a386Sopenharmony_ci ctx.rect(50, 10, 20, 20); 613cb93a386Sopenharmony_ci ctx.resetTransform(); 614cb93a386Sopenharmony_ci 615cb93a386Sopenharmony_ci ctx.translate(30, -2); 616cb93a386Sopenharmony_ci ctx.rect(70, 10, 20, 20); 617cb93a386Sopenharmony_ci ctx.resetTransform(); 618cb93a386Sopenharmony_ci 619cb93a386Sopenharmony_ci ctx.translate(60, 0); 620cb93a386Sopenharmony_ci ctx.rotate(Math.PI / 6); 621cb93a386Sopenharmony_ci ctx.transform(1.5, 0, 0, 0.5, 0, 0); // effectively scale 622cb93a386Sopenharmony_ci ctx.rect(90, 10, 20, 20); 623cb93a386Sopenharmony_ci ctx.resetTransform(); 624cb93a386Sopenharmony_ci 625cb93a386Sopenharmony_ci ctx.save(); 626cb93a386Sopenharmony_ci ctx.setTransform(2, 0, -.5, 2.5, -40, 120); 627cb93a386Sopenharmony_ci ctx.rect(110, 10, 20, 20); 628cb93a386Sopenharmony_ci ctx.lineTo(110, 0); 629cb93a386Sopenharmony_ci ctx.restore(); 630cb93a386Sopenharmony_ci ctx.lineTo(220, 120); 631cb93a386Sopenharmony_ci 632cb93a386Sopenharmony_ci ctx.scale(3.0, 3.0); 633cb93a386Sopenharmony_ci ctx.font = '6pt Noto Mono'; 634cb93a386Sopenharmony_ci ctx.fillText('This text should be huge', 10, 80); 635cb93a386Sopenharmony_ci ctx.resetTransform(); 636cb93a386Sopenharmony_ci 637cb93a386Sopenharmony_ci ctx.strokeStyle = 'black'; 638cb93a386Sopenharmony_ci ctx.lineWidth = 2; 639cb93a386Sopenharmony_ci ctx.stroke(); 640cb93a386Sopenharmony_ci 641cb93a386Sopenharmony_ci ctx.beginPath(); 642cb93a386Sopenharmony_ci ctx.moveTo(250, 30); 643cb93a386Sopenharmony_ci ctx.lineTo(250, 80); 644cb93a386Sopenharmony_ci ctx.scale(3.0, 3.0); 645cb93a386Sopenharmony_ci ctx.lineTo(280/3, 90/3); 646cb93a386Sopenharmony_ci ctx.closePath(); 647cb93a386Sopenharmony_ci ctx.strokeStyle = 'black'; 648cb93a386Sopenharmony_ci ctx.lineWidth = 5; 649cb93a386Sopenharmony_ci ctx.stroke(); 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ci } 652cb93a386Sopenharmony_ci document.getElementById('api3').src = skcanvas.toDataURL(); 653cb93a386Sopenharmony_ci skcanvas.dispose(); 654cb93a386Sopenharmony_ci } 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci function CanvasAPI4(CanvasKit) { 657cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 658cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api4_c'); 659cb93a386Sopenharmony_ci realCanvas.width = 300; 660cb93a386Sopenharmony_ci realCanvas.height = 300; 661cb93a386Sopenharmony_ci 662cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 663cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 664cb93a386Sopenharmony_ci 665cb93a386Sopenharmony_ci ctx.strokeStyle = '#000'; 666cb93a386Sopenharmony_ci ctx.fillStyle = '#CCC'; 667cb93a386Sopenharmony_ci ctx.shadowColor = 'rebeccapurple'; 668cb93a386Sopenharmony_ci ctx.shadowBlur = 1; 669cb93a386Sopenharmony_ci ctx.shadowOffsetX = 3; 670cb93a386Sopenharmony_ci ctx.shadowOffsetY = -8; 671cb93a386Sopenharmony_ci ctx.rect(10, 10, 30, 30); 672cb93a386Sopenharmony_ci 673cb93a386Sopenharmony_ci ctx.save(); 674cb93a386Sopenharmony_ci ctx.strokeStyle = '#C00'; 675cb93a386Sopenharmony_ci ctx.fillStyle = '#00C'; 676cb93a386Sopenharmony_ci ctx.shadowBlur = 0; 677cb93a386Sopenharmony_ci ctx.shadowColor = 'transparent'; 678cb93a386Sopenharmony_ci 679cb93a386Sopenharmony_ci ctx.stroke(); 680cb93a386Sopenharmony_ci 681cb93a386Sopenharmony_ci ctx.restore(); 682cb93a386Sopenharmony_ci ctx.fill(); 683cb93a386Sopenharmony_ci 684cb93a386Sopenharmony_ci ctx.beginPath(); 685cb93a386Sopenharmony_ci ctx.moveTo(36, 148); 686cb93a386Sopenharmony_ci ctx.quadraticCurveTo(66, 188, 120, 136); 687cb93a386Sopenharmony_ci ctx.closePath(); 688cb93a386Sopenharmony_ci ctx.stroke(); 689cb93a386Sopenharmony_ci 690cb93a386Sopenharmony_ci ctx.beginPath(); 691cb93a386Sopenharmony_ci ctx.shadowColor = '#993366AA'; 692cb93a386Sopenharmony_ci ctx.shadowOffsetX = 8; 693cb93a386Sopenharmony_ci ctx.shadowBlur = 5; 694cb93a386Sopenharmony_ci ctx.setTransform(2, 0, -.5, 2.5, -40, 120); 695cb93a386Sopenharmony_ci ctx.rect(110, 10, 20, 20); 696cb93a386Sopenharmony_ci ctx.lineTo(110, 0); 697cb93a386Sopenharmony_ci ctx.resetTransform(); 698cb93a386Sopenharmony_ci ctx.lineTo(220, 120); 699cb93a386Sopenharmony_ci ctx.stroke(); 700cb93a386Sopenharmony_ci 701cb93a386Sopenharmony_ci ctx.fillStyle = 'green'; 702cb93a386Sopenharmony_ci ctx.font = '16pt Noto Mono'; 703cb93a386Sopenharmony_ci ctx.fillText('This should be shadowed', 20, 80); 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci ctx.beginPath(); 706cb93a386Sopenharmony_ci ctx.lineWidth = 6; 707cb93a386Sopenharmony_ci ctx.ellipse(10, 290, 30, 30, 0, 0, Math.PI * 2); 708cb93a386Sopenharmony_ci ctx.scale(2, 1); 709cb93a386Sopenharmony_ci ctx.moveTo(10, 290); 710cb93a386Sopenharmony_ci ctx.ellipse(10, 290, 30, 60, 0, 0, Math.PI * 2); 711cb93a386Sopenharmony_ci ctx.resetTransform(); 712cb93a386Sopenharmony_ci ctx.scale(3, 1); 713cb93a386Sopenharmony_ci ctx.moveTo(10, 290); 714cb93a386Sopenharmony_ci ctx.ellipse(10, 290, 30, 90, 0, 0, Math.PI * 2); 715cb93a386Sopenharmony_ci ctx.stroke(); 716cb93a386Sopenharmony_ci } 717cb93a386Sopenharmony_ci document.getElementById('api4').src = skcanvas.toDataURL(); 718cb93a386Sopenharmony_ci skcanvas.dispose(); 719cb93a386Sopenharmony_ci } 720cb93a386Sopenharmony_ci 721cb93a386Sopenharmony_ci function CanvasAPI5(CanvasKit) { 722cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(600, 600); 723cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api5_c'); 724cb93a386Sopenharmony_ci realCanvas.width = 600; 725cb93a386Sopenharmony_ci realCanvas.height = 600; 726cb93a386Sopenharmony_ci 727cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 728cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 729cb93a386Sopenharmony_ci ctx.scale(1.1, 1.1); 730cb93a386Sopenharmony_ci ctx.translate(10, 10); 731cb93a386Sopenharmony_ci // Shouldn't impact the fillRect calls 732cb93a386Sopenharmony_ci ctx.setLineDash([5, 3]); 733cb93a386Sopenharmony_ci 734cb93a386Sopenharmony_ci ctx.fillStyle = 'rgba(200, 0, 100, 0.81)'; 735cb93a386Sopenharmony_ci ctx.fillRect(20, 30, 100, 100); 736cb93a386Sopenharmony_ci 737cb93a386Sopenharmony_ci ctx.globalAlpha = 0.81; 738cb93a386Sopenharmony_ci ctx.fillStyle = 'rgba(200, 0, 100, 1.0)'; 739cb93a386Sopenharmony_ci ctx.fillRect(120, 30, 100, 100); 740cb93a386Sopenharmony_ci // This shouldn't do anything 741cb93a386Sopenharmony_ci ctx.globalAlpha = 0.1; 742cb93a386Sopenharmony_ci 743cb93a386Sopenharmony_ci ctx.fillStyle = 'rgba(200, 0, 100, 0.9)'; 744cb93a386Sopenharmony_ci ctx.globalAlpha = 0.9; 745cb93a386Sopenharmony_ci // Intentional no-op to check ordering 746cb93a386Sopenharmony_ci ctx.clearRect(220, 30, 100, 100); 747cb93a386Sopenharmony_ci ctx.fillRect(220, 30, 100, 100); 748cb93a386Sopenharmony_ci 749cb93a386Sopenharmony_ci ctx.fillRect(320, 30, 100, 100); 750cb93a386Sopenharmony_ci ctx.clearRect(330, 40, 80, 80); 751cb93a386Sopenharmony_ci 752cb93a386Sopenharmony_ci ctx.strokeStyle = 'blue'; 753cb93a386Sopenharmony_ci ctx.lineWidth = 3; 754cb93a386Sopenharmony_ci ctx.setLineDash([5, 3]); 755cb93a386Sopenharmony_ci ctx.strokeRect(20, 150, 100, 100); 756cb93a386Sopenharmony_ci ctx.setLineDash([50, 30]); 757cb93a386Sopenharmony_ci ctx.strokeRect(125, 150, 100, 100); 758cb93a386Sopenharmony_ci ctx.lineDashOffset = 25; 759cb93a386Sopenharmony_ci ctx.strokeRect(230, 150, 100, 100); 760cb93a386Sopenharmony_ci ctx.setLineDash([2, 5, 9]); 761cb93a386Sopenharmony_ci ctx.strokeRect(335, 150, 100, 100); 762cb93a386Sopenharmony_ci 763cb93a386Sopenharmony_ci ctx.setLineDash([5, 2]); 764cb93a386Sopenharmony_ci ctx.moveTo(336, 400); 765cb93a386Sopenharmony_ci ctx.quadraticCurveTo(366, 488, 120, 450); 766cb93a386Sopenharmony_ci ctx.lineTo(300, 400); 767cb93a386Sopenharmony_ci ctx.stroke(); 768cb93a386Sopenharmony_ci 769cb93a386Sopenharmony_ci ctx.font = '36pt Noto Mono'; 770cb93a386Sopenharmony_ci ctx.strokeText('Dashed', 20, 350); 771cb93a386Sopenharmony_ci ctx.fillText('Not Dashed', 20, 400); 772cb93a386Sopenharmony_ci 773cb93a386Sopenharmony_ci } 774cb93a386Sopenharmony_ci document.getElementById('api5').src = skcanvas.toDataURL(); 775cb93a386Sopenharmony_ci skcanvas.dispose(); 776cb93a386Sopenharmony_ci } 777cb93a386Sopenharmony_ci 778cb93a386Sopenharmony_ci function CanvasAPI6(CanvasKit) { 779cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(600, 600); 780cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api6_c'); 781cb93a386Sopenharmony_ci realCanvas.width = 600; 782cb93a386Sopenharmony_ci realCanvas.height = 600; 783cb93a386Sopenharmony_ci 784cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 785cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 786cb93a386Sopenharmony_ci 787cb93a386Sopenharmony_ci let rgradient = ctx.createRadialGradient(200, 300, 10, 100, 100, 300); 788cb93a386Sopenharmony_ci 789cb93a386Sopenharmony_ci // Add three color stops 790cb93a386Sopenharmony_ci rgradient.addColorStop(0, 'red'); 791cb93a386Sopenharmony_ci rgradient.addColorStop(0.7, 'white'); 792cb93a386Sopenharmony_ci rgradient.addColorStop(1, 'blue'); 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_ci ctx.fillStyle = rgradient; 795cb93a386Sopenharmony_ci ctx.globalAlpha = 0.7; 796cb93a386Sopenharmony_ci ctx.fillRect(0, 0, 600, 600); 797cb93a386Sopenharmony_ci ctx.globalAlpha = 0.95; 798cb93a386Sopenharmony_ci 799cb93a386Sopenharmony_ci ctx.beginPath(); 800cb93a386Sopenharmony_ci ctx.arc(300, 100, 90, 0, Math.PI*1.66); 801cb93a386Sopenharmony_ci ctx.closePath(); 802cb93a386Sopenharmony_ci ctx.strokeStyle = 'yellow'; 803cb93a386Sopenharmony_ci ctx.lineWidth = 5; 804cb93a386Sopenharmony_ci ctx.stroke(); 805cb93a386Sopenharmony_ci ctx.save(); 806cb93a386Sopenharmony_ci ctx.clip(); 807cb93a386Sopenharmony_ci 808cb93a386Sopenharmony_ci let lgradient = ctx.createLinearGradient(200, 20, 420, 40); 809cb93a386Sopenharmony_ci 810cb93a386Sopenharmony_ci // Add three color stops 811cb93a386Sopenharmony_ci lgradient.addColorStop(0, 'green'); 812cb93a386Sopenharmony_ci lgradient.addColorStop(0.5, 'cyan'); 813cb93a386Sopenharmony_ci lgradient.addColorStop(1, 'orange'); 814cb93a386Sopenharmony_ci 815cb93a386Sopenharmony_ci ctx.fillStyle = lgradient; 816cb93a386Sopenharmony_ci 817cb93a386Sopenharmony_ci ctx.fillRect(200, 30, 200, 300); 818cb93a386Sopenharmony_ci 819cb93a386Sopenharmony_ci ctx.restore(); 820cb93a386Sopenharmony_ci ctx.fillRect(550, 550, 40, 40); 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_ci } 823cb93a386Sopenharmony_ci document.getElementById('api6').src = skcanvas.toDataURL(); 824cb93a386Sopenharmony_ci skcanvas.dispose(); 825cb93a386Sopenharmony_ci } 826cb93a386Sopenharmony_ci 827cb93a386Sopenharmony_ci function CanvasAPI7(CanvasKit) { 828cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 829cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api7_c'); 830cb93a386Sopenharmony_ci 831cb93a386Sopenharmony_ci let skPromise = fetch(cdn + 'test.png') 832cb93a386Sopenharmony_ci // if clients want to use a Blob, they are responsible 833cb93a386Sopenharmony_ci // for reading it themselves. 834cb93a386Sopenharmony_ci .then((response) => response.arrayBuffer()) 835cb93a386Sopenharmony_ci .then((buffer) => { 836cb93a386Sopenharmony_ci skcanvas._img = skcanvas.decodeImage(buffer); 837cb93a386Sopenharmony_ci }); 838cb93a386Sopenharmony_ci let realPromise = fetch(cdn + 'test.png') 839cb93a386Sopenharmony_ci .then((response) => response.blob()) 840cb93a386Sopenharmony_ci .then((blob) => createImageBitmap(blob)) 841cb93a386Sopenharmony_ci .then((bitmap) => { 842cb93a386Sopenharmony_ci realCanvas._img = bitmap; 843cb93a386Sopenharmony_ci }); 844cb93a386Sopenharmony_ci 845cb93a386Sopenharmony_ci 846cb93a386Sopenharmony_ci Promise.all([realPromise, skPromise]).then(() => { 847cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 848cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 849cb93a386Sopenharmony_ci ctx.fillStyle = '#EEE'; 850cb93a386Sopenharmony_ci ctx.fillRect(0, 0, 300, 300); 851cb93a386Sopenharmony_ci ctx.lineWidth = 20; 852cb93a386Sopenharmony_ci ctx.scale(0.1, 0.2); 853cb93a386Sopenharmony_ci 854cb93a386Sopenharmony_ci let pattern = ctx.createPattern(canvas._img, 'repeat'); 855cb93a386Sopenharmony_ci ctx.fillStyle = pattern; 856cb93a386Sopenharmony_ci ctx.fillRect(0, 0, 1500, 750); 857cb93a386Sopenharmony_ci 858cb93a386Sopenharmony_ci pattern = ctx.createPattern(canvas._img, 'repeat-x'); 859cb93a386Sopenharmony_ci ctx.fillStyle = pattern; 860cb93a386Sopenharmony_ci ctx.fillRect(1500, 0, 3000, 750); 861cb93a386Sopenharmony_ci 862cb93a386Sopenharmony_ci ctx.globalAlpha = 0.7; 863cb93a386Sopenharmony_ci pattern = ctx.createPattern(canvas._img, 'repeat-y'); 864cb93a386Sopenharmony_ci ctx.fillStyle = pattern; 865cb93a386Sopenharmony_ci ctx.fillRect(0, 750, 1500, 1500); 866cb93a386Sopenharmony_ci ctx.strokeRect(0, 750, 1500, 1500); 867cb93a386Sopenharmony_ci 868cb93a386Sopenharmony_ci pattern = ctx.createPattern(canvas._img, 'no-repeat'); 869cb93a386Sopenharmony_ci ctx.fillStyle = pattern; 870cb93a386Sopenharmony_ci pattern.setTransform({a: 1, b: -.1, c:.1, d: 0.5, e: 1800, f:800}); 871cb93a386Sopenharmony_ci ctx.fillRect(0, 0, 3000, 1500); 872cb93a386Sopenharmony_ci } 873cb93a386Sopenharmony_ci 874cb93a386Sopenharmony_ci document.getElementById('api7').src = skcanvas.toDataURL(); 875cb93a386Sopenharmony_ci skcanvas.dispose(); 876cb93a386Sopenharmony_ci }); 877cb93a386Sopenharmony_ci } 878cb93a386Sopenharmony_ci 879cb93a386Sopenharmony_ci function CanvasAPI8(CanvasKit) { 880cb93a386Sopenharmony_ci let skcanvas = CanvasKit.MakeCanvas(300, 300); 881cb93a386Sopenharmony_ci let realCanvas = document.getElementById('api8_c'); 882cb93a386Sopenharmony_ci 883cb93a386Sopenharmony_ci function drawPoint(ctx, x, y, color) { 884cb93a386Sopenharmony_ci ctx.fillStyle = color; 885cb93a386Sopenharmony_ci ctx.fillRect(x, y, 1, 1); 886cb93a386Sopenharmony_ci } 887cb93a386Sopenharmony_ci const IN = 'purple'; 888cb93a386Sopenharmony_ci const OUT = 'orange'; 889cb93a386Sopenharmony_ci const SCALE = 4; 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci const pts = [[3, 3], [4, 4], [5, 5], [10, 10], [8, 10], [6, 10], 892cb93a386Sopenharmony_ci [6.5, 9], [15, 10], [17, 10], [17, 11], [24, 24], 893cb93a386Sopenharmony_ci [25, 25], [26, 26], [27, 27]]; 894cb93a386Sopenharmony_ci 895cb93a386Sopenharmony_ci const tests = [ 896cb93a386Sopenharmony_ci { 897cb93a386Sopenharmony_ci xOffset: 0, 898cb93a386Sopenharmony_ci yOffset: 0, 899cb93a386Sopenharmony_ci fillType: 'nonzero', 900cb93a386Sopenharmony_ci strokeWidth: 0, 901cb93a386Sopenharmony_ci testFn: (ctx, x, y) => ctx.isPointInPath(x * SCALE, y * SCALE, 'nonzero'), 902cb93a386Sopenharmony_ci }, 903cb93a386Sopenharmony_ci { 904cb93a386Sopenharmony_ci xOffset: 30, 905cb93a386Sopenharmony_ci yOffset: 0, 906cb93a386Sopenharmony_ci fillType: 'evenodd', 907cb93a386Sopenharmony_ci strokeWidth: 0, 908cb93a386Sopenharmony_ci testFn: (ctx, x, y) => ctx.isPointInPath(x * SCALE, y * SCALE, 'evenodd'), 909cb93a386Sopenharmony_ci }, 910cb93a386Sopenharmony_ci { 911cb93a386Sopenharmony_ci xOffset: 0, 912cb93a386Sopenharmony_ci yOffset: 30, 913cb93a386Sopenharmony_ci fillType: null, 914cb93a386Sopenharmony_ci strokeWidth: 1, 915cb93a386Sopenharmony_ci testFn: (ctx, x, y) => ctx.isPointInStroke(x * SCALE, y * SCALE), 916cb93a386Sopenharmony_ci }, 917cb93a386Sopenharmony_ci { 918cb93a386Sopenharmony_ci xOffset: 30, 919cb93a386Sopenharmony_ci yOffset: 30, 920cb93a386Sopenharmony_ci fillType: null, 921cb93a386Sopenharmony_ci strokeWidth: 2, 922cb93a386Sopenharmony_ci testFn: (ctx, x, y) => ctx.isPointInStroke(x * SCALE, y * SCALE), 923cb93a386Sopenharmony_ci }, 924cb93a386Sopenharmony_ci ]; 925cb93a386Sopenharmony_ci 926cb93a386Sopenharmony_ci for (let canvas of [skcanvas, realCanvas]) { 927cb93a386Sopenharmony_ci let ctx = canvas.getContext('2d'); 928cb93a386Sopenharmony_ci ctx.font = '11px Noto Mono'; 929cb93a386Sopenharmony_ci // Draw some visual aids 930cb93a386Sopenharmony_ci ctx.fillText('path-nonzero', 30, 15); 931cb93a386Sopenharmony_ci ctx.fillText('path-evenodd', 150, 15); 932cb93a386Sopenharmony_ci ctx.fillText('stroke-1px-wide', 30, 130); 933cb93a386Sopenharmony_ci ctx.fillText('stroke-2px-wide', 150, 130); 934cb93a386Sopenharmony_ci ctx.fillText('purple is IN, orange is OUT', 10, 280); 935cb93a386Sopenharmony_ci 936cb93a386Sopenharmony_ci // Scale up to make single pixels easier to see 937cb93a386Sopenharmony_ci ctx.scale(SCALE, SCALE); 938cb93a386Sopenharmony_ci for (let test of tests) { 939cb93a386Sopenharmony_ci ctx.beginPath(); 940cb93a386Sopenharmony_ci let xOffset = test.xOffset; 941cb93a386Sopenharmony_ci let yOffset = test.yOffset; 942cb93a386Sopenharmony_ci 943cb93a386Sopenharmony_ci ctx.fillStyle = '#AAA'; 944cb93a386Sopenharmony_ci ctx.lineWidth = test.strokeWidth; 945cb93a386Sopenharmony_ci ctx.rect(5+xOffset, 5+yOffset, 20, 20); 946cb93a386Sopenharmony_ci ctx.arc(15+xOffset, 15+yOffset, 8, 0, Math.PI*2, false); 947cb93a386Sopenharmony_ci if (test.fillType) { 948cb93a386Sopenharmony_ci ctx.fill(test.fillType); 949cb93a386Sopenharmony_ci } else { 950cb93a386Sopenharmony_ci ctx.stroke(); 951cb93a386Sopenharmony_ci } 952cb93a386Sopenharmony_ci 953cb93a386Sopenharmony_ci for (let pt of pts) { 954cb93a386Sopenharmony_ci let [x, y] = pt; 955cb93a386Sopenharmony_ci x += xOffset; 956cb93a386Sopenharmony_ci y += yOffset; 957cb93a386Sopenharmony_ci // naively apply transform when querying because the points queried 958cb93a386Sopenharmony_ci // ignore the CTM. 959cb93a386Sopenharmony_ci if (test.testFn(ctx, x, y)) { 960cb93a386Sopenharmony_ci drawPoint(ctx, x, y, IN); 961cb93a386Sopenharmony_ci } else { 962cb93a386Sopenharmony_ci drawPoint(ctx, x, y, OUT); 963cb93a386Sopenharmony_ci } 964cb93a386Sopenharmony_ci } 965cb93a386Sopenharmony_ci } 966cb93a386Sopenharmony_ci } 967cb93a386Sopenharmony_ci 968cb93a386Sopenharmony_ci document.getElementById('api8').src = skcanvas.toDataURL(); 969cb93a386Sopenharmony_ci skcanvas.dispose(); 970cb93a386Sopenharmony_ci } 971cb93a386Sopenharmony_ci 972cb93a386Sopenharmony_ci function VertexAPI1(CanvasKit) { 973cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('vertex1'); 974cb93a386Sopenharmony_ci if (!surface) { 975cb93a386Sopenharmony_ci console.error('Could not make surface'); 976cb93a386Sopenharmony_ci return; 977cb93a386Sopenharmony_ci } 978cb93a386Sopenharmony_ci const canvas = surface.getCanvas(); 979cb93a386Sopenharmony_ci let paint = new CanvasKit.Paint(); 980cb93a386Sopenharmony_ci 981cb93a386Sopenharmony_ci // See https://fiddle.skia.org/c/f48b22eaad1bb7adcc3faaa321754af6 982cb93a386Sopenharmony_ci // for original c++ version. 983cb93a386Sopenharmony_ci let points = [0, 0, 250, 0, 100, 100, 0, 250]; 984cb93a386Sopenharmony_ci let colors = [CanvasKit.RED, CanvasKit.BLUE, 985cb93a386Sopenharmony_ci CanvasKit.YELLOW, CanvasKit.CYAN]; 986cb93a386Sopenharmony_ci let vertices = CanvasKit.MakeVertices(CanvasKit.VertexMode.TriangleFan, 987cb93a386Sopenharmony_ci points, null, colors, 988cb93a386Sopenharmony_ci false /*isVolatile*/); 989cb93a386Sopenharmony_ci 990cb93a386Sopenharmony_ci canvas.drawVertices(vertices, CanvasKit.BlendMode.Src, paint); 991cb93a386Sopenharmony_ci 992cb93a386Sopenharmony_ci vertices.delete(); 993cb93a386Sopenharmony_ci 994cb93a386Sopenharmony_ci // See https://fiddle.skia.org/c/e8bdae9bea3227758989028424fcac3d 995cb93a386Sopenharmony_ci // for original c++ version. 996cb93a386Sopenharmony_ci points = [300, 300, 50, 300, 200, 200, 300, 50 ]; 997cb93a386Sopenharmony_ci let texs = [ 0, 0, 0, 250, 250, 250, 250, 0 ]; 998cb93a386Sopenharmony_ci vertices = CanvasKit.MakeVertices(CanvasKit.VertexMode.TriangleFan, 999cb93a386Sopenharmony_ci points, texs, colors); 1000cb93a386Sopenharmony_ci 1001cb93a386Sopenharmony_ci let shader = CanvasKit.Shader.MakeLinearGradient([0, 0], [250, 0], 1002cb93a386Sopenharmony_ci colors, null, CanvasKit.TileMode.Clamp); 1003cb93a386Sopenharmony_ci paint.setShader(shader); 1004cb93a386Sopenharmony_ci 1005cb93a386Sopenharmony_ci canvas.drawVertices(vertices, CanvasKit.BlendMode.Darken, paint); 1006cb93a386Sopenharmony_ci surface.flush(); 1007cb93a386Sopenharmony_ci 1008cb93a386Sopenharmony_ci shader.delete(); 1009cb93a386Sopenharmony_ci paint.delete(); 1010cb93a386Sopenharmony_ci surface.delete(); 1011cb93a386Sopenharmony_ci } 1012cb93a386Sopenharmony_ci 1013cb93a386Sopenharmony_ci function GradiantAPI1(CanvasKit) { 1014cb93a386Sopenharmony_ci const surface = CanvasKit.MakeSWCanvasSurface('gradient1'); 1015cb93a386Sopenharmony_ci if (!surface) { 1016cb93a386Sopenharmony_ci console.error('Could not make surface'); 1017cb93a386Sopenharmony_ci return; 1018cb93a386Sopenharmony_ci } 1019cb93a386Sopenharmony_ci const canvas = surface.getCanvas(); 1020cb93a386Sopenharmony_ci let paint = new CanvasKit.Paint(); 1021cb93a386Sopenharmony_ci 1022cb93a386Sopenharmony_ci // See https://fiddle.skia.org/c/f48b22eaad1bb7adcc3faaa321754af6 1023cb93a386Sopenharmony_ci // for original c++ version. 1024cb93a386Sopenharmony_ci let colors = [CanvasKit.BLUE, CanvasKit.YELLOW, CanvasKit.RED]; 1025cb93a386Sopenharmony_ci let pos = [0, .7, 1.0]; 1026cb93a386Sopenharmony_ci let transform = [2, 0, 0, 1027cb93a386Sopenharmony_ci 0, 2, 0, 1028cb93a386Sopenharmony_ci 0, 0, 1]; 1029cb93a386Sopenharmony_ci let shader = CanvasKit.Shader.MakeRadialGradient([150, 150], 130, colors, 1030cb93a386Sopenharmony_ci pos, CanvasKit.TileMode.Mirror, transform); 1031cb93a386Sopenharmony_ci 1032cb93a386Sopenharmony_ci paint.setShader(shader); 1033cb93a386Sopenharmony_ci const textFont = new CanvasKit.Font(null, 75); 1034cb93a386Sopenharmony_ci const textBlob = CanvasKit.TextBlob.MakeFromText('Radial', textFont); 1035cb93a386Sopenharmony_ci 1036cb93a386Sopenharmony_ci canvas.drawTextBlob(textBlob, 10, 200, paint); 1037cb93a386Sopenharmony_ci paint.delete(); 1038cb93a386Sopenharmony_ci textFont.delete(); 1039cb93a386Sopenharmony_ci textBlob.delete(); 1040cb93a386Sopenharmony_ci surface.flush(); 1041cb93a386Sopenharmony_ci } 1042cb93a386Sopenharmony_ci 1043cb93a386Sopenharmony_ci function TextOnPathAPI1(CanvasKit) { 1044cb93a386Sopenharmony_ci const surface = CanvasKit.MakeSWCanvasSurface('textonpath'); 1045cb93a386Sopenharmony_ci if (!surface) { 1046cb93a386Sopenharmony_ci console.error('Could not make surface'); 1047cb93a386Sopenharmony_ci return; 1048cb93a386Sopenharmony_ci } 1049cb93a386Sopenharmony_ci const canvas = surface.getCanvas(); 1050cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 1051cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Stroke); 1052cb93a386Sopenharmony_ci paint.setAntiAlias(true); 1053cb93a386Sopenharmony_ci 1054cb93a386Sopenharmony_ci const font = new CanvasKit.Font(null, 24); 1055cb93a386Sopenharmony_ci const fontPaint = new CanvasKit.Paint(); 1056cb93a386Sopenharmony_ci fontPaint.setStyle(CanvasKit.PaintStyle.Fill); 1057cb93a386Sopenharmony_ci fontPaint.setAntiAlias(true); 1058cb93a386Sopenharmony_ci 1059cb93a386Sopenharmony_ci const arc = new CanvasKit.Path(); 1060cb93a386Sopenharmony_ci arc.arcToOval(CanvasKit.LTRBRect(20, 40, 280, 300), -160, 140, true); 1061cb93a386Sopenharmony_ci arc.lineTo(210, 140); 1062cb93a386Sopenharmony_ci arc.arcToOval(CanvasKit.LTRBRect(20, 0, 280, 260), 160, -140, true); 1063cb93a386Sopenharmony_ci 1064cb93a386Sopenharmony_ci const str = 'This téxt should follow the curve across contours...'; 1065cb93a386Sopenharmony_ci const textBlob = CanvasKit.TextBlob.MakeOnPath(str, arc, font); 1066cb93a386Sopenharmony_ci 1067cb93a386Sopenharmony_ci canvas.drawPath(arc, paint); 1068cb93a386Sopenharmony_ci canvas.drawTextBlob(textBlob, 0, 0, fontPaint); 1069cb93a386Sopenharmony_ci 1070cb93a386Sopenharmony_ci surface.flush(); 1071cb93a386Sopenharmony_ci 1072cb93a386Sopenharmony_ci textBlob.delete(); 1073cb93a386Sopenharmony_ci arc.delete(); 1074cb93a386Sopenharmony_ci paint.delete(); 1075cb93a386Sopenharmony_ci font.delete(); 1076cb93a386Sopenharmony_ci fontPaint.delete(); 1077cb93a386Sopenharmony_ci } 1078cb93a386Sopenharmony_ci 1079cb93a386Sopenharmony_ci function DrawGlyphsAPI1(CanvasKit) { 1080cb93a386Sopenharmony_ci const surface = CanvasKit.MakeSWCanvasSurface('drawGlyphs'); 1081cb93a386Sopenharmony_ci if (!surface) { 1082cb93a386Sopenharmony_ci console.error('Could not make surface'); 1083cb93a386Sopenharmony_ci return; 1084cb93a386Sopenharmony_ci } 1085cb93a386Sopenharmony_ci const canvas = surface.getCanvas(); 1086cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 1087cb93a386Sopenharmony_ci const font = new CanvasKit.Font(null, 16); 1088cb93a386Sopenharmony_ci paint.setAntiAlias(true); 1089cb93a386Sopenharmony_ci 1090cb93a386Sopenharmony_ci let glyphs = []; 1091cb93a386Sopenharmony_ci let positions = []; 1092cb93a386Sopenharmony_ci for (let i = 0; i < 256; ++i) { 1093cb93a386Sopenharmony_ci glyphs.push(i); 1094cb93a386Sopenharmony_ci positions.push((i % 16) * 16); 1095cb93a386Sopenharmony_ci positions.push(Math.round(i/16) * 16); 1096cb93a386Sopenharmony_ci } 1097cb93a386Sopenharmony_ci canvas.drawGlyphs(glyphs, positions, 16, 20, font, paint); 1098cb93a386Sopenharmony_ci 1099cb93a386Sopenharmony_ci surface.flush(); 1100cb93a386Sopenharmony_ci 1101cb93a386Sopenharmony_ci paint.delete(); 1102cb93a386Sopenharmony_ci font.delete(); 1103cb93a386Sopenharmony_ci } 1104cb93a386Sopenharmony_ci 1105cb93a386Sopenharmony_ci function SurfaceAPI1(CanvasKit) { 1106cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('surfaces'); 1107cb93a386Sopenharmony_ci if (!surface) { 1108cb93a386Sopenharmony_ci console.error('Could not make surface'); 1109cb93a386Sopenharmony_ci return; 1110cb93a386Sopenharmony_ci } 1111cb93a386Sopenharmony_ci 1112cb93a386Sopenharmony_ci // create a subsurface as a temporary workspace. 1113cb93a386Sopenharmony_ci const subSurface = surface.makeSurface({ 1114cb93a386Sopenharmony_ci width: 50, 1115cb93a386Sopenharmony_ci height: 50, 1116cb93a386Sopenharmony_ci alphaType: CanvasKit.AlphaType.Premul, 1117cb93a386Sopenharmony_ci colorType: CanvasKit.ColorType.RGBA_8888, 1118cb93a386Sopenharmony_ci colorSpace: CanvasKit.ColorSpace.SRGB, 1119cb93a386Sopenharmony_ci }); 1120cb93a386Sopenharmony_ci 1121cb93a386Sopenharmony_ci if (!subSurface) { 1122cb93a386Sopenharmony_ci console.error('Could not make subsurface'); 1123cb93a386Sopenharmony_ci return; 1124cb93a386Sopenharmony_ci } 1125cb93a386Sopenharmony_ci 1126cb93a386Sopenharmony_ci // draw a small "scene" 1127cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 1128cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(139, 228, 135, 0.95)); // greenish 1129cb93a386Sopenharmony_ci paint.setStyle(CanvasKit.PaintStyle.Fill); 1130cb93a386Sopenharmony_ci paint.setAntiAlias(true); 1131cb93a386Sopenharmony_ci 1132cb93a386Sopenharmony_ci const subCanvas = subSurface.getCanvas(); 1133cb93a386Sopenharmony_ci subCanvas.clear(CanvasKit.BLACK); 1134cb93a386Sopenharmony_ci subCanvas.drawRect(CanvasKit.LTRBRect(5, 15, 45, 40), paint); 1135cb93a386Sopenharmony_ci 1136cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(214, 93, 244)); // purplish 1137cb93a386Sopenharmony_ci for (let i = 0; i < 10; i++) { 1138cb93a386Sopenharmony_ci const x = Math.random() * 50; 1139cb93a386Sopenharmony_ci const y = Math.random() * 50; 1140cb93a386Sopenharmony_ci 1141cb93a386Sopenharmony_ci subCanvas.drawOval(CanvasKit.XYWHRect(x, y, 6, 6), paint); 1142cb93a386Sopenharmony_ci } 1143cb93a386Sopenharmony_ci 1144cb93a386Sopenharmony_ci // Snap it off as an Image - this image will be in the form the 1145cb93a386Sopenharmony_ci // parent surface prefers (e.g. Texture for GPU / Raster for CPU). 1146cb93a386Sopenharmony_ci const img = subSurface.makeImageSnapshot(); 1147cb93a386Sopenharmony_ci 1148cb93a386Sopenharmony_ci // clean up the temporary surface (which also cleans up subCanvas) 1149cb93a386Sopenharmony_ci subSurface.delete(); 1150cb93a386Sopenharmony_ci paint.delete(); 1151cb93a386Sopenharmony_ci 1152cb93a386Sopenharmony_ci // Make it repeat a bunch with a shader 1153cb93a386Sopenharmony_ci const pattern = img.makeShaderCubic(CanvasKit.TileMode.Repeat, CanvasKit.TileMode.Mirror, 1154cb93a386Sopenharmony_ci 1/3, 1/3); 1155cb93a386Sopenharmony_ci const patternPaint = new CanvasKit.Paint(); 1156cb93a386Sopenharmony_ci patternPaint.setShader(pattern); 1157cb93a386Sopenharmony_ci 1158cb93a386Sopenharmony_ci let i = 0; 1159cb93a386Sopenharmony_ci 1160cb93a386Sopenharmony_ci function drawFrame(canvas) { 1161cb93a386Sopenharmony_ci i++; 1162cb93a386Sopenharmony_ci canvas.clear(CanvasKit.WHITE); 1163cb93a386Sopenharmony_ci 1164cb93a386Sopenharmony_ci canvas.drawOval(CanvasKit.LTRBRect(i % 60, i % 60, 300 - (i% 60), 300 - (i % 60)), patternPaint); 1165cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 1166cb93a386Sopenharmony_ci } 1167cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 1168cb93a386Sopenharmony_ci } 1169cb93a386Sopenharmony_ci 1170cb93a386Sopenharmony_ci function AtlasAPI1(CanvasKit, imgData) { 1171cb93a386Sopenharmony_ci if (!CanvasKit || !imgData) { 1172cb93a386Sopenharmony_ci return; 1173cb93a386Sopenharmony_ci } 1174cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('atlas'); 1175cb93a386Sopenharmony_ci if (!surface) { 1176cb93a386Sopenharmony_ci console.error('Could not make surface'); 1177cb93a386Sopenharmony_ci return; 1178cb93a386Sopenharmony_ci } 1179cb93a386Sopenharmony_ci const img = CanvasKit.MakeImageFromEncoded(imgData); 1180cb93a386Sopenharmony_ci 1181cb93a386Sopenharmony_ci const paint = new CanvasKit.Paint(); 1182cb93a386Sopenharmony_ci paint.setColor(CanvasKit.Color(0, 0, 0, 0.8)); 1183cb93a386Sopenharmony_ci 1184cb93a386Sopenharmony_ci // Allocate space for 2 rectangles. 1185cb93a386Sopenharmony_ci const srcs = CanvasKit.Malloc(Float32Array, 8); 1186cb93a386Sopenharmony_ci srcs.toTypedArray().set([ 1187cb93a386Sopenharmony_ci 0, 0, 250, 250, // LTRB 1188cb93a386Sopenharmony_ci 250, 0, 500, 250 1189cb93a386Sopenharmony_ci ]); 1190cb93a386Sopenharmony_ci 1191cb93a386Sopenharmony_ci // Allocate space for 2 RSXForms 1192cb93a386Sopenharmony_ci const dsts = CanvasKit.Malloc(Float32Array, 8); 1193cb93a386Sopenharmony_ci dsts.toTypedArray().set([ 1194cb93a386Sopenharmony_ci .5, 0, 0, 0, // scos, ssin, tx, ty 1195cb93a386Sopenharmony_ci 0, .8, 200, 100 1196cb93a386Sopenharmony_ci ]); 1197cb93a386Sopenharmony_ci 1198cb93a386Sopenharmony_ci // Allocate space for 4 colors. 1199cb93a386Sopenharmony_ci const colors = new CanvasKit.Malloc(Uint32Array, 2); 1200cb93a386Sopenharmony_ci colors.toTypedArray().set([ 1201cb93a386Sopenharmony_ci CanvasKit.ColorAsInt( 85, 170, 10, 128), // light green 1202cb93a386Sopenharmony_ci CanvasKit.ColorAsInt( 51, 51, 191, 128), // light blue 1203cb93a386Sopenharmony_ci ]); 1204cb93a386Sopenharmony_ci 1205cb93a386Sopenharmony_ci let i = 0; 1206cb93a386Sopenharmony_ci 1207cb93a386Sopenharmony_ci function drawFrame(canvas) { 1208cb93a386Sopenharmony_ci canvas.clear(CanvasKit.WHITE); 1209cb93a386Sopenharmony_ci i++; 1210cb93a386Sopenharmony_ci let scale = 0.5 + Math.sin(i/40)/4; 1211cb93a386Sopenharmony_ci 1212cb93a386Sopenharmony_ci // update the coordinates of existing sprites - note that this 1213cb93a386Sopenharmony_ci // does not require a full re-copy of the full array; they are 1214cb93a386Sopenharmony_ci // updated in-place. 1215cb93a386Sopenharmony_ci dsts.toTypedArray().set([0.5, 0, (2*i)%200, (5*Math.round(i/200)) % 200], 0); 1216cb93a386Sopenharmony_ci dsts.toTypedArray().set([scale*Math.sin(i/20), scale*Math.cos(i/20), 200, 100], 4); 1217cb93a386Sopenharmony_ci 1218cb93a386Sopenharmony_ci canvas.drawAtlas(img, srcs, dsts, paint, CanvasKit.BlendMode.Plus, colors, 1219cb93a386Sopenharmony_ci {filter: CanvasKit.FilterMode.Nearest}); 1220cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 1221cb93a386Sopenharmony_ci } 1222cb93a386Sopenharmony_ci surface.requestAnimationFrame(drawFrame); 1223cb93a386Sopenharmony_ci 1224cb93a386Sopenharmony_ci } 1225cb93a386Sopenharmony_ci 1226cb93a386Sopenharmony_ci async function DecodeAPI(CanvasKit, imgData) { 1227cb93a386Sopenharmony_ci if (!CanvasKit || !imgData) { 1228cb93a386Sopenharmony_ci return; 1229cb93a386Sopenharmony_ci } 1230cb93a386Sopenharmony_ci const surface = CanvasKit.MakeCanvasSurface('decode'); 1231cb93a386Sopenharmony_ci if (!surface) { 1232cb93a386Sopenharmony_ci console.error('Could not make surface'); 1233cb93a386Sopenharmony_ci return; 1234cb93a386Sopenharmony_ci } 1235cb93a386Sopenharmony_ci const blob = new Blob([ imgData ]); 1236cb93a386Sopenharmony_ci // ImageBitmap is not supported in Safari 1237cb93a386Sopenharmony_ci const imageBitmap = await createImageBitmap(blob); 1238cb93a386Sopenharmony_ci const img = await CanvasKit.MakeImageFromCanvasImageSource(imageBitmap); 1239cb93a386Sopenharmony_ci 1240cb93a386Sopenharmony_ci surface.drawOnce((canvas) => { 1241cb93a386Sopenharmony_ci canvas.drawImage(img, 0, 0, null); 1242cb93a386Sopenharmony_ci }); 1243cb93a386Sopenharmony_ci } 1244cb93a386Sopenharmony_ci</script> 1245