blob: f6f6bf104d5dadd1fa83c2ecd9848e0563bf53cc [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
145 info.fFormat = GL_RGBA8;
146 colorType = kRGBA_8888_SkColorType;
147
148 GrBackendRenderTarget target(width, height, 0, 8, info);
149
150 sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
151 kBottomLeft_GrSurfaceOrigin,
152 colorType, nullptr, nullptr));
153 return surface;
154}
155
156sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, int width, int height) {
157 SkImageInfo info = SkImageInfo::MakeN32(width, height, SkAlphaType::kPremul_SkAlphaType);
158
159 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
160 SkBudgeted::kYes,
161 info, 0,
162 kBottomLeft_GrSurfaceOrigin,
163 nullptr, true));
164 return surface;
165}
166
167sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, SimpleImageInfo sii) {
168 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
169 SkBudgeted::kYes,
170 toSkImageInfo(sii), 0,
171 kBottomLeft_GrSurfaceOrigin,
172 nullptr, true));
173 return surface;
174}
175#endif
176
177
Kevin Lubick217056c2018-09-20 17:39:31 -0400178//========================================================================================
179// Path things
180//========================================================================================
181
182// All these Apply* methods are simple wrappers to avoid returning an object.
183// The default WASM bindings produce code that will leak if a return value
184// isn't assigned to a JS variable and has delete() called on it.
185// These Apply methods, combined with the smarter binding code allow for chainable
186// commands that don't leak if the return value is ignored (i.e. when used intuitively).
187
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500188void ApplyAddArc(SkPath& orig, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
189 orig.addArc(oval, startAngle, sweepAngle);
190}
191
Kevin Lubicke384df42019-08-26 15:48:09 -0400192void ApplyAddOval(SkPath& orig, const SkRect& oval, bool ccw, unsigned start) {
193 orig.addOval(oval, ccw ? SkPath::Direction::kCCW_Direction :
194 SkPath::Direction::kCW_Direction, start);
195}
196
Kevin Lubick217056c2018-09-20 17:39:31 -0400197void ApplyAddPath(SkPath& orig, const SkPath& newPath,
198 SkScalar scaleX, SkScalar skewX, SkScalar transX,
199 SkScalar skewY, SkScalar scaleY, SkScalar transY,
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500200 SkScalar pers0, SkScalar pers1, SkScalar pers2,
201 bool extendPath) {
Kevin Lubick217056c2018-09-20 17:39:31 -0400202 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
203 skewY , scaleY, transY,
204 pers0 , pers1 , pers2);
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500205 orig.addPath(newPath, m, extendPath ? SkPath::kExtend_AddPathMode :
206 SkPath::kAppend_AddPathMode);
Kevin Lubick217056c2018-09-20 17:39:31 -0400207}
208
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500209void ApplyAddRect(SkPath& path, SkScalar left, SkScalar top,
210 SkScalar right, SkScalar bottom, bool ccw) {
211 path.addRect(left, top, right, bottom,
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500212 ccw ? SkPath::Direction::kCCW_Direction :
213 SkPath::Direction::kCW_Direction);
Alexander Khovansky3e119332018-11-15 02:01:19 +0300214}
215
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500216void ApplyAddRoundRect(SkPath& path, SkScalar left, SkScalar top,
217 SkScalar right, SkScalar bottom, uintptr_t /* SkScalar* */ rPtr,
218 bool ccw) {
219 // See comment below for uintptr_t explanation
220 const SkScalar* radii = reinterpret_cast<const SkScalar*>(rPtr);
221 path.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radii,
222 ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction);
223}
224
225
Kevin Lubick217056c2018-09-20 17:39:31 -0400226void ApplyArcTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
227 SkScalar radius) {
228 p.arcTo(x1, y1, x2, y2, radius);
229}
230
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500231void ApplyArcToAngle(SkPath& p, SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) {
232 p.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
233}
234
Kevin Lubick79b71342019-11-01 14:36:52 -0400235void ApplyArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
236 bool useSmallArc, bool ccw, SkScalar x, SkScalar y) {
Kevin Lubicke384df42019-08-26 15:48:09 -0400237 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
238 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
239 orig.arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y);
240}
241
Kevin Lubick79b71342019-11-01 14:36:52 -0400242void ApplyRArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
243 bool useSmallArc, bool ccw, SkScalar dx, SkScalar dy) {
244 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
245 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
246 orig.rArcTo(rx, ry, xAxisRotate, arcSize, sweep, dx, dy);
247}
248
Kevin Lubick217056c2018-09-20 17:39:31 -0400249void ApplyClose(SkPath& p) {
250 p.close();
251}
252
253void ApplyConicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
254 SkScalar w) {
255 p.conicTo(x1, y1, x2, y2, w);
256}
257
Kevin Lubick79b71342019-11-01 14:36:52 -0400258void ApplyRConicTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
259 SkScalar w) {
260 p.rConicTo(dx1, dy1, dx2, dy2, w);
261}
262
Kevin Lubick217056c2018-09-20 17:39:31 -0400263void ApplyCubicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
264 SkScalar x3, SkScalar y3) {
265 p.cubicTo(x1, y1, x2, y2, x3, y3);
266}
267
Kevin Lubick79b71342019-11-01 14:36:52 -0400268void ApplyRCubicTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
269 SkScalar dx3, SkScalar dy3) {
270 p.rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
271}
272
Kevin Lubick217056c2018-09-20 17:39:31 -0400273void ApplyLineTo(SkPath& p, SkScalar x, SkScalar y) {
274 p.lineTo(x, y);
275}
276
Kevin Lubick79b71342019-11-01 14:36:52 -0400277void ApplyRLineTo(SkPath& p, SkScalar dx, SkScalar dy) {
278 p.rLineTo(dx, dy);
279}
280
Kevin Lubick217056c2018-09-20 17:39:31 -0400281void ApplyMoveTo(SkPath& p, SkScalar x, SkScalar y) {
282 p.moveTo(x, y);
283}
284
Kevin Lubick79b71342019-11-01 14:36:52 -0400285void ApplyRMoveTo(SkPath& p, SkScalar dx, SkScalar dy) {
286 p.rMoveTo(dx, dy);
287}
288
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500289void ApplyReset(SkPath& p) {
290 p.reset();
291}
292
293void ApplyRewind(SkPath& p) {
294 p.rewind();
295}
296
Kevin Lubick217056c2018-09-20 17:39:31 -0400297void ApplyQuadTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
298 p.quadTo(x1, y1, x2, y2);
299}
300
Kevin Lubick79b71342019-11-01 14:36:52 -0400301void ApplyRQuadTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2) {
302 p.rQuadTo(dx1, dy1, dx2, dy2);
303}
304
Kevin Lubick217056c2018-09-20 17:39:31 -0400305void ApplyTransform(SkPath& orig,
306 SkScalar scaleX, SkScalar skewX, SkScalar transX,
307 SkScalar skewY, SkScalar scaleY, SkScalar transY,
308 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
309 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
310 skewY , scaleY, transY,
311 pers0 , pers1 , pers2);
312 orig.transform(m);
313}
314
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400315bool EMSCRIPTEN_KEEPALIVE ApplySimplify(SkPath& path) {
316 return Simplify(path, &path);
317}
318
319bool EMSCRIPTEN_KEEPALIVE ApplyPathOp(SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
320 return Op(pathOne, pathTwo, op, &pathOne);
321}
322
323JSString EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
324 SkString s;
325 SkParsePath::ToSVGString(path, &s);
326 return emscripten::val(s.c_str());
327}
328
Kevin Lubicka40f8322018-12-17 16:01:36 -0500329SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromSVGString(std::string str) {
330 SkPath path;
331 if (SkParsePath::FromSVGString(str.c_str(), &path)) {
332 return emscripten::val(path);
333 }
334 return emscripten::val::null();
335}
336
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400337SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
338 SkPath out;
339 if (Op(pathOne, pathTwo, op, &out)) {
340 return emscripten::val(out);
341 }
342 return emscripten::val::null();
343}
344
Kevin Lubick217056c2018-09-20 17:39:31 -0400345SkPath EMSCRIPTEN_KEEPALIVE CopyPath(const SkPath& a) {
346 SkPath copy(a);
347 return copy;
348}
349
350bool EMSCRIPTEN_KEEPALIVE Equals(const SkPath& a, const SkPath& b) {
351 return a == b;
352}
353
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500354// =================================================================================
355// Creating/Exporting Paths with cmd arrays
356// =================================================================================
357
358static const int MOVE = 0;
359static const int LINE = 1;
360static const int QUAD = 2;
361static const int CONIC = 3;
362static const int CUBIC = 4;
363static const int CLOSE = 5;
364
365template <typename VisitFunc>
366void VisitPath(const SkPath& p, VisitFunc&& f) {
367 SkPath::RawIter iter(p);
368 SkPoint pts[4];
369 SkPath::Verb verb;
370 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
371 f(verb, pts, iter);
372 }
373}
374
375JSArray EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
376 JSArray cmds = emscripten::val::array();
377
378 VisitPath(path, [&cmds](SkPath::Verb verb, const SkPoint pts[4], SkPath::RawIter iter) {
379 JSArray cmd = emscripten::val::array();
380 switch (verb) {
381 case SkPath::kMove_Verb:
382 cmd.call<void>("push", MOVE, pts[0].x(), pts[0].y());
383 break;
384 case SkPath::kLine_Verb:
385 cmd.call<void>("push", LINE, pts[1].x(), pts[1].y());
386 break;
387 case SkPath::kQuad_Verb:
388 cmd.call<void>("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
389 break;
390 case SkPath::kConic_Verb:
391 cmd.call<void>("push", CONIC,
392 pts[1].x(), pts[1].y(),
393 pts[2].x(), pts[2].y(), iter.conicWeight());
394 break;
395 case SkPath::kCubic_Verb:
396 cmd.call<void>("push", CUBIC,
397 pts[1].x(), pts[1].y(),
398 pts[2].x(), pts[2].y(),
399 pts[3].x(), pts[3].y());
400 break;
401 case SkPath::kClose_Verb:
402 cmd.call<void>("push", CLOSE);
403 break;
404 case SkPath::kDone_Verb:
405 SkASSERT(false);
406 break;
407 }
408 cmds.call<void>("push", cmd);
409 });
410 return cmds;
411}
412
413// This type signature is a mess, but it's necessary. See, we can't use "bind" (EMSCRIPTEN_BINDINGS)
414// and pointers to primitive types (Only bound types like SkPoint). We could if we used
415// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
416// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
417// SkPath or SkOpBuilder.
418//
Kevin Lubick61887c72019-09-26 13:20:50 -0400419// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500420// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
421// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
422// the compiler is happy.
423SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromCmds(uintptr_t /* float* */ cptr, int numCmds) {
424 const auto* cmds = reinterpret_cast<const float*>(cptr);
425 SkPath path;
426 float x1, y1, x2, y2, x3, y3;
427
428 // if there are not enough arguments, bail with the path we've constructed so far.
429 #define CHECK_NUM_ARGS(n) \
430 if ((i + n) > numCmds) { \
431 SkDebugf("Not enough args to match the verbs. Saw %d commands\n", numCmds); \
432 return emscripten::val::null(); \
433 }
434
435 for(int i = 0; i < numCmds;){
436 switch (sk_float_floor2int(cmds[i++])) {
437 case MOVE:
438 CHECK_NUM_ARGS(2);
439 x1 = cmds[i++], y1 = cmds[i++];
440 path.moveTo(x1, y1);
441 break;
442 case LINE:
443 CHECK_NUM_ARGS(2);
444 x1 = cmds[i++], y1 = cmds[i++];
445 path.lineTo(x1, y1);
446 break;
447 case QUAD:
448 CHECK_NUM_ARGS(4);
449 x1 = cmds[i++], y1 = cmds[i++];
450 x2 = cmds[i++], y2 = cmds[i++];
451 path.quadTo(x1, y1, x2, y2);
452 break;
453 case CONIC:
454 CHECK_NUM_ARGS(5);
455 x1 = cmds[i++], y1 = cmds[i++];
456 x2 = cmds[i++], y2 = cmds[i++];
457 x3 = cmds[i++]; // weight
458 path.conicTo(x1, y1, x2, y2, x3);
459 break;
460 case CUBIC:
461 CHECK_NUM_ARGS(6);
462 x1 = cmds[i++], y1 = cmds[i++];
463 x2 = cmds[i++], y2 = cmds[i++];
464 x3 = cmds[i++], y3 = cmds[i++];
465 path.cubicTo(x1, y1, x2, y2, x3, y3);
466 break;
467 case CLOSE:
468 path.close();
469 break;
470 default:
471 SkDebugf(" path: UNKNOWN command %f, aborting dump...\n", cmds[i-1]);
472 return emscripten::val::null();
473 }
474 }
475
476 #undef CHECK_NUM_ARGS
477
478 return emscripten::val(path);
479}
480
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400481//========================================================================================
482// Path Effects
483//========================================================================================
484
485bool ApplyDash(SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
486 SkScalar intervals[] = { on, off };
487 auto pe = SkDashPathEffect::Make(intervals, 2, phase);
488 if (!pe) {
489 SkDebugf("Invalid args to dash()\n");
490 return false;
491 }
492 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
493 if (pe->filterPath(&path, path, &rec, nullptr)) {
494 return true;
495 }
496 SkDebugf("Could not make dashed path\n");
497 return false;
Kevin Lubick217056c2018-09-20 17:39:31 -0400498}
499
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400500bool ApplyTrim(SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
501 auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal;
502 auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
503 if (!pe) {
504 SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
505 return false;
506 }
507 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
508 if (pe->filterPath(&path, path, &rec, nullptr)) {
509 return true;
510 }
511 SkDebugf("Could not trim path\n");
512 return false;
513}
514
515struct StrokeOpts {
Kevin Lubickb9db3902018-11-26 11:47:54 -0500516 // Default values are set in interface.js which allows clients
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400517 // to set any number of them. Otherwise, the binding code complains if
518 // any are omitted.
519 SkScalar width;
520 SkScalar miter_limit;
521 SkPaint::Join join;
522 SkPaint::Cap cap;
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500523 float precision;
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400524};
525
526bool ApplyStroke(SkPath& path, StrokeOpts opts) {
527 SkPaint p;
528 p.setStyle(SkPaint::kStroke_Style);
529 p.setStrokeCap(opts.cap);
530 p.setStrokeJoin(opts.join);
531 p.setStrokeWidth(opts.width);
532 p.setStrokeMiter(opts.miter_limit);
533
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500534 return p.getFillPath(path, &path, nullptr, opts.precision);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400535}
536
537// to map from raw memory to a uint8array
538Uint8Array getSkDataBytes(const SkData *data) {
539 return Uint8Array(typed_memory_view(data->size(), data->bytes()));
540}
541
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500542// Text Shaping abstraction
543
544struct ShapedTextOpts {
545 SkFont font;
546 bool leftToRight;
547 std::string text;
548 SkScalar width;
549};
550
551std::unique_ptr<SkShaper> shaper;
552
553static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400554 SkTextBlobBuilderRunHandler builder(opts.text.c_str(), {0, 0});
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500555 if (!shaper) {
556 shaper = SkShaper::Make();
557 }
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400558 shaper->shape(opts.text.c_str(), opts.text.length(),
559 opts.font, opts.leftToRight,
560 opts.width, &builder);
561 *pt = builder.endPoint();
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500562 return builder.makeBlob();
563}
564
565class ShapedText {
566public:
567 ShapedText(ShapedTextOpts opts) : fOpts(opts) {}
568
569 SkRect getBounds() {
570 this->init();
571 return SkRect::MakeLTRB(0, 0, fOpts.width, fPoint.y());
572 }
573
574 SkTextBlob* blob() {
575 this->init();
576 return fBlob.get();
577 }
578private:
579 const ShapedTextOpts fOpts;
580 SkPoint fPoint;
581 sk_sp<SkTextBlob> fBlob;
582
583 void init() {
584 if (!fBlob) {
585 fBlob = do_shaping(fOpts, &fPoint);
586 }
587 }
588};
589
590void drawShapedText(SkCanvas& canvas, ShapedText st, SkScalar x,
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400591 SkScalar y, SkPaint paint) {
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500592 canvas.drawTextBlob(st.blob(), x, y, paint);
593}
594
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400595int saveLayerRec(SkCanvas& canvas, const SkPaint* paint,
596 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags) {
597 return canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, paint, backdrop, flags));
598}
599
600int saveLayerRecBounds(SkCanvas& canvas, const SkPaint* paint, const SkImageFilter* backdrop,
601 SkCanvas::SaveLayerFlags flags, const SkRect& bounds) {
602 return canvas.saveLayer(SkCanvas::SaveLayerRec(&bounds, paint, backdrop, flags));
603}
604
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400605// This is simpler than dealing with an SkPoint and SkVector
606struct PosTan {
607 SkScalar px, py, tx, ty;
608};
609
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400610// SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
611struct SimpleRRect {
612 SkRect rect;
Kevin Lubick7d644e12019-09-11 14:22:22 -0400613
614 SkScalar rx1;
615 SkScalar ry1;
616 SkScalar rx2;
617 SkScalar ry2;
618 SkScalar rx3;
619 SkScalar ry3;
620 SkScalar rx4;
621 SkScalar ry4;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400622};
623
624SkRRect toRRect(const SimpleRRect& r) {
Kevin Lubick7d644e12019-09-11 14:22:22 -0400625 SkVector fRadii[4] = {{r.rx1, r.ry1}, {r.rx2, r.ry2},
626 {r.rx3, r.ry3}, {r.rx4, r.ry4}};
627 SkRRect rr;
628 rr.setRectRadii(r.rect, fRadii);
629 return rr;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400630}
631
Kevin Lubick50f377e2019-09-11 15:23:00 -0400632struct TonalColors {
633 SkColor ambientColor;
634 SkColor spotColor;
635};
636
637TonalColors computeTonalColors(const TonalColors& in) {
638 TonalColors out;
639 SkShadowUtils::ComputeTonalColors(in.ambientColor, in.spotColor,
640 &out.ambientColor, &out.spotColor);
641 return out;
642}
643
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400644// These objects have private destructors / delete methods - I don't think
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400645// we need to do anything other than tell emscripten to do nothing.
Kevin Lubick217056c2018-09-20 17:39:31 -0400646namespace emscripten {
647 namespace internal {
648 template<typename ClassType>
649 void raw_destructor(ClassType *);
650
651 template<>
652 void raw_destructor<SkData>(SkData *ptr) {
653 }
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400654
655 template<>
656 void raw_destructor<SkVertices>(SkVertices *ptr) {
657 }
Kevin Lubickec4903d2019-01-14 08:36:08 -0500658
Kevin Lubick61887c72019-09-26 13:20:50 -0400659#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -0500660 template<>
661 void raw_destructor<SkTextBlob>(SkTextBlob *ptr) {
662 }
Kevin Lubick61887c72019-09-26 13:20:50 -0400663
664 template<>
665 void raw_destructor<SkTypeface>(SkTypeface *ptr) {
666 }
667#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400668 }
669}
670
Kevin Lubick61887c72019-09-26 13:20:50 -0400671// Some signatures below have uintptr_t instead of a pointer to a primitive
Kevin Lubick217056c2018-09-20 17:39:31 -0400672// type (e.g. SkScalar). This is necessary because we can't use "bind" (EMSCRIPTEN_BINDINGS)
673// and pointers to primitive types (Only bound types like SkPoint). We could if we used
674// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
675// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
676// SkPath or SkCanvas.
677//
Kevin Lubick61887c72019-09-26 13:20:50 -0400678// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubick217056c2018-09-20 17:39:31 -0400679// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
680// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
681// the compiler is happy.
682EMSCRIPTEN_BINDINGS(Skia) {
Kevin Lubick53965c92018-10-11 08:51:55 -0400683#if SK_SUPPORT_GPU
Kevin Lubick53965c92018-10-11 08:51:55 -0400684 function("currentContext", &emscripten_webgl_get_current_context);
685 function("setCurrentContext", &emscripten_webgl_make_context_current);
Kevin Lubick543f3522019-03-08 10:04:28 -0500686 function("MakeGrContext", &MakeGrContext);
687 function("MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
688 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, int, int)>(&MakeRenderTarget));
689 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, SimpleImageInfo)>(&MakeRenderTarget));
690
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400691 constant("gpu", true);
Kevin Lubickb07204a2018-11-20 14:07:42 -0500692#endif
Kevin Lubick50f377e2019-09-11 15:23:00 -0400693 function("computeTonalColors", &computeTonalColors);
Kevin Lubick6b921b72019-09-18 16:18:17 -0400694 function("_decodeAnimatedImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
695 size_t length)->sk_sp<SkAnimatedImage> {
696 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
697 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
698 auto codec = SkAndroidCodec::MakeFromData(bytes);
699 if (nullptr == codec) {
700 return nullptr;
701 }
702 return SkAnimatedImage::Make(std::move(codec));
703 }), allow_raw_pointers());
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500704 function("_decodeImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
705 size_t length)->sk_sp<SkImage> {
706 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
Kevin Lubick88aff5f2019-02-28 16:05:09 -0500707 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
708 return SkImage::MakeFromEncoded(std::move(bytes));
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500709 }), allow_raw_pointers());
Kevin Lubickea905ec2018-11-30 14:05:58 -0500710 function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
Kevin Lubick52b9f372018-12-04 13:57:36 -0500711 uintptr_t /* uint8_t* */ pPtr,
Kevin Lubickea905ec2018-11-30 14:05:58 -0500712 size_t rowBytes)->sk_sp<SkSurface> {
Kevin Lubick52b9f372018-12-04 13:57:36 -0500713 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
Kevin Lubickea905ec2018-11-30 14:05:58 -0500714 SkImageInfo imageInfo = toSkImageInfo(ii);
715 return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
716 }), allow_raw_pointers());
Kevin Lubick53965c92018-10-11 08:51:55 -0400717 function("_getRasterN32PremulSurface", optional_override([](int width, int height)->sk_sp<SkSurface> {
718 return SkSurface::MakeRasterN32Premul(width, height, nullptr);
719 }), allow_raw_pointers());
Kevin Lubickb07204a2018-11-20 14:07:42 -0500720
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400721 function("getSkDataBytes", &getSkDataBytes, allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -0400722 function("MakeSkCornerPathEffect", &SkCornerPathEffect::Make, allow_raw_pointers());
723 function("MakeSkDiscretePathEffect", &SkDiscretePathEffect::Make, allow_raw_pointers());
Kevin Lubick15b40232019-10-29 09:55:39 -0400724 // Deprecated: use Canvaskit.SkMaskFilter.MakeBlur
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500725 function("MakeBlurMaskFilter", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
726 // Adds a little helper because emscripten doesn't expose default params.
727 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
728 }), allow_raw_pointers());
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500729 function("_MakePathFromCmds", &MakePathFromCmds);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400730 function("MakePathFromOp", &MakePathFromOp);
Kevin Lubicka40f8322018-12-17 16:01:36 -0500731 function("MakePathFromSVGString", &MakePathFromSVGString);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400732
733 // These won't be called directly, there's a JS helper to deal with typed arrays.
Kevin Lubick217056c2018-09-20 17:39:31 -0400734 function("_MakeSkDashPathEffect", optional_override([](uintptr_t /* float* */ cptr, int count, SkScalar phase)->sk_sp<SkPathEffect> {
735 // See comment above for uintptr_t explanation
736 const float* intervals = reinterpret_cast<const float*>(cptr);
737 return SkDashPathEffect::Make(intervals, count, phase);
738 }), allow_raw_pointers());
Kevin Lubick52b9f372018-12-04 13:57:36 -0500739 function("_MakeImage", optional_override([](SimpleImageInfo ii,
740 uintptr_t /* uint8_t* */ pPtr, int plen,
741 size_t rowBytes)->sk_sp<SkImage> {
742 // See comment above for uintptr_t explanation
743 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
744 SkImageInfo info = toSkImageInfo(ii);
745 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
746
747 return SkImage::MakeRasterData(info, pixelData, rowBytes);
748 }), allow_raw_pointers());
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400749 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
750 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400751 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400752 SkPoint points[] = { start, end };
753 // See comment above for uintptr_t explanation
754 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
755 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
756
757 return SkGradientShader::MakeLinear(points, colors, positions, count,
758 mode, flags, nullptr);
759 }), allow_raw_pointers());
760 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
761 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400762 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400763 const SimpleMatrix& lm)->sk_sp<SkShader> {
764 SkPoint points[] = { start, end };
765 // See comment above for uintptr_t explanation
766 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
767 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
768
769 SkMatrix localMatrix = toSkMatrix(lm);
770
771 return SkGradientShader::MakeLinear(points, colors, positions, count,
772 mode, flags, &localMatrix);
773 }), allow_raw_pointers());
774 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
775 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400776 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400777 // See comment above for uintptr_t explanation
778 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
779 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
780
781 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
782 mode, flags, nullptr);
783 }), allow_raw_pointers());
784 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
785 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400786 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400787 const SimpleMatrix& lm)->sk_sp<SkShader> {
788 // See comment above for uintptr_t explanation
789 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
790 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
791
792 SkMatrix localMatrix = toSkMatrix(lm);
793 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
794 mode, flags, &localMatrix);
795 }), allow_raw_pointers());
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500796 function("_MakeTwoPointConicalGradientShader", optional_override([](
797 SkPoint start, SkScalar startRadius,
798 SkPoint end, SkScalar endRadius,
799 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400800 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500801 // See comment above for uintptr_t explanation
802 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
803 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
804
805 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
806 colors, positions, count, mode,
807 flags, nullptr);
808 }), allow_raw_pointers());
809 function("_MakeTwoPointConicalGradientShader", optional_override([](
810 SkPoint start, SkScalar startRadius,
811 SkPoint end, SkScalar endRadius,
812 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400813 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500814 const SimpleMatrix& lm)->sk_sp<SkShader> {
815 // See comment above for uintptr_t explanation
816 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
817 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
818
819 SkMatrix localMatrix = toSkMatrix(lm);
820 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
821 colors, positions, count, mode,
822 flags, &localMatrix);
823 }), allow_raw_pointers());
824
Kevin Lubick543f3522019-03-08 10:04:28 -0500825#if SK_SUPPORT_GPU
826 class_<GrContext>("GrContext")
Kevin Lubickcd544662019-03-22 15:41:36 -0400827 .smart_ptr<sk_sp<GrContext>>("sk_sp<GrContext>")
828 .function("getResourceCacheLimitBytes", optional_override([](GrContext& self)->size_t {
829 int maxResources = 0;// ignored
830 size_t currMax = 0;
831 self.getResourceCacheLimits(&maxResources, &currMax);
832 return currMax;
833 }))
834 .function("getResourceCacheUsageBytes", optional_override([](GrContext& self)->size_t {
835 int usedResources = 0;// ignored
836 size_t currUsage = 0;
837 self.getResourceCacheUsage(&usedResources, &currUsage);
838 return currUsage;
839 }))
840 .function("setResourceCacheLimitBytes", optional_override([](GrContext& self, size_t maxResourceBytes)->void {
841 int maxResources = 0;
842 size_t currMax = 0; // ignored
843 self.getResourceCacheLimits(&maxResources, &currMax);
844 self.setResourceCacheLimits(maxResources, maxResourceBytes);
845 }));
Kevin Lubick543f3522019-03-08 10:04:28 -0500846#endif
847
Kevin Lubick6b921b72019-09-18 16:18:17 -0400848 class_<SkAnimatedImage>("SkAnimatedImage")
849 .smart_ptr<sk_sp<SkAnimatedImage>>("sk_sp<SkAnimatedImage>")
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800850 .function("decodeNextFrame", &SkAnimatedImage::decodeNextFrame)
851 .function("getFrameCount", &SkAnimatedImage::getFrameCount)
Kevin Lubick6b921b72019-09-18 16:18:17 -0400852 .function("getRepetitionCount", &SkAnimatedImage::getRepetitionCount)
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800853 .function("height", optional_override([](SkAnimatedImage& self)->int32_t {
854 return self.dimensions().height();
855 }))
856 .function("reset", &SkAnimatedImage::reset)
857 .function("width", optional_override([](SkAnimatedImage& self)->int32_t {
858 return self.dimensions().width();
859 }));
Kevin Lubick6b921b72019-09-18 16:18:17 -0400860
Kevin Lubick217056c2018-09-20 17:39:31 -0400861 class_<SkCanvas>("SkCanvas")
862 .constructor<>()
Kevin Lubickee91c072019-03-29 10:39:52 -0400863 .function("clear", &SkCanvas::clear)
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500864 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
Kevin Lubick47bd9f12019-11-08 06:55:15 -0800865 .function("clipRRect", optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400866 self.clipRRect(toRRect(r), op, doAntiAlias);
867 }))
Kevin Lubick52b9f372018-12-04 13:57:36 -0500868 .function("clipRect", select_overload<void (const SkRect&, SkClipOp, bool)>(&SkCanvas::clipRect))
869 .function("concat", optional_override([](SkCanvas& self, const SimpleMatrix& m) {
870 self.concat(toSkMatrix(m));
871 }))
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500872 .function("drawArc", &SkCanvas::drawArc)
Kevin Lubickee91c072019-03-29 10:39:52 -0400873 .function("_drawAtlas", optional_override([](SkCanvas& self,
874 const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
875 uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
876 SkBlendMode mode, const SkPaint* paint)->void {
877 // See comment above for uintptr_t explanation
878 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
879 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
880 const SkColor* colors = nullptr;
881 if (cptr) {
882 colors = reinterpret_cast<const SkColor*>(cptr);
883 }
884 self.drawAtlas(atlas, dstXforms, srcRects, colors, count, mode, nullptr, paint);
885 }), allow_raw_pointers())
Kevin Lubicke384df42019-08-26 15:48:09 -0400886 .function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400887 .function("drawColor", &SkCanvas::drawColor)
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400888 .function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
889 self.drawDRRect(toRRect(o), toRRect(i), paint);
890 }))
Kevin Lubick6b921b72019-09-18 16:18:17 -0400891 .function("drawAnimatedImage", optional_override([](SkCanvas& self, sk_sp<SkAnimatedImage>& aImg,
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500892 SkScalar x, SkScalar y)->void {
Kevin Lubick6b921b72019-09-18 16:18:17 -0400893 self.drawDrawable(aImg.get(), x, y);
894 }), allow_raw_pointers())
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500895 .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 -0500896 .function("drawImageNine", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
897 SkIRect center, SkRect dst,
898 const SkPaint* paint)->void {
899 self.drawImageNine(image, center, dst, paint);
900 }), allow_raw_pointers())
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500901 .function("drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
902 SkRect src, SkRect dst,
903 const SkPaint* paint, bool fastSample)->void {
904 self.drawImageRect(image, src, dst, paint,
905 fastSample ? SkCanvas::kFast_SrcRectConstraint :
906 SkCanvas::kStrict_SrcRectConstraint);
907 }), allow_raw_pointers())
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500908 .function("drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
909 .function("drawOval", &SkCanvas::drawOval)
Kevin Lubick217056c2018-09-20 17:39:31 -0400910 .function("drawPaint", &SkCanvas::drawPaint)
Kevin Lubick369f6a52019-10-03 11:22:08 -0400911#ifdef SK_INCLUDE_PARAGRAPH
912 .function("drawParagraph", optional_override([](SkCanvas& self, skia::textlayout::Paragraph* p,
913 SkScalar x, SkScalar y) {
914 p->paint(&self, x, y);
915 }), allow_raw_pointers())
916#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400917 .function("drawPath", &SkCanvas::drawPath)
Kevin Lubickcc13fd32019-04-05 13:00:01 -0400918 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
919 // a bitmap. An SkPicture is a series of draw commands.
920 .function("drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
Kevin Lubick37ab53e2019-11-11 10:06:08 -0500921 .function("_drawPoints", optional_override([](SkCanvas& self, SkCanvas::PointMode mode,
922 uintptr_t /* SkPoint* */ pptr,
923 int count, SkPaint paint)->void {
924 // See comment above for uintptr_t explanation
925 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
926 self.drawPoints(mode, count, pts, paint);
927 }))
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400928 .function("drawRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, const SkPaint& paint) {
929 self.drawRRect(toRRect(r), paint);
930 }))
Kevin Lubick217056c2018-09-20 17:39:31 -0400931 .function("drawRect", &SkCanvas::drawRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500932 .function("drawRoundRect", &SkCanvas::drawRoundRect)
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500933 .function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
934 const SkPoint3& zPlaneParams,
935 const SkPoint3& lightPos, SkScalar lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400936 SkColor ambientColor, SkColor spotColor,
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500937 uint32_t flags) {
938 SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400939 ambientColor, spotColor, flags);
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500940 }))
Kevin Lubick61887c72019-09-26 13:20:50 -0400941#ifndef SK_NO_FONTS
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500942 .function("_drawShapedText", &drawShapedText)
Kevin Lubickec4903d2019-01-14 08:36:08 -0500943 .function("_drawSimpleText", optional_override([](SkCanvas& self, uintptr_t /* char* */ sptr,
944 size_t len, SkScalar x, SkScalar y, const SkFont& font,
945 const SkPaint& paint) {
946 // See comment above for uintptr_t explanation
947 const char* str = reinterpret_cast<const char*>(sptr);
948
949 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
Kevin Lubick217056c2018-09-20 17:39:31 -0400950 }))
Kevin Lubickec4903d2019-01-14 08:36:08 -0500951 .function("drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
Kevin Lubick61887c72019-09-26 13:20:50 -0400952#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400953 .function("drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
Kevin Lubick217056c2018-09-20 17:39:31 -0400954 .function("flush", &SkCanvas::flush)
Kevin Lubicke384df42019-08-26 15:48:09 -0400955 .function("getSaveCount", &SkCanvas::getSaveCount)
Kevin Lubick5d5723c2018-12-07 10:09:11 -0500956 .function("getTotalMatrix", optional_override([](const SkCanvas& self)->SimpleMatrix {
957 SkMatrix m = self.getTotalMatrix();
958 return toSimpleSkMatrix(m);
959 }))
Kevin Lubick543f3522019-03-08 10:04:28 -0500960 .function("makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
961 return self.makeSurface(toSkImageInfo(sii), nullptr);
962 }), allow_raw_pointers())
Kevin Lubick52b9f372018-12-04 13:57:36 -0500963 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
964 uintptr_t /* uint8_t* */ pPtr,
965 size_t dstRowBytes, int srcX, int srcY) {
966 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
967 SkImageInfo dstInfo = toSkImageInfo(di);
968
969 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
970 }))
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500971 .function("restore", &SkCanvas::restore)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500972 .function("restoreToCount", &SkCanvas::restoreToCount)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400973 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
Kevin Lubick217056c2018-09-20 17:39:31 -0400974 .function("save", &SkCanvas::save)
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400975 // 2 params
Kevin Lubickb3574c92019-03-06 08:25:36 -0500976 .function("saveLayer", select_overload<int (const SkRect&, const SkPaint*)>(&SkCanvas::saveLayer),
977 allow_raw_pointers())
Kevin Lubick77d9b5c2019-10-29 10:48:26 -0400978 // 3 params (effectively with SaveLayerRec, but no bounds)
979 .function("saveLayer", saveLayerRec, allow_raw_pointers())
980 // 4 params (effectively with SaveLayerRec)
981 .function("saveLayer", saveLayerRecBounds, allow_raw_pointers())
982
Kevin Lubick006a6f32018-10-19 14:34:34 -0400983 .function("scale", &SkCanvas::scale)
Kevin Lubick006a6f32018-10-19 14:34:34 -0400984 .function("skew", &SkCanvas::skew)
Kevin Lubick52b9f372018-12-04 13:57:36 -0500985 .function("translate", &SkCanvas::translate)
986 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
987 uintptr_t /* uint8_t* */ pPtr,
988 size_t srcRowBytes, int dstX, int dstY) {
989 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
990 SkImageInfo dstInfo = toSkImageInfo(di);
991
992 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
Kevin Lubick369f6a52019-10-03 11:22:08 -0400993 }));
Kevin Lubick217056c2018-09-20 17:39:31 -0400994
Kevin Lubickd3729342019-09-12 11:11:25 -0400995 class_<SkColorFilter>("SkColorFilter")
996 .smart_ptr<sk_sp<SkColorFilter>>("sk_sp<SkColorFilter>>")
997 .class_function("MakeBlend", &SkColorFilters::Blend)
998 .class_function("MakeCompose", &SkColorFilters::Compose)
999 .class_function("MakeLerp", &SkColorFilters::Lerp)
1000 .class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
1001 .class_function("_makeMatrix", optional_override([](uintptr_t /* float* */ fPtr) {
1002 float* twentyFloats = reinterpret_cast<float*>(fPtr);
1003 return SkColorFilters::Matrix(twentyFloats);
1004 }))
1005 .class_function("MakeSRGBToLinearGamma", &SkColorFilters::SRGBToLinearGamma);
1006
Kevin Lubick217056c2018-09-20 17:39:31 -04001007 class_<SkData>("SkData")
1008 .smart_ptr<sk_sp<SkData>>("sk_sp<SkData>>")
1009 .function("size", &SkData::size);
1010
Kevin Lubick6b921b72019-09-18 16:18:17 -04001011 class_<SkDrawable>("SkDrawable")
1012 .smart_ptr<sk_sp<SkDrawable>>("sk_sp<SkDrawable>>");
1013
Kevin Lubick61887c72019-09-26 13:20:50 -04001014#ifndef SK_NO_FONTS
Kevin Lubick35ac0382019-01-02 15:13:57 -05001015 class_<SkFont>("SkFont")
1016 .constructor<>()
1017 .constructor<sk_sp<SkTypeface>>()
1018 .constructor<sk_sp<SkTypeface>, SkScalar>()
1019 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
1020 .function("getScaleX", &SkFont::getScaleX)
1021 .function("getSize", &SkFont::getSize)
1022 .function("getSkewX", &SkFont::getSkewX)
1023 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001024 .function("_getWidths", optional_override([](SkFont& self, uintptr_t /* char* */ sptr,
1025 size_t strLen, size_t expectedCodePoints,
1026 uintptr_t /* SkScalar* */ wptr) -> bool {
1027 char* str = reinterpret_cast<char*>(sptr);
1028 SkScalar* widths = reinterpret_cast<SkScalar*>(wptr);
1029
1030 SkGlyphID* glyphStorage = new SkGlyphID[expectedCodePoints];
1031 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
1032 glyphStorage, expectedCodePoints);
1033 if (actualCodePoints != expectedCodePoints) {
1034 SkDebugf("Actually %d glyphs, expected only %d\n",
1035 actualCodePoints, expectedCodePoints);
1036 return false;
1037 }
1038
1039 self.getWidths(glyphStorage, actualCodePoints, widths);
1040 delete[] glyphStorage;
1041 return true;
1042 }))
Kevin Lubick35ac0382019-01-02 15:13:57 -05001043 .function("measureText", optional_override([](SkFont& self, std::string text) {
1044 // TODO(kjlubick): This does not work well for non-ascii
1045 // Need to maybe add a helper in interface.js that supports UTF-8
1046 // Otherwise, go with std::wstring and set UTF-32 encoding.
1047 return self.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
1048 }))
1049 .function("setScaleX", &SkFont::setScaleX)
1050 .function("setSize", &SkFont::setSize)
1051 .function("setSkewX", &SkFont::setSkewX)
1052 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
1053
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001054 class_<ShapedText>("ShapedText")
1055 .constructor<ShapedTextOpts>()
1056 .function("getBounds", &ShapedText::getBounds);
1057
Kevin Lubickddd0a332018-12-12 10:35:13 -05001058 class_<SkFontMgr>("SkFontMgr")
1059 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<SkFontMgr>")
Kevin Lubick61887c72019-09-26 13:20:50 -04001060 .class_function("_fromData", optional_override([](uintptr_t /* uint8_t** */ dPtr,
1061 uintptr_t /* size_t* */ sPtr,
1062 int numFonts)->sk_sp<SkFontMgr> {
1063 // See comment above for uintptr_t explanation
1064 auto datas = reinterpret_cast<const uint8_t**>(dPtr);
1065 auto sizes = reinterpret_cast<const size_t*>(sPtr);
1066
1067 return SkFontMgr_New_Custom_Data(datas, sizes, numFonts);
1068 }), allow_raw_pointers())
Kevin Lubickddd0a332018-12-12 10:35:13 -05001069 .class_function("RefDefault", &SkFontMgr::RefDefault)
1070#ifdef SK_DEBUG
1071 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
1072 int numFam = self.countFamilies();
Kevin Lubick61887c72019-09-26 13:20:50 -04001073 SkDebugf("There are %d font families\n", numFam);
Kevin Lubickddd0a332018-12-12 10:35:13 -05001074 for (int i = 0 ; i< numFam; i++) {
1075 SkString s;
1076 self.getFamilyName(i, &s);
Kevin Lubick61887c72019-09-26 13:20:50 -04001077 SkDebugf("\t%s\n", s.c_str());
Kevin Lubickddd0a332018-12-12 10:35:13 -05001078 }
1079 }))
1080#endif
1081 .function("countFamilies", &SkFontMgr::countFamilies)
1082 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
1083 uintptr_t /* uint8_t* */ fPtr,
1084 int flen)->sk_sp<SkTypeface> {
1085 // See comment above for uintptr_t explanation
1086 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
1087 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
1088
1089 return self.makeFromData(fontData);
1090 }), allow_raw_pointers());
Kevin Lubick61887c72019-09-26 13:20:50 -04001091#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001092
Kevin Lubick217056c2018-09-20 17:39:31 -04001093 class_<SkImage>("SkImage")
1094 .smart_ptr<sk_sp<SkImage>>("sk_sp<SkImage>")
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001095 .function("height", &SkImage::height)
1096 .function("width", &SkImage::width)
Alexander Khovansky3e119332018-11-15 02:01:19 +03001097 .function("_encodeToData", select_overload<sk_sp<SkData>()const>(&SkImage::encodeToData))
Kevin Lubicka064c282019-04-04 09:28:53 -04001098 .function("_encodeToDataWithFormat", select_overload<sk_sp<SkData>(SkEncodedImageFormat encodedImageFormat, int quality)const>(&SkImage::encodeToData))
1099 // Allow localMatrix to be optional, so we have 2 declarations of these shaders
1100 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1101 SkTileMode tx, SkTileMode ty)->sk_sp<SkShader> {
1102 return self->makeShader(tx, ty, nullptr);
1103 }), allow_raw_pointers())
1104 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1105 SkTileMode tx, SkTileMode ty,
1106 const SimpleMatrix& lm)->sk_sp<SkShader> {
1107 SkMatrix localMatrix = toSkMatrix(lm);
1108
1109 return self->makeShader(tx, ty, &localMatrix);
Kevin Lubickd6b32ed2019-05-06 13:04:03 -04001110 }), allow_raw_pointers())
1111 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1112 SimpleImageInfo sii, uintptr_t /* uint8_t* */ pPtr,
1113 size_t dstRowBytes, int srcX, int srcY)->bool {
1114 // See comment above for uintptr_t explanation
1115 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1116 SkImageInfo ii = toSkImageInfo(sii);
1117
1118 return self->readPixels(ii, pixels, dstRowBytes, srcX, srcY);
Kevin Lubicka064c282019-04-04 09:28:53 -04001119 }), allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -04001120
Kevin Lubick15b40232019-10-29 09:55:39 -04001121 class_<SkImageFilter>("SkImageFilter")
1122 .smart_ptr<sk_sp<SkImageFilter>>("sk_sp<SkImageFilter>")
1123 .class_function("MakeBlur", optional_override([](SkScalar sigmaX, SkScalar sigmaY,
1124 SkTileMode tileMode, sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1125 // Emscripten does not like default args nor SkIRect* much
1126 return SkImageFilters::Blur(sigmaX, sigmaY, tileMode, input);
1127 }))
1128 .class_function("MakeColorFilter", optional_override([](sk_sp<SkColorFilter> cf,
1129 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1130 // Emscripten does not like default args nor SkIRect* much
1131 return SkImageFilters::ColorFilter(cf, input);
1132 }))
1133 .class_function("MakeCompose", &SkImageFilters::Compose);
1134
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001135 class_<SkMaskFilter>("SkMaskFilter")
Kevin Lubick15b40232019-10-29 09:55:39 -04001136 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<SkMaskFilter>")
1137 .class_function("MakeBlur", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
1138 // Adds a little helper because emscripten doesn't expose default params.
1139 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
1140 }), allow_raw_pointers());
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001141
Kevin Lubick217056c2018-09-20 17:39:31 -04001142 class_<SkPaint>("SkPaint")
1143 .constructor<>()
1144 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
1145 SkPaint p(self);
1146 return p;
1147 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001148 .function("getBlendMode", &SkPaint::getBlendMode)
Kevin Lubickee91c072019-03-29 10:39:52 -04001149 .function("getColor", &SkPaint::getColor)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001150 .function("getFilterQuality", &SkPaint::getFilterQuality)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001151 .function("getStrokeCap", &SkPaint::getStrokeCap)
1152 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001153 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
1154 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
Kevin Lubick217056c2018-09-20 17:39:31 -04001155 .function("setAntiAlias", &SkPaint::setAntiAlias)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001156 .function("setBlendMode", &SkPaint::setBlendMode)
Mike Reeddc2b98f2019-05-20 11:47:49 -04001157 .function("setColor", optional_override([](SkPaint& self, SkColor c) {
1158 self.setColor(c);
1159 }))
1160 .function("setColorf", optional_override([](SkPaint& self,
1161 float r, float g, float b, float a) {
1162 self.setColor({r, g, b, a});
1163 }))
Kevin Lubickd3729342019-09-12 11:11:25 -04001164 .function("setColorFilter", &SkPaint::setColorFilter)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001165 .function("setFilterQuality", &SkPaint::setFilterQuality)
Kevin Lubick15b40232019-10-29 09:55:39 -04001166 .function("setImageFilter", &SkPaint::setImageFilter)
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001167 .function("setMaskFilter", &SkPaint::setMaskFilter)
Kevin Lubick217056c2018-09-20 17:39:31 -04001168 .function("setPathEffect", &SkPaint::setPathEffect)
1169 .function("setShader", &SkPaint::setShader)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001170 .function("setStrokeCap", &SkPaint::setStrokeCap)
1171 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001172 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
1173 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
Kevin Lubickec4903d2019-01-14 08:36:08 -05001174 .function("setStyle", &SkPaint::setStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001175
1176 class_<SkPathEffect>("SkPathEffect")
1177 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>");
1178
Kevin Lubick217056c2018-09-20 17:39:31 -04001179 class_<SkPath>("SkPath")
1180 .constructor<>()
1181 .constructor<const SkPath&>()
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001182 .function("_addArc", &ApplyAddArc)
Kevin Lubick217056c2018-09-20 17:39:31 -04001183 // interface.js has 3 overloads of addPath
Kevin Lubicke384df42019-08-26 15:48:09 -04001184 .function("_addOval", &ApplyAddOval)
Kevin Lubick217056c2018-09-20 17:39:31 -04001185 .function("_addPath", &ApplyAddPath)
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001186 .function("_addPoly", optional_override([](SkPath& self,
1187 uintptr_t /* SkPoint* */ pptr,
1188 int count, bool close)->void {
1189 // See comment above for uintptr_t explanation
1190 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
1191 self.addPoly(pts, count, close);
1192 }))
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001193 // interface.js has 4 overloads of addRect
1194 .function("_addRect", &ApplyAddRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001195 // interface.js has 4 overloads of addRoundRect
1196 .function("_addRoundRect", &ApplyAddRoundRect)
Kevin Lubick217056c2018-09-20 17:39:31 -04001197 .function("_arcTo", &ApplyArcTo)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001198 .function("_arcTo", &ApplyArcToAngle)
Kevin Lubick79b71342019-11-01 14:36:52 -04001199 .function("_arcTo", &ApplyArcToArcSize)
Kevin Lubick217056c2018-09-20 17:39:31 -04001200 .function("_close", &ApplyClose)
1201 .function("_conicTo", &ApplyConicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001202 .function("countPoints", &SkPath::countPoints)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001203 .function("contains", &SkPath::contains)
Kevin Lubick217056c2018-09-20 17:39:31 -04001204 .function("_cubicTo", &ApplyCubicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001205 .function("getPoint", &SkPath::getPoint)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001206 .function("isEmpty", &SkPath::isEmpty)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001207 .function("isVolatile", &SkPath::isVolatile)
Kevin Lubick217056c2018-09-20 17:39:31 -04001208 .function("_lineTo", &ApplyLineTo)
1209 .function("_moveTo", &ApplyMoveTo)
Kevin Lubick79b71342019-11-01 14:36:52 -04001210 .function("_quadTo", &ApplyQuadTo)
1211 .function("_rArcTo", &ApplyRArcToArcSize)
1212 .function("_rConicTo", &ApplyRConicTo)
1213 .function("_rCubicTo", &ApplyRCubicTo)
1214 .function("_rLineTo", &ApplyRLineTo)
1215 .function("_rMoveTo", &ApplyRMoveTo)
1216 .function("_rQuadTo", &ApplyRQuadTo)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001217 .function("reset", &ApplyReset)
1218 .function("rewind", &ApplyRewind)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001219 .function("setIsVolatile", &SkPath::setIsVolatile)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001220 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
Kevin Lubick217056c2018-09-20 17:39:31 -04001221
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001222 // PathEffects
1223 .function("_dash", &ApplyDash)
1224 .function("_trim", &ApplyTrim)
1225 .function("_stroke", &ApplyStroke)
1226
1227 // PathOps
1228 .function("_simplify", &ApplySimplify)
1229 .function("_op", &ApplyPathOp)
1230
1231 // Exporting
1232 .function("toSVGString", &ToSVGString)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001233 .function("toCmds", &ToCmds)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001234
Kevin Lubick217056c2018-09-20 17:39:31 -04001235 .function("setFillType", &SkPath::setFillType)
1236 .function("getFillType", &SkPath::getFillType)
1237 .function("getBounds", &SkPath::getBounds)
1238 .function("computeTightBounds", &SkPath::computeTightBounds)
1239 .function("equals", &Equals)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001240 .function("copy", &CopyPath)
1241#ifdef SK_DEBUG
1242 .function("dump", select_overload<void() const>(&SkPath::dump))
1243 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
1244#endif
1245 ;
Kevin Lubick217056c2018-09-20 17:39:31 -04001246
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001247 class_<SkPathMeasure>("SkPathMeasure")
1248 .constructor<const SkPath&, bool, SkScalar>()
1249 .function("getLength", &SkPathMeasure::getLength)
1250 .function("getPosTan", optional_override([](SkPathMeasure& self,
1251 SkScalar distance) -> PosTan {
1252 SkPoint p{0, 0};
1253 SkVector v{0, 0};
1254 if (!self.getPosTan(distance, &p, &v)) {
1255 SkDebugf("zero-length path in getPosTan\n");
1256 }
1257 return PosTan{p.x(), p.y(), v.x(), v.y()};
1258 }))
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001259 .function("getSegment", optional_override([](SkPathMeasure& self, SkScalar startD,
1260 SkScalar stopD, bool startWithMoveTo) -> SkPath {
1261 SkPath p;
1262 bool ok = self.getSegment(startD, stopD, &p, startWithMoveTo);
1263 if (ok) {
1264 return p;
1265 }
1266 return SkPath();
1267 }))
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001268 .function("isClosed", &SkPathMeasure::isClosed)
1269 .function("nextContour", &SkPathMeasure::nextContour);
1270
Kevin Lubickcc13fd32019-04-05 13:00:01 -04001271 class_<SkPictureRecorder>("SkPictureRecorder")
1272 .constructor<>()
1273 .function("beginRecording", optional_override([](SkPictureRecorder& self,
1274 const SkRect& bounds) -> SkCanvas* {
1275 return self.beginRecording(bounds, nullptr, 0);
1276 }), allow_raw_pointers())
1277 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
1278 -> sk_sp<SkPicture> {
1279 return self.finishRecordingAsPicture(0);
1280 }), allow_raw_pointers());
1281
1282 class_<SkPicture>("SkPicture")
1283 .smart_ptr<sk_sp<SkPicture>>("sk_sp<SkPicture>")
1284 // The serialized format of an SkPicture (informally called an "skp"), is not something
1285 // that clients should ever rely on. It is useful when filing bug reports, but that's
1286 // about it. The format may change at anytime and no promises are made for backwards
1287 // or forward compatibility.
1288 .function("DEBUGONLY_serialize", optional_override([](SkPicture& self) -> sk_sp<SkData> {
1289 // Emscripten doesn't play well with optional arguments, which we don't
1290 // want to expose anyway.
1291 return self.serialize();
1292 }), allow_raw_pointers());
1293
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001294 class_<SkShader>("SkShader")
1295 .smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>");
1296
Kevin Lubick217056c2018-09-20 17:39:31 -04001297 class_<SkSurface>("SkSurface")
1298 .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
Greg Danielbae71212019-03-01 15:24:35 -05001299 .function("_flush", select_overload<void()>(&SkSurface::flush))
Kevin Lubick543f3522019-03-08 10:04:28 -05001300 .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
1301 .function("height", &SkSurface::height)
Mike Reed114bde82018-11-21 09:12:09 -05001302 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
1303 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
Kevin Lubick543f3522019-03-08 10:04:28 -05001304 .function("makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1305 return self.makeSurface(toSkImageInfo(sii));
1306 }), allow_raw_pointers())
1307 .function("width", &SkSurface::width);
Kevin Lubick217056c2018-09-20 17:39:31 -04001308
Kevin Lubick61887c72019-09-26 13:20:50 -04001309#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -05001310 class_<SkTextBlob>("SkTextBlob")
1311 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<SkTextBlob>>")
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001312 .class_function("_MakeFromRSXform", optional_override([](uintptr_t /* char* */ sptr,
1313 size_t strBtyes,
1314 uintptr_t /* SkRSXform* */ xptr,
1315 const SkFont& font,
1316 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
1317 // See comment above for uintptr_t explanation
1318 const char* str = reinterpret_cast<const char*>(sptr);
1319 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
1320
1321 return SkTextBlob::MakeFromRSXform(str, strBtyes, xforms, font, encoding);
1322 }), allow_raw_pointers())
Kevin Lubick543f3522019-03-08 10:04:28 -05001323 .class_function("_MakeFromText", optional_override([](uintptr_t /* char* */ sptr,
1324 size_t len, const SkFont& font,
1325 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
Kevin Lubickec4903d2019-01-14 08:36:08 -05001326 // See comment above for uintptr_t explanation
1327 const char* str = reinterpret_cast<const char*>(sptr);
1328 return SkTextBlob::MakeFromText(str, len, font, encoding);
1329 }), allow_raw_pointers());
1330
Kevin Lubickddd0a332018-12-12 10:35:13 -05001331 class_<SkTypeface>("SkTypeface")
1332 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<SkTypeface>");
Kevin Lubick61887c72019-09-26 13:20:50 -04001333#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001334
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001335 class_<SkVertices>("SkVertices")
1336 .smart_ptr<sk_sp<SkVertices>>("sk_sp<SkVertices>")
1337 .function("_applyBones", optional_override([](SkVertices& self, uintptr_t /* Bone* */ bptr, int boneCount)->sk_sp<SkVertices> {
1338 // See comment above for uintptr_t explanation
1339 const Bone* bones = reinterpret_cast<const Bone*>(bptr);
1340 return self.applyBones(bones, boneCount);
1341 }))
1342 .function("bounds", &SkVertices::bounds)
1343 .function("mode", &SkVertices::mode)
1344 .function("uniqueID", &SkVertices::uniqueID)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001345#ifdef SK_DEBUG
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001346 .function("dumpPositions", optional_override([](SkVertices& self)->void {
1347 auto pos = self.positions();
1348 for(int i = 0; i< self.vertexCount(); i++) {
1349 SkDebugf("position[%d] = (%f, %f)\n", i, pos[i].x(), pos[i].y());
1350 }
1351 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001352#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001353 .function("vertexCount", &SkVertices::vertexCount);
1354
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001355 // Not intended to be called directly by clients
1356 class_<SkVertices::Builder>("_SkVerticesBuilder")
1357 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
1358 .function("boneIndices", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneIndices* */{
1359 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1360 return reinterpret_cast<uintptr_t>(self.boneIndices());
1361 }))
1362 .function("boneWeights", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneWeights* */{
1363 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1364 return reinterpret_cast<uintptr_t>(self.boneWeights());
1365 }))
1366 .function("colors", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkColor* */{
1367 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1368 return reinterpret_cast<uintptr_t>(self.colors());
1369 }))
1370 .function("detach", &SkVertices::Builder::detach)
1371 .function("indices", optional_override([](SkVertices::Builder& self)->uintptr_t /* uint16_t* */{
1372 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1373 return reinterpret_cast<uintptr_t>(self.indices());
1374 }))
1375 .function("positions", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1376 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1377 return reinterpret_cast<uintptr_t>(self.positions());
1378 }))
1379 .function("texCoords", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1380 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1381 return reinterpret_cast<uintptr_t>(self.texCoords());
1382 }));
1383
Kevin Lubickea905ec2018-11-30 14:05:58 -05001384 enum_<SkAlphaType>("AlphaType")
1385 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
1386 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
1387 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001388
1389 enum_<SkBlendMode>("BlendMode")
1390 .value("Clear", SkBlendMode::kClear)
1391 .value("Src", SkBlendMode::kSrc)
1392 .value("Dst", SkBlendMode::kDst)
1393 .value("SrcOver", SkBlendMode::kSrcOver)
1394 .value("DstOver", SkBlendMode::kDstOver)
1395 .value("SrcIn", SkBlendMode::kSrcIn)
1396 .value("DstIn", SkBlendMode::kDstIn)
1397 .value("SrcOut", SkBlendMode::kSrcOut)
1398 .value("DstOut", SkBlendMode::kDstOut)
1399 .value("SrcATop", SkBlendMode::kSrcATop)
1400 .value("DstATop", SkBlendMode::kDstATop)
1401 .value("Xor", SkBlendMode::kXor)
1402 .value("Plus", SkBlendMode::kPlus)
1403 .value("Modulate", SkBlendMode::kModulate)
1404 .value("Screen", SkBlendMode::kScreen)
1405 .value("Overlay", SkBlendMode::kOverlay)
1406 .value("Darken", SkBlendMode::kDarken)
1407 .value("Lighten", SkBlendMode::kLighten)
1408 .value("ColorDodge", SkBlendMode::kColorDodge)
1409 .value("ColorBurn", SkBlendMode::kColorBurn)
1410 .value("HardLight", SkBlendMode::kHardLight)
1411 .value("SoftLight", SkBlendMode::kSoftLight)
1412 .value("Difference", SkBlendMode::kDifference)
1413 .value("Exclusion", SkBlendMode::kExclusion)
1414 .value("Multiply", SkBlendMode::kMultiply)
1415 .value("Hue", SkBlendMode::kHue)
1416 .value("Saturation", SkBlendMode::kSaturation)
1417 .value("Color", SkBlendMode::kColor)
1418 .value("Luminosity", SkBlendMode::kLuminosity);
Kevin Lubick217056c2018-09-20 17:39:31 -04001419
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001420 enum_<SkBlurStyle>("BlurStyle")
1421 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
1422 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
1423 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
1424 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001425
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001426 enum_<SkClipOp>("ClipOp")
1427 .value("Difference", SkClipOp::kDifference)
1428 .value("Intersect", SkClipOp::kIntersect);
1429
Kevin Lubickea905ec2018-11-30 14:05:58 -05001430 enum_<SkColorType>("ColorType")
1431 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
1432 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
1433 .value("ARGB_4444", SkColorType::kARGB_4444_SkColorType)
1434 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
1435 .value("RGB_888x", SkColorType::kRGB_888x_SkColorType)
1436 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
1437 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
1438 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
1439 .value("Gray_8", SkColorType::kGray_8_SkColorType)
1440 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
Robert Phillipsd470e1b2019-09-04 15:05:35 -04001441 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType)
Robert Phillipsea1b30b2019-09-19 16:05:48 -04001442 .value("R8G8_unorm", SkColorType::kR8G8_unorm_SkColorType)
1443 .value("A16_unorm", SkColorType::kA16_unorm_SkColorType)
1444 .value("R16G16_unorm", SkColorType::kR16G16_unorm_SkColorType)
1445 .value("A16_float", SkColorType::kA16_float_SkColorType)
1446 .value("R16G16_float", SkColorType::kR16G16_float_SkColorType)
1447 .value("R16G16B16A16_unorm", SkColorType::kR16G16B16A16_unorm_SkColorType);
Kevin Lubickea905ec2018-11-30 14:05:58 -05001448
Kevin Lubick217056c2018-09-20 17:39:31 -04001449 enum_<SkPath::FillType>("FillType")
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001450 .value("Winding", SkPath::FillType::kWinding_FillType)
1451 .value("EvenOdd", SkPath::FillType::kEvenOdd_FillType)
1452 .value("InverseWinding", SkPath::FillType::kInverseWinding_FillType)
1453 .value("InverseEvenOdd", SkPath::FillType::kInverseEvenOdd_FillType);
1454
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001455 enum_<SkFilterQuality>("FilterQuality")
1456 .value("None", SkFilterQuality::kNone_SkFilterQuality)
1457 .value("Low", SkFilterQuality::kLow_SkFilterQuality)
1458 .value("Medium", SkFilterQuality::kMedium_SkFilterQuality)
1459 .value("High", SkFilterQuality::kHigh_SkFilterQuality);
1460
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001461 enum_<SkEncodedImageFormat>("ImageFormat")
1462 .value("PNG", SkEncodedImageFormat::kPNG)
1463 .value("JPEG", SkEncodedImageFormat::kJPEG);
1464
1465 enum_<SkPaint::Style>("PaintStyle")
1466 .value("Fill", SkPaint::Style::kFill_Style)
1467 .value("Stroke", SkPaint::Style::kStroke_Style)
1468 .value("StrokeAndFill", SkPaint::Style::kStrokeAndFill_Style);
1469
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001470 enum_<SkPathOp>("PathOp")
1471 .value("Difference", SkPathOp::kDifference_SkPathOp)
1472 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
1473 .value("Union", SkPathOp::kUnion_SkPathOp)
1474 .value("XOR", SkPathOp::kXOR_SkPathOp)
1475 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
1476
Kevin Lubick37ab53e2019-11-11 10:06:08 -05001477 enum_<SkCanvas::PointMode>("PointMode")
1478 .value("Points", SkCanvas::PointMode::kPoints_PointMode)
1479 .value("Lines", SkCanvas::PointMode::kLines_PointMode)
1480 .value("Polygon", SkCanvas::PointMode::kPolygon_PointMode);
1481
Kevin Lubickb9db3902018-11-26 11:47:54 -05001482 enum_<SkPaint::Cap>("StrokeCap")
1483 .value("Butt", SkPaint::Cap::kButt_Cap)
1484 .value("Round", SkPaint::Cap::kRound_Cap)
1485 .value("Square", SkPaint::Cap::kSquare_Cap);
1486
1487 enum_<SkPaint::Join>("StrokeJoin")
1488 .value("Miter", SkPaint::Join::kMiter_Join)
1489 .value("Round", SkPaint::Join::kRound_Join)
1490 .value("Bevel", SkPaint::Join::kBevel_Join);
1491
Kevin Lubickec4903d2019-01-14 08:36:08 -05001492 enum_<SkTextEncoding>("TextEncoding")
1493 .value("UTF8", SkTextEncoding::kUTF8)
1494 .value("UTF16", SkTextEncoding::kUTF16)
1495 .value("UTF32", SkTextEncoding::kUTF32)
1496 .value("GlyphID", SkTextEncoding::kGlyphID);
Kevin Lubickb9db3902018-11-26 11:47:54 -05001497
Mike Reed5c5de212019-04-03 16:51:47 -04001498 enum_<SkTileMode>("TileMode")
1499 .value("Clamp", SkTileMode::kClamp)
1500 .value("Repeat", SkTileMode::kRepeat)
1501 .value("Mirror", SkTileMode::kMirror)
Mike Reed5c5de212019-04-03 16:51:47 -04001502 .value("Decal", SkTileMode::kDecal);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001503
1504 enum_<SkVertices::VertexMode>("VertexMode")
1505 .value("Triangles", SkVertices::VertexMode::kTriangles_VertexMode)
1506 .value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001507 .value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001508
Kevin Lubick217056c2018-09-20 17:39:31 -04001509
1510 // A value object is much simpler than a class - it is returned as a JS
1511 // object and does not require delete().
1512 // https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001513 value_object<ShapedTextOpts>("ShapedTextOpts")
1514 .field("font", &ShapedTextOpts::font)
1515 .field("leftToRight", &ShapedTextOpts::leftToRight)
1516 .field("text", &ShapedTextOpts::text)
1517 .field("width", &ShapedTextOpts::width);
1518
Kevin Lubick217056c2018-09-20 17:39:31 -04001519 value_object<SkRect>("SkRect")
1520 .field("fLeft", &SkRect::fLeft)
1521 .field("fTop", &SkRect::fTop)
1522 .field("fRight", &SkRect::fRight)
1523 .field("fBottom", &SkRect::fBottom);
1524
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001525 value_object<SimpleRRect>("SkRRect")
1526 .field("rect", &SimpleRRect::rect)
Kevin Lubick7d644e12019-09-11 14:22:22 -04001527 .field("rx1", &SimpleRRect::rx1)
1528 .field("ry1", &SimpleRRect::ry1)
1529 .field("rx2", &SimpleRRect::rx2)
1530 .field("ry2", &SimpleRRect::ry2)
1531 .field("rx3", &SimpleRRect::rx3)
1532 .field("ry3", &SimpleRRect::ry3)
1533 .field("rx4", &SimpleRRect::rx4)
1534 .field("ry4", &SimpleRRect::ry4);
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001535
Mike Reed114bde82018-11-21 09:12:09 -05001536 value_object<SkIRect>("SkIRect")
1537 .field("fLeft", &SkIRect::fLeft)
1538 .field("fTop", &SkIRect::fTop)
1539 .field("fRight", &SkIRect::fRight)
1540 .field("fBottom", &SkIRect::fBottom);
1541
Kevin Lubick50f377e2019-09-11 15:23:00 -04001542 value_object<TonalColors>("TonalColors")
1543 .field("ambient", &TonalColors::ambientColor)
1544 .field("spot", &TonalColors::spotColor);
1545
Kevin Lubickea905ec2018-11-30 14:05:58 -05001546 value_object<SimpleImageInfo>("SkImageInfo")
1547 .field("width", &SimpleImageInfo::width)
1548 .field("height", &SimpleImageInfo::height)
1549 .field("colorType", &SimpleImageInfo::colorType)
1550 .field("alphaType", &SimpleImageInfo::alphaType);
1551
Kevin Lubick217056c2018-09-20 17:39:31 -04001552 // SkPoints can be represented by [x, y]
1553 value_array<SkPoint>("SkPoint")
1554 .element(&SkPoint::fX)
1555 .element(&SkPoint::fY);
1556
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001557 // SkPoint3s can be represented by [x, y, z]
1558 value_array<SkPoint3>("SkPoint3")
1559 .element(&SkPoint3::fX)
1560 .element(&SkPoint3::fY)
1561 .element(&SkPoint3::fZ);
1562
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001563 // PosTan can be represented by [px, py, tx, ty]
1564 value_array<PosTan>("PosTan")
1565 .element(&PosTan::px)
1566 .element(&PosTan::py)
1567 .element(&PosTan::tx)
1568 .element(&PosTan::ty);
1569
Kevin Lubick217056c2018-09-20 17:39:31 -04001570 // {"w": Number, "h", Number}
1571 value_object<SkSize>("SkSize")
1572 .field("w", &SkSize::fWidth)
1573 .field("h", &SkSize::fHeight);
1574
1575 value_object<SkISize>("SkISize")
1576 .field("w", &SkISize::fWidth)
1577 .field("h", &SkISize::fHeight);
1578
Kevin Lubickec4903d2019-01-14 08:36:08 -05001579 value_object<StrokeOpts>("StrokeOpts")
1580 .field("width", &StrokeOpts::width)
1581 .field("miter_limit", &StrokeOpts::miter_limit)
1582 .field("join", &StrokeOpts::join)
1583 .field("cap", &StrokeOpts::cap)
1584 .field("precision", &StrokeOpts::precision);
1585
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001586 // Allows clients to supply a 1D array of 9 elements and the bindings
1587 // will automatically turn it into a 3x3 2D matrix.
1588 // e.g. path.transform([0,1,2,3,4,5,6,7,8])
1589 // This is likely simpler for the client than exposing SkMatrix
1590 // directly and requiring them to do a lot of .delete().
1591 value_array<SimpleMatrix>("SkMatrix")
1592 .element(&SimpleMatrix::scaleX)
1593 .element(&SimpleMatrix::skewX)
1594 .element(&SimpleMatrix::transX)
1595
1596 .element(&SimpleMatrix::skewY)
1597 .element(&SimpleMatrix::scaleY)
1598 .element(&SimpleMatrix::transY)
1599
1600 .element(&SimpleMatrix::pers0)
1601 .element(&SimpleMatrix::pers1)
1602 .element(&SimpleMatrix::pers2);
1603
Kevin Lubickee91c072019-03-29 10:39:52 -04001604 constant("TRANSPARENT", SK_ColorTRANSPARENT);
1605 constant("RED", SK_ColorRED);
1606 constant("BLUE", SK_ColorBLUE);
1607 constant("YELLOW", SK_ColorYELLOW);
1608 constant("CYAN", SK_ColorCYAN);
1609 constant("BLACK", SK_ColorBLACK);
1610 constant("WHITE", SK_ColorWHITE);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001611 // TODO(?)
1612
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001613 constant("MOVE_VERB", MOVE);
1614 constant("LINE_VERB", LINE);
1615 constant("QUAD_VERB", QUAD);
1616 constant("CONIC_VERB", CONIC);
1617 constant("CUBIC_VERB", CUBIC);
1618 constant("CLOSE_VERB", CLOSE);
Kevin Lubick77d9b5c2019-10-29 10:48:26 -04001619
1620 constant("SaveLayerInitWithPrevious", SkCanvas::SaveLayerFlagsSet::kInitWithPrevious_SaveLayerFlag);
1621 constant("SaveLayerF16ColorType", SkCanvas::SaveLayerFlagsSet::kF16ColorType);
1622
Kevin Lubick217056c2018-09-20 17:39:31 -04001623}