blob: 9183ba188fc5cfd96966074f3eff24a3fc4e95b2 [file] [log] [blame]
Kevin Lubick217056c2018-09-20 17:39:31 -04001/*
2 * Copyright 2018 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Kevin Lubick6b921b72019-09-18 16:18:17 -04008#include "include/android/SkAnimatedImage.h"
9#include "include/codec/SkAndroidCodec.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkBlendMode.h"
11#include "include/core/SkBlurTypes.h"
12#include "include/core/SkCanvas.h"
13#include "include/core/SkColor.h"
Kevin Lubickd3729342019-09-12 11:11:25 -040014#include "include/core/SkColorFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/core/SkData.h"
Kevin Lubick6b921b72019-09-18 16:18:17 -040016#include "include/core/SkDrawable.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/core/SkEncodedImageFormat.h"
18#include "include/core/SkFilterQuality.h"
19#include "include/core/SkFont.h"
20#include "include/core/SkFontMgr.h"
21#include "include/core/SkFontTypes.h"
22#include "include/core/SkImage.h"
Kevin Lubick15b40232019-10-29 09:55:39 -040023#include "include/core/SkImageFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkImageInfo.h"
25#include "include/core/SkMaskFilter.h"
26#include "include/core/SkPaint.h"
27#include "include/core/SkPath.h"
28#include "include/core/SkPathEffect.h"
29#include "include/core/SkPathMeasure.h"
30#include "include/core/SkPicture.h"
31#include "include/core/SkPictureRecorder.h"
Kevin Lubick2e5fe352019-09-03 12:59:06 -040032#include "include/core/SkRRect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050033#include "include/core/SkScalar.h"
34#include "include/core/SkShader.h"
35#include "include/core/SkString.h"
36#include "include/core/SkStrokeRec.h"
37#include "include/core/SkSurface.h"
38#include "include/core/SkSurfaceProps.h"
39#include "include/core/SkTextBlob.h"
40#include "include/core/SkTypeface.h"
41#include "include/core/SkTypes.h"
42#include "include/core/SkVertices.h"
43#include "include/effects/SkCornerPathEffect.h"
44#include "include/effects/SkDashPathEffect.h"
45#include "include/effects/SkDiscretePathEffect.h"
46#include "include/effects/SkGradientShader.h"
Kevin Lubick15b40232019-10-29 09:55:39 -040047#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050048#include "include/effects/SkTrimPathEffect.h"
49#include "include/pathops/SkPathOps.h"
50#include "include/utils/SkParsePath.h"
51#include "include/utils/SkShadowUtils.h"
52#include "modules/skshaper/include/SkShaper.h"
53#include "src/core/SkFontMgrPriv.h"
54#include "src/core/SkMakeUnique.h"
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040055
Kevin Lubick217056c2018-09-20 17:39:31 -040056#include <iostream>
57#include <string>
Kevin Lubick217056c2018-09-20 17:39:31 -040058
Mike Kleinc0bd9f92019-04-23 12:05:21 -050059#include "modules/canvaskit/WasmAliases.h"
Kevin Lubick217056c2018-09-20 17:39:31 -040060#include <emscripten.h>
61#include <emscripten/bind.h>
Kevin Lubick46839422019-01-03 14:27:27 -050062
Kevin Lubick53965c92018-10-11 08:51:55 -040063#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -050064#include "include/gpu/GrBackendSurface.h"
65#include "include/gpu/GrContext.h"
66#include "include/gpu/gl/GrGLInterface.h"
67#include "include/gpu/gl/GrGLTypes.h"
Kevin Lubick3f67f412019-03-11 16:11:58 -040068
Kevin Lubick53965c92018-10-11 08:51:55 -040069#include <GL/gl.h>
Kevin Lubick217056c2018-09-20 17:39:31 -040070#include <emscripten/html5.h>
Kevin Lubick53965c92018-10-11 08:51:55 -040071#endif
Kevin Lubick217056c2018-09-20 17:39:31 -040072
Kevin Lubick369f6a52019-10-03 11:22:08 -040073#ifdef SK_INCLUDE_PARAGRAPH
74#include "modules/skparagraph/include/Paragraph.h"
75#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040076// Aliases for less typing
77using BoneIndices = SkVertices::BoneIndices;
78using BoneWeights = SkVertices::BoneWeights;
79using Bone = SkVertices::Bone;
Kevin Lubick217056c2018-09-20 17:39:31 -040080
Kevin Lubick61887c72019-09-26 13:20:50 -040081#ifndef SK_NO_FONTS
82sk_sp<SkFontMgr> SkFontMgr_New_Custom_Data(const uint8_t** datas, const size_t* sizes, int n);
83#endif
84
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040085struct SimpleMatrix {
86 SkScalar scaleX, skewX, transX;
87 SkScalar skewY, scaleY, transY;
88 SkScalar pers0, pers1, pers2;
89};
90
91SkMatrix toSkMatrix(const SimpleMatrix& sm) {
92 return SkMatrix::MakeAll(sm.scaleX, sm.skewX , sm.transX,
93 sm.skewY , sm.scaleY, sm.transY,
94 sm.pers0 , sm.pers1 , sm.pers2);
Kevin Lubick217056c2018-09-20 17:39:31 -040095}
96
Kevin Lubick5d5723c2018-12-07 10:09:11 -050097SimpleMatrix toSimpleSkMatrix(const SkMatrix& sm) {
98 SimpleMatrix m {sm[0], sm[1], sm[2],
99 sm[3], sm[4], sm[5],
100 sm[6], sm[7], sm[8]};
101 return m;
102}
103
Kevin Lubickea905ec2018-11-30 14:05:58 -0500104struct SimpleImageInfo {
105 int width;
106 int height;
107 SkColorType colorType;
108 SkAlphaType alphaType;
109 // TODO color spaces?
110};
111
112SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
113 return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
114}
115
Kevin Lubick543f3522019-03-08 10:04:28 -0500116#if SK_SUPPORT_GPU
117sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
118{
119 EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
120 if (r < 0) {
121 printf("failed to make webgl context current %d\n", r);
122 return nullptr;
123 }
124 // setup GrContext
125 auto interface = GrGLMakeNativeInterface();
126 // setup contexts
127 sk_sp<GrContext> grContext(GrContext::MakeGL(interface));
128 return grContext;
129}
130
131sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height) {
132 glClearColor(0, 0, 0, 0);
133 glClearStencil(0);
134 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
135
136
137 // Wrap the frame buffer object attached to the screen in a Skia render
138 // target so Skia can render to it
139 GrGLint buffer;
140 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
141 GrGLFramebufferInfo info;
142 info.fFBOID = (GrGLuint) buffer;
143 SkColorType colorType;
144
Kevin Lubick14967582019-11-15 11:02:15 -0500145 GrGLint stencil;
146 glGetIntegerv(GL_STENCIL_BITS, &stencil);
147
Kevin Lubick543f3522019-03-08 10:04:28 -0500148 info.fFormat = GL_RGBA8;
149 colorType = kRGBA_8888_SkColorType;
150
Kevin Lubick14967582019-11-15 11:02:15 -0500151 GrBackendRenderTarget target(width, height, 0, stencil, info);
Kevin Lubick543f3522019-03-08 10:04:28 -0500152
153 sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
154 kBottomLeft_GrSurfaceOrigin,
155 colorType, nullptr, nullptr));
156 return surface;
157}
158
159sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, int width, int height) {
160 SkImageInfo info = SkImageInfo::MakeN32(width, height, SkAlphaType::kPremul_SkAlphaType);
161
162 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
163 SkBudgeted::kYes,
164 info, 0,
165 kBottomLeft_GrSurfaceOrigin,
166 nullptr, true));
167 return surface;
168}
169
170sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, SimpleImageInfo sii) {
171 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
172 SkBudgeted::kYes,
173 toSkImageInfo(sii), 0,
174 kBottomLeft_GrSurfaceOrigin,
175 nullptr, true));
176 return surface;
177}
178#endif
179
180
Kevin Lubick217056c2018-09-20 17:39:31 -0400181//========================================================================================
182// Path things
183//========================================================================================
184
185// All these Apply* methods are simple wrappers to avoid returning an object.
186// The default WASM bindings produce code that will leak if a return value
187// isn't assigned to a JS variable and has delete() called on it.
188// These Apply methods, combined with the smarter binding code allow for chainable
189// commands that don't leak if the return value is ignored (i.e. when used intuitively).
190
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500191void ApplyAddArc(SkPath& orig, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
192 orig.addArc(oval, startAngle, sweepAngle);
193}
194
Kevin Lubicke384df42019-08-26 15:48:09 -0400195void ApplyAddOval(SkPath& orig, const SkRect& oval, bool ccw, unsigned start) {
Mike Reed7cda6f32019-11-22 11:03:22 +0000196 orig.addOval(oval, ccw ? SkPath::Direction::kCCW_Direction :
197 SkPath::Direction::kCW_Direction, start);
Kevin Lubicke384df42019-08-26 15:48:09 -0400198}
199
Kevin Lubick217056c2018-09-20 17:39:31 -0400200void ApplyAddPath(SkPath& orig, const SkPath& newPath,
201 SkScalar scaleX, SkScalar skewX, SkScalar transX,
202 SkScalar skewY, SkScalar scaleY, SkScalar transY,
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500203 SkScalar pers0, SkScalar pers1, SkScalar pers2,
204 bool extendPath) {
Kevin Lubick217056c2018-09-20 17:39:31 -0400205 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
206 skewY , scaleY, transY,
207 pers0 , pers1 , pers2);
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500208 orig.addPath(newPath, m, extendPath ? SkPath::kExtend_AddPathMode :
209 SkPath::kAppend_AddPathMode);
Kevin Lubick217056c2018-09-20 17:39:31 -0400210}
211
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500212void ApplyAddRect(SkPath& path, SkScalar left, SkScalar top,
213 SkScalar right, SkScalar bottom, bool ccw) {
Mike Reed7cda6f32019-11-22 11:03:22 +0000214 path.addRect(left, top, right, bottom,
215 ccw ? SkPath::Direction::kCCW_Direction :
216 SkPath::Direction::kCW_Direction);
Alexander Khovansky3e119332018-11-15 02:01:19 +0300217}
218
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500219void ApplyAddRoundRect(SkPath& path, SkScalar left, SkScalar top,
220 SkScalar right, SkScalar bottom, uintptr_t /* SkScalar* */ rPtr,
221 bool ccw) {
222 // See comment below for uintptr_t explanation
223 const SkScalar* radii = reinterpret_cast<const SkScalar*>(rPtr);
224 path.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radii,
Mike Reed7cda6f32019-11-22 11:03:22 +0000225 ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction);
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500226}
227
228
Kevin Lubick217056c2018-09-20 17:39:31 -0400229void ApplyArcTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
230 SkScalar radius) {
231 p.arcTo(x1, y1, x2, y2, radius);
232}
233
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500234void ApplyArcToAngle(SkPath& p, SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) {
235 p.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
236}
237
Kevin Lubick79b71342019-11-01 14:36:52 -0400238void ApplyArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
239 bool useSmallArc, bool ccw, SkScalar x, SkScalar y) {
Kevin Lubicke384df42019-08-26 15:48:09 -0400240 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
Mike Reed7cda6f32019-11-22 11:03:22 +0000241 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
Kevin Lubicke384df42019-08-26 15:48:09 -0400242 orig.arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y);
243}
244
Kevin Lubick79b71342019-11-01 14:36:52 -0400245void ApplyRArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
246 bool useSmallArc, bool ccw, SkScalar dx, SkScalar dy) {
247 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
Mike Reed7cda6f32019-11-22 11:03:22 +0000248 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
Kevin Lubick79b71342019-11-01 14:36:52 -0400249 orig.rArcTo(rx, ry, xAxisRotate, arcSize, sweep, dx, dy);
250}
251
Kevin Lubick217056c2018-09-20 17:39:31 -0400252void ApplyClose(SkPath& p) {
253 p.close();
254}
255
256void ApplyConicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
257 SkScalar w) {
258 p.conicTo(x1, y1, x2, y2, w);
259}
260
Kevin Lubick79b71342019-11-01 14:36:52 -0400261void ApplyRConicTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
262 SkScalar w) {
263 p.rConicTo(dx1, dy1, dx2, dy2, w);
264}
265
Kevin Lubick217056c2018-09-20 17:39:31 -0400266void ApplyCubicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
267 SkScalar x3, SkScalar y3) {
268 p.cubicTo(x1, y1, x2, y2, x3, y3);
269}
270
Kevin Lubick79b71342019-11-01 14:36:52 -0400271void ApplyRCubicTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
272 SkScalar dx3, SkScalar dy3) {
273 p.rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
274}
275
Kevin Lubick217056c2018-09-20 17:39:31 -0400276void ApplyLineTo(SkPath& p, SkScalar x, SkScalar y) {
277 p.lineTo(x, y);
278}
279
Kevin Lubick79b71342019-11-01 14:36:52 -0400280void ApplyRLineTo(SkPath& p, SkScalar dx, SkScalar dy) {
281 p.rLineTo(dx, dy);
282}
283
Kevin Lubick217056c2018-09-20 17:39:31 -0400284void ApplyMoveTo(SkPath& p, SkScalar x, SkScalar y) {
285 p.moveTo(x, y);
286}
287
Kevin Lubick79b71342019-11-01 14:36:52 -0400288void ApplyRMoveTo(SkPath& p, SkScalar dx, SkScalar dy) {
289 p.rMoveTo(dx, dy);
290}
291
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500292void ApplyReset(SkPath& p) {
293 p.reset();
294}
295
296void ApplyRewind(SkPath& p) {
297 p.rewind();
298}
299
Kevin Lubick217056c2018-09-20 17:39:31 -0400300void ApplyQuadTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
301 p.quadTo(x1, y1, x2, y2);
302}
303
Kevin Lubick79b71342019-11-01 14:36:52 -0400304void ApplyRQuadTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2) {
305 p.rQuadTo(dx1, dy1, dx2, dy2);
306}
307
Kevin Lubick217056c2018-09-20 17:39:31 -0400308void ApplyTransform(SkPath& orig,
309 SkScalar scaleX, SkScalar skewX, SkScalar transX,
310 SkScalar skewY, SkScalar scaleY, SkScalar transY,
311 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
312 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
313 skewY , scaleY, transY,
314 pers0 , pers1 , pers2);
315 orig.transform(m);
316}
317
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400318bool EMSCRIPTEN_KEEPALIVE ApplySimplify(SkPath& path) {
319 return Simplify(path, &path);
320}
321
322bool EMSCRIPTEN_KEEPALIVE ApplyPathOp(SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
323 return Op(pathOne, pathTwo, op, &pathOne);
324}
325
326JSString EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
327 SkString s;
328 SkParsePath::ToSVGString(path, &s);
329 return emscripten::val(s.c_str());
330}
331
Kevin Lubicka40f8322018-12-17 16:01:36 -0500332SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromSVGString(std::string str) {
333 SkPath path;
334 if (SkParsePath::FromSVGString(str.c_str(), &path)) {
335 return emscripten::val(path);
336 }
337 return emscripten::val::null();
338}
339
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400340SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
341 SkPath out;
342 if (Op(pathOne, pathTwo, op, &out)) {
343 return emscripten::val(out);
344 }
345 return emscripten::val::null();
346}
347
Kevin Lubick217056c2018-09-20 17:39:31 -0400348SkPath EMSCRIPTEN_KEEPALIVE CopyPath(const SkPath& a) {
349 SkPath copy(a);
350 return copy;
351}
352
353bool EMSCRIPTEN_KEEPALIVE Equals(const SkPath& a, const SkPath& b) {
354 return a == b;
355}
356
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500357// =================================================================================
358// Creating/Exporting Paths with cmd arrays
359// =================================================================================
360
361static const int MOVE = 0;
362static const int LINE = 1;
363static const int QUAD = 2;
364static const int CONIC = 3;
365static const int CUBIC = 4;
366static const int CLOSE = 5;
367
368template <typename VisitFunc>
369void VisitPath(const SkPath& p, VisitFunc&& f) {
370 SkPath::RawIter iter(p);
371 SkPoint pts[4];
372 SkPath::Verb verb;
373 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
374 f(verb, pts, iter);
375 }
376}
377
378JSArray EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
379 JSArray cmds = emscripten::val::array();
380
381 VisitPath(path, [&cmds](SkPath::Verb verb, const SkPoint pts[4], SkPath::RawIter iter) {
382 JSArray cmd = emscripten::val::array();
383 switch (verb) {
384 case SkPath::kMove_Verb:
385 cmd.call<void>("push", MOVE, pts[0].x(), pts[0].y());
386 break;
387 case SkPath::kLine_Verb:
388 cmd.call<void>("push", LINE, pts[1].x(), pts[1].y());
389 break;
390 case SkPath::kQuad_Verb:
391 cmd.call<void>("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
392 break;
393 case SkPath::kConic_Verb:
394 cmd.call<void>("push", CONIC,
395 pts[1].x(), pts[1].y(),
396 pts[2].x(), pts[2].y(), iter.conicWeight());
397 break;
398 case SkPath::kCubic_Verb:
399 cmd.call<void>("push", CUBIC,
400 pts[1].x(), pts[1].y(),
401 pts[2].x(), pts[2].y(),
402 pts[3].x(), pts[3].y());
403 break;
404 case SkPath::kClose_Verb:
405 cmd.call<void>("push", CLOSE);
406 break;
407 case SkPath::kDone_Verb:
408 SkASSERT(false);
409 break;
410 }
411 cmds.call<void>("push", cmd);
412 });
413 return cmds;
414}
415
416// This type signature is a mess, but it's necessary. See, we can't use "bind" (EMSCRIPTEN_BINDINGS)
417// and pointers to primitive types (Only bound types like SkPoint). We could if we used
418// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
419// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
420// SkPath or SkOpBuilder.
421//
Kevin Lubick61887c72019-09-26 13:20:50 -0400422// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500423// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
424// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
425// the compiler is happy.
426SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromCmds(uintptr_t /* float* */ cptr, int numCmds) {
427 const auto* cmds = reinterpret_cast<const float*>(cptr);
428 SkPath path;
429 float x1, y1, x2, y2, x3, y3;
430
431 // if there are not enough arguments, bail with the path we've constructed so far.
432 #define CHECK_NUM_ARGS(n) \
433 if ((i + n) > numCmds) { \
434 SkDebugf("Not enough args to match the verbs. Saw %d commands\n", numCmds); \
435 return emscripten::val::null(); \
436 }
437
438 for(int i = 0; i < numCmds;){
439 switch (sk_float_floor2int(cmds[i++])) {
440 case MOVE:
441 CHECK_NUM_ARGS(2);
442 x1 = cmds[i++], y1 = cmds[i++];
443 path.moveTo(x1, y1);
444 break;
445 case LINE:
446 CHECK_NUM_ARGS(2);
447 x1 = cmds[i++], y1 = cmds[i++];
448 path.lineTo(x1, y1);
449 break;
450 case QUAD:
451 CHECK_NUM_ARGS(4);
452 x1 = cmds[i++], y1 = cmds[i++];
453 x2 = cmds[i++], y2 = cmds[i++];
454 path.quadTo(x1, y1, x2, y2);
455 break;
456 case CONIC:
457 CHECK_NUM_ARGS(5);
458 x1 = cmds[i++], y1 = cmds[i++];
459 x2 = cmds[i++], y2 = cmds[i++];
460 x3 = cmds[i++]; // weight
461 path.conicTo(x1, y1, x2, y2, x3);
462 break;
463 case CUBIC:
464 CHECK_NUM_ARGS(6);
465 x1 = cmds[i++], y1 = cmds[i++];
466 x2 = cmds[i++], y2 = cmds[i++];
467 x3 = cmds[i++], y3 = cmds[i++];
468 path.cubicTo(x1, y1, x2, y2, x3, y3);
469 break;
470 case CLOSE:
471 path.close();
472 break;
473 default:
474 SkDebugf(" path: UNKNOWN command %f, aborting dump...\n", cmds[i-1]);
475 return emscripten::val::null();
476 }
477 }
478
479 #undef CHECK_NUM_ARGS
480
481 return emscripten::val(path);
482}
483
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400484//========================================================================================
485// Path Effects
486//========================================================================================
487
488bool ApplyDash(SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
489 SkScalar intervals[] = { on, off };
490 auto pe = SkDashPathEffect::Make(intervals, 2, phase);
491 if (!pe) {
492 SkDebugf("Invalid args to dash()\n");
493 return false;
494 }
495 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
496 if (pe->filterPath(&path, path, &rec, nullptr)) {
497 return true;
498 }
499 SkDebugf("Could not make dashed path\n");
500 return false;
Kevin Lubick217056c2018-09-20 17:39:31 -0400501}
502
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400503bool ApplyTrim(SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
504 auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal;
505 auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
506 if (!pe) {
507 SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
508 return false;
509 }
510 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
511 if (pe->filterPath(&path, path, &rec, nullptr)) {
512 return true;
513 }
514 SkDebugf("Could not trim path\n");
515 return false;
516}
517
518struct StrokeOpts {
Kevin Lubickb9db3902018-11-26 11:47:54 -0500519 // Default values are set in interface.js which allows clients
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400520 // to set any number of them. Otherwise, the binding code complains if
521 // any are omitted.
522 SkScalar width;
523 SkScalar miter_limit;
524 SkPaint::Join join;
525 SkPaint::Cap cap;
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500526 float precision;
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400527};
528
529bool ApplyStroke(SkPath& path, StrokeOpts opts) {
530 SkPaint p;
531 p.setStyle(SkPaint::kStroke_Style);
532 p.setStrokeCap(opts.cap);
533 p.setStrokeJoin(opts.join);
534 p.setStrokeWidth(opts.width);
535 p.setStrokeMiter(opts.miter_limit);
536
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500537 return p.getFillPath(path, &path, nullptr, opts.precision);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400538}
539
540// to map from raw memory to a uint8array
541Uint8Array getSkDataBytes(const SkData *data) {
542 return Uint8Array(typed_memory_view(data->size(), data->bytes()));
543}
544
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500545// Text Shaping abstraction
546
547struct ShapedTextOpts {
548 SkFont font;
549 bool leftToRight;
550 std::string text;
551 SkScalar width;
552};
553
554std::unique_ptr<SkShaper> shaper;
555
556static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400557 SkTextBlobBuilderRunHandler builder(opts.text.c_str(), {0, 0});
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500558 if (!shaper) {
559 shaper = SkShaper::Make();
560 }
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400561 shaper->shape(opts.text.c_str(), opts.text.length(),
562 opts.font, opts.leftToRight,
563 opts.width, &builder);
564 *pt = builder.endPoint();
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500565 return builder.makeBlob();
566}
567
568class ShapedText {
569public:
570 ShapedText(ShapedTextOpts opts) : fOpts(opts) {}
571
572 SkRect getBounds() {
573 this->init();
574 return SkRect::MakeLTRB(0, 0, fOpts.width, fPoint.y());
575 }
576
577 SkTextBlob* blob() {
578 this->init();
579 return fBlob.get();
580 }
581private:
582 const ShapedTextOpts fOpts;
583 SkPoint fPoint;
584 sk_sp<SkTextBlob> fBlob;
585
586 void init() {
587 if (!fBlob) {
588 fBlob = do_shaping(fOpts, &fPoint);
589 }
590 }
591};
592
593void drawShapedText(SkCanvas& canvas, ShapedText st, SkScalar x,
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400594 SkScalar y, SkPaint paint) {
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500595 canvas.drawTextBlob(st.blob(), x, y, paint);
596}
597
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400598int saveLayerRec(SkCanvas& canvas, const SkPaint* paint,
599 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
600 return canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, paint, backdrop, flags));
601}
602
603int saveLayerRecBounds(SkCanvas& canvas, const SkPaint* paint, const SkImageFilter* backdrop,
604 SkCanvas::SaveLayerFlags flags, const SkRect& bounds) {
605 return canvas.saveLayer(SkCanvas::SaveLayerRec(&bounds, paint, backdrop, flags));
606}
607
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400608// This is simpler than dealing with an SkPoint and SkVector
609struct PosTan {
610 SkScalar px, py, tx, ty;
611};
612
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400613// SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
614struct SimpleRRect {
615 SkRect rect;
Kevin Lubick7d644e12019-09-11 14:22:22 -0400616
617 SkScalar rx1;
618 SkScalar ry1;
619 SkScalar rx2;
620 SkScalar ry2;
621 SkScalar rx3;
622 SkScalar ry3;
623 SkScalar rx4;
624 SkScalar ry4;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400625};
626
627SkRRect toRRect(const SimpleRRect& r) {
Kevin Lubick7d644e12019-09-11 14:22:22 -0400628 SkVector fRadii[4] = {{r.rx1, r.ry1}, {r.rx2, r.ry2},
629 {r.rx3, r.ry3}, {r.rx4, r.ry4}};
630 SkRRect rr;
631 rr.setRectRadii(r.rect, fRadii);
632 return rr;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400633}
634
Kevin Lubick50f377e2019-09-11 15:23:00 -0400635struct TonalColors {
636 SkColor ambientColor;
637 SkColor spotColor;
638};
639
640TonalColors computeTonalColors(const TonalColors& in) {
641 TonalColors out;
642 SkShadowUtils::ComputeTonalColors(in.ambientColor, in.spotColor,
643 &out.ambientColor, &out.spotColor);
644 return out;
645}
646
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400647// These objects have private destructors / delete methods - I don't think
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400648// we need to do anything other than tell emscripten to do nothing.
Kevin Lubick217056c2018-09-20 17:39:31 -0400649namespace emscripten {
650 namespace internal {
651 template<typename ClassType>
652 void raw_destructor(ClassType *);
653
654 template<>
Kevin Lubicke59c1672019-11-20 14:17:53 -0500655 void raw_destructor<SkContourMeasure>(SkContourMeasure *ptr) {
656 }
657
658 template<>
Kevin Lubick217056c2018-09-20 17:39:31 -0400659 void raw_destructor<SkData>(SkData *ptr) {
660 }
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400661
662 template<>
663 void raw_destructor<SkVertices>(SkVertices *ptr) {
664 }
Kevin Lubickec4903d2019-01-14 08:36:08 -0500665
Kevin Lubick61887c72019-09-26 13:20:50 -0400666#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -0500667 template<>
668 void raw_destructor<SkTextBlob>(SkTextBlob *ptr) {
669 }
Kevin Lubick61887c72019-09-26 13:20:50 -0400670
671 template<>
672 void raw_destructor<SkTypeface>(SkTypeface *ptr) {
673 }
674#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400675 }
676}
677
Kevin Lubick61887c72019-09-26 13:20:50 -0400678// Some signatures below have uintptr_t instead of a pointer to a primitive
Kevin Lubick217056c2018-09-20 17:39:31 -0400679// type (e.g. SkScalar). This is necessary because we can't use "bind" (EMSCRIPTEN_BINDINGS)
680// and pointers to primitive types (Only bound types like SkPoint). We could if we used
681// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
682// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
683// SkPath or SkCanvas.
684//
Kevin Lubick61887c72019-09-26 13:20:50 -0400685// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubick217056c2018-09-20 17:39:31 -0400686// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
687// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
688// the compiler is happy.
689EMSCRIPTEN_BINDINGS(Skia) {
Kevin Lubick53965c92018-10-11 08:51:55 -0400690#if SK_SUPPORT_GPU
Kevin Lubick53965c92018-10-11 08:51:55 -0400691 function("currentContext", &emscripten_webgl_get_current_context);
692 function("setCurrentContext", &emscripten_webgl_make_context_current);
Kevin Lubick543f3522019-03-08 10:04:28 -0500693 function("MakeGrContext", &MakeGrContext);
694 function("MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
695 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, int, int)>(&MakeRenderTarget));
696 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, SimpleImageInfo)>(&MakeRenderTarget));
697
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400698 constant("gpu", true);
Kevin Lubickb07204a2018-11-20 14:07:42 -0500699#endif
Kevin Lubick50f377e2019-09-11 15:23:00 -0400700 function("computeTonalColors", &computeTonalColors);
Kevin Lubick6b921b72019-09-18 16:18:17 -0400701 function("_decodeAnimatedImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
702 size_t length)->sk_sp<SkAnimatedImage> {
703 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
704 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
705 auto codec = SkAndroidCodec::MakeFromData(bytes);
706 if (nullptr == codec) {
707 return nullptr;
708 }
709 return SkAnimatedImage::Make(std::move(codec));
710 }), allow_raw_pointers());
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500711 function("_decodeImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
712 size_t length)->sk_sp<SkImage> {
713 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
Kevin Lubick88aff5f2019-02-28 16:05:09 -0500714 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
715 return SkImage::MakeFromEncoded(std::move(bytes));
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500716 }), allow_raw_pointers());
Kevin Lubickea905ec2018-11-30 14:05:58 -0500717 function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
Kevin Lubick52b9f372018-12-04 13:57:36 -0500718 uintptr_t /* uint8_t* */ pPtr,
Kevin Lubickea905ec2018-11-30 14:05:58 -0500719 size_t rowBytes)->sk_sp<SkSurface> {
Kevin Lubick52b9f372018-12-04 13:57:36 -0500720 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
Kevin Lubickea905ec2018-11-30 14:05:58 -0500721 SkImageInfo imageInfo = toSkImageInfo(ii);
722 return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
723 }), allow_raw_pointers());
Kevin Lubick53965c92018-10-11 08:51:55 -0400724 function("_getRasterN32PremulSurface", optional_override([](int width, int height)->sk_sp<SkSurface> {
725 return SkSurface::MakeRasterN32Premul(width, height, nullptr);
726 }), allow_raw_pointers());
Kevin Lubickb07204a2018-11-20 14:07:42 -0500727
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400728 function("getSkDataBytes", &getSkDataBytes, allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -0400729 function("MakeSkCornerPathEffect", &SkCornerPathEffect::Make, allow_raw_pointers());
730 function("MakeSkDiscretePathEffect", &SkDiscretePathEffect::Make, allow_raw_pointers());
Kevin Lubick15b40232019-10-29 09:55:39 -0400731 // Deprecated: use Canvaskit.SkMaskFilter.MakeBlur
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500732 function("MakeBlurMaskFilter", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
733 // Adds a little helper because emscripten doesn't expose default params.
734 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
735 }), allow_raw_pointers());
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500736 function("_MakePathFromCmds", &MakePathFromCmds);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400737 function("MakePathFromOp", &MakePathFromOp);
Kevin Lubicka40f8322018-12-17 16:01:36 -0500738 function("MakePathFromSVGString", &MakePathFromSVGString);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400739
740 // These won't be called directly, there's a JS helper to deal with typed arrays.
Kevin Lubick217056c2018-09-20 17:39:31 -0400741 function("_MakeSkDashPathEffect", optional_override([](uintptr_t /* float* */ cptr, int count, SkScalar phase)->sk_sp<SkPathEffect> {
742 // See comment above for uintptr_t explanation
743 const float* intervals = reinterpret_cast<const float*>(cptr);
744 return SkDashPathEffect::Make(intervals, count, phase);
745 }), allow_raw_pointers());
Kevin Lubick52b9f372018-12-04 13:57:36 -0500746 function("_MakeImage", optional_override([](SimpleImageInfo ii,
747 uintptr_t /* uint8_t* */ pPtr, int plen,
748 size_t rowBytes)->sk_sp<SkImage> {
749 // See comment above for uintptr_t explanation
750 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
751 SkImageInfo info = toSkImageInfo(ii);
752 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
753
754 return SkImage::MakeRasterData(info, pixelData, rowBytes);
755 }), allow_raw_pointers());
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400756 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
757 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400758 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400759 SkPoint points[] = { start, end };
760 // See comment above for uintptr_t explanation
761 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
762 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
763
764 return SkGradientShader::MakeLinear(points, colors, positions, count,
765 mode, flags, nullptr);
766 }), allow_raw_pointers());
767 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
768 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400769 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400770 const SimpleMatrix& lm)->sk_sp<SkShader> {
771 SkPoint points[] = { start, end };
772 // See comment above for uintptr_t explanation
773 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
774 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
775
776 SkMatrix localMatrix = toSkMatrix(lm);
777
778 return SkGradientShader::MakeLinear(points, colors, positions, count,
779 mode, flags, &localMatrix);
780 }), allow_raw_pointers());
781 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
782 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400783 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400784 // See comment above for uintptr_t explanation
785 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
786 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
787
788 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
789 mode, flags, nullptr);
790 }), allow_raw_pointers());
791 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
792 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400793 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400794 const SimpleMatrix& lm)->sk_sp<SkShader> {
795 // See comment above for uintptr_t explanation
796 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
797 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
798
799 SkMatrix localMatrix = toSkMatrix(lm);
800 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
801 mode, flags, &localMatrix);
802 }), allow_raw_pointers());
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500803 function("_MakeTwoPointConicalGradientShader", optional_override([](
804 SkPoint start, SkScalar startRadius,
805 SkPoint end, SkScalar endRadius,
806 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400807 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500808 // See comment above for uintptr_t explanation
809 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
810 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
811
812 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
813 colors, positions, count, mode,
814 flags, nullptr);
815 }), allow_raw_pointers());
816 function("_MakeTwoPointConicalGradientShader", optional_override([](
817 SkPoint start, SkScalar startRadius,
818 SkPoint end, SkScalar endRadius,
819 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400820 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500821 const SimpleMatrix& lm)->sk_sp<SkShader> {
822 // See comment above for uintptr_t explanation
823 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
824 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
825
826 SkMatrix localMatrix = toSkMatrix(lm);
827 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
828 colors, positions, count, mode,
829 flags, &localMatrix);
830 }), allow_raw_pointers());
831
Kevin Lubick543f3522019-03-08 10:04:28 -0500832#if SK_SUPPORT_GPU
833 class_<GrContext>("GrContext")
Kevin Lubickcd544662019-03-22 15:41:36 -0400834 .smart_ptr<sk_sp<GrContext>>("sk_sp<GrContext>")
835 .function("getResourceCacheLimitBytes", optional_override([](GrContext& self)->size_t {
836 int maxResources = 0;// ignored
837 size_t currMax = 0;
838 self.getResourceCacheLimits(&maxResources, &currMax);
839 return currMax;
840 }))
841 .function("getResourceCacheUsageBytes", optional_override([](GrContext& self)->size_t {
842 int usedResources = 0;// ignored
843 size_t currUsage = 0;
844 self.getResourceCacheUsage(&usedResources, &currUsage);
845 return currUsage;
846 }))
847 .function("setResourceCacheLimitBytes", optional_override([](GrContext& self, size_t maxResourceBytes)->void {
848 int maxResources = 0;
849 size_t currMax = 0; // ignored
850 self.getResourceCacheLimits(&maxResources, &currMax);
851 self.setResourceCacheLimits(maxResources, maxResourceBytes);
852 }));
Kevin Lubick543f3522019-03-08 10:04:28 -0500853#endif
854
Kevin Lubick6b921b72019-09-18 16:18:17 -0400855 class_<SkAnimatedImage>("SkAnimatedImage")
856 .smart_ptr<sk_sp<SkAnimatedImage>>("sk_sp<SkAnimatedImage>")
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800857 .function("decodeNextFrame", &SkAnimatedImage::decodeNextFrame)
858 .function("getFrameCount", &SkAnimatedImage::getFrameCount)
Kevin Lubick6b921b72019-09-18 16:18:17 -0400859 .function("getRepetitionCount", &SkAnimatedImage::getRepetitionCount)
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800860 .function("height", optional_override([](SkAnimatedImage& self)->int32_t {
861 return self.dimensions().height();
862 }))
863 .function("reset", &SkAnimatedImage::reset)
864 .function("width", optional_override([](SkAnimatedImage& self)->int32_t {
865 return self.dimensions().width();
866 }));
Kevin Lubick6b921b72019-09-18 16:18:17 -0400867
Kevin Lubick217056c2018-09-20 17:39:31 -0400868 class_<SkCanvas>("SkCanvas")
869 .constructor<>()
Kevin Lubickee91c072019-03-29 10:39:52 -0400870 .function("clear", &SkCanvas::clear)
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500871 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800872 .function("clipRRect", optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400873 self.clipRRect(toRRect(r), op, doAntiAlias);
874 }))
Kevin Lubick52b9f372018-12-04 13:57:36 -0500875 .function("clipRect", select_overload<void (const SkRect&, SkClipOp, bool)>(&SkCanvas::clipRect))
876 .function("concat", optional_override([](SkCanvas& self, const SimpleMatrix& m) {
877 self.concat(toSkMatrix(m));
878 }))
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500879 .function("drawArc", &SkCanvas::drawArc)
Kevin Lubickee91c072019-03-29 10:39:52 -0400880 .function("_drawAtlas", optional_override([](SkCanvas& self,
881 const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
882 uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
883 SkBlendMode mode, const SkPaint* paint)->void {
884 // See comment above for uintptr_t explanation
885 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
886 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
887 const SkColor* colors = nullptr;
888 if (cptr) {
889 colors = reinterpret_cast<const SkColor*>(cptr);
890 }
891 self.drawAtlas(atlas, dstXforms, srcRects, colors, count, mode, nullptr, paint);
892 }), allow_raw_pointers())
Kevin Lubicke384df42019-08-26 15:48:09 -0400893 .function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400894 .function("drawColor", &SkCanvas::drawColor)
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400895 .function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
896 self.drawDRRect(toRRect(o), toRRect(i), paint);
897 }))
Kevin Lubick6b921b72019-09-18 16:18:17 -0400898 .function("drawAnimatedImage", optional_override([](SkCanvas& self, sk_sp<SkAnimatedImage>& aImg,
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500899 SkScalar x, SkScalar y)->void {
Kevin Lubick6b921b72019-09-18 16:18:17 -0400900 self.drawDrawable(aImg.get(), x, y);
901 }), allow_raw_pointers())
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500902 .function("drawImage", select_overload<void (const sk_sp<SkImage>&, SkScalar, SkScalar, const SkPaint*)>(&SkCanvas::drawImage), allow_raw_pointers())
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500903 .function("drawImageNine", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
904 SkIRect center, SkRect dst,
905 const SkPaint* paint)->void {
906 self.drawImageNine(image, center, dst, paint);
907 }), allow_raw_pointers())
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500908 .function("drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
909 SkRect src, SkRect dst,
910 const SkPaint* paint, bool fastSample)->void {
911 self.drawImageRect(image, src, dst, paint,
912 fastSample ? SkCanvas::kFast_SrcRectConstraint :
913 SkCanvas::kStrict_SrcRectConstraint);
914 }), allow_raw_pointers())
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500915 .function("drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
916 .function("drawOval", &SkCanvas::drawOval)
Kevin Lubick217056c2018-09-20 17:39:31 -0400917 .function("drawPaint", &SkCanvas::drawPaint)
Kevin Lubick369f6a52019-10-03 11:22:08 -0400918#ifdef SK_INCLUDE_PARAGRAPH
919 .function("drawParagraph", optional_override([](SkCanvas& self, skia::textlayout::Paragraph* p,
920 SkScalar x, SkScalar y) {
921 p->paint(&self, x, y);
922 }), allow_raw_pointers())
923#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400924 .function("drawPath", &SkCanvas::drawPath)
Kevin Lubickcc13fd32019-04-05 13:00:01 -0400925 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
926 // a bitmap. An SkPicture is a series of draw commands.
927 .function("drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500928 .function("_drawPoints", optional_override([](SkCanvas& self, SkCanvas::PointMode mode,
929 uintptr_t /* SkPoint* */ pptr,
930 int count, SkPaint paint)->void {
931 // See comment above for uintptr_t explanation
932 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
933 self.drawPoints(mode, count, pts, paint);
934 }))
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400935 .function("drawRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, const SkPaint& paint) {
936 self.drawRRect(toRRect(r), paint);
937 }))
Kevin Lubick217056c2018-09-20 17:39:31 -0400938 .function("drawRect", &SkCanvas::drawRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500939 .function("drawRoundRect", &SkCanvas::drawRoundRect)
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500940 .function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
941 const SkPoint3& zPlaneParams,
942 const SkPoint3& lightPos, SkScalar lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400943 SkColor ambientColor, SkColor spotColor,
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500944 uint32_t flags) {
945 SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400946 ambientColor, spotColor, flags);
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500947 }))
Kevin Lubick61887c72019-09-26 13:20:50 -0400948#ifndef SK_NO_FONTS
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500949 .function("_drawShapedText", &drawShapedText)
Kevin Lubickec4903d2019-01-14 08:36:08 -0500950 .function("_drawSimpleText", optional_override([](SkCanvas& self, uintptr_t /* char* */ sptr,
951 size_t len, SkScalar x, SkScalar y, const SkFont& font,
952 const SkPaint& paint) {
953 // See comment above for uintptr_t explanation
954 const char* str = reinterpret_cast<const char*>(sptr);
955
956 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
Kevin Lubick217056c2018-09-20 17:39:31 -0400957 }))
Kevin Lubickec4903d2019-01-14 08:36:08 -0500958 .function("drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
Kevin Lubick61887c72019-09-26 13:20:50 -0400959#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400960 .function("drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
Kevin Lubick217056c2018-09-20 17:39:31 -0400961 .function("flush", &SkCanvas::flush)
Kevin Lubicke384df42019-08-26 15:48:09 -0400962 .function("getSaveCount", &SkCanvas::getSaveCount)
Kevin Lubick5d5723c2018-12-07 10:09:11 -0500963 .function("getTotalMatrix", optional_override([](const SkCanvas& self)->SimpleMatrix {
964 SkMatrix m = self.getTotalMatrix();
965 return toSimpleSkMatrix(m);
966 }))
Kevin Lubick543f3522019-03-08 10:04:28 -0500967 .function("makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
968 return self.makeSurface(toSkImageInfo(sii), nullptr);
969 }), allow_raw_pointers())
Kevin Lubick52b9f372018-12-04 13:57:36 -0500970 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
971 uintptr_t /* uint8_t* */ pPtr,
972 size_t dstRowBytes, int srcX, int srcY) {
973 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
974 SkImageInfo dstInfo = toSkImageInfo(di);
975
976 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
977 }))
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500978 .function("restore", &SkCanvas::restore)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500979 .function("restoreToCount", &SkCanvas::restoreToCount)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400980 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
Kevin Lubick217056c2018-09-20 17:39:31 -0400981 .function("save", &SkCanvas::save)
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400982 // 2 params
Kevin Lubickb3574c92019-03-06 08:25:36 -0500983 .function("saveLayer", select_overload<int (const SkRect&, const SkPaint*)>(&SkCanvas::saveLayer),
984 allow_raw_pointers())
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400985 // 3 params (effectively with SaveLayerRec, but no bounds)
986 .function("saveLayer", saveLayerRec, allow_raw_pointers())
987 // 4 params (effectively with SaveLayerRec)
988 .function("saveLayer", saveLayerRecBounds, allow_raw_pointers())
989
Kevin Lubick006a6f32018-10-19 14:34:34 -0400990 .function("scale", &SkCanvas::scale)
Kevin Lubick006a6f32018-10-19 14:34:34 -0400991 .function("skew", &SkCanvas::skew)
Kevin Lubick52b9f372018-12-04 13:57:36 -0500992 .function("translate", &SkCanvas::translate)
993 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
994 uintptr_t /* uint8_t* */ pPtr,
995 size_t srcRowBytes, int dstX, int dstY) {
996 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
997 SkImageInfo dstInfo = toSkImageInfo(di);
998
999 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
Kevin Lubick369f6a52019-10-03 11:22:08 -04001000 }));
Kevin Lubick217056c2018-09-20 17:39:31 -04001001
Kevin Lubickd3729342019-09-12 11:11:25 -04001002 class_<SkColorFilter>("SkColorFilter")
1003 .smart_ptr<sk_sp<SkColorFilter>>("sk_sp<SkColorFilter>>")
1004 .class_function("MakeBlend", &SkColorFilters::Blend)
1005 .class_function("MakeCompose", &SkColorFilters::Compose)
1006 .class_function("MakeLerp", &SkColorFilters::Lerp)
1007 .class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
1008 .class_function("_makeMatrix", optional_override([](uintptr_t /* float* */ fPtr) {
1009 float* twentyFloats = reinterpret_cast<float*>(fPtr);
1010 return SkColorFilters::Matrix(twentyFloats);
1011 }))
1012 .class_function("MakeSRGBToLinearGamma", &SkColorFilters::SRGBToLinearGamma);
1013
Kevin Lubicke59c1672019-11-20 14:17:53 -05001014 class_<SkContourMeasureIter>("SkContourMeasureIter")
1015 .constructor<const SkPath&, bool, SkScalar>()
1016 .function("next", &SkContourMeasureIter::next);
1017
1018 class_<SkContourMeasure>("SkContourMeasure")
1019 .smart_ptr<sk_sp<SkContourMeasure>>("sk_sp<SkContourMeasure>>")
1020 .function("getPosTan", optional_override([](SkContourMeasure& self,
1021 SkScalar distance) -> PosTan {
1022 SkPoint p{0, 0};
1023 SkVector v{0, 0};
1024 if (!self.getPosTan(distance, &p, &v)) {
1025 SkDebugf("zero-length path in getPosTan\n");
1026 }
1027 return PosTan{p.x(), p.y(), v.x(), v.y()};
1028 }))
1029 .function("getSegment", optional_override([](SkContourMeasure& self, SkScalar startD,
1030 SkScalar stopD, bool startWithMoveTo) -> SkPath {
1031 SkPath p;
1032 bool ok = self.getSegment(startD, stopD, &p, startWithMoveTo);
1033 if (ok) {
1034 return p;
1035 }
1036 return SkPath();
1037 }))
1038 .function("isClosed", &SkContourMeasure::isClosed)
1039 .function("length", &SkContourMeasure::length);
1040
Kevin Lubick217056c2018-09-20 17:39:31 -04001041 class_<SkData>("SkData")
1042 .smart_ptr<sk_sp<SkData>>("sk_sp<SkData>>")
1043 .function("size", &SkData::size);
1044
Kevin Lubick6b921b72019-09-18 16:18:17 -04001045 class_<SkDrawable>("SkDrawable")
1046 .smart_ptr<sk_sp<SkDrawable>>("sk_sp<SkDrawable>>");
1047
Kevin Lubick61887c72019-09-26 13:20:50 -04001048#ifndef SK_NO_FONTS
Kevin Lubick35ac0382019-01-02 15:13:57 -05001049 class_<SkFont>("SkFont")
1050 .constructor<>()
1051 .constructor<sk_sp<SkTypeface>>()
1052 .constructor<sk_sp<SkTypeface>, SkScalar>()
1053 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
1054 .function("getScaleX", &SkFont::getScaleX)
1055 .function("getSize", &SkFont::getSize)
1056 .function("getSkewX", &SkFont::getSkewX)
1057 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001058 .function("_getWidths", optional_override([](SkFont& self, uintptr_t /* char* */ sptr,
1059 size_t strLen, size_t expectedCodePoints,
1060 uintptr_t /* SkScalar* */ wptr) -> bool {
1061 char* str = reinterpret_cast<char*>(sptr);
1062 SkScalar* widths = reinterpret_cast<SkScalar*>(wptr);
1063
1064 SkGlyphID* glyphStorage = new SkGlyphID[expectedCodePoints];
1065 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
1066 glyphStorage, expectedCodePoints);
1067 if (actualCodePoints != expectedCodePoints) {
1068 SkDebugf("Actually %d glyphs, expected only %d\n",
1069 actualCodePoints, expectedCodePoints);
1070 return false;
1071 }
1072
1073 self.getWidths(glyphStorage, actualCodePoints, widths);
1074 delete[] glyphStorage;
1075 return true;
1076 }))
Kevin Lubick35ac0382019-01-02 15:13:57 -05001077 .function("measureText", optional_override([](SkFont& self, std::string text) {
1078 // TODO(kjlubick): This does not work well for non-ascii
1079 // Need to maybe add a helper in interface.js that supports UTF-8
1080 // Otherwise, go with std::wstring and set UTF-32 encoding.
1081 return self.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
1082 }))
1083 .function("setScaleX", &SkFont::setScaleX)
1084 .function("setSize", &SkFont::setSize)
1085 .function("setSkewX", &SkFont::setSkewX)
1086 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
1087
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001088 class_<ShapedText>("ShapedText")
1089 .constructor<ShapedTextOpts>()
1090 .function("getBounds", &ShapedText::getBounds);
1091
Kevin Lubickddd0a332018-12-12 10:35:13 -05001092 class_<SkFontMgr>("SkFontMgr")
1093 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<SkFontMgr>")
Kevin Lubick61887c72019-09-26 13:20:50 -04001094 .class_function("_fromData", optional_override([](uintptr_t /* uint8_t** */ dPtr,
1095 uintptr_t /* size_t* */ sPtr,
1096 int numFonts)->sk_sp<SkFontMgr> {
1097 // See comment above for uintptr_t explanation
1098 auto datas = reinterpret_cast<const uint8_t**>(dPtr);
1099 auto sizes = reinterpret_cast<const size_t*>(sPtr);
1100
1101 return SkFontMgr_New_Custom_Data(datas, sizes, numFonts);
1102 }), allow_raw_pointers())
Kevin Lubickddd0a332018-12-12 10:35:13 -05001103 .class_function("RefDefault", &SkFontMgr::RefDefault)
1104#ifdef SK_DEBUG
1105 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
1106 int numFam = self.countFamilies();
Kevin Lubick61887c72019-09-26 13:20:50 -04001107 SkDebugf("There are %d font families\n", numFam);
Kevin Lubickddd0a332018-12-12 10:35:13 -05001108 for (int i = 0 ; i< numFam; i++) {
1109 SkString s;
1110 self.getFamilyName(i, &s);
Kevin Lubick61887c72019-09-26 13:20:50 -04001111 SkDebugf("\t%s\n", s.c_str());
Kevin Lubickddd0a332018-12-12 10:35:13 -05001112 }
1113 }))
1114#endif
1115 .function("countFamilies", &SkFontMgr::countFamilies)
1116 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
1117 uintptr_t /* uint8_t* */ fPtr,
1118 int flen)->sk_sp<SkTypeface> {
1119 // See comment above for uintptr_t explanation
1120 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
1121 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
1122
1123 return self.makeFromData(fontData);
1124 }), allow_raw_pointers());
Kevin Lubick61887c72019-09-26 13:20:50 -04001125#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001126
Kevin Lubick217056c2018-09-20 17:39:31 -04001127 class_<SkImage>("SkImage")
1128 .smart_ptr<sk_sp<SkImage>>("sk_sp<SkImage>")
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001129 .function("height", &SkImage::height)
1130 .function("width", &SkImage::width)
Alexander Khovansky3e119332018-11-15 02:01:19 +03001131 .function("_encodeToData", select_overload<sk_sp<SkData>()const>(&SkImage::encodeToData))
Kevin Lubicka064c282019-04-04 09:28:53 -04001132 .function("_encodeToDataWithFormat", select_overload<sk_sp<SkData>(SkEncodedImageFormat encodedImageFormat, int quality)const>(&SkImage::encodeToData))
1133 // Allow localMatrix to be optional, so we have 2 declarations of these shaders
1134 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1135 SkTileMode tx, SkTileMode ty)->sk_sp<SkShader> {
1136 return self->makeShader(tx, ty, nullptr);
1137 }), allow_raw_pointers())
1138 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1139 SkTileMode tx, SkTileMode ty,
1140 const SimpleMatrix& lm)->sk_sp<SkShader> {
1141 SkMatrix localMatrix = toSkMatrix(lm);
1142
1143 return self->makeShader(tx, ty, &localMatrix);
Kevin Lubickd6b32ed2019-05-06 13:04:03 -04001144 }), allow_raw_pointers())
1145 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1146 SimpleImageInfo sii, uintptr_t /* uint8_t* */ pPtr,
1147 size_t dstRowBytes, int srcX, int srcY)->bool {
1148 // See comment above for uintptr_t explanation
1149 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1150 SkImageInfo ii = toSkImageInfo(sii);
1151
1152 return self->readPixels(ii, pixels, dstRowBytes, srcX, srcY);
Kevin Lubicka064c282019-04-04 09:28:53 -04001153 }), allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -04001154
Kevin Lubick15b40232019-10-29 09:55:39 -04001155 class_<SkImageFilter>("SkImageFilter")
1156 .smart_ptr<sk_sp<SkImageFilter>>("sk_sp<SkImageFilter>")
1157 .class_function("MakeBlur", optional_override([](SkScalar sigmaX, SkScalar sigmaY,
1158 SkTileMode tileMode, sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1159 // Emscripten does not like default args nor SkIRect* much
1160 return SkImageFilters::Blur(sigmaX, sigmaY, tileMode, input);
1161 }))
1162 .class_function("MakeColorFilter", optional_override([](sk_sp<SkColorFilter> cf,
1163 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1164 // Emscripten does not like default args nor SkIRect* much
1165 return SkImageFilters::ColorFilter(cf, input);
1166 }))
Kevin Lubickd2677192019-11-15 14:13:20 -05001167 .class_function("MakeCompose", &SkImageFilters::Compose)
1168 .class_function("MakeMatrixTransform", optional_override([](SimpleMatrix sm, SkFilterQuality fq,
1169 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1170 return SkImageFilters::MatrixTransform(toSkMatrix(sm), fq, input);
1171 }));
Kevin Lubick15b40232019-10-29 09:55:39 -04001172
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001173 class_<SkMaskFilter>("SkMaskFilter")
Kevin Lubick15b40232019-10-29 09:55:39 -04001174 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<SkMaskFilter>")
1175 .class_function("MakeBlur", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
1176 // Adds a little helper because emscripten doesn't expose default params.
1177 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
1178 }), allow_raw_pointers());
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001179
Kevin Lubick217056c2018-09-20 17:39:31 -04001180 class_<SkPaint>("SkPaint")
1181 .constructor<>()
1182 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
1183 SkPaint p(self);
1184 return p;
1185 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001186 .function("getBlendMode", &SkPaint::getBlendMode)
Kevin Lubickee91c072019-03-29 10:39:52 -04001187 .function("getColor", &SkPaint::getColor)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001188 .function("getFilterQuality", &SkPaint::getFilterQuality)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001189 .function("getStrokeCap", &SkPaint::getStrokeCap)
1190 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001191 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
1192 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
Kevin Lubick217056c2018-09-20 17:39:31 -04001193 .function("setAntiAlias", &SkPaint::setAntiAlias)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001194 .function("setBlendMode", &SkPaint::setBlendMode)
Mike Reeddc2b98f2019-05-20 11:47:49 -04001195 .function("setColor", optional_override([](SkPaint& self, SkColor c) {
1196 self.setColor(c);
1197 }))
1198 .function("setColorf", optional_override([](SkPaint& self,
1199 float r, float g, float b, float a) {
1200 self.setColor({r, g, b, a});
1201 }))
Kevin Lubickd3729342019-09-12 11:11:25 -04001202 .function("setColorFilter", &SkPaint::setColorFilter)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001203 .function("setFilterQuality", &SkPaint::setFilterQuality)
Kevin Lubick15b40232019-10-29 09:55:39 -04001204 .function("setImageFilter", &SkPaint::setImageFilter)
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001205 .function("setMaskFilter", &SkPaint::setMaskFilter)
Kevin Lubick217056c2018-09-20 17:39:31 -04001206 .function("setPathEffect", &SkPaint::setPathEffect)
1207 .function("setShader", &SkPaint::setShader)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001208 .function("setStrokeCap", &SkPaint::setStrokeCap)
1209 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001210 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
1211 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
Kevin Lubickec4903d2019-01-14 08:36:08 -05001212 .function("setStyle", &SkPaint::setStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001213
1214 class_<SkPathEffect>("SkPathEffect")
1215 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>");
1216
Kevin Lubick217056c2018-09-20 17:39:31 -04001217 class_<SkPath>("SkPath")
1218 .constructor<>()
1219 .constructor<const SkPath&>()
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001220 .function("_addArc", &ApplyAddArc)
Kevin Lubick217056c2018-09-20 17:39:31 -04001221 // interface.js has 3 overloads of addPath
Kevin Lubicke384df42019-08-26 15:48:09 -04001222 .function("_addOval", &ApplyAddOval)
Kevin Lubick217056c2018-09-20 17:39:31 -04001223 .function("_addPath", &ApplyAddPath)
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001224 .function("_addPoly", optional_override([](SkPath& self,
1225 uintptr_t /* SkPoint* */ pptr,
1226 int count, bool close)->void {
1227 // See comment above for uintptr_t explanation
1228 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
1229 self.addPoly(pts, count, close);
1230 }))
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001231 // interface.js has 4 overloads of addRect
1232 .function("_addRect", &ApplyAddRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001233 // interface.js has 4 overloads of addRoundRect
1234 .function("_addRoundRect", &ApplyAddRoundRect)
Kevin Lubick217056c2018-09-20 17:39:31 -04001235 .function("_arcTo", &ApplyArcTo)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001236 .function("_arcTo", &ApplyArcToAngle)
Kevin Lubick79b71342019-11-01 14:36:52 -04001237 .function("_arcTo", &ApplyArcToArcSize)
Kevin Lubick217056c2018-09-20 17:39:31 -04001238 .function("_close", &ApplyClose)
1239 .function("_conicTo", &ApplyConicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001240 .function("countPoints", &SkPath::countPoints)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001241 .function("contains", &SkPath::contains)
Kevin Lubick217056c2018-09-20 17:39:31 -04001242 .function("_cubicTo", &ApplyCubicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001243 .function("getPoint", &SkPath::getPoint)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001244 .function("isEmpty", &SkPath::isEmpty)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001245 .function("isVolatile", &SkPath::isVolatile)
Kevin Lubick217056c2018-09-20 17:39:31 -04001246 .function("_lineTo", &ApplyLineTo)
1247 .function("_moveTo", &ApplyMoveTo)
Kevin Lubick79b71342019-11-01 14:36:52 -04001248 .function("_quadTo", &ApplyQuadTo)
1249 .function("_rArcTo", &ApplyRArcToArcSize)
1250 .function("_rConicTo", &ApplyRConicTo)
1251 .function("_rCubicTo", &ApplyRCubicTo)
1252 .function("_rLineTo", &ApplyRLineTo)
1253 .function("_rMoveTo", &ApplyRMoveTo)
1254 .function("_rQuadTo", &ApplyRQuadTo)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001255 .function("reset", &ApplyReset)
1256 .function("rewind", &ApplyRewind)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001257 .function("setIsVolatile", &SkPath::setIsVolatile)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001258 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
Kevin Lubick217056c2018-09-20 17:39:31 -04001259
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001260 // PathEffects
1261 .function("_dash", &ApplyDash)
1262 .function("_trim", &ApplyTrim)
1263 .function("_stroke", &ApplyStroke)
1264
1265 // PathOps
1266 .function("_simplify", &ApplySimplify)
1267 .function("_op", &ApplyPathOp)
1268
1269 // Exporting
1270 .function("toSVGString", &ToSVGString)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001271 .function("toCmds", &ToCmds)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001272
Kevin Lubick217056c2018-09-20 17:39:31 -04001273 .function("setFillType", &SkPath::setFillType)
1274 .function("getFillType", &SkPath::getFillType)
1275 .function("getBounds", &SkPath::getBounds)
1276 .function("computeTightBounds", &SkPath::computeTightBounds)
1277 .function("equals", &Equals)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001278 .function("copy", &CopyPath)
1279#ifdef SK_DEBUG
1280 .function("dump", select_overload<void() const>(&SkPath::dump))
1281 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
1282#endif
1283 ;
Kevin Lubick217056c2018-09-20 17:39:31 -04001284
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001285 class_<SkPathMeasure>("SkPathMeasure")
1286 .constructor<const SkPath&, bool, SkScalar>()
1287 .function("getLength", &SkPathMeasure::getLength)
1288 .function("getPosTan", optional_override([](SkPathMeasure& self,
1289 SkScalar distance) -> PosTan {
1290 SkPoint p{0, 0};
1291 SkVector v{0, 0};
1292 if (!self.getPosTan(distance, &p, &v)) {
1293 SkDebugf("zero-length path in getPosTan\n");
1294 }
1295 return PosTan{p.x(), p.y(), v.x(), v.y()};
1296 }))
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001297 .function("getSegment", optional_override([](SkPathMeasure& self, SkScalar startD,
1298 SkScalar stopD, bool startWithMoveTo) -> SkPath {
1299 SkPath p;
1300 bool ok = self.getSegment(startD, stopD, &p, startWithMoveTo);
1301 if (ok) {
1302 return p;
1303 }
1304 return SkPath();
1305 }))
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001306 .function("isClosed", &SkPathMeasure::isClosed)
1307 .function("nextContour", &SkPathMeasure::nextContour);
1308
Kevin Lubickcc13fd32019-04-05 13:00:01 -04001309 class_<SkPictureRecorder>("SkPictureRecorder")
1310 .constructor<>()
1311 .function("beginRecording", optional_override([](SkPictureRecorder& self,
1312 const SkRect& bounds) -> SkCanvas* {
1313 return self.beginRecording(bounds, nullptr, 0);
1314 }), allow_raw_pointers())
1315 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
1316 -> sk_sp<SkPicture> {
1317 return self.finishRecordingAsPicture(0);
1318 }), allow_raw_pointers());
1319
1320 class_<SkPicture>("SkPicture")
1321 .smart_ptr<sk_sp<SkPicture>>("sk_sp<SkPicture>")
1322 // The serialized format of an SkPicture (informally called an "skp"), is not something
1323 // that clients should ever rely on. It is useful when filing bug reports, but that's
1324 // about it. The format may change at anytime and no promises are made for backwards
1325 // or forward compatibility.
1326 .function("DEBUGONLY_serialize", optional_override([](SkPicture& self) -> sk_sp<SkData> {
1327 // Emscripten doesn't play well with optional arguments, which we don't
1328 // want to expose anyway.
1329 return self.serialize();
1330 }), allow_raw_pointers());
1331
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001332 class_<SkShader>("SkShader")
1333 .smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>");
1334
Kevin Lubick217056c2018-09-20 17:39:31 -04001335 class_<SkSurface>("SkSurface")
1336 .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
Greg Danielbae71212019-03-01 15:24:35 -05001337 .function("_flush", select_overload<void()>(&SkSurface::flush))
Kevin Lubick543f3522019-03-08 10:04:28 -05001338 .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
1339 .function("height", &SkSurface::height)
Mike Reed114bde82018-11-21 09:12:09 -05001340 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
1341 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
Kevin Lubick543f3522019-03-08 10:04:28 -05001342 .function("makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1343 return self.makeSurface(toSkImageInfo(sii));
1344 }), allow_raw_pointers())
1345 .function("width", &SkSurface::width);
Kevin Lubick217056c2018-09-20 17:39:31 -04001346
Kevin Lubick61887c72019-09-26 13:20:50 -04001347#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -05001348 class_<SkTextBlob>("SkTextBlob")
1349 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<SkTextBlob>>")
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001350 .class_function("_MakeFromRSXform", optional_override([](uintptr_t /* char* */ sptr,
1351 size_t strBtyes,
1352 uintptr_t /* SkRSXform* */ xptr,
1353 const SkFont& font,
1354 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
1355 // See comment above for uintptr_t explanation
1356 const char* str = reinterpret_cast<const char*>(sptr);
1357 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
1358
1359 return SkTextBlob::MakeFromRSXform(str, strBtyes, xforms, font, encoding);
1360 }), allow_raw_pointers())
Kevin Lubick543f3522019-03-08 10:04:28 -05001361 .class_function("_MakeFromText", optional_override([](uintptr_t /* char* */ sptr,
1362 size_t len, const SkFont& font,
1363 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
Kevin Lubickec4903d2019-01-14 08:36:08 -05001364 // See comment above for uintptr_t explanation
1365 const char* str = reinterpret_cast<const char*>(sptr);
1366 return SkTextBlob::MakeFromText(str, len, font, encoding);
1367 }), allow_raw_pointers());
1368
Kevin Lubickddd0a332018-12-12 10:35:13 -05001369 class_<SkTypeface>("SkTypeface")
1370 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<SkTypeface>");
Kevin Lubick61887c72019-09-26 13:20:50 -04001371#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001372
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001373 class_<SkVertices>("SkVertices")
1374 .smart_ptr<sk_sp<SkVertices>>("sk_sp<SkVertices>")
1375 .function("_applyBones", optional_override([](SkVertices& self, uintptr_t /* Bone* */ bptr, int boneCount)->sk_sp<SkVertices> {
1376 // See comment above for uintptr_t explanation
1377 const Bone* bones = reinterpret_cast<const Bone*>(bptr);
1378 return self.applyBones(bones, boneCount);
1379 }))
1380 .function("bounds", &SkVertices::bounds)
1381 .function("mode", &SkVertices::mode)
1382 .function("uniqueID", &SkVertices::uniqueID)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001383#ifdef SK_DEBUG
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001384 .function("dumpPositions", optional_override([](SkVertices& self)->void {
1385 auto pos = self.positions();
1386 for(int i = 0; i< self.vertexCount(); i++) {
1387 SkDebugf("position[%d] = (%f, %f)\n", i, pos[i].x(), pos[i].y());
1388 }
1389 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001390#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001391 .function("vertexCount", &SkVertices::vertexCount);
1392
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001393 // Not intended to be called directly by clients
1394 class_<SkVertices::Builder>("_SkVerticesBuilder")
1395 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
1396 .function("boneIndices", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneIndices* */{
1397 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1398 return reinterpret_cast<uintptr_t>(self.boneIndices());
1399 }))
1400 .function("boneWeights", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneWeights* */{
1401 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1402 return reinterpret_cast<uintptr_t>(self.boneWeights());
1403 }))
1404 .function("colors", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkColor* */{
1405 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1406 return reinterpret_cast<uintptr_t>(self.colors());
1407 }))
1408 .function("detach", &SkVertices::Builder::detach)
1409 .function("indices", optional_override([](SkVertices::Builder& self)->uintptr_t /* uint16_t* */{
1410 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1411 return reinterpret_cast<uintptr_t>(self.indices());
1412 }))
1413 .function("positions", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1414 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1415 return reinterpret_cast<uintptr_t>(self.positions());
1416 }))
1417 .function("texCoords", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1418 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1419 return reinterpret_cast<uintptr_t>(self.texCoords());
1420 }));
1421
Kevin Lubickea905ec2018-11-30 14:05:58 -05001422 enum_<SkAlphaType>("AlphaType")
1423 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
1424 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
1425 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001426
1427 enum_<SkBlendMode>("BlendMode")
1428 .value("Clear", SkBlendMode::kClear)
1429 .value("Src", SkBlendMode::kSrc)
1430 .value("Dst", SkBlendMode::kDst)
1431 .value("SrcOver", SkBlendMode::kSrcOver)
1432 .value("DstOver", SkBlendMode::kDstOver)
1433 .value("SrcIn", SkBlendMode::kSrcIn)
1434 .value("DstIn", SkBlendMode::kDstIn)
1435 .value("SrcOut", SkBlendMode::kSrcOut)
1436 .value("DstOut", SkBlendMode::kDstOut)
1437 .value("SrcATop", SkBlendMode::kSrcATop)
1438 .value("DstATop", SkBlendMode::kDstATop)
1439 .value("Xor", SkBlendMode::kXor)
1440 .value("Plus", SkBlendMode::kPlus)
1441 .value("Modulate", SkBlendMode::kModulate)
1442 .value("Screen", SkBlendMode::kScreen)
1443 .value("Overlay", SkBlendMode::kOverlay)
1444 .value("Darken", SkBlendMode::kDarken)
1445 .value("Lighten", SkBlendMode::kLighten)
1446 .value("ColorDodge", SkBlendMode::kColorDodge)
1447 .value("ColorBurn", SkBlendMode::kColorBurn)
1448 .value("HardLight", SkBlendMode::kHardLight)
1449 .value("SoftLight", SkBlendMode::kSoftLight)
1450 .value("Difference", SkBlendMode::kDifference)
1451 .value("Exclusion", SkBlendMode::kExclusion)
1452 .value("Multiply", SkBlendMode::kMultiply)
1453 .value("Hue", SkBlendMode::kHue)
1454 .value("Saturation", SkBlendMode::kSaturation)
1455 .value("Color", SkBlendMode::kColor)
1456 .value("Luminosity", SkBlendMode::kLuminosity);
Kevin Lubick217056c2018-09-20 17:39:31 -04001457
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001458 enum_<SkBlurStyle>("BlurStyle")
1459 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
1460 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
1461 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
1462 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001463
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001464 enum_<SkClipOp>("ClipOp")
1465 .value("Difference", SkClipOp::kDifference)
1466 .value("Intersect", SkClipOp::kIntersect);
1467
Kevin Lubickea905ec2018-11-30 14:05:58 -05001468 enum_<SkColorType>("ColorType")
1469 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
1470 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
1471 .value("ARGB_4444", SkColorType::kARGB_4444_SkColorType)
1472 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
1473 .value("RGB_888x", SkColorType::kRGB_888x_SkColorType)
1474 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
1475 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
1476 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
1477 .value("Gray_8", SkColorType::kGray_8_SkColorType)
1478 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
Robert Phillipsd470e1b2019-09-04 15:05:35 -04001479 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType)
Robert Phillipsea1b30b2019-09-19 16:05:48 -04001480 .value("R8G8_unorm", SkColorType::kR8G8_unorm_SkColorType)
1481 .value("A16_unorm", SkColorType::kA16_unorm_SkColorType)
1482 .value("R16G16_unorm", SkColorType::kR16G16_unorm_SkColorType)
1483 .value("A16_float", SkColorType::kA16_float_SkColorType)
1484 .value("R16G16_float", SkColorType::kR16G16_float_SkColorType)
1485 .value("R16G16B16A16_unorm", SkColorType::kR16G16B16A16_unorm_SkColorType);
Kevin Lubickea905ec2018-11-30 14:05:58 -05001486
Kevin Lubick217056c2018-09-20 17:39:31 -04001487 enum_<SkPath::FillType>("FillType")
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001488 .value("Winding", SkPath::FillType::kWinding_FillType)
1489 .value("EvenOdd", SkPath::FillType::kEvenOdd_FillType)
1490 .value("InverseWinding", SkPath::FillType::kInverseWinding_FillType)
1491 .value("InverseEvenOdd", SkPath::FillType::kInverseEvenOdd_FillType);
1492
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001493 enum_<SkFilterQuality>("FilterQuality")
1494 .value("None", SkFilterQuality::kNone_SkFilterQuality)
1495 .value("Low", SkFilterQuality::kLow_SkFilterQuality)
1496 .value("Medium", SkFilterQuality::kMedium_SkFilterQuality)
1497 .value("High", SkFilterQuality::kHigh_SkFilterQuality);
1498
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001499 enum_<SkEncodedImageFormat>("ImageFormat")
1500 .value("PNG", SkEncodedImageFormat::kPNG)
1501 .value("JPEG", SkEncodedImageFormat::kJPEG);
1502
1503 enum_<SkPaint::Style>("PaintStyle")
1504 .value("Fill", SkPaint::Style::kFill_Style)
1505 .value("Stroke", SkPaint::Style::kStroke_Style)
1506 .value("StrokeAndFill", SkPaint::Style::kStrokeAndFill_Style);
1507
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001508 enum_<SkPathOp>("PathOp")
1509 .value("Difference", SkPathOp::kDifference_SkPathOp)
1510 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
1511 .value("Union", SkPathOp::kUnion_SkPathOp)
1512 .value("XOR", SkPathOp::kXOR_SkPathOp)
1513 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
1514
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001515 enum_<SkCanvas::PointMode>("PointMode")
1516 .value("Points", SkCanvas::PointMode::kPoints_PointMode)
1517 .value("Lines", SkCanvas::PointMode::kLines_PointMode)
1518 .value("Polygon", SkCanvas::PointMode::kPolygon_PointMode);
1519
Kevin Lubickb9db3902018-11-26 11:47:54 -05001520 enum_<SkPaint::Cap>("StrokeCap")
1521 .value("Butt", SkPaint::Cap::kButt_Cap)
1522 .value("Round", SkPaint::Cap::kRound_Cap)
1523 .value("Square", SkPaint::Cap::kSquare_Cap);
1524
1525 enum_<SkPaint::Join>("StrokeJoin")
1526 .value("Miter", SkPaint::Join::kMiter_Join)
1527 .value("Round", SkPaint::Join::kRound_Join)
1528 .value("Bevel", SkPaint::Join::kBevel_Join);
1529
Kevin Lubickec4903d2019-01-14 08:36:08 -05001530 enum_<SkTextEncoding>("TextEncoding")
1531 .value("UTF8", SkTextEncoding::kUTF8)
1532 .value("UTF16", SkTextEncoding::kUTF16)
1533 .value("UTF32", SkTextEncoding::kUTF32)
1534 .value("GlyphID", SkTextEncoding::kGlyphID);
Kevin Lubickb9db3902018-11-26 11:47:54 -05001535
Mike Reed5c5de212019-04-03 16:51:47 -04001536 enum_<SkTileMode>("TileMode")
1537 .value("Clamp", SkTileMode::kClamp)
1538 .value("Repeat", SkTileMode::kRepeat)
1539 .value("Mirror", SkTileMode::kMirror)
Mike Reed5c5de212019-04-03 16:51:47 -04001540 .value("Decal", SkTileMode::kDecal);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001541
1542 enum_<SkVertices::VertexMode>("VertexMode")
1543 .value("Triangles", SkVertices::VertexMode::kTriangles_VertexMode)
1544 .value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001545 .value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001546
Kevin Lubick217056c2018-09-20 17:39:31 -04001547
1548 // A value object is much simpler than a class - it is returned as a JS
1549 // object and does not require delete().
1550 // https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001551 value_object<ShapedTextOpts>("ShapedTextOpts")
1552 .field("font", &ShapedTextOpts::font)
1553 .field("leftToRight", &ShapedTextOpts::leftToRight)
1554 .field("text", &ShapedTextOpts::text)
1555 .field("width", &ShapedTextOpts::width);
1556
Kevin Lubick217056c2018-09-20 17:39:31 -04001557 value_object<SkRect>("SkRect")
1558 .field("fLeft", &SkRect::fLeft)
1559 .field("fTop", &SkRect::fTop)
1560 .field("fRight", &SkRect::fRight)
1561 .field("fBottom", &SkRect::fBottom);
1562
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001563 value_object<SimpleRRect>("SkRRect")
1564 .field("rect", &SimpleRRect::rect)
Kevin Lubick7d644e12019-09-11 14:22:22 -04001565 .field("rx1", &SimpleRRect::rx1)
1566 .field("ry1", &SimpleRRect::ry1)
1567 .field("rx2", &SimpleRRect::rx2)
1568 .field("ry2", &SimpleRRect::ry2)
1569 .field("rx3", &SimpleRRect::rx3)
1570 .field("ry3", &SimpleRRect::ry3)
1571 .field("rx4", &SimpleRRect::rx4)
1572 .field("ry4", &SimpleRRect::ry4);
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001573
Mike Reed114bde82018-11-21 09:12:09 -05001574 value_object<SkIRect>("SkIRect")
1575 .field("fLeft", &SkIRect::fLeft)
1576 .field("fTop", &SkIRect::fTop)
1577 .field("fRight", &SkIRect::fRight)
1578 .field("fBottom", &SkIRect::fBottom);
1579
Kevin Lubick50f377e2019-09-11 15:23:00 -04001580 value_object<TonalColors>("TonalColors")
1581 .field("ambient", &TonalColors::ambientColor)
1582 .field("spot", &TonalColors::spotColor);
1583
Kevin Lubickea905ec2018-11-30 14:05:58 -05001584 value_object<SimpleImageInfo>("SkImageInfo")
1585 .field("width", &SimpleImageInfo::width)
1586 .field("height", &SimpleImageInfo::height)
1587 .field("colorType", &SimpleImageInfo::colorType)
1588 .field("alphaType", &SimpleImageInfo::alphaType);
1589
Kevin Lubick217056c2018-09-20 17:39:31 -04001590 // SkPoints can be represented by [x, y]
1591 value_array<SkPoint>("SkPoint")
1592 .element(&SkPoint::fX)
1593 .element(&SkPoint::fY);
1594
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001595 // SkPoint3s can be represented by [x, y, z]
1596 value_array<SkPoint3>("SkPoint3")
1597 .element(&SkPoint3::fX)
1598 .element(&SkPoint3::fY)
1599 .element(&SkPoint3::fZ);
1600
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001601 // PosTan can be represented by [px, py, tx, ty]
1602 value_array<PosTan>("PosTan")
1603 .element(&PosTan::px)
1604 .element(&PosTan::py)
1605 .element(&PosTan::tx)
1606 .element(&PosTan::ty);
1607
Kevin Lubick217056c2018-09-20 17:39:31 -04001608 // {"w": Number, "h", Number}
1609 value_object<SkSize>("SkSize")
1610 .field("w", &SkSize::fWidth)
1611 .field("h", &SkSize::fHeight);
1612
1613 value_object<SkISize>("SkISize")
1614 .field("w", &SkISize::fWidth)
1615 .field("h", &SkISize::fHeight);
1616
Kevin Lubickec4903d2019-01-14 08:36:08 -05001617 value_object<StrokeOpts>("StrokeOpts")
1618 .field("width", &StrokeOpts::width)
1619 .field("miter_limit", &StrokeOpts::miter_limit)
1620 .field("join", &StrokeOpts::join)
1621 .field("cap", &StrokeOpts::cap)
1622 .field("precision", &StrokeOpts::precision);
1623
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001624 // Allows clients to supply a 1D array of 9 elements and the bindings
1625 // will automatically turn it into a 3x3 2D matrix.
1626 // e.g. path.transform([0,1,2,3,4,5,6,7,8])
1627 // This is likely simpler for the client than exposing SkMatrix
1628 // directly and requiring them to do a lot of .delete().
1629 value_array<SimpleMatrix>("SkMatrix")
1630 .element(&SimpleMatrix::scaleX)
1631 .element(&SimpleMatrix::skewX)
1632 .element(&SimpleMatrix::transX)
1633
1634 .element(&SimpleMatrix::skewY)
1635 .element(&SimpleMatrix::scaleY)
1636 .element(&SimpleMatrix::transY)
1637
1638 .element(&SimpleMatrix::pers0)
1639 .element(&SimpleMatrix::pers1)
1640 .element(&SimpleMatrix::pers2);
1641
Kevin Lubickee91c072019-03-29 10:39:52 -04001642 constant("TRANSPARENT", SK_ColorTRANSPARENT);
1643 constant("RED", SK_ColorRED);
1644 constant("BLUE", SK_ColorBLUE);
1645 constant("YELLOW", SK_ColorYELLOW);
1646 constant("CYAN", SK_ColorCYAN);
1647 constant("BLACK", SK_ColorBLACK);
1648 constant("WHITE", SK_ColorWHITE);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001649 // TODO(?)
1650
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001651 constant("MOVE_VERB", MOVE);
1652 constant("LINE_VERB", LINE);
1653 constant("QUAD_VERB", QUAD);
1654 constant("CONIC_VERB", CONIC);
1655 constant("CUBIC_VERB", CUBIC);
1656 constant("CLOSE_VERB", CLOSE);
Kevin Lubick77d9b5c2019-10-29 10:48:26 -04001657
1658 constant("SaveLayerInitWithPrevious", SkCanvas::SaveLayerFlagsSet::kInitWithPrevious_SaveLayerFlag);
1659 constant("SaveLayerF16ColorType", SkCanvas::SaveLayerFlagsSet::kF16ColorType);
1660
Kevin Lubick217056c2018-09-20 17:39:31 -04001661}