1cb93a386Sopenharmony_ci---
2cb93a386Sopenharmony_cititle: 'PathKit - Geometry in the Browser'
3cb93a386Sopenharmony_cilinkTitle: 'PathKit - Geometry in the Browser'
4cb93a386Sopenharmony_ci
5cb93a386Sopenharmony_ciweight: 30
6cb93a386Sopenharmony_ci---
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ciSkia has made its [SkPath](https://api.skia.org/classSkPath.html) object and
9cb93a386Sopenharmony_cimany related methods available to JS clients (e.g. Web Browsers) using
10cb93a386Sopenharmony_ciWebAssembly and asm.js.
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci## Features
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ciPathKit is still under rapid development, so the exact API is subject to change.
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciThe primary features are:
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci- API compatibility (e.g. drop-in replacement) with
19cb93a386Sopenharmony_ci  [Path2D](https://developer.mozilla.org/en-US/docs/Web/API/Path2D)
20cb93a386Sopenharmony_ci- Can output to SVG / Canvas / Path2D
21cb93a386Sopenharmony_ci- Exposes a variety of path effects:
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ci<style>
24cb93a386Sopenharmony_ci  canvas.patheffect {
25cb93a386Sopenharmony_ci    border: 1px dashed #AAA;
26cb93a386Sopenharmony_ci    width: 200px;
27cb93a386Sopenharmony_ci    height: 200px;
28cb93a386Sopenharmony_ci  }
29cb93a386Sopenharmony_ci</style>
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci<div id=effects>
32cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas1 title="Plain: A drawn star with overlapping solid lines"></canvas>
33cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas2 title="Dash: A drawn star with overlapping dashed lines"></canvas>
34cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas3 title="Trim: A portion of a drawn star with overlapping solid lines"></canvas>
35cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas4 title="Simplify: A drawn star with non-overlapping solid lines."></canvas>
36cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas5 title="Stroke: A drawn star with non-overlapping solid lines stroked at various thicknesses and with square edges"></canvas>
37cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas6 title="Grow: A drawn star's expanding outline"></canvas>
38cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvas7 title="Shrink: A solid drawn star shrunk down"></canvas>
39cb93a386Sopenharmony_ci  <canvas class=patheffect id=canvasTransform title="Transform: A drawn star moved and rotated by an Affine Matrix"></canvas>
40cb93a386Sopenharmony_ci</div>
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci<script type="text/javascript">
43cb93a386Sopenharmony_ci(function() {
44cb93a386Sopenharmony_ci  // Tries to load the WASM version if supported, then falls back to asmjs
45cb93a386Sopenharmony_ci  let s = document.createElement('script');
46cb93a386Sopenharmony_ci  if (window.WebAssembly && typeof window.WebAssembly.compile === 'function') {
47cb93a386Sopenharmony_ci    console.log('WebAssembly is supported! Using the wasm version of PathKit');
48cb93a386Sopenharmony_ci    window.__pathkit_locate_file = 'https://unpkg.com/pathkit-wasm@0.6.0/bin/';
49cb93a386Sopenharmony_ci  } else {
50cb93a386Sopenharmony_ci    console.log('WebAssembly is not supported (yet) on this browser. Using the asmjs version of PathKit');
51cb93a386Sopenharmony_ci    window.__pathkit_locate_file = 'https://unpkg.com/pathkit-asmjs@0.6.0/bin/';
52cb93a386Sopenharmony_ci  }
53cb93a386Sopenharmony_ci  s.src = window.__pathkit_locate_file+'pathkit.js';
54cb93a386Sopenharmony_ci  s.onload = () => {
55cb93a386Sopenharmony_ci    // TODO(kjlubick) remove .ready() when we update the version served here.
56cb93a386Sopenharmony_ci    try {
57cb93a386Sopenharmony_ci      PathKitInit({
58cb93a386Sopenharmony_ci        locateFile: (file) => window.__pathkit_locate_file+file,
59cb93a386Sopenharmony_ci      }).ready().then((PathKit) => {
60cb93a386Sopenharmony_ci        // Code goes here using PathKit
61cb93a386Sopenharmony_ci        PathEffectsExample(PathKit);
62cb93a386Sopenharmony_ci        MatrixTransformExample(PathKit);
63cb93a386Sopenharmony_ci      });
64cb93a386Sopenharmony_ci    }
65cb93a386Sopenharmony_ci    catch(error) {
66cb93a386Sopenharmony_ci      console.warn(error, 'falling back to image');
67cb93a386Sopenharmony_ci      document.getElementById('effects').innerHTML = '<img width=800 src="./PathKit_effects.png"/>'
68cb93a386Sopenharmony_ci    }
69cb93a386Sopenharmony_ci  }
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci  document.head.appendChild(s);
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci  function setCanvasSize(ctx, width, height) {
74cb93a386Sopenharmony_ci    ctx.canvas.width = width;
75cb93a386Sopenharmony_ci    ctx.canvas.height = height;
76cb93a386Sopenharmony_ci  }
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci  function drawStar(path) {
79cb93a386Sopenharmony_ci    let R = 115.2, C = 128.0;
80cb93a386Sopenharmony_ci    path.moveTo(C + R + 22, C);
81cb93a386Sopenharmony_ci    for (let i = 1; i < 8; i++) {
82cb93a386Sopenharmony_ci      let a = 2.6927937 * i;
83cb93a386Sopenharmony_ci      path.lineTo(C + R * Math.cos(a) + 22, C + R * Math.sin(a));
84cb93a386Sopenharmony_ci    }
85cb93a386Sopenharmony_ci    path.closePath();
86cb93a386Sopenharmony_ci    return path;
87cb93a386Sopenharmony_ci  }
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci  function PathEffectsExample(PathKit) {
90cb93a386Sopenharmony_ci    let effects = [
91cb93a386Sopenharmony_ci      // no-op
92cb93a386Sopenharmony_ci      (path) => path,
93cb93a386Sopenharmony_ci      // dash
94cb93a386Sopenharmony_ci      (path, counter) => path.dash(10, 3, counter/5),
95cb93a386Sopenharmony_ci      // trim (takes optional 3rd param for returning the trimmed part
96cb93a386Sopenharmony_ci      // or the complement)
97cb93a386Sopenharmony_ci      (path, counter) => path.trim((counter/100) % 1, 0.8, false),
98cb93a386Sopenharmony_ci      // simplify
99cb93a386Sopenharmony_ci      (path) => path.simplify(),
100cb93a386Sopenharmony_ci      // stroke
101cb93a386Sopenharmony_ci      (path, counter) => path.stroke({
102cb93a386Sopenharmony_ci        width: 10 * (Math.sin(counter/30) + 1),
103cb93a386Sopenharmony_ci        join: PathKit.StrokeJoin.BEVEL,
104cb93a386Sopenharmony_ci        cap: PathKit.StrokeCap.BUTT,
105cb93a386Sopenharmony_ci        miter_limit: 1,
106cb93a386Sopenharmony_ci      }),
107cb93a386Sopenharmony_ci      // "offset effect", that is, making a border around the shape.
108cb93a386Sopenharmony_ci      (path, counter) => {
109cb93a386Sopenharmony_ci        let orig = path.copy();
110cb93a386Sopenharmony_ci        path.stroke({
111cb93a386Sopenharmony_ci          width: 10 + (counter / 4) % 50,
112cb93a386Sopenharmony_ci          join: PathKit.StrokeJoin.ROUND,
113cb93a386Sopenharmony_ci          cap: PathKit.StrokeCap.SQUARE,
114cb93a386Sopenharmony_ci        })
115cb93a386Sopenharmony_ci          .op(orig, PathKit.PathOp.DIFFERENCE);
116cb93a386Sopenharmony_ci        orig.delete();
117cb93a386Sopenharmony_ci      },
118cb93a386Sopenharmony_ci      (path, counter) => {
119cb93a386Sopenharmony_ci        let simplified = path.simplify().copy();
120cb93a386Sopenharmony_ci        path.stroke({
121cb93a386Sopenharmony_ci          width: 2 + (counter / 2) % 100,
122cb93a386Sopenharmony_ci          join: PathKit.StrokeJoin.BEVEL,
123cb93a386Sopenharmony_ci          cap: PathKit.StrokeCap.BUTT,
124cb93a386Sopenharmony_ci        })
125cb93a386Sopenharmony_ci          .op(simplified, PathKit.PathOp.REVERSE_DIFFERENCE);
126cb93a386Sopenharmony_ci        simplified.delete();
127cb93a386Sopenharmony_ci      }
128cb93a386Sopenharmony_ci    ];
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ci    let names = ["(plain)", "Dash", "Trim", "Simplify", "Stroke", "Grow", "Shrink"];
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci    let counter = 0;
133cb93a386Sopenharmony_ci    function frame() {
134cb93a386Sopenharmony_ci      counter++;
135cb93a386Sopenharmony_ci      for (let i = 0; i < effects.length; i++) {
136cb93a386Sopenharmony_ci        let path = PathKit.NewPath();
137cb93a386Sopenharmony_ci        drawStar(path);
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci        // The transforms apply directly to the path.
140cb93a386Sopenharmony_ci        effects[i](path, counter);
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci        let ctx = document.getElementById(`canvas${i+1}`);
143cb93a386Sopenharmony_ci        if (!ctx) {
144cb93a386Sopenharmony_ci          return;
145cb93a386Sopenharmony_ci        } else {
146cb93a386Sopenharmony_ci          ctx = ctx.getContext('2d');
147cb93a386Sopenharmony_ci        }
148cb93a386Sopenharmony_ci        setCanvasSize(ctx, 300, 300);
149cb93a386Sopenharmony_ci        ctx.strokeStyle = '#3c597a';
150cb93a386Sopenharmony_ci        ctx.fillStyle = '#3c597a';
151cb93a386Sopenharmony_ci        if (i >=4 ) {
152cb93a386Sopenharmony_ci          ctx.fill(path.toPath2D(), path.getFillTypeString());
153cb93a386Sopenharmony_ci        } else {
154cb93a386Sopenharmony_ci          ctx.stroke(path.toPath2D());
155cb93a386Sopenharmony_ci        }
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci        ctx.font = '42px monospace';
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci        let x = 150-ctx.measureText(names[i]).width/2;
160cb93a386Sopenharmony_ci        ctx.strokeText(names[i], x, 290);
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci        path.delete();
163cb93a386Sopenharmony_ci      }
164cb93a386Sopenharmony_ci      window.requestAnimationFrame(frame);
165cb93a386Sopenharmony_ci    }
166cb93a386Sopenharmony_ci    window.requestAnimationFrame(frame);
167cb93a386Sopenharmony_ci  }
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_ci  function MatrixTransformExample(PathKit) {
170cb93a386Sopenharmony_ci    // Creates an animated star that twists and moves.
171cb93a386Sopenharmony_ci    let ctx = document.getElementById('canvasTransform').getContext('2d');
172cb93a386Sopenharmony_ci    setCanvasSize(ctx, 300, 300);
173cb93a386Sopenharmony_ci    ctx.strokeStyle = '#3c597a';
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci    let path = drawStar(PathKit.NewPath());
176cb93a386Sopenharmony_ci    // TODO(kjlubick): Perhaps expose some matrix helper functions to allow
177cb93a386Sopenharmony_ci    // clients to build their own matrices like this?
178cb93a386Sopenharmony_ci    // These matrices represent a 2 degree rotation and a 1% scale factor.
179cb93a386Sopenharmony_ci    let scaleUp = [1.0094, -0.0352,  3.1041,
180cb93a386Sopenharmony_ci                   0.0352,  1.0094, -6.4885,
181cb93a386Sopenharmony_ci                   0     ,  0      , 1];
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    let scaleDown = [ 0.9895, 0.0346, -2.8473,
184cb93a386Sopenharmony_ci                     -0.0346, 0.9895,  6.5276,
185cb93a386Sopenharmony_ci                      0     , 0     ,  1];
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci    let i = 0;
188cb93a386Sopenharmony_ci    function frame(){
189cb93a386Sopenharmony_ci      i++;
190cb93a386Sopenharmony_ci      if (Math.round(i/100) % 2) {
191cb93a386Sopenharmony_ci        path.transform(scaleDown);
192cb93a386Sopenharmony_ci      } else {
193cb93a386Sopenharmony_ci        path.transform(scaleUp);
194cb93a386Sopenharmony_ci      }
195cb93a386Sopenharmony_ci
196cb93a386Sopenharmony_ci      ctx.clearRect(0, 0, 300, 300);
197cb93a386Sopenharmony_ci      ctx.stroke(path.toPath2D());
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_ci      ctx.font = '42px monospace';
200cb93a386Sopenharmony_ci      let x = 150-ctx.measureText('Transform').width/2;
201cb93a386Sopenharmony_ci      ctx.strokeText('Transform', x, 290);
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci      window.requestAnimationFrame(frame);
204cb93a386Sopenharmony_ci    }
205cb93a386Sopenharmony_ci    window.requestAnimationFrame(frame);
206cb93a386Sopenharmony_ci  }
207cb93a386Sopenharmony_ci})();
208cb93a386Sopenharmony_ci</script>
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci## Example Code
211cb93a386Sopenharmony_ci
212cb93a386Sopenharmony_ciThe best place to look for examples on how to use PathKit would be in the
213cb93a386Sopenharmony_ci[example.html](https://github.com/google/skia/blob/main/modules/pathkit/npm-wasm/example.html#L45),
214cb93a386Sopenharmony_ciwhich comes in the npm package.
215cb93a386Sopenharmony_ci
216cb93a386Sopenharmony_ci## Download the library
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ciSee the the npm page for either the
219cb93a386Sopenharmony_ci[WebAssembly](https://www.npmjs.com/package/pathkit-wasm) version or the
220cb93a386Sopenharmony_ci[asm.js](https://www.npmjs.com/package/pathkit-asmjs) version for details on
221cb93a386Sopenharmony_cidownloading and getting started.
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ciWebAssembly has faster load times and better overall performance but is
224cb93a386Sopenharmony_cicurrently supported by Chrome, Firefox, Edge, and Safari. The asm.js version
225cb93a386Sopenharmony_cishould run anywhere JavaScript does.
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci## API
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ciThe primary feature of the library is the `SkPath` object. It can be created:
230cb93a386Sopenharmony_ci
231cb93a386Sopenharmony_ci- From the SVG string of a path `PathKit.FromSVGString(str)`
232cb93a386Sopenharmony_ci- From a 2D array of verbs and arguments `PathKit.FromCmds(cmds)`
233cb93a386Sopenharmony_ci- From `PathKit.NewPath()` (It will be blank)
234cb93a386Sopenharmony_ci- As a copy of an existing `SkPath` with `path.copy()` or
235cb93a386Sopenharmony_ci  `PathKit.NewPath(path)`
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ciIt can be exported as:
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci- An SVG string `path.toSVGString()`
240cb93a386Sopenharmony_ci- A [Path2D](https://developer.mozilla.org/en-US/docs/Web/API/Path2D) object
241cb93a386Sopenharmony_ci  `path.toPath2D()`
242cb93a386Sopenharmony_ci- Directly to a canvas 2D context `path.toCanvas(ctx)`
243cb93a386Sopenharmony_ci- A 2D array of verbs and arguments `path.toCmds()`
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ciOnce an SkPath object has been made, it can be interacted with in the following
246cb93a386Sopenharmony_ciways:
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_ci- expanded by any of the Path2D operations (`moveTo`, `lineTo`, `rect`, `arc`,
249cb93a386Sopenharmony_ci  etc)
250cb93a386Sopenharmony_ci- combined with other paths using `op` or `PathKit.MakeFromOp(p1, p2, op)`. For
251cb93a386Sopenharmony_ci  example, `path1.op(path2, PathKit.PathOp.INTERSECT)` will set path1 to be the
252cb93a386Sopenharmony_ci  area represented by where path1 and path2 overlap (intersect).
253cb93a386Sopenharmony_ci  `PathKit.MakeFromOp(path1, path2, PathKit.PathOp.INTERSECT)` will do the same
254cb93a386Sopenharmony_ci  but returned as a new `SkPath` object.
255cb93a386Sopenharmony_ci- adjusted with some of the effects (`trim`, `dash`, `stroke`, etc)
256cb93a386Sopenharmony_ci
257cb93a386Sopenharmony_ci**Important**: Any objects (`SkPath`, `SkOpBuilder`, etc) that are created must
258cb93a386Sopenharmony_cibe cleaned up with `path.delete()` when they leave the scope to avoid leaking
259cb93a386Sopenharmony_cithe memory in the WASM heap. This includes any of the constructors, `copy()`, or
260cb93a386Sopenharmony_ciany function prefixed with "make".
261cb93a386Sopenharmony_ci
262cb93a386Sopenharmony_ci### PathKit
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_ci#### `FromSVGString(str)`
265cb93a386Sopenharmony_ci
266cb93a386Sopenharmony_ci**str** - `String` representing an
267cb93a386Sopenharmony_ci[SVGPath](https://www.w3schools.com/graphics/svg_path.asp)
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ciReturns an `SkPath` with the same verbs and arguments as the SVG string, or
270cb93a386Sopenharmony_ci`null` on a failure.
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ciExample:
273cb93a386Sopenharmony_ci
274cb93a386Sopenharmony_ci    let path = PathKit.FromSVGString('M150 0 L75 200 L225 200 Z');
275cb93a386Sopenharmony_ci    // path represents a triangle
276cb93a386Sopenharmony_ci    // don't forget to do path.delete() when it goes out of scope.
277cb93a386Sopenharmony_ci
278cb93a386Sopenharmony_ci#### `FromCmds(cmds)`
279cb93a386Sopenharmony_ci
280cb93a386Sopenharmony_ci**cmds** - `Array<Array<Number>>`, a 2D array of commands, where a command is a
281cb93a386Sopenharmony_civerb followed by its arguments.
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ciReturns an `SkPath` with the verbs and arguments from the list or `null` on a
284cb93a386Sopenharmony_cifailure.
285cb93a386Sopenharmony_ci
286cb93a386Sopenharmony_ciThis can be faster than calling `.moveTo()`, `.lineTo()`, etc many times.
287cb93a386Sopenharmony_ci
288cb93a386Sopenharmony_ciExample:
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    let cmds = [
291cb93a386Sopenharmony_ci        [PathKit.MOVE_VERB, 0, 10],
292cb93a386Sopenharmony_ci        [PathKit.LINE_VERB, 30, 40],
293cb93a386Sopenharmony_ci        [PathKit.QUAD_VERB, 20, 50, 45, 60],
294cb93a386Sopenharmony_ci    ];
295cb93a386Sopenharmony_ci    let path = PathKit.FromCmds(cmds);
296cb93a386Sopenharmony_ci    // path is the same as if a user had done
297cb93a386Sopenharmony_ci    // let path = PathKit.NewPath().moveTo(0, 10).lineTo(30, 40).quadTo(20, 50, 45, 60);
298cb93a386Sopenharmony_ci    // don't forget to do path.delete() when it goes out of scope.
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci#### `NewPath()`
301cb93a386Sopenharmony_ci
302cb93a386Sopenharmony_ciReturns an empty `SkPath` object.
303cb93a386Sopenharmony_ci
304cb93a386Sopenharmony_ciExample:
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    let path = PathKit.NewPath();
307cb93a386Sopenharmony_ci    path.moveTo(0, 10)
308cb93a386Sopenharmony_ci        .lineTo(30, 40)
309cb93a386Sopenharmony_ci        .quadTo(20, 50, 45, 60);
310cb93a386Sopenharmony_ci    // don't forget to do path.delete() when it goes out of scope.
311cb93a386Sopenharmony_ci    // Users can also do let path = new PathKit.SkPath();
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_ci#### `NewPath(pathToCopy)`
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci**pathToCopy** - SkPath, a path to make a copy of.
316cb93a386Sopenharmony_ci
317cb93a386Sopenharmony_ciReturns a `SkPath` that is a copy of the passed in `SkPath`.
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ciExample:
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    let otherPath = ...;
322cb93a386Sopenharmony_ci    let clone = PathKit.NewPath(otherPath);
323cb93a386Sopenharmony_ci    clone.simplify();
324cb93a386Sopenharmony_ci    // don't forget to do clone.delete() when it goes out of scope.
325cb93a386Sopenharmony_ci    // Users can also do let clone = new PathKit.SkPath(otherPath);
326cb93a386Sopenharmony_ci    // or let clone = otherPath.copy();
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci#### `MakeFromOp(pathOne, pathTwo, op)`
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_ci**pathOne** - `SkPath`, a path. <br> **pathTwo** - `SkPath`, a path. <br>
331cb93a386Sopenharmony_ci**op** - `PathOp`, an op to apply
332cb93a386Sopenharmony_ci
333cb93a386Sopenharmony_ciReturns a new `SkPath` that is the result of applying the given PathOp to the
334cb93a386Sopenharmony_cifirst and second path (order matters).
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ciExample:
337cb93a386Sopenharmony_ci
338cb93a386Sopenharmony_ci    let pathOne = PathKit.NewPath().moveTo(0, 20).lineTo(10, 10).lineTo(20, 20).close();
339cb93a386Sopenharmony_ci    let pathTwo = PathKit.NewPath().moveTo(10, 20).lineTo(20, 10).lineTo(30, 20).close();
340cb93a386Sopenharmony_ci    let mountains = PathKit.MakeFromOp(pathOne, pathTwo, PathKit.PathOp.UNION);
341cb93a386Sopenharmony_ci    // don't forget to do mountains.delete() when it goes out of scope.
342cb93a386Sopenharmony_ci    // Users can also do pathOne.op(pathTwo, PathKit.PathOp.UNION);
343cb93a386Sopenharmony_ci    // to have the resulting path be stored to pathOne and avoid allocating another object.
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ci#### `cubicYFromX(cpx1, cpy1, cpx2, cpy2, X)`
346cb93a386Sopenharmony_ci
347cb93a386Sopenharmony_ci**cpx1, cpy1, cpx2, cpy2** - `Number`, coordinates for control points. <br>
348cb93a386Sopenharmony_ci**X** - `Number`, The X coordinate for which to find the corresponding Y
349cb93a386Sopenharmony_cicoordinate.
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_ciFast evaluation of a cubic ease-in / ease-out curve. This is defined as a
352cb93a386Sopenharmony_ciparametric cubic curve inside the unit square. Makes the following assumptions:
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci- pt[0] is implicitly { 0, 0 }
355cb93a386Sopenharmony_ci- pt[3] is implicitly { 1, 1 }
356cb93a386Sopenharmony_ci- pts[1, 2] are inside the unit square
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ciThis returns the Y coordinate for the given X coordinate.
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci#### `cubicPtFromT(cpx1, cpy1, cpx2, cpy2, T)`
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci**cpx1, cpy1, cpx2, cpy2** - `Number`, coordinates for control points. <br>
363cb93a386Sopenharmony_ci**T** - `Number`, The T param for which to find the corresponding (X, Y)
364cb93a386Sopenharmony_cicoordinates.
365cb93a386Sopenharmony_ci
366cb93a386Sopenharmony_ciFast evaluation of a cubic ease-in / ease-out curve. This is defined as a
367cb93a386Sopenharmony_ciparametric cubic curve inside the unit square. Makes the following assumptions:
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci- pt[0] is implicitly { 0, 0 }
370cb93a386Sopenharmony_ci- pt[3] is implicitly { 1, 1 }
371cb93a386Sopenharmony_ci- pts[1, 2] are inside the unit square
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ciThis returns the (X, Y) coordinate for the given T value as a length 2 array.
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci### SkPath (object)
376cb93a386Sopenharmony_ci
377cb93a386Sopenharmony_ci#### `addPath(otherPath)`
378cb93a386Sopenharmony_ci
379cb93a386Sopenharmony_ci**otherPath** - `SkPath`, a path to append to this path
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ciAdds the given path to `this` and then returns `this` for chaining purposes.
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ci#### `addPath(otherPath, transform)`
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci**otherPath** - `SkPath`, a path to append to this path. <br> **transform** -
386cb93a386Sopenharmony_ci[SVGMatrix](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix), a
387cb93a386Sopenharmony_citransform to apply to otherPath before appending it.
388cb93a386Sopenharmony_ci
389cb93a386Sopenharmony_ciAdds the given path to `this` after applying the transform and then returns
390cb93a386Sopenharmony_ci`this` for chaining purposes. See
391cb93a386Sopenharmony_ci[Path2D.addPath()](https://developer.mozilla.org/en-US/docs/Web/API/Path2D/addPath)
392cb93a386Sopenharmony_cifor more details.
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ci#### `addPath(otherPath, a, b, c, d, e, f)`
395cb93a386Sopenharmony_ci
396cb93a386Sopenharmony_ci**otherPath** - `SkPath`, a path to append to this path. <br> **a, b, c, d, e,
397cb93a386Sopenharmony_cif** - `Number`, the six components of an
398cb93a386Sopenharmony_ci[SVGMatrix](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix), which
399cb93a386Sopenharmony_cidefine the transform to apply to otherPath before appending it.
400cb93a386Sopenharmony_ci
401cb93a386Sopenharmony_ciAdds the given path to `this` after applying the transform and then returns
402cb93a386Sopenharmony_ci`this` for chaining purposes. See
403cb93a386Sopenharmony_ci[Path2D.addPath()](https://developer.mozilla.org/en-US/docs/Web/API/Path2D/addPath)
404cb93a386Sopenharmony_cifor more details.
405cb93a386Sopenharmony_ci
406cb93a386Sopenharmony_ciExample:
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
409cb93a386Sopenharmony_ci    let moreBoxes = PathKit.NewPath();
410cb93a386Sopenharmony_ci    // add box un-transformed (i.e. at 0, 0)
411cb93a386Sopenharmony_ci    moreBoxes.addPath(box)
412cb93a386Sopenharmony_ci    // the params fill out a 2d matrix like:
413cb93a386Sopenharmony_ci    //     a c e
414cb93a386Sopenharmony_ci    //     b d f
415cb93a386Sopenharmony_ci    //     0 0 1
416cb93a386Sopenharmony_ci    // add box 300 points to the right
417cb93a386Sopenharmony_ci             .addPath(box, 1, 0, 0, 1, 300, 0)
418cb93a386Sopenharmony_ci    // add a box shrunk by 50% in both directions
419cb93a386Sopenharmony_ci             .addPath(box, 0.5, 0, 0, 0.5, 0, 0);
420cb93a386Sopenharmony_ci    // moreBoxes now has 3 paths appended to it
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_ci#### `addPath(otherPath, scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2)`
423cb93a386Sopenharmony_ci
424cb93a386Sopenharmony_ci**otherPath** - `SkPath`, a path to append to this path. <br> **scaleX, skewX,
425cb93a386Sopenharmony_citransX, skewY, scaleY, transY, pers0, pers1, pers2** - `Number`, the nine
426cb93a386Sopenharmony_cicomponents of an
427cb93a386Sopenharmony_ci[Affine Matrix](https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations),
428cb93a386Sopenharmony_ciwhich define the transform to apply to otherPath before appending it.
429cb93a386Sopenharmony_ci
430cb93a386Sopenharmony_ciAdds the given path to `this` after applying the transform and then returns
431cb93a386Sopenharmony_ci`this` for chaining purposes.
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ciExample:
434cb93a386Sopenharmony_ci
435cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
436cb93a386Sopenharmony_ci    let moreBoxes = PathKit.NewPath();
437cb93a386Sopenharmony_ci    // add box un-transformed (i.e. at 0, 0)
438cb93a386Sopenharmony_ci    moreBoxes.addPath(box)
439cb93a386Sopenharmony_ci    // add box 300 points to the right
440cb93a386Sopenharmony_ci             .addPath(box, 1, 0, 0,
441cb93a386Sopenharmony_ci                           0, 1, 300,
442cb93a386Sopenharmony_ci                           0, 0 ,1)
443cb93a386Sopenharmony_ci    // add a box shrunk by 50% in both directions
444cb93a386Sopenharmony_ci             .addPath(box, 0.5, 0,   0,
445cb93a386Sopenharmony_ci                           0,   0.5, 0,
446cb93a386Sopenharmony_ci                           0,   0,   1)
447cb93a386Sopenharmony_ci    // moreBoxes now has 3 paths appended to it
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ci#### `arc(x, y, radius, startAngle, endAngle, ccw=false)`
450cb93a386Sopenharmony_ci
451cb93a386Sopenharmony_ci**x, y** - `Number`, The coordinates of the arc's center. <br> **radius** -
452cb93a386Sopenharmony_ci`Number`, The radius of the arc. <br> **startAngle, endAngle** - `Number`, the
453cb93a386Sopenharmony_cistart and end of the angle, measured clockwise from the positive x axis and in
454cb93a386Sopenharmony_ciradians. <br> **ccw** - `Boolean`, optional argument specifying if the arc
455cb93a386Sopenharmony_cishould be drawn counter-clockwise between **startAngle** and **endAngle**
456cb93a386Sopenharmony_ciinstead of clockwise, the default.
457cb93a386Sopenharmony_ci
458cb93a386Sopenharmony_ciAdds the described arc to `this` then returns `this` for chaining purposes. See
459cb93a386Sopenharmony_ci[Path2D.arc()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc)
460cb93a386Sopenharmony_cifor more details.
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ciExample:
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci    let path = PathKit.NewPath();
465cb93a386Sopenharmony_ci    path.moveTo(20, 120);
466cb93a386Sopenharmony_ci        .arc(20, 120, 18, 0, 1.75 * Math.PI);
467cb93a386Sopenharmony_ci        .lineTo(20, 120);
468cb93a386Sopenharmony_ci    // path looks like a pie with a 1/8th slice removed.
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_ci#### `arcTo(x1, y1, x2, y2, radius)`
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci**x1, y1, x2, y2** - `Number`, The coordinates defining the control points. <br>
473cb93a386Sopenharmony_ci**radius** - `Number`, The radius of the arc.
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ciAdds the described arc to `this` (appending a line, if needed) then returns
476cb93a386Sopenharmony_ci`this` for chaining purposes. See
477cb93a386Sopenharmony_ci[Path2D.arcTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arcTo)
478cb93a386Sopenharmony_cifor more details.
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ci#### `close()` or `closePath()`
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_ciReturns the pen to the start of the current sub-path, then returns `this` for
483cb93a386Sopenharmony_cichaining purposes. See
484cb93a386Sopenharmony_ci[Path2D.closePath()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/closePath)
485cb93a386Sopenharmony_cifor more details.
486cb93a386Sopenharmony_ci
487cb93a386Sopenharmony_ci#### `computeTightBounds()`
488cb93a386Sopenharmony_ci
489cb93a386Sopenharmony_ciReturns an `SkRect` that represents the minimum and maximum area of `this` path.
490cb93a386Sopenharmony_ciSee
491cb93a386Sopenharmony_ci[SkPath reference](https://api.skia.org/classSkPath.html#a597c8fcc5e4750542e2688b057a14e9e)
492cb93a386Sopenharmony_cifor more details.
493cb93a386Sopenharmony_ci
494cb93a386Sopenharmony_ci#### `conicTo(x1, y1, x2, y2, w)`
495cb93a386Sopenharmony_ci
496cb93a386Sopenharmony_ci**x1, y1, x2, y2** - `Number`, The coordinates defining the control point and
497cb93a386Sopenharmony_cithe end point. <br> **w** - `Number`, The weight of the conic.
498cb93a386Sopenharmony_ci
499cb93a386Sopenharmony_ciAdds the described conic line to `this` (appending a line, if needed) then
500cb93a386Sopenharmony_cireturns `this` for chaining purposes. See
501cb93a386Sopenharmony_ci[SkPath reference](https://api.skia.org/classSkPath.html#a9edc41978765cfe9a0b16e9ecf4d276e)
502cb93a386Sopenharmony_cifor more details.
503cb93a386Sopenharmony_ci
504cb93a386Sopenharmony_ci#### `copy()`
505cb93a386Sopenharmony_ci
506cb93a386Sopenharmony_ciReturn a copy of `this` path.
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ci#### `cubicTo(cp1x, cp1y, cp2x, cp2y, x, y)` or `bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)`
509cb93a386Sopenharmony_ci
510cb93a386Sopenharmony_ci**cp1x, cp1y, cp2x, cp2y** - `Number`, The coordinates defining the control
511cb93a386Sopenharmony_cipoints. <br> **x,y** - `Number`, The coordinates defining the end point
512cb93a386Sopenharmony_ci
513cb93a386Sopenharmony_ciAdds the described cubic line to `this` (appending a line, if needed) then
514cb93a386Sopenharmony_cireturns `this` for chaining purposes. See
515cb93a386Sopenharmony_ci[Path2D.bezierCurveTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo)
516cb93a386Sopenharmony_cifor more details.
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ci#### `dash(on, off, phase)`
519cb93a386Sopenharmony_ci
520cb93a386Sopenharmony_ci**on, off** - `Number`, The number of pixels the dash should be on (drawn) and
521cb93a386Sopenharmony_cioff (blank). <br> **phase** - `Number`, The number of pixels the on/off should
522cb93a386Sopenharmony_cibe offset (mod **on** + **off**)
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ciApplies a dashed path effect to `this` then returns `this` for chaining
525cb93a386Sopenharmony_cipurposes. See the "Dash" effect above for a visual example.
526cb93a386Sopenharmony_ci
527cb93a386Sopenharmony_ciExample:
528cb93a386Sopenharmony_ci
529cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
530cb93a386Sopenharmony_ci    box.dash(20, 10, 3);
531cb93a386Sopenharmony_ci    // box is now a dashed rectangle that will draw for 20 pixels, then
532cb93a386Sopenharmony_ci    // stop for 10 pixels.  Since phase is 3, the first line won't start
533cb93a386Sopenharmony_ci    // at (0, 0), but 3 pixels around the path (3, 0)
534cb93a386Sopenharmony_ci
535cb93a386Sopenharmony_ci#### `ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, ccw=false)`
536cb93a386Sopenharmony_ci
537cb93a386Sopenharmony_ci**x, y** - `Number`, The coordinates of the center of the ellipse. <br>
538cb93a386Sopenharmony_ci**radiusX, radiusY** - `Number`, The radii in the X and Y directions. <br>
539cb93a386Sopenharmony_ci**rotation** - `Number`, The rotation in radians of this ellipse. <br>
540cb93a386Sopenharmony_ci**startAngle, endAngle** - `Number`, the starting and ending angles of which to
541cb93a386Sopenharmony_cidraw, measured in radians from the positive x axis. <br> **ccw** - `Boolean`,
542cb93a386Sopenharmony_cioptional argument specifying if the ellipse should be drawn counter-clockwise
543cb93a386Sopenharmony_cibetween **startAngle** and **endAngle** instead of clockwise, the default.
544cb93a386Sopenharmony_ci
545cb93a386Sopenharmony_ciAdds the described ellipse to `this` then returns `this` for chaining purposes.
546cb93a386Sopenharmony_ciSee
547cb93a386Sopenharmony_ci[Path2D.ellipse](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/ellipse)
548cb93a386Sopenharmony_cifor more details.
549cb93a386Sopenharmony_ci
550cb93a386Sopenharmony_ci#### `equals(otherPath)`
551cb93a386Sopenharmony_ci
552cb93a386Sopenharmony_ci**otherPath** - `SkPath`, the path to compare to.
553cb93a386Sopenharmony_ci
554cb93a386Sopenharmony_ciReturns a `Boolean` value based on if `this` path is equal to **otherPath**.
555cb93a386Sopenharmony_ci
556cb93a386Sopenharmony_ci#### `getBounds()`
557cb93a386Sopenharmony_ci
558cb93a386Sopenharmony_ciReturns an `SkRect` that represents the minimum and maximum area of `this` path.
559cb93a386Sopenharmony_ciSee
560cb93a386Sopenharmony_ci[SkPath reference](https://api.skia.org/classSkPath.html#ac60188dc6075d6ebb56b5398fbba0c10)
561cb93a386Sopenharmony_cifor more details.
562cb93a386Sopenharmony_ci
563cb93a386Sopenharmony_ci#### `getFillType()`
564cb93a386Sopenharmony_ci
565cb93a386Sopenharmony_ciReturns a `FillType` based on what this path is. This defaults to
566cb93a386Sopenharmony_ci`PathKit.FillType.WINDING`, but may change with `op()` or `simplify()`.
567cb93a386Sopenharmony_ci
568cb93a386Sopenharmony_ciClients will typically want `getFillTypeString()` because that value can be
569cb93a386Sopenharmony_cipassed directly to an SVG or Canvas.
570cb93a386Sopenharmony_ci
571cb93a386Sopenharmony_ci#### `getFillTypeString()`
572cb93a386Sopenharmony_ci
573cb93a386Sopenharmony_ciReturns a `String` representing the fillType of `this` path. The values are
574cb93a386Sopenharmony_cieither "nonzero" or "evenodd".
575cb93a386Sopenharmony_ci
576cb93a386Sopenharmony_ciExample:
577cb93a386Sopenharmony_ci
578cb93a386Sopenharmony_ci    let path = ...;
579cb93a386Sopenharmony_ci    let ctx = document.getElementById('canvas1').getContext('2d');
580cb93a386Sopenharmony_ci    ctx.strokeStyle = 'green';
581cb93a386Sopenharmony_ci    ctx.fill(path.toPath2D(), path.getFillTypeString());
582cb93a386Sopenharmony_ci
583cb93a386Sopenharmony_ci#### `moveTo(x, y)`
584cb93a386Sopenharmony_ci
585cb93a386Sopenharmony_ci**x, y** - `Number`, The coordinates of where the pen should be moved to.
586cb93a386Sopenharmony_ci
587cb93a386Sopenharmony_ciMoves the pen (without drawing) to the given coordinates then returns `this` for
588cb93a386Sopenharmony_cichaining purposes. See
589cb93a386Sopenharmony_ci[Path2D.moveTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/moveTo)
590cb93a386Sopenharmony_cifor more details.
591cb93a386Sopenharmony_ci
592cb93a386Sopenharmony_ci#### `lineTo(x, y)`
593cb93a386Sopenharmony_ci
594cb93a386Sopenharmony_ci**x, y** - `Number`, The coordinates of where the pen should be moved to.
595cb93a386Sopenharmony_ci
596cb93a386Sopenharmony_ciDraws a straight line to the given coordinates then returns `this` for chaining
597cb93a386Sopenharmony_cipurposes. See
598cb93a386Sopenharmony_ci[Path2D.lineTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineTo)
599cb93a386Sopenharmony_cifor more details.
600cb93a386Sopenharmony_ci
601cb93a386Sopenharmony_ci#### `op(otherPath, operation)`
602cb93a386Sopenharmony_ci
603cb93a386Sopenharmony_ci**otherPath** - `SkPath`, The other path to be combined with `this`. <br>
604cb93a386Sopenharmony_ci**operation** - `PathOp`, The operation to apply to the two paths.
605cb93a386Sopenharmony_ci
606cb93a386Sopenharmony_ciCombines otherPath into `this` path with the given operation and returns `this`
607cb93a386Sopenharmony_cifor chaining purposes.
608cb93a386Sopenharmony_ci
609cb93a386Sopenharmony_ciExample:
610cb93a386Sopenharmony_ci
611cb93a386Sopenharmony_ci    let pathOne = PathKit.NewPath().moveTo(0, 20).lineTo(10, 10).lineTo(20, 20).close();
612cb93a386Sopenharmony_ci    let pathTwo = PathKit.NewPath().moveTo(10, 20).lineTo(20, 10).lineTo(30, 20).close();
613cb93a386Sopenharmony_ci    // Combine the two triangles to look like two mountains
614cb93a386Sopenharmony_ci    let mountains = pathOne.copy().op(pathOne, pathTwo, PathKit.PathOp.UNION);
615cb93a386Sopenharmony_ci    // set pathOne to be the small triangle where pathOne and pathTwo overlap
616cb93a386Sopenharmony_ci    pathOne.op(pathOne, pathTwo, PathKit.PathOp.INTERSECT);
617cb93a386Sopenharmony_ci    // since copy() was called, don't forget to call delete() on mountains.
618cb93a386Sopenharmony_ci
619cb93a386Sopenharmony_ci#### `quadTo(cpx, cpy, x, y)` or `quadraticCurveTo(cpx, cpy, x, y)`
620cb93a386Sopenharmony_ci
621cb93a386Sopenharmony_ci**cpx, cpy** - `Number`, The coordinates for the control point. <br> **x, y** -
622cb93a386Sopenharmony_ci`Number`, The coordinates for the end point.
623cb93a386Sopenharmony_ci
624cb93a386Sopenharmony_ciDraws a quadratic Bézier curve with the given coordinates then returns `this`
625cb93a386Sopenharmony_cifor chaining purposes. See
626cb93a386Sopenharmony_ci[Path2D.quadraticCurveTo](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/quadraticCurveTo)
627cb93a386Sopenharmony_cifor more details.
628cb93a386Sopenharmony_ci
629cb93a386Sopenharmony_ci#### `rect(x, y, w, h)`
630cb93a386Sopenharmony_ci
631cb93a386Sopenharmony_ci**x, y** - `Number`, The coordinates of the upper-left corner of the rectangle.
632cb93a386Sopenharmony_ci<br> **w, h** - `Number`, The width and height of the rectangle
633cb93a386Sopenharmony_ci
634cb93a386Sopenharmony_ciDraws a rectangle on `this`, then returns `this` for chaining purposes. See
635cb93a386Sopenharmony_ci[Path2D.rect](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rect)
636cb93a386Sopenharmony_cifor more details.
637cb93a386Sopenharmony_ci
638cb93a386Sopenharmony_ci#### `setFillType(fillType)`
639cb93a386Sopenharmony_ci
640cb93a386Sopenharmony_ci**fillType** - `FillType`, the new fillType.
641cb93a386Sopenharmony_ci
642cb93a386Sopenharmony_ciSet the fillType of the path. See
643cb93a386Sopenharmony_ci[SkPath reference](https://api.skia.org/SkPathTypes_8h.html#acc5b8721019c4a4b1beb8c759baab011)
644cb93a386Sopenharmony_cifor more details.
645cb93a386Sopenharmony_ci
646cb93a386Sopenharmony_ci#### `simplify()`
647cb93a386Sopenharmony_ci
648cb93a386Sopenharmony_ciSet `this` path to a set of _non-overlapping_ contours that describe the same
649cb93a386Sopenharmony_ciarea as the original path. See the "Simplify" effect above for a visual example.
650cb93a386Sopenharmony_ci
651cb93a386Sopenharmony_ci#### `stroke(opts)`
652cb93a386Sopenharmony_ci
653cb93a386Sopenharmony_ci**opts** - `StrokeOpts`, contains the options for stroking.
654cb93a386Sopenharmony_ci
655cb93a386Sopenharmony_ciStrokes `this` path out with the given options. This can be used for a variety
656cb93a386Sopenharmony_ciof effects. See the "Stroke", "Grow", and "Shrink" effects above for visual
657cb93a386Sopenharmony_ciexamples.
658cb93a386Sopenharmony_ci
659cb93a386Sopenharmony_ciExample:
660cb93a386Sopenharmony_ci
661cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
662cb93a386Sopenharmony_ci    // Stroke the path with width 10 and rounded corners
663cb93a386Sopenharmony_ci    let rounded = box.copy().stroke({width: 10, join: PathKit.StrokeJoin.ROUND});
664cb93a386Sopenharmony_ci    // Grow effect, that is, a 20 pixel expansion around the box.
665cb93a386Sopenharmony_ci    let grow = box.copy().stroke({width: 20}).op(box, PathKit.PathOp.DIFFERENCE);
666cb93a386Sopenharmony_ci    // Shrink effect, in which we subtract away from the original
667cb93a386Sopenharmony_ci    let simplified = box.copy().simplify(); // sometimes required for complicated paths
668cb93a386Sopenharmony_ci    let shrink = box.copy().stroke({width: 15, cap: PathKit.StrokeCap.BUTT})
669cb93a386Sopenharmony_ci                           .op(simplified, PathKit.PathOp.REVERSE_DIFFERENCE);
670cb93a386Sopenharmony_ci    // Don't forget to call delete() on each of the copies!
671cb93a386Sopenharmony_ci
672cb93a386Sopenharmony_ci#### `toCanvas(ctx)`
673cb93a386Sopenharmony_ci
674cb93a386Sopenharmony_ci**ctx** - `Canvas2DContext`, Canvas on which to draw the path.
675cb93a386Sopenharmony_ci
676cb93a386Sopenharmony_ciDraws `this` path on the passed in
677cb93a386Sopenharmony_ci[Canvas Context](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D).
678cb93a386Sopenharmony_ci
679cb93a386Sopenharmony_ciExample:
680cb93a386Sopenharmony_ci
681cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
682cb93a386Sopenharmony_ci    let ctx = document.getElementById('canvas1').getContext('2d');
683cb93a386Sopenharmony_ci    ctx.strokeStyle = 'green';
684cb93a386Sopenharmony_ci    ctx.beginPath();
685cb93a386Sopenharmony_ci    box.toCanvas(ctx);
686cb93a386Sopenharmony_ci    ctx.stroke();  // could also ctx.fill()
687cb93a386Sopenharmony_ci
688cb93a386Sopenharmony_ci#### `toCmds()`
689cb93a386Sopenharmony_ci
690cb93a386Sopenharmony_ciReturns a 2D Array of verbs and args. See `PathKit.FromCmds()` for more details.
691cb93a386Sopenharmony_ci
692cb93a386Sopenharmony_ci#### `toPath2D()`
693cb93a386Sopenharmony_ci
694cb93a386Sopenharmony_ciReturns a [Path2D](https://developer.mozilla.org/en-US/docs/Web/API/Path2D)
695cb93a386Sopenharmony_ciobject that has the same operations as `this` path.
696cb93a386Sopenharmony_ci
697cb93a386Sopenharmony_ciExample:
698cb93a386Sopenharmony_ci
699cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
700cb93a386Sopenharmony_ci    let ctx = document.getElementById('canvas1').getContext('2d');
701cb93a386Sopenharmony_ci    ctx.strokeStyle = 'green';
702cb93a386Sopenharmony_ci    ctx.stroke(box.toPath2D());
703cb93a386Sopenharmony_ci
704cb93a386Sopenharmony_ci#### `toSVGString()`
705cb93a386Sopenharmony_ci
706cb93a386Sopenharmony_ciReturns a `String` representing an
707cb93a386Sopenharmony_ci[SVGPath](https://www.w3schools.com/graphics/svg_path.asp) based on `this` path.
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ciExample:
710cb93a386Sopenharmony_ci
711cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
712cb93a386Sopenharmony_ci    let svg = document.getElementById('svg1');
713cb93a386Sopenharmony_ci    let newPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
714cb93a386Sopenharmony_ci    newPath.setAttribute('stroke', 'green');
715cb93a386Sopenharmony_ci    newPath.setAttribute('fill', 'white');
716cb93a386Sopenharmony_ci    newPath.setAttribute('d', box.toSVGString());
717cb93a386Sopenharmony_ci    svg.appendChild(newPath);
718cb93a386Sopenharmony_ci
719cb93a386Sopenharmony_ci#### `transform(matr)`
720cb93a386Sopenharmony_ci
721cb93a386Sopenharmony_ci**matr** - `SkMatrix`, i.e. an `Array<Number>` of the nine numbers of an Affine
722cb93a386Sopenharmony_ciTransform Matrix.
723cb93a386Sopenharmony_ci
724cb93a386Sopenharmony_ciApplies the specified
725cb93a386Sopenharmony_ci[transform](https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations)
726cb93a386Sopenharmony_cito `this` and then returns `this` for chaining purposes.
727cb93a386Sopenharmony_ci
728cb93a386Sopenharmony_ci#### `transform(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2)`
729cb93a386Sopenharmony_ci
730cb93a386Sopenharmony_ci**scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2** -
731cb93a386Sopenharmony_ci`Number`, the nine numbers of an Affine Transform Matrix.
732cb93a386Sopenharmony_ci
733cb93a386Sopenharmony_ciApplies the specified
734cb93a386Sopenharmony_ci[transform](https://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations)
735cb93a386Sopenharmony_cito `this` and then returns `this` for chaining purposes.
736cb93a386Sopenharmony_ci
737cb93a386Sopenharmony_ciExample:
738cb93a386Sopenharmony_ci
739cb93a386Sopenharmony_ci    let path = PathKit.NewPath().rect(0, 0, 100, 100);
740cb93a386Sopenharmony_ci    // scale up the path by 5x
741cb93a386Sopenharmony_ci    path.transform([5, 0, 0,
742cb93a386Sopenharmony_ci                    0, 5, 0,
743cb93a386Sopenharmony_ci                    0, 0, 1]);
744cb93a386Sopenharmony_ci    // move the path 75 px to the right.
745cb93a386Sopenharmony_ci    path.transform(1, 0, 75,
746cb93a386Sopenharmony_ci                   0, 1, 0,
747cb93a386Sopenharmony_ci                   0, 0, 1);
748cb93a386Sopenharmony_ci
749cb93a386Sopenharmony_ci#### `trim(startT, stopT, isComplement=false)`
750cb93a386Sopenharmony_ci
751cb93a386Sopenharmony_ci**startT, stopT** - `Number`, values in [0, 1] that indicate the start and stop
752cb93a386Sopenharmony_ci"percentages" of the path to draw <br> **isComplement** - `Boolean`, If the
753cb93a386Sopenharmony_cicomplement of the trimmed section should be drawn instead of the areas between
754cb93a386Sopenharmony_ci**startT** and **stopT**.
755cb93a386Sopenharmony_ci
756cb93a386Sopenharmony_ciSets `this` path to be a subset of the original path, then returns `this` for
757cb93a386Sopenharmony_cichaining purposes. See the "Trim" effect above for a visual example.
758cb93a386Sopenharmony_ci
759cb93a386Sopenharmony_ciExample:
760cb93a386Sopenharmony_ci
761cb93a386Sopenharmony_ci    let box = PathKit.NewPath().rect(0, 0, 100, 100);
762cb93a386Sopenharmony_ci    box.trim(0.25, 1.0);
763cb93a386Sopenharmony_ci    // box is now the 3 segments that look like a U
764cb93a386Sopenharmony_ci    // (the top segment has been removed).
765cb93a386Sopenharmony_ci
766cb93a386Sopenharmony_ci### SkOpBuilder (object)
767cb93a386Sopenharmony_ci
768cb93a386Sopenharmony_ciThis object enables chaining multiple PathOps together. Create one with
769cb93a386Sopenharmony_ci`let builder = new PathKit.SkOpBuilder();` When created, the internal state is
770cb93a386Sopenharmony_ci"empty path". Don't forget to call `delete()` on both the builder and the result
771cb93a386Sopenharmony_ciof `resolve()`
772cb93a386Sopenharmony_ci
773cb93a386Sopenharmony_ci#### `add(path, operation)`
774cb93a386Sopenharmony_ci
775cb93a386Sopenharmony_ci**path** - `SkPath`, The path to be combined with the given rule. <br>
776cb93a386Sopenharmony_ci**operation** - `PathOp`, The operation to apply to the two paths.
777cb93a386Sopenharmony_ci
778cb93a386Sopenharmony_ciAdds a path and the operand to the builder.
779cb93a386Sopenharmony_ci
780cb93a386Sopenharmony_ci#### `make()` or `resolve()`
781cb93a386Sopenharmony_ci
782cb93a386Sopenharmony_ciCreates and returns a new `SkPath` based on all the given paths and operands.
783cb93a386Sopenharmony_ci
784cb93a386Sopenharmony_ciDon't forget to call `.delete()` on the returned path when it goes out of scope.
785cb93a386Sopenharmony_ci
786cb93a386Sopenharmony_ci### SkMatrix (struct)
787cb93a386Sopenharmony_ci
788cb93a386Sopenharmony_ci`SkMatrix` translates between a C++ struct and a JS Array. It basically takes a
789cb93a386Sopenharmony_cinine element 1D Array and turns it into a 3x3 2D Affine Matrix.
790cb93a386Sopenharmony_ci
791cb93a386Sopenharmony_ci### SkRect (struct)
792cb93a386Sopenharmony_ci
793cb93a386Sopenharmony_ci`SkRect` translates between a C++ struct and a JS Object with the following keys
794cb93a386Sopenharmony_ci(all values are `Number`:
795cb93a386Sopenharmony_ci
796cb93a386Sopenharmony_ci- **fLeft**: x coordinate of top-left corner
797cb93a386Sopenharmony_ci- **fTop**: y coordinate of top-left corner
798cb93a386Sopenharmony_ci- **fRight**: x coordinate of bottom-right corner
799cb93a386Sopenharmony_ci- **fBottom**: y coordinate of bottom-rightcorner
800cb93a386Sopenharmony_ci
801cb93a386Sopenharmony_ci### StrokeOpts (struct)
802cb93a386Sopenharmony_ci
803cb93a386Sopenharmony_ci`StrokeOpts` translates between a C++ struct and a JS Object with the following
804cb93a386Sopenharmony_cikeys:
805cb93a386Sopenharmony_ci
806cb93a386Sopenharmony_ci- **width**, `Number` the width of the lines of the path. Default 1.
807cb93a386Sopenharmony_ci- **miter_limit**, `Number`, the miter limit. Defautl 4. See
808cb93a386Sopenharmony_ci  [SkPaint reference](https://api.skia.org/classSkPaint.html#a2e767abfeb7795ed251a08b5ed85033f)
809cb93a386Sopenharmony_ci  for more details.
810cb93a386Sopenharmony_ci- **join**, `StrokeJoin`, the join to use. Default `PathKit.StrokeJoin.MITER`.
811cb93a386Sopenharmony_ci  See
812cb93a386Sopenharmony_ci  [SkPaint reference](https://api.skia.org/classSkPaint.html#ac582b0cbf59909c9056de34a6b977cca)
813cb93a386Sopenharmony_ci  for more details.
814cb93a386Sopenharmony_ci- **cap**, `StrokeCap`, the cap to use. Default `PathKit.StrokeCap.BUTT`. See
815cb93a386Sopenharmony_ci  [SkPaint reference](https://api.skia.org/classSkPaint.html#a0f78de8559b795defba93171f6cb6333)
816cb93a386Sopenharmony_ci  for more details.
817cb93a386Sopenharmony_ci
818cb93a386Sopenharmony_ci### PathOp (enum)
819cb93a386Sopenharmony_ci
820cb93a386Sopenharmony_ciThe following enum values are exposed. They are essentially constant objects,
821cb93a386Sopenharmony_cidifferentiated by their `.value` property.
822cb93a386Sopenharmony_ci
823cb93a386Sopenharmony_ci- `PathKit.PathOp.DIFFERENCE`
824cb93a386Sopenharmony_ci- `PathKit.PathOp.INTERSECT`
825cb93a386Sopenharmony_ci- `PathKit.PathOp.REVERSE_DIFFERENCE`
826cb93a386Sopenharmony_ci- `PathKit.PathOp.UNION`
827cb93a386Sopenharmony_ci- `PathKit.PathOp.XOR`
828cb93a386Sopenharmony_ci
829cb93a386Sopenharmony_ciThese are used in `PathKit.MakeFromOp()` and `SkPath.op()`.
830cb93a386Sopenharmony_ci
831cb93a386Sopenharmony_ci### FillType (enum)
832cb93a386Sopenharmony_ci
833cb93a386Sopenharmony_ciThe following enum values are exposed. They are essentially constant objects,
834cb93a386Sopenharmony_cidifferentiated by their `.value` property.
835cb93a386Sopenharmony_ci
836cb93a386Sopenharmony_ci- `PathKit.FillType.WINDING` (also known as nonzero)
837cb93a386Sopenharmony_ci- `PathKit.FillType.EVENODD`
838cb93a386Sopenharmony_ci- `PathKit.FillType.INVERSE_WINDING`
839cb93a386Sopenharmony_ci- `PathKit.FillType.INVERSE_EVENODD`
840cb93a386Sopenharmony_ci
841cb93a386Sopenharmony_ciThese are used by `SkPath.getFillType()` and `SkPath.setFillType()`, but
842cb93a386Sopenharmony_cigenerally clients will want `SkPath.getFillTypeString()`.
843cb93a386Sopenharmony_ci
844cb93a386Sopenharmony_ci### StrokeJoin (enum)
845cb93a386Sopenharmony_ci
846cb93a386Sopenharmony_ciThe following enum values are exposed. They are essentially constant objects,
847cb93a386Sopenharmony_cidifferentiated by their `.value` property.
848cb93a386Sopenharmony_ci
849cb93a386Sopenharmony_ci- `PathKit.StrokeJoin.MITER`
850cb93a386Sopenharmony_ci- `PathKit.StrokeJoin.ROUND`
851cb93a386Sopenharmony_ci- `PathKit.StrokeJoin.BEVEL`
852cb93a386Sopenharmony_ci
853cb93a386Sopenharmony_ciSee
854cb93a386Sopenharmony_ci[SkPaint reference](https://api.skia.org/classSkPaint.html#ac582b0cbf59909c9056de34a6b977cca)
855cb93a386Sopenharmony_cifor more details.
856cb93a386Sopenharmony_ci
857cb93a386Sopenharmony_ci### StrokeCap (enum)
858cb93a386Sopenharmony_ci
859cb93a386Sopenharmony_ciThe following enum values are exposed. They are essentially constant objects,
860cb93a386Sopenharmony_cidifferentiated by their `.value` property.
861cb93a386Sopenharmony_ci
862cb93a386Sopenharmony_ci- `PathKit.StrokeCap.BUTT`
863cb93a386Sopenharmony_ci- `PathKit.StrokeCap.ROUND`
864cb93a386Sopenharmony_ci- `PathKit.StrokeCap.SQUARE`
865cb93a386Sopenharmony_ci
866cb93a386Sopenharmony_ciSee
867cb93a386Sopenharmony_ci[SkPaint reference](https://api.skia.org/classSkPaint.html#a0f78de8559b795defba93171f6cb6333)
868cb93a386Sopenharmony_cifor more details.
869cb93a386Sopenharmony_ci
870cb93a386Sopenharmony_ci### Constants
871cb93a386Sopenharmony_ci
872cb93a386Sopenharmony_ciThe following constants are exposed:
873cb93a386Sopenharmony_ci
874cb93a386Sopenharmony_ci- `PathKit.MOVE_VERB` = 0
875cb93a386Sopenharmony_ci- `PathKit.LINE_VERB` = 1
876cb93a386Sopenharmony_ci- `PathKit.QUAD_VERB` = 2
877cb93a386Sopenharmony_ci- `PathKit.CONIC_VERB` = 3
878cb93a386Sopenharmony_ci- `PathKit.CUBIC_VERB` = 4
879cb93a386Sopenharmony_ci- `PathKit.CLOSE_VERB` = 5
880cb93a386Sopenharmony_ci
881cb93a386Sopenharmony_ciThese are only needed for `PathKit.FromCmds()`.
882cb93a386Sopenharmony_ci
883cb93a386Sopenharmony_ci### Functions for testing only
884cb93a386Sopenharmony_ci
885cb93a386Sopenharmony_ci#### `PathKit.LTRBRect(left, top, right, bottom)`
886cb93a386Sopenharmony_ci
887cb93a386Sopenharmony_ci**left** - `Number`, x coordinate of top-left corner of the `SkRect`. <br>
888cb93a386Sopenharmony_ci**top** - `Number`, y coordinate of top-left corner of the `SkRect`. <br>
889cb93a386Sopenharmony_ci**right** - `Number`, x coordinate of bottom-right corner of the `SkRect`. <br>
890cb93a386Sopenharmony_ci**bottom** - `Number`, y coordinate of bottom-right corner of the `SkRect`.
891cb93a386Sopenharmony_ci
892cb93a386Sopenharmony_ciReturns an `SkRect` object with the given params.
893cb93a386Sopenharmony_ci
894cb93a386Sopenharmony_ci#### `SkPath.dump()`
895cb93a386Sopenharmony_ci
896cb93a386Sopenharmony_ciPrints all the verbs and arguments to the console. Only available on Debug and
897cb93a386Sopenharmony_ciTest builds.
898