blob: 4705200ecee5f7bbcf01c6f930bc61f303c07f0d [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBlendMode.h"
9#include "include/core/SkBlurTypes.h"
10#include "include/core/SkCanvas.h"
11#include "include/core/SkColor.h"
12#include "include/core/SkData.h"
13#include "include/core/SkEncodedImageFormat.h"
14#include "include/core/SkFilterQuality.h"
15#include "include/core/SkFont.h"
16#include "include/core/SkFontMgr.h"
17#include "include/core/SkFontTypes.h"
18#include "include/core/SkImage.h"
19#include "include/core/SkImageInfo.h"
20#include "include/core/SkMaskFilter.h"
21#include "include/core/SkPaint.h"
22#include "include/core/SkPath.h"
23#include "include/core/SkPathEffect.h"
24#include "include/core/SkPathMeasure.h"
25#include "include/core/SkPicture.h"
26#include "include/core/SkPictureRecorder.h"
Kevin Lubick2e5fe352019-09-03 12:59:06 -040027#include "include/core/SkRRect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "include/core/SkScalar.h"
29#include "include/core/SkShader.h"
30#include "include/core/SkString.h"
31#include "include/core/SkStrokeRec.h"
32#include "include/core/SkSurface.h"
33#include "include/core/SkSurfaceProps.h"
34#include "include/core/SkTextBlob.h"
35#include "include/core/SkTypeface.h"
36#include "include/core/SkTypes.h"
37#include "include/core/SkVertices.h"
38#include "include/effects/SkCornerPathEffect.h"
39#include "include/effects/SkDashPathEffect.h"
40#include "include/effects/SkDiscretePathEffect.h"
41#include "include/effects/SkGradientShader.h"
42#include "include/effects/SkTrimPathEffect.h"
43#include "include/pathops/SkPathOps.h"
44#include "include/utils/SkParsePath.h"
45#include "include/utils/SkShadowUtils.h"
46#include "modules/skshaper/include/SkShaper.h"
47#include "src/core/SkFontMgrPriv.h"
48#include "src/core/SkMakeUnique.h"
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040049
Kevin Lubick217056c2018-09-20 17:39:31 -040050#include <iostream>
51#include <string>
Kevin Lubick217056c2018-09-20 17:39:31 -040052
Mike Kleinc0bd9f92019-04-23 12:05:21 -050053#include "modules/canvaskit/WasmAliases.h"
Kevin Lubick217056c2018-09-20 17:39:31 -040054#include <emscripten.h>
55#include <emscripten/bind.h>
Kevin Lubick46839422019-01-03 14:27:27 -050056
Kevin Lubick53965c92018-10-11 08:51:55 -040057#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -050058#include "include/gpu/GrBackendSurface.h"
59#include "include/gpu/GrContext.h"
60#include "include/gpu/gl/GrGLInterface.h"
61#include "include/gpu/gl/GrGLTypes.h"
Kevin Lubick3f67f412019-03-11 16:11:58 -040062
Kevin Lubick53965c92018-10-11 08:51:55 -040063#include <GL/gl.h>
Kevin Lubick217056c2018-09-20 17:39:31 -040064#include <emscripten/html5.h>
Kevin Lubick53965c92018-10-11 08:51:55 -040065#endif
Kevin Lubick217056c2018-09-20 17:39:31 -040066
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040067// Aliases for less typing
68using BoneIndices = SkVertices::BoneIndices;
69using BoneWeights = SkVertices::BoneWeights;
70using Bone = SkVertices::Bone;
Kevin Lubick217056c2018-09-20 17:39:31 -040071
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040072struct SimpleMatrix {
73 SkScalar scaleX, skewX, transX;
74 SkScalar skewY, scaleY, transY;
75 SkScalar pers0, pers1, pers2;
76};
77
78SkMatrix toSkMatrix(const SimpleMatrix& sm) {
79 return SkMatrix::MakeAll(sm.scaleX, sm.skewX , sm.transX,
80 sm.skewY , sm.scaleY, sm.transY,
81 sm.pers0 , sm.pers1 , sm.pers2);
Kevin Lubick217056c2018-09-20 17:39:31 -040082}
83
Kevin Lubick5d5723c2018-12-07 10:09:11 -050084SimpleMatrix toSimpleSkMatrix(const SkMatrix& sm) {
85 SimpleMatrix m {sm[0], sm[1], sm[2],
86 sm[3], sm[4], sm[5],
87 sm[6], sm[7], sm[8]};
88 return m;
89}
90
Kevin Lubickea905ec2018-11-30 14:05:58 -050091struct SimpleImageInfo {
92 int width;
93 int height;
94 SkColorType colorType;
95 SkAlphaType alphaType;
96 // TODO color spaces?
97};
98
99SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
100 return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
101}
102
Kevin Lubick543f3522019-03-08 10:04:28 -0500103#if SK_SUPPORT_GPU
104sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
105{
106 EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
107 if (r < 0) {
108 printf("failed to make webgl context current %d\n", r);
109 return nullptr;
110 }
111 // setup GrContext
112 auto interface = GrGLMakeNativeInterface();
113 // setup contexts
114 sk_sp<GrContext> grContext(GrContext::MakeGL(interface));
115 return grContext;
116}
117
118sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height) {
119 glClearColor(0, 0, 0, 0);
120 glClearStencil(0);
121 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
122
123
124 // Wrap the frame buffer object attached to the screen in a Skia render
125 // target so Skia can render to it
126 GrGLint buffer;
127 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
128 GrGLFramebufferInfo info;
129 info.fFBOID = (GrGLuint) buffer;
130 SkColorType colorType;
131
132 info.fFormat = GL_RGBA8;
133 colorType = kRGBA_8888_SkColorType;
134
135 GrBackendRenderTarget target(width, height, 0, 8, info);
136
137 sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
138 kBottomLeft_GrSurfaceOrigin,
139 colorType, nullptr, nullptr));
140 return surface;
141}
142
143sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, int width, int height) {
144 SkImageInfo info = SkImageInfo::MakeN32(width, height, SkAlphaType::kPremul_SkAlphaType);
145
146 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
147 SkBudgeted::kYes,
148 info, 0,
149 kBottomLeft_GrSurfaceOrigin,
150 nullptr, true));
151 return surface;
152}
153
154sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, SimpleImageInfo sii) {
155 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
156 SkBudgeted::kYes,
157 toSkImageInfo(sii), 0,
158 kBottomLeft_GrSurfaceOrigin,
159 nullptr, true));
160 return surface;
161}
162#endif
163
164
Kevin Lubick217056c2018-09-20 17:39:31 -0400165//========================================================================================
166// Path things
167//========================================================================================
168
169// All these Apply* methods are simple wrappers to avoid returning an object.
170// The default WASM bindings produce code that will leak if a return value
171// isn't assigned to a JS variable and has delete() called on it.
172// These Apply methods, combined with the smarter binding code allow for chainable
173// commands that don't leak if the return value is ignored (i.e. when used intuitively).
174
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500175void ApplyAddArc(SkPath& orig, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
176 orig.addArc(oval, startAngle, sweepAngle);
177}
178
Kevin Lubicke384df42019-08-26 15:48:09 -0400179void ApplyAddOval(SkPath& orig, const SkRect& oval, bool ccw, unsigned start) {
180 orig.addOval(oval, ccw ? SkPath::Direction::kCCW_Direction :
181 SkPath::Direction::kCW_Direction, start);
182}
183
Kevin Lubick217056c2018-09-20 17:39:31 -0400184void ApplyAddPath(SkPath& orig, const SkPath& newPath,
185 SkScalar scaleX, SkScalar skewX, SkScalar transX,
186 SkScalar skewY, SkScalar scaleY, SkScalar transY,
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500187 SkScalar pers0, SkScalar pers1, SkScalar pers2,
188 bool extendPath) {
Kevin Lubick217056c2018-09-20 17:39:31 -0400189 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
190 skewY , scaleY, transY,
191 pers0 , pers1 , pers2);
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500192 orig.addPath(newPath, m, extendPath ? SkPath::kExtend_AddPathMode :
193 SkPath::kAppend_AddPathMode);
Kevin Lubick217056c2018-09-20 17:39:31 -0400194}
195
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500196void ApplyAddRect(SkPath& path, SkScalar left, SkScalar top,
197 SkScalar right, SkScalar bottom, bool ccw) {
198 path.addRect(left, top, right, bottom,
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500199 ccw ? SkPath::Direction::kCCW_Direction :
200 SkPath::Direction::kCW_Direction);
Alexander Khovansky3e119332018-11-15 02:01:19 +0300201}
202
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500203void ApplyAddRoundRect(SkPath& path, SkScalar left, SkScalar top,
204 SkScalar right, SkScalar bottom, uintptr_t /* SkScalar* */ rPtr,
205 bool ccw) {
206 // See comment below for uintptr_t explanation
207 const SkScalar* radii = reinterpret_cast<const SkScalar*>(rPtr);
208 path.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radii,
209 ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction);
210}
211
212
Kevin Lubick217056c2018-09-20 17:39:31 -0400213void ApplyArcTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
214 SkScalar radius) {
215 p.arcTo(x1, y1, x2, y2, radius);
216}
217
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500218void ApplyArcToAngle(SkPath& p, SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) {
219 p.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
220}
221
Kevin Lubicke384df42019-08-26 15:48:09 -0400222void ApplyAddArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
223 bool useSmallArc, bool ccw, SkScalar x, SkScalar y) {
224 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
225 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
226 orig.arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y);
227}
228
Kevin Lubick217056c2018-09-20 17:39:31 -0400229void ApplyClose(SkPath& p) {
230 p.close();
231}
232
233void ApplyConicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
234 SkScalar w) {
235 p.conicTo(x1, y1, x2, y2, w);
236}
237
238void ApplyCubicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
239 SkScalar x3, SkScalar y3) {
240 p.cubicTo(x1, y1, x2, y2, x3, y3);
241}
242
243void ApplyLineTo(SkPath& p, SkScalar x, SkScalar y) {
244 p.lineTo(x, y);
245}
246
247void ApplyMoveTo(SkPath& p, SkScalar x, SkScalar y) {
248 p.moveTo(x, y);
249}
250
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500251void ApplyReset(SkPath& p) {
252 p.reset();
253}
254
255void ApplyRewind(SkPath& p) {
256 p.rewind();
257}
258
Kevin Lubick217056c2018-09-20 17:39:31 -0400259void ApplyQuadTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
260 p.quadTo(x1, y1, x2, y2);
261}
262
263void ApplyTransform(SkPath& orig,
264 SkScalar scaleX, SkScalar skewX, SkScalar transX,
265 SkScalar skewY, SkScalar scaleY, SkScalar transY,
266 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
267 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
268 skewY , scaleY, transY,
269 pers0 , pers1 , pers2);
270 orig.transform(m);
271}
272
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400273bool EMSCRIPTEN_KEEPALIVE ApplySimplify(SkPath& path) {
274 return Simplify(path, &path);
275}
276
277bool EMSCRIPTEN_KEEPALIVE ApplyPathOp(SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
278 return Op(pathOne, pathTwo, op, &pathOne);
279}
280
281JSString EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
282 SkString s;
283 SkParsePath::ToSVGString(path, &s);
284 return emscripten::val(s.c_str());
285}
286
Kevin Lubicka40f8322018-12-17 16:01:36 -0500287SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromSVGString(std::string str) {
288 SkPath path;
289 if (SkParsePath::FromSVGString(str.c_str(), &path)) {
290 return emscripten::val(path);
291 }
292 return emscripten::val::null();
293}
294
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400295SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
296 SkPath out;
297 if (Op(pathOne, pathTwo, op, &out)) {
298 return emscripten::val(out);
299 }
300 return emscripten::val::null();
301}
302
Kevin Lubick217056c2018-09-20 17:39:31 -0400303SkPath EMSCRIPTEN_KEEPALIVE CopyPath(const SkPath& a) {
304 SkPath copy(a);
305 return copy;
306}
307
308bool EMSCRIPTEN_KEEPALIVE Equals(const SkPath& a, const SkPath& b) {
309 return a == b;
310}
311
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500312// =================================================================================
313// Creating/Exporting Paths with cmd arrays
314// =================================================================================
315
316static const int MOVE = 0;
317static const int LINE = 1;
318static const int QUAD = 2;
319static const int CONIC = 3;
320static const int CUBIC = 4;
321static const int CLOSE = 5;
322
323template <typename VisitFunc>
324void VisitPath(const SkPath& p, VisitFunc&& f) {
325 SkPath::RawIter iter(p);
326 SkPoint pts[4];
327 SkPath::Verb verb;
328 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
329 f(verb, pts, iter);
330 }
331}
332
333JSArray EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
334 JSArray cmds = emscripten::val::array();
335
336 VisitPath(path, [&cmds](SkPath::Verb verb, const SkPoint pts[4], SkPath::RawIter iter) {
337 JSArray cmd = emscripten::val::array();
338 switch (verb) {
339 case SkPath::kMove_Verb:
340 cmd.call<void>("push", MOVE, pts[0].x(), pts[0].y());
341 break;
342 case SkPath::kLine_Verb:
343 cmd.call<void>("push", LINE, pts[1].x(), pts[1].y());
344 break;
345 case SkPath::kQuad_Verb:
346 cmd.call<void>("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
347 break;
348 case SkPath::kConic_Verb:
349 cmd.call<void>("push", CONIC,
350 pts[1].x(), pts[1].y(),
351 pts[2].x(), pts[2].y(), iter.conicWeight());
352 break;
353 case SkPath::kCubic_Verb:
354 cmd.call<void>("push", CUBIC,
355 pts[1].x(), pts[1].y(),
356 pts[2].x(), pts[2].y(),
357 pts[3].x(), pts[3].y());
358 break;
359 case SkPath::kClose_Verb:
360 cmd.call<void>("push", CLOSE);
361 break;
362 case SkPath::kDone_Verb:
363 SkASSERT(false);
364 break;
365 }
366 cmds.call<void>("push", cmd);
367 });
368 return cmds;
369}
370
371// This type signature is a mess, but it's necessary. See, we can't use "bind" (EMSCRIPTEN_BINDINGS)
372// and pointers to primitive types (Only bound types like SkPoint). We could if we used
373// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
374// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
375// SkPath or SkOpBuilder.
376//
377// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primative pointers
378// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
379// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
380// the compiler is happy.
381SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromCmds(uintptr_t /* float* */ cptr, int numCmds) {
382 const auto* cmds = reinterpret_cast<const float*>(cptr);
383 SkPath path;
384 float x1, y1, x2, y2, x3, y3;
385
386 // if there are not enough arguments, bail with the path we've constructed so far.
387 #define CHECK_NUM_ARGS(n) \
388 if ((i + n) > numCmds) { \
389 SkDebugf("Not enough args to match the verbs. Saw %d commands\n", numCmds); \
390 return emscripten::val::null(); \
391 }
392
393 for(int i = 0; i < numCmds;){
394 switch (sk_float_floor2int(cmds[i++])) {
395 case MOVE:
396 CHECK_NUM_ARGS(2);
397 x1 = cmds[i++], y1 = cmds[i++];
398 path.moveTo(x1, y1);
399 break;
400 case LINE:
401 CHECK_NUM_ARGS(2);
402 x1 = cmds[i++], y1 = cmds[i++];
403 path.lineTo(x1, y1);
404 break;
405 case QUAD:
406 CHECK_NUM_ARGS(4);
407 x1 = cmds[i++], y1 = cmds[i++];
408 x2 = cmds[i++], y2 = cmds[i++];
409 path.quadTo(x1, y1, x2, y2);
410 break;
411 case CONIC:
412 CHECK_NUM_ARGS(5);
413 x1 = cmds[i++], y1 = cmds[i++];
414 x2 = cmds[i++], y2 = cmds[i++];
415 x3 = cmds[i++]; // weight
416 path.conicTo(x1, y1, x2, y2, x3);
417 break;
418 case CUBIC:
419 CHECK_NUM_ARGS(6);
420 x1 = cmds[i++], y1 = cmds[i++];
421 x2 = cmds[i++], y2 = cmds[i++];
422 x3 = cmds[i++], y3 = cmds[i++];
423 path.cubicTo(x1, y1, x2, y2, x3, y3);
424 break;
425 case CLOSE:
426 path.close();
427 break;
428 default:
429 SkDebugf(" path: UNKNOWN command %f, aborting dump...\n", cmds[i-1]);
430 return emscripten::val::null();
431 }
432 }
433
434 #undef CHECK_NUM_ARGS
435
436 return emscripten::val(path);
437}
438
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400439//========================================================================================
440// Path Effects
441//========================================================================================
442
443bool ApplyDash(SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
444 SkScalar intervals[] = { on, off };
445 auto pe = SkDashPathEffect::Make(intervals, 2, phase);
446 if (!pe) {
447 SkDebugf("Invalid args to dash()\n");
448 return false;
449 }
450 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
451 if (pe->filterPath(&path, path, &rec, nullptr)) {
452 return true;
453 }
454 SkDebugf("Could not make dashed path\n");
455 return false;
Kevin Lubick217056c2018-09-20 17:39:31 -0400456}
457
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400458bool ApplyTrim(SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
459 auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal;
460 auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
461 if (!pe) {
462 SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
463 return false;
464 }
465 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
466 if (pe->filterPath(&path, path, &rec, nullptr)) {
467 return true;
468 }
469 SkDebugf("Could not trim path\n");
470 return false;
471}
472
473struct StrokeOpts {
Kevin Lubickb9db3902018-11-26 11:47:54 -0500474 // Default values are set in interface.js which allows clients
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400475 // to set any number of them. Otherwise, the binding code complains if
476 // any are omitted.
477 SkScalar width;
478 SkScalar miter_limit;
479 SkPaint::Join join;
480 SkPaint::Cap cap;
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500481 float precision;
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400482};
483
484bool ApplyStroke(SkPath& path, StrokeOpts opts) {
485 SkPaint p;
486 p.setStyle(SkPaint::kStroke_Style);
487 p.setStrokeCap(opts.cap);
488 p.setStrokeJoin(opts.join);
489 p.setStrokeWidth(opts.width);
490 p.setStrokeMiter(opts.miter_limit);
491
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500492 return p.getFillPath(path, &path, nullptr, opts.precision);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400493}
494
495// to map from raw memory to a uint8array
496Uint8Array getSkDataBytes(const SkData *data) {
497 return Uint8Array(typed_memory_view(data->size(), data->bytes()));
498}
499
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500500// Text Shaping abstraction
501
502struct ShapedTextOpts {
503 SkFont font;
504 bool leftToRight;
505 std::string text;
506 SkScalar width;
507};
508
509std::unique_ptr<SkShaper> shaper;
510
511static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400512 SkTextBlobBuilderRunHandler builder(opts.text.c_str(), {0, 0});
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500513 if (!shaper) {
514 shaper = SkShaper::Make();
515 }
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400516 shaper->shape(opts.text.c_str(), opts.text.length(),
517 opts.font, opts.leftToRight,
518 opts.width, &builder);
519 *pt = builder.endPoint();
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500520 return builder.makeBlob();
521}
522
523class ShapedText {
524public:
525 ShapedText(ShapedTextOpts opts) : fOpts(opts) {}
526
527 SkRect getBounds() {
528 this->init();
529 return SkRect::MakeLTRB(0, 0, fOpts.width, fPoint.y());
530 }
531
532 SkTextBlob* blob() {
533 this->init();
534 return fBlob.get();
535 }
536private:
537 const ShapedTextOpts fOpts;
538 SkPoint fPoint;
539 sk_sp<SkTextBlob> fBlob;
540
541 void init() {
542 if (!fBlob) {
543 fBlob = do_shaping(fOpts, &fPoint);
544 }
545 }
546};
547
548void drawShapedText(SkCanvas& canvas, ShapedText st, SkScalar x,
549 SkScalar y, SkPaint paint) {
550 canvas.drawTextBlob(st.blob(), x, y, paint);
551}
552
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400553// This is simpler than dealing with an SkPoint and SkVector
554struct PosTan {
555 SkScalar px, py, tx, ty;
556};
557
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400558// SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
559struct SimpleRRect {
560 SkRect rect;
561 SkScalar rx;
562 SkScalar ry;
563};
564
565SkRRect toRRect(const SimpleRRect& r) {
566 return SkRRect::MakeRectXY(r.rect, r.rx, r.ry);
567}
568
569// These objects have private destructors / delete methods - I don't think
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400570// we need to do anything other than tell emscripten to do nothing.
Kevin Lubick217056c2018-09-20 17:39:31 -0400571namespace emscripten {
572 namespace internal {
573 template<typename ClassType>
574 void raw_destructor(ClassType *);
575
576 template<>
577 void raw_destructor<SkData>(SkData *ptr) {
578 }
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400579
580 template<>
Kevin Lubickddd0a332018-12-12 10:35:13 -0500581 void raw_destructor<SkTypeface>(SkTypeface *ptr) {
582 }
583
584 template<>
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400585 void raw_destructor<SkVertices>(SkVertices *ptr) {
586 }
Kevin Lubickec4903d2019-01-14 08:36:08 -0500587
588 template<>
589 void raw_destructor<SkTextBlob>(SkTextBlob *ptr) {
590 }
Kevin Lubick217056c2018-09-20 17:39:31 -0400591 }
592}
593
594// Some timesignatures below have uintptr_t instead of a pointer to a primative
595// type (e.g. SkScalar). This is necessary because we can't use "bind" (EMSCRIPTEN_BINDINGS)
596// and pointers to primitive types (Only bound types like SkPoint). We could if we used
597// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
598// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
599// SkPath or SkCanvas.
600//
601// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primative pointers
602// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
603// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
604// the compiler is happy.
605EMSCRIPTEN_BINDINGS(Skia) {
Kevin Lubick53965c92018-10-11 08:51:55 -0400606#if SK_SUPPORT_GPU
Kevin Lubick53965c92018-10-11 08:51:55 -0400607 function("currentContext", &emscripten_webgl_get_current_context);
608 function("setCurrentContext", &emscripten_webgl_make_context_current);
Kevin Lubick543f3522019-03-08 10:04:28 -0500609 function("MakeGrContext", &MakeGrContext);
610 function("MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
611 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, int, int)>(&MakeRenderTarget));
612 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, SimpleImageInfo)>(&MakeRenderTarget));
613
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400614 constant("gpu", true);
Kevin Lubickb07204a2018-11-20 14:07:42 -0500615#endif
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500616 function("_decodeImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
617 size_t length)->sk_sp<SkImage> {
618 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
Kevin Lubick88aff5f2019-02-28 16:05:09 -0500619 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
620 return SkImage::MakeFromEncoded(std::move(bytes));
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500621 }), allow_raw_pointers());
Kevin Lubickea905ec2018-11-30 14:05:58 -0500622 function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
Kevin Lubick52b9f372018-12-04 13:57:36 -0500623 uintptr_t /* uint8_t* */ pPtr,
Kevin Lubickea905ec2018-11-30 14:05:58 -0500624 size_t rowBytes)->sk_sp<SkSurface> {
Kevin Lubick52b9f372018-12-04 13:57:36 -0500625 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
Kevin Lubickea905ec2018-11-30 14:05:58 -0500626 SkImageInfo imageInfo = toSkImageInfo(ii);
627 return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
628 }), allow_raw_pointers());
Kevin Lubick53965c92018-10-11 08:51:55 -0400629 function("_getRasterN32PremulSurface", optional_override([](int width, int height)->sk_sp<SkSurface> {
630 return SkSurface::MakeRasterN32Premul(width, height, nullptr);
631 }), allow_raw_pointers());
Kevin Lubickb07204a2018-11-20 14:07:42 -0500632
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400633 function("getSkDataBytes", &getSkDataBytes, allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -0400634 function("MakeSkCornerPathEffect", &SkCornerPathEffect::Make, allow_raw_pointers());
635 function("MakeSkDiscretePathEffect", &SkDiscretePathEffect::Make, allow_raw_pointers());
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500636 function("MakeBlurMaskFilter", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
637 // Adds a little helper because emscripten doesn't expose default params.
638 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
639 }), allow_raw_pointers());
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500640 function("_MakePathFromCmds", &MakePathFromCmds);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400641 function("MakePathFromOp", &MakePathFromOp);
Kevin Lubicka40f8322018-12-17 16:01:36 -0500642 function("MakePathFromSVGString", &MakePathFromSVGString);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400643
644 // These won't be called directly, there's a JS helper to deal with typed arrays.
Kevin Lubick217056c2018-09-20 17:39:31 -0400645 function("_MakeSkDashPathEffect", optional_override([](uintptr_t /* float* */ cptr, int count, SkScalar phase)->sk_sp<SkPathEffect> {
646 // See comment above for uintptr_t explanation
647 const float* intervals = reinterpret_cast<const float*>(cptr);
648 return SkDashPathEffect::Make(intervals, count, phase);
649 }), allow_raw_pointers());
Kevin Lubick52b9f372018-12-04 13:57:36 -0500650 function("_MakeImage", optional_override([](SimpleImageInfo ii,
651 uintptr_t /* uint8_t* */ pPtr, int plen,
652 size_t rowBytes)->sk_sp<SkImage> {
653 // See comment above for uintptr_t explanation
654 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
655 SkImageInfo info = toSkImageInfo(ii);
656 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
657
658 return SkImage::MakeRasterData(info, pixelData, rowBytes);
659 }), allow_raw_pointers());
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400660 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
661 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400662 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400663 SkPoint points[] = { start, end };
664 // See comment above for uintptr_t explanation
665 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
666 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
667
668 return SkGradientShader::MakeLinear(points, colors, positions, count,
669 mode, flags, nullptr);
670 }), allow_raw_pointers());
671 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
672 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400673 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400674 const SimpleMatrix& lm)->sk_sp<SkShader> {
675 SkPoint points[] = { start, end };
676 // See comment above for uintptr_t explanation
677 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
678 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
679
680 SkMatrix localMatrix = toSkMatrix(lm);
681
682 return SkGradientShader::MakeLinear(points, colors, positions, count,
683 mode, flags, &localMatrix);
684 }), allow_raw_pointers());
685 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
686 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400687 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400688 // See comment above for uintptr_t explanation
689 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
690 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
691
692 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
693 mode, flags, nullptr);
694 }), allow_raw_pointers());
695 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
696 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400697 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400698 const SimpleMatrix& lm)->sk_sp<SkShader> {
699 // See comment above for uintptr_t explanation
700 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
701 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
702
703 SkMatrix localMatrix = toSkMatrix(lm);
704 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
705 mode, flags, &localMatrix);
706 }), allow_raw_pointers());
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500707 function("_MakeTwoPointConicalGradientShader", optional_override([](
708 SkPoint start, SkScalar startRadius,
709 SkPoint end, SkScalar endRadius,
710 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400711 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500712 // See comment above for uintptr_t explanation
713 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
714 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
715
716 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
717 colors, positions, count, mode,
718 flags, nullptr);
719 }), allow_raw_pointers());
720 function("_MakeTwoPointConicalGradientShader", optional_override([](
721 SkPoint start, SkScalar startRadius,
722 SkPoint end, SkScalar endRadius,
723 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400724 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500725 const SimpleMatrix& lm)->sk_sp<SkShader> {
726 // See comment above for uintptr_t explanation
727 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
728 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
729
730 SkMatrix localMatrix = toSkMatrix(lm);
731 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
732 colors, positions, count, mode,
733 flags, &localMatrix);
734 }), allow_raw_pointers());
735
Kevin Lubick543f3522019-03-08 10:04:28 -0500736#if SK_SUPPORT_GPU
737 class_<GrContext>("GrContext")
Kevin Lubickcd544662019-03-22 15:41:36 -0400738 .smart_ptr<sk_sp<GrContext>>("sk_sp<GrContext>")
739 .function("getResourceCacheLimitBytes", optional_override([](GrContext& self)->size_t {
740 int maxResources = 0;// ignored
741 size_t currMax = 0;
742 self.getResourceCacheLimits(&maxResources, &currMax);
743 return currMax;
744 }))
745 .function("getResourceCacheUsageBytes", optional_override([](GrContext& self)->size_t {
746 int usedResources = 0;// ignored
747 size_t currUsage = 0;
748 self.getResourceCacheUsage(&usedResources, &currUsage);
749 return currUsage;
750 }))
751 .function("setResourceCacheLimitBytes", optional_override([](GrContext& self, size_t maxResourceBytes)->void {
752 int maxResources = 0;
753 size_t currMax = 0; // ignored
754 self.getResourceCacheLimits(&maxResources, &currMax);
755 self.setResourceCacheLimits(maxResources, maxResourceBytes);
756 }));
Kevin Lubick543f3522019-03-08 10:04:28 -0500757#endif
758
Kevin Lubick217056c2018-09-20 17:39:31 -0400759 class_<SkCanvas>("SkCanvas")
760 .constructor<>()
Kevin Lubickee91c072019-03-29 10:39:52 -0400761 .function("clear", &SkCanvas::clear)
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500762 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
Kevin Lubick52b9f372018-12-04 13:57:36 -0500763 .function("clipRect", select_overload<void (const SkRect&, SkClipOp, bool)>(&SkCanvas::clipRect))
764 .function("concat", optional_override([](SkCanvas& self, const SimpleMatrix& m) {
765 self.concat(toSkMatrix(m));
766 }))
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500767 .function("drawArc", &SkCanvas::drawArc)
Kevin Lubickee91c072019-03-29 10:39:52 -0400768 .function("_drawAtlas", optional_override([](SkCanvas& self,
769 const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
770 uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
771 SkBlendMode mode, const SkPaint* paint)->void {
772 // See comment above for uintptr_t explanation
773 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
774 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
775 const SkColor* colors = nullptr;
776 if (cptr) {
777 colors = reinterpret_cast<const SkColor*>(cptr);
778 }
779 self.drawAtlas(atlas, dstXforms, srcRects, colors, count, mode, nullptr, paint);
780 }), allow_raw_pointers())
Kevin Lubicke384df42019-08-26 15:48:09 -0400781 .function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400782 .function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
783 self.drawDRRect(toRRect(o), toRRect(i), paint);
784 }))
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500785 .function("drawImage", select_overload<void (const sk_sp<SkImage>&, SkScalar, SkScalar, const SkPaint*)>(&SkCanvas::drawImage), allow_raw_pointers())
786 .function("drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
787 SkRect src, SkRect dst,
788 const SkPaint* paint, bool fastSample)->void {
789 self.drawImageRect(image, src, dst, paint,
790 fastSample ? SkCanvas::kFast_SrcRectConstraint :
791 SkCanvas::kStrict_SrcRectConstraint);
792 }), allow_raw_pointers())
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500793 .function("drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
794 .function("drawOval", &SkCanvas::drawOval)
Kevin Lubick217056c2018-09-20 17:39:31 -0400795 .function("drawPaint", &SkCanvas::drawPaint)
796 .function("drawPath", &SkCanvas::drawPath)
Kevin Lubickcc13fd32019-04-05 13:00:01 -0400797 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
798 // a bitmap. An SkPicture is a series of draw commands.
799 .function("drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400800 .function("drawRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, const SkPaint& paint) {
801 self.drawRRect(toRRect(r), paint);
802 }))
Kevin Lubick217056c2018-09-20 17:39:31 -0400803 .function("drawRect", &SkCanvas::drawRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500804 .function("drawRoundRect", &SkCanvas::drawRoundRect)
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500805 .function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
806 const SkPoint3& zPlaneParams,
807 const SkPoint3& lightPos, SkScalar lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400808 SkColor ambientColor, SkColor spotColor,
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500809 uint32_t flags) {
810 SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400811 ambientColor, spotColor, flags);
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500812 }))
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500813 .function("_drawShapedText", &drawShapedText)
Kevin Lubickec4903d2019-01-14 08:36:08 -0500814 .function("_drawSimpleText", optional_override([](SkCanvas& self, uintptr_t /* char* */ sptr,
815 size_t len, SkScalar x, SkScalar y, const SkFont& font,
816 const SkPaint& paint) {
817 // See comment above for uintptr_t explanation
818 const char* str = reinterpret_cast<const char*>(sptr);
819
820 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
Kevin Lubick217056c2018-09-20 17:39:31 -0400821 }))
Kevin Lubickec4903d2019-01-14 08:36:08 -0500822 .function("drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400823 .function("drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
Kevin Lubick217056c2018-09-20 17:39:31 -0400824 .function("flush", &SkCanvas::flush)
Kevin Lubicke384df42019-08-26 15:48:09 -0400825 .function("getSaveCount", &SkCanvas::getSaveCount)
Kevin Lubick5d5723c2018-12-07 10:09:11 -0500826 .function("getTotalMatrix", optional_override([](const SkCanvas& self)->SimpleMatrix {
827 SkMatrix m = self.getTotalMatrix();
828 return toSimpleSkMatrix(m);
829 }))
Kevin Lubick543f3522019-03-08 10:04:28 -0500830 .function("makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
831 return self.makeSurface(toSkImageInfo(sii), nullptr);
832 }), allow_raw_pointers())
Kevin Lubick52b9f372018-12-04 13:57:36 -0500833 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
834 uintptr_t /* uint8_t* */ pPtr,
835 size_t dstRowBytes, int srcX, int srcY) {
836 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
837 SkImageInfo dstInfo = toSkImageInfo(di);
838
839 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
840 }))
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500841 .function("restore", &SkCanvas::restore)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500842 .function("restoreToCount", &SkCanvas::restoreToCount)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400843 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
Kevin Lubick217056c2018-09-20 17:39:31 -0400844 .function("save", &SkCanvas::save)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500845 .function("saveLayer", select_overload<int (const SkRect&, const SkPaint*)>(&SkCanvas::saveLayer),
846 allow_raw_pointers())
Kevin Lubick006a6f32018-10-19 14:34:34 -0400847 .function("scale", &SkCanvas::scale)
Kevin Lubick006a6f32018-10-19 14:34:34 -0400848 .function("skew", &SkCanvas::skew)
Kevin Lubick52b9f372018-12-04 13:57:36 -0500849 .function("translate", &SkCanvas::translate)
850 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
851 uintptr_t /* uint8_t* */ pPtr,
852 size_t srcRowBytes, int dstX, int dstY) {
853 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
854 SkImageInfo dstInfo = toSkImageInfo(di);
855
856 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
857 }))
858 ;
Kevin Lubick217056c2018-09-20 17:39:31 -0400859
860 class_<SkData>("SkData")
861 .smart_ptr<sk_sp<SkData>>("sk_sp<SkData>>")
862 .function("size", &SkData::size);
863
Kevin Lubick35ac0382019-01-02 15:13:57 -0500864 class_<SkFont>("SkFont")
865 .constructor<>()
866 .constructor<sk_sp<SkTypeface>>()
867 .constructor<sk_sp<SkTypeface>, SkScalar>()
868 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
869 .function("getScaleX", &SkFont::getScaleX)
870 .function("getSize", &SkFont::getSize)
871 .function("getSkewX", &SkFont::getSkewX)
872 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400873 .function("_getWidths", optional_override([](SkFont& self, uintptr_t /* char* */ sptr,
874 size_t strLen, size_t expectedCodePoints,
875 uintptr_t /* SkScalar* */ wptr) -> bool {
876 char* str = reinterpret_cast<char*>(sptr);
877 SkScalar* widths = reinterpret_cast<SkScalar*>(wptr);
878
879 SkGlyphID* glyphStorage = new SkGlyphID[expectedCodePoints];
880 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
881 glyphStorage, expectedCodePoints);
882 if (actualCodePoints != expectedCodePoints) {
883 SkDebugf("Actually %d glyphs, expected only %d\n",
884 actualCodePoints, expectedCodePoints);
885 return false;
886 }
887
888 self.getWidths(glyphStorage, actualCodePoints, widths);
889 delete[] glyphStorage;
890 return true;
891 }))
Kevin Lubick35ac0382019-01-02 15:13:57 -0500892 .function("measureText", optional_override([](SkFont& self, std::string text) {
893 // TODO(kjlubick): This does not work well for non-ascii
894 // Need to maybe add a helper in interface.js that supports UTF-8
895 // Otherwise, go with std::wstring and set UTF-32 encoding.
896 return self.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
897 }))
898 .function("setScaleX", &SkFont::setScaleX)
899 .function("setSize", &SkFont::setSize)
900 .function("setSkewX", &SkFont::setSkewX)
901 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
902
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500903 class_<ShapedText>("ShapedText")
904 .constructor<ShapedTextOpts>()
905 .function("getBounds", &ShapedText::getBounds);
906
Kevin Lubickddd0a332018-12-12 10:35:13 -0500907 class_<SkFontMgr>("SkFontMgr")
908 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<SkFontMgr>")
909 .class_function("RefDefault", &SkFontMgr::RefDefault)
910#ifdef SK_DEBUG
911 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
912 int numFam = self.countFamilies();
913 SkDebugf("There are %d font families\n");
914 for (int i = 0 ; i< numFam; i++) {
915 SkString s;
916 self.getFamilyName(i, &s);
917 SkDebugf("\t%s", s.c_str());
918 }
919 }))
920#endif
921 .function("countFamilies", &SkFontMgr::countFamilies)
922 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
923 uintptr_t /* uint8_t* */ fPtr,
924 int flen)->sk_sp<SkTypeface> {
925 // See comment above for uintptr_t explanation
926 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
927 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
928
929 return self.makeFromData(fontData);
930 }), allow_raw_pointers());
931
Kevin Lubick217056c2018-09-20 17:39:31 -0400932 class_<SkImage>("SkImage")
933 .smart_ptr<sk_sp<SkImage>>("sk_sp<SkImage>")
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500934 .function("height", &SkImage::height)
935 .function("width", &SkImage::width)
Alexander Khovansky3e119332018-11-15 02:01:19 +0300936 .function("_encodeToData", select_overload<sk_sp<SkData>()const>(&SkImage::encodeToData))
Kevin Lubicka064c282019-04-04 09:28:53 -0400937 .function("_encodeToDataWithFormat", select_overload<sk_sp<SkData>(SkEncodedImageFormat encodedImageFormat, int quality)const>(&SkImage::encodeToData))
938 // Allow localMatrix to be optional, so we have 2 declarations of these shaders
939 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
940 SkTileMode tx, SkTileMode ty)->sk_sp<SkShader> {
941 return self->makeShader(tx, ty, nullptr);
942 }), allow_raw_pointers())
943 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
944 SkTileMode tx, SkTileMode ty,
945 const SimpleMatrix& lm)->sk_sp<SkShader> {
946 SkMatrix localMatrix = toSkMatrix(lm);
947
948 return self->makeShader(tx, ty, &localMatrix);
Kevin Lubickd6b32ed2019-05-06 13:04:03 -0400949 }), allow_raw_pointers())
950 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
951 SimpleImageInfo sii, uintptr_t /* uint8_t* */ pPtr,
952 size_t dstRowBytes, int srcX, int srcY)->bool {
953 // See comment above for uintptr_t explanation
954 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
955 SkImageInfo ii = toSkImageInfo(sii);
956
957 return self->readPixels(ii, pixels, dstRowBytes, srcX, srcY);
Kevin Lubicka064c282019-04-04 09:28:53 -0400958 }), allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -0400959
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500960 class_<SkMaskFilter>("SkMaskFilter")
961 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<SkMaskFilter>");
962
Kevin Lubick217056c2018-09-20 17:39:31 -0400963 class_<SkPaint>("SkPaint")
964 .constructor<>()
965 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
966 SkPaint p(self);
967 return p;
968 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -0500969 .function("getBlendMode", &SkPaint::getBlendMode)
Kevin Lubickee91c072019-03-29 10:39:52 -0400970 .function("getColor", &SkPaint::getColor)
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500971 .function("getFilterQuality", &SkPaint::getFilterQuality)
Kevin Lubickb9db3902018-11-26 11:47:54 -0500972 .function("getStrokeCap", &SkPaint::getStrokeCap)
973 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500974 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
975 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
Kevin Lubick217056c2018-09-20 17:39:31 -0400976 .function("setAntiAlias", &SkPaint::setAntiAlias)
Kevin Lubick12c0e502018-11-28 12:51:56 -0500977 .function("setBlendMode", &SkPaint::setBlendMode)
Mike Reeddc2b98f2019-05-20 11:47:49 -0400978 .function("setColor", optional_override([](SkPaint& self, SkColor c) {
979 self.setColor(c);
980 }))
981 .function("setColorf", optional_override([](SkPaint& self,
982 float r, float g, float b, float a) {
983 self.setColor({r, g, b, a});
984 }))
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500985 .function("setFilterQuality", &SkPaint::setFilterQuality)
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500986 .function("setMaskFilter", &SkPaint::setMaskFilter)
Kevin Lubick217056c2018-09-20 17:39:31 -0400987 .function("setPathEffect", &SkPaint::setPathEffect)
988 .function("setShader", &SkPaint::setShader)
Kevin Lubickb9db3902018-11-26 11:47:54 -0500989 .function("setStrokeCap", &SkPaint::setStrokeCap)
990 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500991 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
992 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
Kevin Lubickec4903d2019-01-14 08:36:08 -0500993 .function("setStyle", &SkPaint::setStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -0400994
995 class_<SkPathEffect>("SkPathEffect")
996 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>");
997
Kevin Lubick217056c2018-09-20 17:39:31 -0400998 class_<SkPath>("SkPath")
999 .constructor<>()
1000 .constructor<const SkPath&>()
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001001 .function("_addArc", &ApplyAddArc)
Kevin Lubick217056c2018-09-20 17:39:31 -04001002 // interface.js has 3 overloads of addPath
Kevin Lubicke384df42019-08-26 15:48:09 -04001003 .function("_addOval", &ApplyAddOval)
Kevin Lubick217056c2018-09-20 17:39:31 -04001004 .function("_addPath", &ApplyAddPath)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001005 // interface.js has 4 overloads of addRect
1006 .function("_addRect", &ApplyAddRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001007 // interface.js has 4 overloads of addRoundRect
1008 .function("_addRoundRect", &ApplyAddRoundRect)
Kevin Lubick217056c2018-09-20 17:39:31 -04001009 .function("_arcTo", &ApplyArcTo)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001010 .function("_arcTo", &ApplyArcToAngle)
Kevin Lubicke384df42019-08-26 15:48:09 -04001011 .function("_arcTo", &ApplyAddArcToArcSize)
Kevin Lubick217056c2018-09-20 17:39:31 -04001012 .function("_close", &ApplyClose)
1013 .function("_conicTo", &ApplyConicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001014 .function("countPoints", &SkPath::countPoints)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001015 .function("contains", &SkPath::contains)
Kevin Lubick217056c2018-09-20 17:39:31 -04001016 .function("_cubicTo", &ApplyCubicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001017 .function("getPoint", &SkPath::getPoint)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001018 .function("isEmpty", &SkPath::isEmpty)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001019 .function("isVolatile", &SkPath::isVolatile)
Kevin Lubick217056c2018-09-20 17:39:31 -04001020 .function("_lineTo", &ApplyLineTo)
1021 .function("_moveTo", &ApplyMoveTo)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001022 .function("reset", &ApplyReset)
1023 .function("rewind", &ApplyRewind)
Kevin Lubick217056c2018-09-20 17:39:31 -04001024 .function("_quadTo", &ApplyQuadTo)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001025 .function("setIsVolatile", &SkPath::setIsVolatile)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001026 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
Kevin Lubick217056c2018-09-20 17:39:31 -04001027
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001028 // PathEffects
1029 .function("_dash", &ApplyDash)
1030 .function("_trim", &ApplyTrim)
1031 .function("_stroke", &ApplyStroke)
1032
1033 // PathOps
1034 .function("_simplify", &ApplySimplify)
1035 .function("_op", &ApplyPathOp)
1036
1037 // Exporting
1038 .function("toSVGString", &ToSVGString)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001039 .function("toCmds", &ToCmds)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001040
Kevin Lubick217056c2018-09-20 17:39:31 -04001041 .function("setFillType", &SkPath::setFillType)
1042 .function("getFillType", &SkPath::getFillType)
1043 .function("getBounds", &SkPath::getBounds)
1044 .function("computeTightBounds", &SkPath::computeTightBounds)
1045 .function("equals", &Equals)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001046 .function("copy", &CopyPath)
1047#ifdef SK_DEBUG
1048 .function("dump", select_overload<void() const>(&SkPath::dump))
1049 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
1050#endif
1051 ;
Kevin Lubick217056c2018-09-20 17:39:31 -04001052
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001053 class_<SkPathMeasure>("SkPathMeasure")
1054 .constructor<const SkPath&, bool, SkScalar>()
1055 .function("getLength", &SkPathMeasure::getLength)
1056 .function("getPosTan", optional_override([](SkPathMeasure& self,
1057 SkScalar distance) -> PosTan {
1058 SkPoint p{0, 0};
1059 SkVector v{0, 0};
1060 if (!self.getPosTan(distance, &p, &v)) {
1061 SkDebugf("zero-length path in getPosTan\n");
1062 }
1063 return PosTan{p.x(), p.y(), v.x(), v.y()};
1064 }))
1065 .function("isClosed", &SkPathMeasure::isClosed)
1066 .function("nextContour", &SkPathMeasure::nextContour);
1067
Kevin Lubickcc13fd32019-04-05 13:00:01 -04001068 class_<SkPictureRecorder>("SkPictureRecorder")
1069 .constructor<>()
1070 .function("beginRecording", optional_override([](SkPictureRecorder& self,
1071 const SkRect& bounds) -> SkCanvas* {
1072 return self.beginRecording(bounds, nullptr, 0);
1073 }), allow_raw_pointers())
1074 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
1075 -> sk_sp<SkPicture> {
1076 return self.finishRecordingAsPicture(0);
1077 }), allow_raw_pointers());
1078
1079 class_<SkPicture>("SkPicture")
1080 .smart_ptr<sk_sp<SkPicture>>("sk_sp<SkPicture>")
1081 // The serialized format of an SkPicture (informally called an "skp"), is not something
1082 // that clients should ever rely on. It is useful when filing bug reports, but that's
1083 // about it. The format may change at anytime and no promises are made for backwards
1084 // or forward compatibility.
1085 .function("DEBUGONLY_serialize", optional_override([](SkPicture& self) -> sk_sp<SkData> {
1086 // Emscripten doesn't play well with optional arguments, which we don't
1087 // want to expose anyway.
1088 return self.serialize();
1089 }), allow_raw_pointers());
1090
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001091 class_<SkShader>("SkShader")
1092 .smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>");
1093
Kevin Lubick217056c2018-09-20 17:39:31 -04001094 class_<SkSurface>("SkSurface")
1095 .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
Greg Danielbae71212019-03-01 15:24:35 -05001096 .function("_flush", select_overload<void()>(&SkSurface::flush))
Kevin Lubick543f3522019-03-08 10:04:28 -05001097 .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
1098 .function("height", &SkSurface::height)
Mike Reed114bde82018-11-21 09:12:09 -05001099 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
1100 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
Kevin Lubick543f3522019-03-08 10:04:28 -05001101 .function("makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1102 return self.makeSurface(toSkImageInfo(sii));
1103 }), allow_raw_pointers())
1104 .function("width", &SkSurface::width);
Kevin Lubick217056c2018-09-20 17:39:31 -04001105
Kevin Lubickec4903d2019-01-14 08:36:08 -05001106 class_<SkTextBlob>("SkTextBlob")
1107 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<SkTextBlob>>")
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001108 .class_function("_MakeFromRSXform", optional_override([](uintptr_t /* char* */ sptr,
1109 size_t strBtyes,
1110 uintptr_t /* SkRSXform* */ xptr,
1111 const SkFont& font,
1112 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
1113 // See comment above for uintptr_t explanation
1114 const char* str = reinterpret_cast<const char*>(sptr);
1115 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
1116
1117 return SkTextBlob::MakeFromRSXform(str, strBtyes, xforms, font, encoding);
1118 }), allow_raw_pointers())
Kevin Lubick543f3522019-03-08 10:04:28 -05001119 .class_function("_MakeFromText", optional_override([](uintptr_t /* char* */ sptr,
1120 size_t len, const SkFont& font,
1121 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
Kevin Lubickec4903d2019-01-14 08:36:08 -05001122 // See comment above for uintptr_t explanation
1123 const char* str = reinterpret_cast<const char*>(sptr);
1124 return SkTextBlob::MakeFromText(str, len, font, encoding);
1125 }), allow_raw_pointers());
1126
1127
Kevin Lubickddd0a332018-12-12 10:35:13 -05001128 class_<SkTypeface>("SkTypeface")
1129 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<SkTypeface>");
1130
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001131 class_<SkVertices>("SkVertices")
1132 .smart_ptr<sk_sp<SkVertices>>("sk_sp<SkVertices>")
1133 .function("_applyBones", optional_override([](SkVertices& self, uintptr_t /* Bone* */ bptr, int boneCount)->sk_sp<SkVertices> {
1134 // See comment above for uintptr_t explanation
1135 const Bone* bones = reinterpret_cast<const Bone*>(bptr);
1136 return self.applyBones(bones, boneCount);
1137 }))
1138 .function("bounds", &SkVertices::bounds)
1139 .function("mode", &SkVertices::mode)
1140 .function("uniqueID", &SkVertices::uniqueID)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001141#ifdef SK_DEBUG
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001142 .function("dumpPositions", optional_override([](SkVertices& self)->void {
1143 auto pos = self.positions();
1144 for(int i = 0; i< self.vertexCount(); i++) {
1145 SkDebugf("position[%d] = (%f, %f)\n", i, pos[i].x(), pos[i].y());
1146 }
1147 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001148#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001149 .function("vertexCount", &SkVertices::vertexCount);
1150
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001151 // Not intended to be called directly by clients
1152 class_<SkVertices::Builder>("_SkVerticesBuilder")
1153 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
1154 .function("boneIndices", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneIndices* */{
1155 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1156 return reinterpret_cast<uintptr_t>(self.boneIndices());
1157 }))
1158 .function("boneWeights", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneWeights* */{
1159 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1160 return reinterpret_cast<uintptr_t>(self.boneWeights());
1161 }))
1162 .function("colors", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkColor* */{
1163 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1164 return reinterpret_cast<uintptr_t>(self.colors());
1165 }))
1166 .function("detach", &SkVertices::Builder::detach)
1167 .function("indices", optional_override([](SkVertices::Builder& self)->uintptr_t /* uint16_t* */{
1168 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1169 return reinterpret_cast<uintptr_t>(self.indices());
1170 }))
1171 .function("positions", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1172 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1173 return reinterpret_cast<uintptr_t>(self.positions());
1174 }))
1175 .function("texCoords", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1176 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1177 return reinterpret_cast<uintptr_t>(self.texCoords());
1178 }));
1179
Kevin Lubickea905ec2018-11-30 14:05:58 -05001180 enum_<SkAlphaType>("AlphaType")
1181 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
1182 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
1183 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001184
1185 enum_<SkBlendMode>("BlendMode")
1186 .value("Clear", SkBlendMode::kClear)
1187 .value("Src", SkBlendMode::kSrc)
1188 .value("Dst", SkBlendMode::kDst)
1189 .value("SrcOver", SkBlendMode::kSrcOver)
1190 .value("DstOver", SkBlendMode::kDstOver)
1191 .value("SrcIn", SkBlendMode::kSrcIn)
1192 .value("DstIn", SkBlendMode::kDstIn)
1193 .value("SrcOut", SkBlendMode::kSrcOut)
1194 .value("DstOut", SkBlendMode::kDstOut)
1195 .value("SrcATop", SkBlendMode::kSrcATop)
1196 .value("DstATop", SkBlendMode::kDstATop)
1197 .value("Xor", SkBlendMode::kXor)
1198 .value("Plus", SkBlendMode::kPlus)
1199 .value("Modulate", SkBlendMode::kModulate)
1200 .value("Screen", SkBlendMode::kScreen)
1201 .value("Overlay", SkBlendMode::kOverlay)
1202 .value("Darken", SkBlendMode::kDarken)
1203 .value("Lighten", SkBlendMode::kLighten)
1204 .value("ColorDodge", SkBlendMode::kColorDodge)
1205 .value("ColorBurn", SkBlendMode::kColorBurn)
1206 .value("HardLight", SkBlendMode::kHardLight)
1207 .value("SoftLight", SkBlendMode::kSoftLight)
1208 .value("Difference", SkBlendMode::kDifference)
1209 .value("Exclusion", SkBlendMode::kExclusion)
1210 .value("Multiply", SkBlendMode::kMultiply)
1211 .value("Hue", SkBlendMode::kHue)
1212 .value("Saturation", SkBlendMode::kSaturation)
1213 .value("Color", SkBlendMode::kColor)
1214 .value("Luminosity", SkBlendMode::kLuminosity);
Kevin Lubick217056c2018-09-20 17:39:31 -04001215
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001216 enum_<SkBlurStyle>("BlurStyle")
1217 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
1218 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
1219 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
1220 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001221
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001222 enum_<SkClipOp>("ClipOp")
1223 .value("Difference", SkClipOp::kDifference)
1224 .value("Intersect", SkClipOp::kIntersect);
1225
Kevin Lubickea905ec2018-11-30 14:05:58 -05001226 enum_<SkColorType>("ColorType")
1227 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
1228 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
1229 .value("ARGB_4444", SkColorType::kARGB_4444_SkColorType)
1230 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
1231 .value("RGB_888x", SkColorType::kRGB_888x_SkColorType)
1232 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
1233 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
1234 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
1235 .value("Gray_8", SkColorType::kGray_8_SkColorType)
1236 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
1237 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType);
1238
Kevin Lubick217056c2018-09-20 17:39:31 -04001239 enum_<SkPath::FillType>("FillType")
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001240 .value("Winding", SkPath::FillType::kWinding_FillType)
1241 .value("EvenOdd", SkPath::FillType::kEvenOdd_FillType)
1242 .value("InverseWinding", SkPath::FillType::kInverseWinding_FillType)
1243 .value("InverseEvenOdd", SkPath::FillType::kInverseEvenOdd_FillType);
1244
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001245 enum_<SkFilterQuality>("FilterQuality")
1246 .value("None", SkFilterQuality::kNone_SkFilterQuality)
1247 .value("Low", SkFilterQuality::kLow_SkFilterQuality)
1248 .value("Medium", SkFilterQuality::kMedium_SkFilterQuality)
1249 .value("High", SkFilterQuality::kHigh_SkFilterQuality);
1250
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001251 enum_<SkEncodedImageFormat>("ImageFormat")
1252 .value("PNG", SkEncodedImageFormat::kPNG)
1253 .value("JPEG", SkEncodedImageFormat::kJPEG);
1254
1255 enum_<SkPaint::Style>("PaintStyle")
1256 .value("Fill", SkPaint::Style::kFill_Style)
1257 .value("Stroke", SkPaint::Style::kStroke_Style)
1258 .value("StrokeAndFill", SkPaint::Style::kStrokeAndFill_Style);
1259
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001260 enum_<SkPathOp>("PathOp")
1261 .value("Difference", SkPathOp::kDifference_SkPathOp)
1262 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
1263 .value("Union", SkPathOp::kUnion_SkPathOp)
1264 .value("XOR", SkPathOp::kXOR_SkPathOp)
1265 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
1266
Kevin Lubickb9db3902018-11-26 11:47:54 -05001267 enum_<SkPaint::Cap>("StrokeCap")
1268 .value("Butt", SkPaint::Cap::kButt_Cap)
1269 .value("Round", SkPaint::Cap::kRound_Cap)
1270 .value("Square", SkPaint::Cap::kSquare_Cap);
1271
1272 enum_<SkPaint::Join>("StrokeJoin")
1273 .value("Miter", SkPaint::Join::kMiter_Join)
1274 .value("Round", SkPaint::Join::kRound_Join)
1275 .value("Bevel", SkPaint::Join::kBevel_Join);
1276
Kevin Lubickec4903d2019-01-14 08:36:08 -05001277 enum_<SkTextEncoding>("TextEncoding")
1278 .value("UTF8", SkTextEncoding::kUTF8)
1279 .value("UTF16", SkTextEncoding::kUTF16)
1280 .value("UTF32", SkTextEncoding::kUTF32)
1281 .value("GlyphID", SkTextEncoding::kGlyphID);
Kevin Lubickb9db3902018-11-26 11:47:54 -05001282
Mike Reed5c5de212019-04-03 16:51:47 -04001283 enum_<SkTileMode>("TileMode")
1284 .value("Clamp", SkTileMode::kClamp)
1285 .value("Repeat", SkTileMode::kRepeat)
1286 .value("Mirror", SkTileMode::kMirror)
Mike Reed5c5de212019-04-03 16:51:47 -04001287 .value("Decal", SkTileMode::kDecal);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001288
1289 enum_<SkVertices::VertexMode>("VertexMode")
1290 .value("Triangles", SkVertices::VertexMode::kTriangles_VertexMode)
1291 .value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001292 .value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001293
Kevin Lubick217056c2018-09-20 17:39:31 -04001294
1295 // A value object is much simpler than a class - it is returned as a JS
1296 // object and does not require delete().
1297 // https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001298 value_object<ShapedTextOpts>("ShapedTextOpts")
1299 .field("font", &ShapedTextOpts::font)
1300 .field("leftToRight", &ShapedTextOpts::leftToRight)
1301 .field("text", &ShapedTextOpts::text)
1302 .field("width", &ShapedTextOpts::width);
1303
Kevin Lubick217056c2018-09-20 17:39:31 -04001304 value_object<SkRect>("SkRect")
1305 .field("fLeft", &SkRect::fLeft)
1306 .field("fTop", &SkRect::fTop)
1307 .field("fRight", &SkRect::fRight)
1308 .field("fBottom", &SkRect::fBottom);
1309
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001310 value_object<SimpleRRect>("SkRRect")
1311 .field("rect", &SimpleRRect::rect)
1312 .field("rx", &SimpleRRect::rx)
1313 .field("ry", &SimpleRRect::ry);
1314
Mike Reed114bde82018-11-21 09:12:09 -05001315 value_object<SkIRect>("SkIRect")
1316 .field("fLeft", &SkIRect::fLeft)
1317 .field("fTop", &SkIRect::fTop)
1318 .field("fRight", &SkIRect::fRight)
1319 .field("fBottom", &SkIRect::fBottom);
1320
Kevin Lubickea905ec2018-11-30 14:05:58 -05001321 value_object<SimpleImageInfo>("SkImageInfo")
1322 .field("width", &SimpleImageInfo::width)
1323 .field("height", &SimpleImageInfo::height)
1324 .field("colorType", &SimpleImageInfo::colorType)
1325 .field("alphaType", &SimpleImageInfo::alphaType);
1326
Kevin Lubick217056c2018-09-20 17:39:31 -04001327 // SkPoints can be represented by [x, y]
1328 value_array<SkPoint>("SkPoint")
1329 .element(&SkPoint::fX)
1330 .element(&SkPoint::fY);
1331
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001332 // SkPoint3s can be represented by [x, y, z]
1333 value_array<SkPoint3>("SkPoint3")
1334 .element(&SkPoint3::fX)
1335 .element(&SkPoint3::fY)
1336 .element(&SkPoint3::fZ);
1337
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001338 // PosTan can be represented by [px, py, tx, ty]
1339 value_array<PosTan>("PosTan")
1340 .element(&PosTan::px)
1341 .element(&PosTan::py)
1342 .element(&PosTan::tx)
1343 .element(&PosTan::ty);
1344
Kevin Lubick217056c2018-09-20 17:39:31 -04001345 // {"w": Number, "h", Number}
1346 value_object<SkSize>("SkSize")
1347 .field("w", &SkSize::fWidth)
1348 .field("h", &SkSize::fHeight);
1349
1350 value_object<SkISize>("SkISize")
1351 .field("w", &SkISize::fWidth)
1352 .field("h", &SkISize::fHeight);
1353
Kevin Lubickec4903d2019-01-14 08:36:08 -05001354 value_object<StrokeOpts>("StrokeOpts")
1355 .field("width", &StrokeOpts::width)
1356 .field("miter_limit", &StrokeOpts::miter_limit)
1357 .field("join", &StrokeOpts::join)
1358 .field("cap", &StrokeOpts::cap)
1359 .field("precision", &StrokeOpts::precision);
1360
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001361 // Allows clients to supply a 1D array of 9 elements and the bindings
1362 // will automatically turn it into a 3x3 2D matrix.
1363 // e.g. path.transform([0,1,2,3,4,5,6,7,8])
1364 // This is likely simpler for the client than exposing SkMatrix
1365 // directly and requiring them to do a lot of .delete().
1366 value_array<SimpleMatrix>("SkMatrix")
1367 .element(&SimpleMatrix::scaleX)
1368 .element(&SimpleMatrix::skewX)
1369 .element(&SimpleMatrix::transX)
1370
1371 .element(&SimpleMatrix::skewY)
1372 .element(&SimpleMatrix::scaleY)
1373 .element(&SimpleMatrix::transY)
1374
1375 .element(&SimpleMatrix::pers0)
1376 .element(&SimpleMatrix::pers1)
1377 .element(&SimpleMatrix::pers2);
1378
Kevin Lubickee91c072019-03-29 10:39:52 -04001379 constant("TRANSPARENT", SK_ColorTRANSPARENT);
1380 constant("RED", SK_ColorRED);
1381 constant("BLUE", SK_ColorBLUE);
1382 constant("YELLOW", SK_ColorYELLOW);
1383 constant("CYAN", SK_ColorCYAN);
1384 constant("BLACK", SK_ColorBLACK);
1385 constant("WHITE", SK_ColorWHITE);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001386 // TODO(?)
1387
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001388 constant("MOVE_VERB", MOVE);
1389 constant("LINE_VERB", LINE);
1390 constant("QUAD_VERB", QUAD);
1391 constant("CONIC_VERB", CONIC);
1392 constant("CUBIC_VERB", CUBIC);
1393 constant("CLOSE_VERB", CLOSE);
Kevin Lubick217056c2018-09-20 17:39:31 -04001394}