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