blob: f6bb18d7b30d022f9775df4ae1238efdcb7a32d7 [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"
23#include "include/core/SkImageInfo.h"
24#include "include/core/SkMaskFilter.h"
25#include "include/core/SkPaint.h"
26#include "include/core/SkPath.h"
27#include "include/core/SkPathEffect.h"
28#include "include/core/SkPathMeasure.h"
29#include "include/core/SkPicture.h"
30#include "include/core/SkPictureRecorder.h"
Kevin Lubick2e5fe352019-09-03 12:59:06 -040031#include "include/core/SkRRect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050032#include "include/core/SkScalar.h"
33#include "include/core/SkShader.h"
34#include "include/core/SkString.h"
35#include "include/core/SkStrokeRec.h"
36#include "include/core/SkSurface.h"
37#include "include/core/SkSurfaceProps.h"
38#include "include/core/SkTextBlob.h"
39#include "include/core/SkTypeface.h"
40#include "include/core/SkTypes.h"
41#include "include/core/SkVertices.h"
42#include "include/effects/SkCornerPathEffect.h"
43#include "include/effects/SkDashPathEffect.h"
44#include "include/effects/SkDiscretePathEffect.h"
45#include "include/effects/SkGradientShader.h"
46#include "include/effects/SkTrimPathEffect.h"
47#include "include/pathops/SkPathOps.h"
48#include "include/utils/SkParsePath.h"
49#include "include/utils/SkShadowUtils.h"
50#include "modules/skshaper/include/SkShaper.h"
51#include "src/core/SkFontMgrPriv.h"
52#include "src/core/SkMakeUnique.h"
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040053
Kevin Lubick217056c2018-09-20 17:39:31 -040054#include <iostream>
55#include <string>
Kevin Lubick217056c2018-09-20 17:39:31 -040056
Mike Kleinc0bd9f92019-04-23 12:05:21 -050057#include "modules/canvaskit/WasmAliases.h"
Kevin Lubick217056c2018-09-20 17:39:31 -040058#include <emscripten.h>
59#include <emscripten/bind.h>
Kevin Lubick46839422019-01-03 14:27:27 -050060
Kevin Lubick53965c92018-10-11 08:51:55 -040061#if SK_SUPPORT_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -050062#include "include/gpu/GrBackendSurface.h"
63#include "include/gpu/GrContext.h"
64#include "include/gpu/gl/GrGLInterface.h"
65#include "include/gpu/gl/GrGLTypes.h"
Kevin Lubick3f67f412019-03-11 16:11:58 -040066
Kevin Lubick53965c92018-10-11 08:51:55 -040067#include <GL/gl.h>
Kevin Lubick217056c2018-09-20 17:39:31 -040068#include <emscripten/html5.h>
Kevin Lubick53965c92018-10-11 08:51:55 -040069#endif
Kevin Lubick217056c2018-09-20 17:39:31 -040070
Kevin Lubick369f6a52019-10-03 11:22:08 -040071#ifdef SK_INCLUDE_PARAGRAPH
72#include "modules/skparagraph/include/Paragraph.h"
73#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040074// Aliases for less typing
75using BoneIndices = SkVertices::BoneIndices;
76using BoneWeights = SkVertices::BoneWeights;
77using Bone = SkVertices::Bone;
Kevin Lubick217056c2018-09-20 17:39:31 -040078
Kevin Lubick61887c72019-09-26 13:20:50 -040079#ifndef SK_NO_FONTS
80sk_sp<SkFontMgr> SkFontMgr_New_Custom_Data(const uint8_t** datas, const size_t* sizes, int n);
81#endif
82
Kevin Lubickb5ae3b52018-11-03 07:51:19 -040083struct SimpleMatrix {
84 SkScalar scaleX, skewX, transX;
85 SkScalar skewY, scaleY, transY;
86 SkScalar pers0, pers1, pers2;
87};
88
89SkMatrix toSkMatrix(const SimpleMatrix& sm) {
90 return SkMatrix::MakeAll(sm.scaleX, sm.skewX , sm.transX,
91 sm.skewY , sm.scaleY, sm.transY,
92 sm.pers0 , sm.pers1 , sm.pers2);
Kevin Lubick217056c2018-09-20 17:39:31 -040093}
94
Kevin Lubick5d5723c2018-12-07 10:09:11 -050095SimpleMatrix toSimpleSkMatrix(const SkMatrix& sm) {
96 SimpleMatrix m {sm[0], sm[1], sm[2],
97 sm[3], sm[4], sm[5],
98 sm[6], sm[7], sm[8]};
99 return m;
100}
101
Kevin Lubickea905ec2018-11-30 14:05:58 -0500102struct SimpleImageInfo {
103 int width;
104 int height;
105 SkColorType colorType;
106 SkAlphaType alphaType;
107 // TODO color spaces?
108};
109
110SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
111 return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
112}
113
Kevin Lubick543f3522019-03-08 10:04:28 -0500114#if SK_SUPPORT_GPU
115sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
116{
117 EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
118 if (r < 0) {
119 printf("failed to make webgl context current %d\n", r);
120 return nullptr;
121 }
122 // setup GrContext
123 auto interface = GrGLMakeNativeInterface();
124 // setup contexts
125 sk_sp<GrContext> grContext(GrContext::MakeGL(interface));
126 return grContext;
127}
128
129sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height) {
130 glClearColor(0, 0, 0, 0);
131 glClearStencil(0);
132 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
133
134
135 // Wrap the frame buffer object attached to the screen in a Skia render
136 // target so Skia can render to it
137 GrGLint buffer;
138 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
139 GrGLFramebufferInfo info;
140 info.fFBOID = (GrGLuint) buffer;
141 SkColorType colorType;
142
143 info.fFormat = GL_RGBA8;
144 colorType = kRGBA_8888_SkColorType;
145
146 GrBackendRenderTarget target(width, height, 0, 8, info);
147
148 sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
149 kBottomLeft_GrSurfaceOrigin,
150 colorType, nullptr, nullptr));
151 return surface;
152}
153
154sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, int width, int height) {
155 SkImageInfo info = SkImageInfo::MakeN32(width, height, SkAlphaType::kPremul_SkAlphaType);
156
157 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
158 SkBudgeted::kYes,
159 info, 0,
160 kBottomLeft_GrSurfaceOrigin,
161 nullptr, true));
162 return surface;
163}
164
165sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrContext> grContext, SimpleImageInfo sii) {
166 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(grContext.get(),
167 SkBudgeted::kYes,
168 toSkImageInfo(sii), 0,
169 kBottomLeft_GrSurfaceOrigin,
170 nullptr, true));
171 return surface;
172}
173#endif
174
175
Kevin Lubick217056c2018-09-20 17:39:31 -0400176//========================================================================================
177// Path things
178//========================================================================================
179
180// All these Apply* methods are simple wrappers to avoid returning an object.
181// The default WASM bindings produce code that will leak if a return value
182// isn't assigned to a JS variable and has delete() called on it.
183// These Apply methods, combined with the smarter binding code allow for chainable
184// commands that don't leak if the return value is ignored (i.e. when used intuitively).
185
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500186void ApplyAddArc(SkPath& orig, const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle) {
187 orig.addArc(oval, startAngle, sweepAngle);
188}
189
Kevin Lubicke384df42019-08-26 15:48:09 -0400190void ApplyAddOval(SkPath& orig, const SkRect& oval, bool ccw, unsigned start) {
191 orig.addOval(oval, ccw ? SkPath::Direction::kCCW_Direction :
192 SkPath::Direction::kCW_Direction, start);
193}
194
Kevin Lubick217056c2018-09-20 17:39:31 -0400195void ApplyAddPath(SkPath& orig, const SkPath& newPath,
196 SkScalar scaleX, SkScalar skewX, SkScalar transX,
197 SkScalar skewY, SkScalar scaleY, SkScalar transY,
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500198 SkScalar pers0, SkScalar pers1, SkScalar pers2,
199 bool extendPath) {
Kevin Lubick217056c2018-09-20 17:39:31 -0400200 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
201 skewY , scaleY, transY,
202 pers0 , pers1 , pers2);
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500203 orig.addPath(newPath, m, extendPath ? SkPath::kExtend_AddPathMode :
204 SkPath::kAppend_AddPathMode);
Kevin Lubick217056c2018-09-20 17:39:31 -0400205}
206
Kevin Lubick1a05fce2018-11-20 12:51:16 -0500207void ApplyAddRect(SkPath& path, SkScalar left, SkScalar top,
208 SkScalar right, SkScalar bottom, bool ccw) {
209 path.addRect(left, top, right, bottom,
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500210 ccw ? SkPath::Direction::kCCW_Direction :
211 SkPath::Direction::kCW_Direction);
Alexander Khovansky3e119332018-11-15 02:01:19 +0300212}
213
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500214void ApplyAddRoundRect(SkPath& path, SkScalar left, SkScalar top,
215 SkScalar right, SkScalar bottom, uintptr_t /* SkScalar* */ rPtr,
216 bool ccw) {
217 // See comment below for uintptr_t explanation
218 const SkScalar* radii = reinterpret_cast<const SkScalar*>(rPtr);
219 path.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radii,
220 ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction);
221}
222
223
Kevin Lubick217056c2018-09-20 17:39:31 -0400224void ApplyArcTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
225 SkScalar radius) {
226 p.arcTo(x1, y1, x2, y2, radius);
227}
228
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500229void ApplyArcToAngle(SkPath& p, SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo) {
230 p.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
231}
232
Kevin Lubicke384df42019-08-26 15:48:09 -0400233void ApplyAddArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
234 bool useSmallArc, bool ccw, SkScalar x, SkScalar y) {
235 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
236 auto sweep = ccw ? SkPath::Direction::kCCW_Direction : SkPath::Direction::kCW_Direction;
237 orig.arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y);
238}
239
Kevin Lubick217056c2018-09-20 17:39:31 -0400240void ApplyClose(SkPath& p) {
241 p.close();
242}
243
244void ApplyConicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
245 SkScalar w) {
246 p.conicTo(x1, y1, x2, y2, w);
247}
248
249void ApplyCubicTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
250 SkScalar x3, SkScalar y3) {
251 p.cubicTo(x1, y1, x2, y2, x3, y3);
252}
253
254void ApplyLineTo(SkPath& p, SkScalar x, SkScalar y) {
255 p.lineTo(x, y);
256}
257
258void ApplyMoveTo(SkPath& p, SkScalar x, SkScalar y) {
259 p.moveTo(x, y);
260}
261
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500262void ApplyReset(SkPath& p) {
263 p.reset();
264}
265
266void ApplyRewind(SkPath& p) {
267 p.rewind();
268}
269
Kevin Lubick217056c2018-09-20 17:39:31 -0400270void ApplyQuadTo(SkPath& p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
271 p.quadTo(x1, y1, x2, y2);
272}
273
274void ApplyTransform(SkPath& orig,
275 SkScalar scaleX, SkScalar skewX, SkScalar transX,
276 SkScalar skewY, SkScalar scaleY, SkScalar transY,
277 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
278 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
279 skewY , scaleY, transY,
280 pers0 , pers1 , pers2);
281 orig.transform(m);
282}
283
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400284bool EMSCRIPTEN_KEEPALIVE ApplySimplify(SkPath& path) {
285 return Simplify(path, &path);
286}
287
288bool EMSCRIPTEN_KEEPALIVE ApplyPathOp(SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
289 return Op(pathOne, pathTwo, op, &pathOne);
290}
291
292JSString EMSCRIPTEN_KEEPALIVE ToSVGString(const SkPath& path) {
293 SkString s;
294 SkParsePath::ToSVGString(path, &s);
295 return emscripten::val(s.c_str());
296}
297
Kevin Lubicka40f8322018-12-17 16:01:36 -0500298SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromSVGString(std::string str) {
299 SkPath path;
300 if (SkParsePath::FromSVGString(str.c_str(), &path)) {
301 return emscripten::val(path);
302 }
303 return emscripten::val::null();
304}
305
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400306SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
307 SkPath out;
308 if (Op(pathOne, pathTwo, op, &out)) {
309 return emscripten::val(out);
310 }
311 return emscripten::val::null();
312}
313
Kevin Lubick217056c2018-09-20 17:39:31 -0400314SkPath EMSCRIPTEN_KEEPALIVE CopyPath(const SkPath& a) {
315 SkPath copy(a);
316 return copy;
317}
318
319bool EMSCRIPTEN_KEEPALIVE Equals(const SkPath& a, const SkPath& b) {
320 return a == b;
321}
322
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500323// =================================================================================
324// Creating/Exporting Paths with cmd arrays
325// =================================================================================
326
327static const int MOVE = 0;
328static const int LINE = 1;
329static const int QUAD = 2;
330static const int CONIC = 3;
331static const int CUBIC = 4;
332static const int CLOSE = 5;
333
334template <typename VisitFunc>
335void VisitPath(const SkPath& p, VisitFunc&& f) {
336 SkPath::RawIter iter(p);
337 SkPoint pts[4];
338 SkPath::Verb verb;
339 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
340 f(verb, pts, iter);
341 }
342}
343
344JSArray EMSCRIPTEN_KEEPALIVE ToCmds(const SkPath& path) {
345 JSArray cmds = emscripten::val::array();
346
347 VisitPath(path, [&cmds](SkPath::Verb verb, const SkPoint pts[4], SkPath::RawIter iter) {
348 JSArray cmd = emscripten::val::array();
349 switch (verb) {
350 case SkPath::kMove_Verb:
351 cmd.call<void>("push", MOVE, pts[0].x(), pts[0].y());
352 break;
353 case SkPath::kLine_Verb:
354 cmd.call<void>("push", LINE, pts[1].x(), pts[1].y());
355 break;
356 case SkPath::kQuad_Verb:
357 cmd.call<void>("push", QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y());
358 break;
359 case SkPath::kConic_Verb:
360 cmd.call<void>("push", CONIC,
361 pts[1].x(), pts[1].y(),
362 pts[2].x(), pts[2].y(), iter.conicWeight());
363 break;
364 case SkPath::kCubic_Verb:
365 cmd.call<void>("push", CUBIC,
366 pts[1].x(), pts[1].y(),
367 pts[2].x(), pts[2].y(),
368 pts[3].x(), pts[3].y());
369 break;
370 case SkPath::kClose_Verb:
371 cmd.call<void>("push", CLOSE);
372 break;
373 case SkPath::kDone_Verb:
374 SkASSERT(false);
375 break;
376 }
377 cmds.call<void>("push", cmd);
378 });
379 return cmds;
380}
381
382// This type signature is a mess, but it's necessary. See, we can't use "bind" (EMSCRIPTEN_BINDINGS)
383// and pointers to primitive types (Only bound types like SkPoint). We could if we used
384// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
385// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
386// SkPath or SkOpBuilder.
387//
Kevin Lubick61887c72019-09-26 13:20:50 -0400388// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500389// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
390// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
391// the compiler is happy.
392SkPathOrNull EMSCRIPTEN_KEEPALIVE MakePathFromCmds(uintptr_t /* float* */ cptr, int numCmds) {
393 const auto* cmds = reinterpret_cast<const float*>(cptr);
394 SkPath path;
395 float x1, y1, x2, y2, x3, y3;
396
397 // if there are not enough arguments, bail with the path we've constructed so far.
398 #define CHECK_NUM_ARGS(n) \
399 if ((i + n) > numCmds) { \
400 SkDebugf("Not enough args to match the verbs. Saw %d commands\n", numCmds); \
401 return emscripten::val::null(); \
402 }
403
404 for(int i = 0; i < numCmds;){
405 switch (sk_float_floor2int(cmds[i++])) {
406 case MOVE:
407 CHECK_NUM_ARGS(2);
408 x1 = cmds[i++], y1 = cmds[i++];
409 path.moveTo(x1, y1);
410 break;
411 case LINE:
412 CHECK_NUM_ARGS(2);
413 x1 = cmds[i++], y1 = cmds[i++];
414 path.lineTo(x1, y1);
415 break;
416 case QUAD:
417 CHECK_NUM_ARGS(4);
418 x1 = cmds[i++], y1 = cmds[i++];
419 x2 = cmds[i++], y2 = cmds[i++];
420 path.quadTo(x1, y1, x2, y2);
421 break;
422 case CONIC:
423 CHECK_NUM_ARGS(5);
424 x1 = cmds[i++], y1 = cmds[i++];
425 x2 = cmds[i++], y2 = cmds[i++];
426 x3 = cmds[i++]; // weight
427 path.conicTo(x1, y1, x2, y2, x3);
428 break;
429 case CUBIC:
430 CHECK_NUM_ARGS(6);
431 x1 = cmds[i++], y1 = cmds[i++];
432 x2 = cmds[i++], y2 = cmds[i++];
433 x3 = cmds[i++], y3 = cmds[i++];
434 path.cubicTo(x1, y1, x2, y2, x3, y3);
435 break;
436 case CLOSE:
437 path.close();
438 break;
439 default:
440 SkDebugf(" path: UNKNOWN command %f, aborting dump...\n", cmds[i-1]);
441 return emscripten::val::null();
442 }
443 }
444
445 #undef CHECK_NUM_ARGS
446
447 return emscripten::val(path);
448}
449
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400450//========================================================================================
451// Path Effects
452//========================================================================================
453
454bool ApplyDash(SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
455 SkScalar intervals[] = { on, off };
456 auto pe = SkDashPathEffect::Make(intervals, 2, phase);
457 if (!pe) {
458 SkDebugf("Invalid args to dash()\n");
459 return false;
460 }
461 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
462 if (pe->filterPath(&path, path, &rec, nullptr)) {
463 return true;
464 }
465 SkDebugf("Could not make dashed path\n");
466 return false;
Kevin Lubick217056c2018-09-20 17:39:31 -0400467}
468
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400469bool ApplyTrim(SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
470 auto mode = isComplement ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal;
471 auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
472 if (!pe) {
473 SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
474 return false;
475 }
476 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
477 if (pe->filterPath(&path, path, &rec, nullptr)) {
478 return true;
479 }
480 SkDebugf("Could not trim path\n");
481 return false;
482}
483
484struct StrokeOpts {
Kevin Lubickb9db3902018-11-26 11:47:54 -0500485 // Default values are set in interface.js which allows clients
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400486 // to set any number of them. Otherwise, the binding code complains if
487 // any are omitted.
488 SkScalar width;
489 SkScalar miter_limit;
490 SkPaint::Join join;
491 SkPaint::Cap cap;
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500492 float precision;
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400493};
494
495bool ApplyStroke(SkPath& path, StrokeOpts opts) {
496 SkPaint p;
497 p.setStyle(SkPaint::kStroke_Style);
498 p.setStrokeCap(opts.cap);
499 p.setStrokeJoin(opts.join);
500 p.setStrokeWidth(opts.width);
501 p.setStrokeMiter(opts.miter_limit);
502
Kevin Lubick1646e7d2018-12-07 13:03:08 -0500503 return p.getFillPath(path, &path, nullptr, opts.precision);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400504}
505
506// to map from raw memory to a uint8array
507Uint8Array getSkDataBytes(const SkData *data) {
508 return Uint8Array(typed_memory_view(data->size(), data->bytes()));
509}
510
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500511// Text Shaping abstraction
512
513struct ShapedTextOpts {
514 SkFont font;
515 bool leftToRight;
516 std::string text;
517 SkScalar width;
518};
519
520std::unique_ptr<SkShaper> shaper;
521
522static sk_sp<SkTextBlob> do_shaping(const ShapedTextOpts& opts, SkPoint* pt) {
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400523 SkTextBlobBuilderRunHandler builder(opts.text.c_str(), {0, 0});
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500524 if (!shaper) {
525 shaper = SkShaper::Make();
526 }
Ben Wagner3bdb69c2019-04-01 19:01:09 -0400527 shaper->shape(opts.text.c_str(), opts.text.length(),
528 opts.font, opts.leftToRight,
529 opts.width, &builder);
530 *pt = builder.endPoint();
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500531 return builder.makeBlob();
532}
533
534class ShapedText {
535public:
536 ShapedText(ShapedTextOpts opts) : fOpts(opts) {}
537
538 SkRect getBounds() {
539 this->init();
540 return SkRect::MakeLTRB(0, 0, fOpts.width, fPoint.y());
541 }
542
543 SkTextBlob* blob() {
544 this->init();
545 return fBlob.get();
546 }
547private:
548 const ShapedTextOpts fOpts;
549 SkPoint fPoint;
550 sk_sp<SkTextBlob> fBlob;
551
552 void init() {
553 if (!fBlob) {
554 fBlob = do_shaping(fOpts, &fPoint);
555 }
556 }
557};
558
559void drawShapedText(SkCanvas& canvas, ShapedText st, SkScalar x,
560 SkScalar y, SkPaint paint) {
561 canvas.drawTextBlob(st.blob(), x, y, paint);
562}
563
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400564// This is simpler than dealing with an SkPoint and SkVector
565struct PosTan {
566 SkScalar px, py, tx, ty;
567};
568
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400569// SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
570struct SimpleRRect {
571 SkRect rect;
Kevin Lubick7d644e12019-09-11 14:22:22 -0400572
573 SkScalar rx1;
574 SkScalar ry1;
575 SkScalar rx2;
576 SkScalar ry2;
577 SkScalar rx3;
578 SkScalar ry3;
579 SkScalar rx4;
580 SkScalar ry4;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400581};
582
583SkRRect toRRect(const SimpleRRect& r) {
Kevin Lubick7d644e12019-09-11 14:22:22 -0400584 SkVector fRadii[4] = {{r.rx1, r.ry1}, {r.rx2, r.ry2},
585 {r.rx3, r.ry3}, {r.rx4, r.ry4}};
586 SkRRect rr;
587 rr.setRectRadii(r.rect, fRadii);
588 return rr;
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400589}
590
Kevin Lubick50f377e2019-09-11 15:23:00 -0400591struct TonalColors {
592 SkColor ambientColor;
593 SkColor spotColor;
594};
595
596TonalColors computeTonalColors(const TonalColors& in) {
597 TonalColors out;
598 SkShadowUtils::ComputeTonalColors(in.ambientColor, in.spotColor,
599 &out.ambientColor, &out.spotColor);
600 return out;
601}
602
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400603// These objects have private destructors / delete methods - I don't think
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400604// we need to do anything other than tell emscripten to do nothing.
Kevin Lubick217056c2018-09-20 17:39:31 -0400605namespace emscripten {
606 namespace internal {
607 template<typename ClassType>
608 void raw_destructor(ClassType *);
609
610 template<>
611 void raw_destructor<SkData>(SkData *ptr) {
612 }
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400613
614 template<>
615 void raw_destructor<SkVertices>(SkVertices *ptr) {
616 }
Kevin Lubickec4903d2019-01-14 08:36:08 -0500617
Kevin Lubick61887c72019-09-26 13:20:50 -0400618#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -0500619 template<>
620 void raw_destructor<SkTextBlob>(SkTextBlob *ptr) {
621 }
Kevin Lubick61887c72019-09-26 13:20:50 -0400622
623 template<>
624 void raw_destructor<SkTypeface>(SkTypeface *ptr) {
625 }
626#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400627 }
628}
629
Kevin Lubick61887c72019-09-26 13:20:50 -0400630// Some signatures below have uintptr_t instead of a pointer to a primitive
Kevin Lubick217056c2018-09-20 17:39:31 -0400631// type (e.g. SkScalar). This is necessary because we can't use "bind" (EMSCRIPTEN_BINDINGS)
632// and pointers to primitive types (Only bound types like SkPoint). We could if we used
633// cwrap (see https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97)
634// but that requires us to stick to C code and, AFAIK, doesn't allow us to return nice things like
635// SkPath or SkCanvas.
636//
Kevin Lubick61887c72019-09-26 13:20:50 -0400637// So, basically, if we are using C++ and EMSCRIPTEN_BINDINGS, we can't have primitive pointers
Kevin Lubick217056c2018-09-20 17:39:31 -0400638// in our function type signatures. (this gives an error message like "Cannot call foo due to unbound
639// types Pi, Pf"). But, we can just pretend they are numbers and cast them to be pointers and
640// the compiler is happy.
641EMSCRIPTEN_BINDINGS(Skia) {
Kevin Lubick53965c92018-10-11 08:51:55 -0400642#if SK_SUPPORT_GPU
Kevin Lubick53965c92018-10-11 08:51:55 -0400643 function("currentContext", &emscripten_webgl_get_current_context);
644 function("setCurrentContext", &emscripten_webgl_make_context_current);
Kevin Lubick543f3522019-03-08 10:04:28 -0500645 function("MakeGrContext", &MakeGrContext);
646 function("MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
647 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, int, int)>(&MakeRenderTarget));
648 function("MakeRenderTarget", select_overload<sk_sp<SkSurface>(sk_sp<GrContext>, SimpleImageInfo)>(&MakeRenderTarget));
649
Kevin Lubick3d99b1e2018-10-16 10:15:01 -0400650 constant("gpu", true);
Kevin Lubickb07204a2018-11-20 14:07:42 -0500651#endif
Kevin Lubick50f377e2019-09-11 15:23:00 -0400652 function("computeTonalColors", &computeTonalColors);
Kevin Lubick6b921b72019-09-18 16:18:17 -0400653 function("_decodeAnimatedImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
654 size_t length)->sk_sp<SkAnimatedImage> {
655 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
656 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
657 auto codec = SkAndroidCodec::MakeFromData(bytes);
658 if (nullptr == codec) {
659 return nullptr;
660 }
661 return SkAnimatedImage::Make(std::move(codec));
662 }), allow_raw_pointers());
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500663 function("_decodeImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
664 size_t length)->sk_sp<SkImage> {
665 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
Kevin Lubick88aff5f2019-02-28 16:05:09 -0500666 sk_sp<SkData> bytes = SkData::MakeFromMalloc(imgData, length);
667 return SkImage::MakeFromEncoded(std::move(bytes));
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500668 }), allow_raw_pointers());
Kevin Lubickea905ec2018-11-30 14:05:58 -0500669 function("_getRasterDirectSurface", optional_override([](const SimpleImageInfo ii,
Kevin Lubick52b9f372018-12-04 13:57:36 -0500670 uintptr_t /* uint8_t* */ pPtr,
Kevin Lubickea905ec2018-11-30 14:05:58 -0500671 size_t rowBytes)->sk_sp<SkSurface> {
Kevin Lubick52b9f372018-12-04 13:57:36 -0500672 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
Kevin Lubickea905ec2018-11-30 14:05:58 -0500673 SkImageInfo imageInfo = toSkImageInfo(ii);
674 return SkSurface::MakeRasterDirect(imageInfo, pixels, rowBytes, nullptr);
675 }), allow_raw_pointers());
Kevin Lubick53965c92018-10-11 08:51:55 -0400676 function("_getRasterN32PremulSurface", optional_override([](int width, int height)->sk_sp<SkSurface> {
677 return SkSurface::MakeRasterN32Premul(width, height, nullptr);
678 }), allow_raw_pointers());
Kevin Lubickb07204a2018-11-20 14:07:42 -0500679
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400680 function("getSkDataBytes", &getSkDataBytes, allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -0400681 function("MakeSkCornerPathEffect", &SkCornerPathEffect::Make, allow_raw_pointers());
682 function("MakeSkDiscretePathEffect", &SkDiscretePathEffect::Make, allow_raw_pointers());
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500683 function("MakeBlurMaskFilter", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
684 // Adds a little helper because emscripten doesn't expose default params.
685 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
686 }), allow_raw_pointers());
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500687 function("_MakePathFromCmds", &MakePathFromCmds);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400688 function("MakePathFromOp", &MakePathFromOp);
Kevin Lubicka40f8322018-12-17 16:01:36 -0500689 function("MakePathFromSVGString", &MakePathFromSVGString);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400690
691 // These won't be called directly, there's a JS helper to deal with typed arrays.
Kevin Lubick217056c2018-09-20 17:39:31 -0400692 function("_MakeSkDashPathEffect", optional_override([](uintptr_t /* float* */ cptr, int count, SkScalar phase)->sk_sp<SkPathEffect> {
693 // See comment above for uintptr_t explanation
694 const float* intervals = reinterpret_cast<const float*>(cptr);
695 return SkDashPathEffect::Make(intervals, count, phase);
696 }), allow_raw_pointers());
Kevin Lubick52b9f372018-12-04 13:57:36 -0500697 function("_MakeImage", optional_override([](SimpleImageInfo ii,
698 uintptr_t /* uint8_t* */ pPtr, int plen,
699 size_t rowBytes)->sk_sp<SkImage> {
700 // See comment above for uintptr_t explanation
701 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
702 SkImageInfo info = toSkImageInfo(ii);
703 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
704
705 return SkImage::MakeRasterData(info, pixelData, rowBytes);
706 }), allow_raw_pointers());
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400707 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
708 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400709 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400710 SkPoint points[] = { start, end };
711 // See comment above for uintptr_t explanation
712 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
713 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
714
715 return SkGradientShader::MakeLinear(points, colors, positions, count,
716 mode, flags, nullptr);
717 }), allow_raw_pointers());
718 function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
719 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400720 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400721 const SimpleMatrix& lm)->sk_sp<SkShader> {
722 SkPoint points[] = { start, end };
723 // See comment above for uintptr_t explanation
724 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
725 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
726
727 SkMatrix localMatrix = toSkMatrix(lm);
728
729 return SkGradientShader::MakeLinear(points, colors, positions, count,
730 mode, flags, &localMatrix);
731 }), allow_raw_pointers());
732 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
733 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400734 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400735 // See comment above for uintptr_t explanation
736 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
737 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
738
739 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
740 mode, flags, nullptr);
741 }), allow_raw_pointers());
742 function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
743 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400744 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400745 const SimpleMatrix& lm)->sk_sp<SkShader> {
746 // See comment above for uintptr_t explanation
747 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
748 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
749
750 SkMatrix localMatrix = toSkMatrix(lm);
751 return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
752 mode, flags, &localMatrix);
753 }), allow_raw_pointers());
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500754 function("_MakeTwoPointConicalGradientShader", optional_override([](
755 SkPoint start, SkScalar startRadius,
756 SkPoint end, SkScalar endRadius,
757 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400758 int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500759 // See comment above for uintptr_t explanation
760 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
761 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
762
763 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
764 colors, positions, count, mode,
765 flags, nullptr);
766 }), allow_raw_pointers());
767 function("_MakeTwoPointConicalGradientShader", optional_override([](
768 SkPoint start, SkScalar startRadius,
769 SkPoint end, SkScalar endRadius,
770 uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
Mike Reed5c5de212019-04-03 16:51:47 -0400771 int count, SkTileMode mode, uint32_t flags,
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500772 const SimpleMatrix& lm)->sk_sp<SkShader> {
773 // See comment above for uintptr_t explanation
774 const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
775 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
776
777 SkMatrix localMatrix = toSkMatrix(lm);
778 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
779 colors, positions, count, mode,
780 flags, &localMatrix);
781 }), allow_raw_pointers());
782
Kevin Lubick543f3522019-03-08 10:04:28 -0500783#if SK_SUPPORT_GPU
784 class_<GrContext>("GrContext")
Kevin Lubickcd544662019-03-22 15:41:36 -0400785 .smart_ptr<sk_sp<GrContext>>("sk_sp<GrContext>")
786 .function("getResourceCacheLimitBytes", optional_override([](GrContext& self)->size_t {
787 int maxResources = 0;// ignored
788 size_t currMax = 0;
789 self.getResourceCacheLimits(&maxResources, &currMax);
790 return currMax;
791 }))
792 .function("getResourceCacheUsageBytes", optional_override([](GrContext& self)->size_t {
793 int usedResources = 0;// ignored
794 size_t currUsage = 0;
795 self.getResourceCacheUsage(&usedResources, &currUsage);
796 return currUsage;
797 }))
798 .function("setResourceCacheLimitBytes", optional_override([](GrContext& self, size_t maxResourceBytes)->void {
799 int maxResources = 0;
800 size_t currMax = 0; // ignored
801 self.getResourceCacheLimits(&maxResources, &currMax);
802 self.setResourceCacheLimits(maxResources, maxResourceBytes);
803 }));
Kevin Lubick543f3522019-03-08 10:04:28 -0500804#endif
805
Kevin Lubick6b921b72019-09-18 16:18:17 -0400806 class_<SkAnimatedImage>("SkAnimatedImage")
807 .smart_ptr<sk_sp<SkAnimatedImage>>("sk_sp<SkAnimatedImage>")
808 .function("getRepetitionCount", &SkAnimatedImage::getRepetitionCount)
809 .function("decodeNextFrame", &SkAnimatedImage::decodeNextFrame);
810
Kevin Lubick217056c2018-09-20 17:39:31 -0400811 class_<SkCanvas>("SkCanvas")
812 .constructor<>()
Kevin Lubickee91c072019-03-29 10:39:52 -0400813 .function("clear", &SkCanvas::clear)
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500814 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400815 .function("clipRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
816 self.clipRRect(toRRect(r), op, doAntiAlias);
817 }))
Kevin Lubick52b9f372018-12-04 13:57:36 -0500818 .function("clipRect", select_overload<void (const SkRect&, SkClipOp, bool)>(&SkCanvas::clipRect))
819 .function("concat", optional_override([](SkCanvas& self, const SimpleMatrix& m) {
820 self.concat(toSkMatrix(m));
821 }))
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500822 .function("drawArc", &SkCanvas::drawArc)
Kevin Lubickee91c072019-03-29 10:39:52 -0400823 .function("_drawAtlas", optional_override([](SkCanvas& self,
824 const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
825 uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
826 SkBlendMode mode, const SkPaint* paint)->void {
827 // See comment above for uintptr_t explanation
828 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
829 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
830 const SkColor* colors = nullptr;
831 if (cptr) {
832 colors = reinterpret_cast<const SkColor*>(cptr);
833 }
834 self.drawAtlas(atlas, dstXforms, srcRects, colors, count, mode, nullptr, paint);
835 }), allow_raw_pointers())
Kevin Lubicke384df42019-08-26 15:48:09 -0400836 .function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
Kevin Lubick6dbc4ed2019-10-22 09:43:34 -0400837 .function("drawColor", &SkCanvas::drawColor)
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400838 .function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
839 self.drawDRRect(toRRect(o), toRRect(i), paint);
840 }))
Kevin Lubick6b921b72019-09-18 16:18:17 -0400841 .function("drawAnimatedImage", optional_override([](SkCanvas& self, sk_sp<SkAnimatedImage>& aImg,
842 SkScalar x, SkScalar y)->void {
843 self.drawDrawable(aImg.get(), x, y);
844 }), allow_raw_pointers())
Kevin Lubick0a1293c2018-12-03 12:31:04 -0500845 .function("drawImage", select_overload<void (const sk_sp<SkImage>&, SkScalar, SkScalar, const SkPaint*)>(&SkCanvas::drawImage), allow_raw_pointers())
846 .function("drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
847 SkRect src, SkRect dst,
848 const SkPaint* paint, bool fastSample)->void {
849 self.drawImageRect(image, src, dst, paint,
850 fastSample ? SkCanvas::kFast_SrcRectConstraint :
851 SkCanvas::kStrict_SrcRectConstraint);
852 }), allow_raw_pointers())
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500853 .function("drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
854 .function("drawOval", &SkCanvas::drawOval)
Kevin Lubick217056c2018-09-20 17:39:31 -0400855 .function("drawPaint", &SkCanvas::drawPaint)
Kevin Lubick369f6a52019-10-03 11:22:08 -0400856#ifdef SK_INCLUDE_PARAGRAPH
857 .function("drawParagraph", optional_override([](SkCanvas& self, skia::textlayout::Paragraph* p,
858 SkScalar x, SkScalar y) {
859 p->paint(&self, x, y);
860 }), allow_raw_pointers())
861#endif
Kevin Lubick217056c2018-09-20 17:39:31 -0400862 .function("drawPath", &SkCanvas::drawPath)
Kevin Lubickcc13fd32019-04-05 13:00:01 -0400863 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
864 // a bitmap. An SkPicture is a series of draw commands.
865 .function("drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
Kevin Lubick2e5fe352019-09-03 12:59:06 -0400866 .function("drawRRect",optional_override([](SkCanvas& self, const SimpleRRect& r, const SkPaint& paint) {
867 self.drawRRect(toRRect(r), paint);
868 }))
Kevin Lubick217056c2018-09-20 17:39:31 -0400869 .function("drawRect", &SkCanvas::drawRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -0500870 .function("drawRoundRect", &SkCanvas::drawRoundRect)
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500871 .function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
872 const SkPoint3& zPlaneParams,
873 const SkPoint3& lightPos, SkScalar lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400874 SkColor ambientColor, SkColor spotColor,
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500875 uint32_t flags) {
876 SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
Kevin Lubickee91c072019-03-29 10:39:52 -0400877 ambientColor, spotColor, flags);
Kevin Lubick61ef7b22018-11-27 13:26:59 -0500878 }))
Kevin Lubick61887c72019-09-26 13:20:50 -0400879#ifndef SK_NO_FONTS
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500880 .function("_drawShapedText", &drawShapedText)
Kevin Lubickec4903d2019-01-14 08:36:08 -0500881 .function("_drawSimpleText", optional_override([](SkCanvas& self, uintptr_t /* char* */ sptr,
882 size_t len, SkScalar x, SkScalar y, const SkFont& font,
883 const SkPaint& paint) {
884 // See comment above for uintptr_t explanation
885 const char* str = reinterpret_cast<const char*>(sptr);
886
887 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
Kevin Lubick217056c2018-09-20 17:39:31 -0400888 }))
Kevin Lubickec4903d2019-01-14 08:36:08 -0500889 .function("drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
Kevin Lubick61887c72019-09-26 13:20:50 -0400890#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400891 .function("drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
Kevin Lubick217056c2018-09-20 17:39:31 -0400892 .function("flush", &SkCanvas::flush)
Kevin Lubicke384df42019-08-26 15:48:09 -0400893 .function("getSaveCount", &SkCanvas::getSaveCount)
Kevin Lubick5d5723c2018-12-07 10:09:11 -0500894 .function("getTotalMatrix", optional_override([](const SkCanvas& self)->SimpleMatrix {
895 SkMatrix m = self.getTotalMatrix();
896 return toSimpleSkMatrix(m);
897 }))
Kevin Lubick543f3522019-03-08 10:04:28 -0500898 .function("makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
899 return self.makeSurface(toSkImageInfo(sii), nullptr);
900 }), allow_raw_pointers())
Kevin Lubick52b9f372018-12-04 13:57:36 -0500901 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
902 uintptr_t /* uint8_t* */ pPtr,
903 size_t dstRowBytes, int srcX, int srcY) {
904 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
905 SkImageInfo dstInfo = toSkImageInfo(di);
906
907 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
908 }))
Kevin Lubickeb2f6b02018-11-29 15:07:02 -0500909 .function("restore", &SkCanvas::restore)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500910 .function("restoreToCount", &SkCanvas::restoreToCount)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -0400911 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
Kevin Lubick217056c2018-09-20 17:39:31 -0400912 .function("save", &SkCanvas::save)
Kevin Lubickb3574c92019-03-06 08:25:36 -0500913 .function("saveLayer", select_overload<int (const SkRect&, const SkPaint*)>(&SkCanvas::saveLayer),
914 allow_raw_pointers())
Kevin Lubick006a6f32018-10-19 14:34:34 -0400915 .function("scale", &SkCanvas::scale)
Kevin Lubick006a6f32018-10-19 14:34:34 -0400916 .function("skew", &SkCanvas::skew)
Kevin Lubick52b9f372018-12-04 13:57:36 -0500917 .function("translate", &SkCanvas::translate)
918 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
919 uintptr_t /* uint8_t* */ pPtr,
920 size_t srcRowBytes, int dstX, int dstY) {
921 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
922 SkImageInfo dstInfo = toSkImageInfo(di);
923
924 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
Kevin Lubick369f6a52019-10-03 11:22:08 -0400925 }));
Kevin Lubick217056c2018-09-20 17:39:31 -0400926
Kevin Lubickd3729342019-09-12 11:11:25 -0400927 class_<SkColorFilter>("SkColorFilter")
928 .smart_ptr<sk_sp<SkColorFilter>>("sk_sp<SkColorFilter>>")
929 .class_function("MakeBlend", &SkColorFilters::Blend)
930 .class_function("MakeCompose", &SkColorFilters::Compose)
931 .class_function("MakeLerp", &SkColorFilters::Lerp)
932 .class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
933 .class_function("_makeMatrix", optional_override([](uintptr_t /* float* */ fPtr) {
934 float* twentyFloats = reinterpret_cast<float*>(fPtr);
935 return SkColorFilters::Matrix(twentyFloats);
936 }))
937 .class_function("MakeSRGBToLinearGamma", &SkColorFilters::SRGBToLinearGamma);
938
Kevin Lubick217056c2018-09-20 17:39:31 -0400939 class_<SkData>("SkData")
940 .smart_ptr<sk_sp<SkData>>("sk_sp<SkData>>")
941 .function("size", &SkData::size);
942
Kevin Lubick6b921b72019-09-18 16:18:17 -0400943 class_<SkDrawable>("SkDrawable")
944 .smart_ptr<sk_sp<SkDrawable>>("sk_sp<SkDrawable>>");
945
Kevin Lubick61887c72019-09-26 13:20:50 -0400946#ifndef SK_NO_FONTS
Kevin Lubick35ac0382019-01-02 15:13:57 -0500947 class_<SkFont>("SkFont")
948 .constructor<>()
949 .constructor<sk_sp<SkTypeface>>()
950 .constructor<sk_sp<SkTypeface>, SkScalar>()
951 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
952 .function("getScaleX", &SkFont::getScaleX)
953 .function("getSize", &SkFont::getSize)
954 .function("getSkewX", &SkFont::getSkewX)
955 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
Kevin Lubickd3cfbca2019-03-15 15:36:29 -0400956 .function("_getWidths", optional_override([](SkFont& self, uintptr_t /* char* */ sptr,
957 size_t strLen, size_t expectedCodePoints,
958 uintptr_t /* SkScalar* */ wptr) -> bool {
959 char* str = reinterpret_cast<char*>(sptr);
960 SkScalar* widths = reinterpret_cast<SkScalar*>(wptr);
961
962 SkGlyphID* glyphStorage = new SkGlyphID[expectedCodePoints];
963 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
964 glyphStorage, expectedCodePoints);
965 if (actualCodePoints != expectedCodePoints) {
966 SkDebugf("Actually %d glyphs, expected only %d\n",
967 actualCodePoints, expectedCodePoints);
968 return false;
969 }
970
971 self.getWidths(glyphStorage, actualCodePoints, widths);
972 delete[] glyphStorage;
973 return true;
974 }))
Kevin Lubick35ac0382019-01-02 15:13:57 -0500975 .function("measureText", optional_override([](SkFont& self, std::string text) {
976 // TODO(kjlubick): This does not work well for non-ascii
977 // Need to maybe add a helper in interface.js that supports UTF-8
978 // Otherwise, go with std::wstring and set UTF-32 encoding.
979 return self.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8);
980 }))
981 .function("setScaleX", &SkFont::setScaleX)
982 .function("setSize", &SkFont::setSize)
983 .function("setSkewX", &SkFont::setSkewX)
984 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
985
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -0500986 class_<ShapedText>("ShapedText")
987 .constructor<ShapedTextOpts>()
988 .function("getBounds", &ShapedText::getBounds);
989
Kevin Lubickddd0a332018-12-12 10:35:13 -0500990 class_<SkFontMgr>("SkFontMgr")
991 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<SkFontMgr>")
Kevin Lubick61887c72019-09-26 13:20:50 -0400992 .class_function("_fromData", optional_override([](uintptr_t /* uint8_t** */ dPtr,
993 uintptr_t /* size_t* */ sPtr,
994 int numFonts)->sk_sp<SkFontMgr> {
995 // See comment above for uintptr_t explanation
996 auto datas = reinterpret_cast<const uint8_t**>(dPtr);
997 auto sizes = reinterpret_cast<const size_t*>(sPtr);
998
999 return SkFontMgr_New_Custom_Data(datas, sizes, numFonts);
1000 }), allow_raw_pointers())
Kevin Lubickddd0a332018-12-12 10:35:13 -05001001 .class_function("RefDefault", &SkFontMgr::RefDefault)
1002#ifdef SK_DEBUG
1003 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
1004 int numFam = self.countFamilies();
Kevin Lubick61887c72019-09-26 13:20:50 -04001005 SkDebugf("There are %d font families\n", numFam);
Kevin Lubickddd0a332018-12-12 10:35:13 -05001006 for (int i = 0 ; i< numFam; i++) {
1007 SkString s;
1008 self.getFamilyName(i, &s);
Kevin Lubick61887c72019-09-26 13:20:50 -04001009 SkDebugf("\t%s\n", s.c_str());
Kevin Lubickddd0a332018-12-12 10:35:13 -05001010 }
1011 }))
1012#endif
1013 .function("countFamilies", &SkFontMgr::countFamilies)
1014 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
1015 uintptr_t /* uint8_t* */ fPtr,
1016 int flen)->sk_sp<SkTypeface> {
1017 // See comment above for uintptr_t explanation
1018 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
1019 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
1020
1021 return self.makeFromData(fontData);
1022 }), allow_raw_pointers());
Kevin Lubick61887c72019-09-26 13:20:50 -04001023#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001024
Kevin Lubick217056c2018-09-20 17:39:31 -04001025 class_<SkImage>("SkImage")
1026 .smart_ptr<sk_sp<SkImage>>("sk_sp<SkImage>")
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001027 .function("height", &SkImage::height)
1028 .function("width", &SkImage::width)
Alexander Khovansky3e119332018-11-15 02:01:19 +03001029 .function("_encodeToData", select_overload<sk_sp<SkData>()const>(&SkImage::encodeToData))
Kevin Lubicka064c282019-04-04 09:28:53 -04001030 .function("_encodeToDataWithFormat", select_overload<sk_sp<SkData>(SkEncodedImageFormat encodedImageFormat, int quality)const>(&SkImage::encodeToData))
1031 // Allow localMatrix to be optional, so we have 2 declarations of these shaders
1032 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1033 SkTileMode tx, SkTileMode ty)->sk_sp<SkShader> {
1034 return self->makeShader(tx, ty, nullptr);
1035 }), allow_raw_pointers())
1036 .function("_makeShader", optional_override([](sk_sp<SkImage> self,
1037 SkTileMode tx, SkTileMode ty,
1038 const SimpleMatrix& lm)->sk_sp<SkShader> {
1039 SkMatrix localMatrix = toSkMatrix(lm);
1040
1041 return self->makeShader(tx, ty, &localMatrix);
Kevin Lubickd6b32ed2019-05-06 13:04:03 -04001042 }), allow_raw_pointers())
1043 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1044 SimpleImageInfo sii, uintptr_t /* uint8_t* */ pPtr,
1045 size_t dstRowBytes, int srcX, int srcY)->bool {
1046 // See comment above for uintptr_t explanation
1047 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1048 SkImageInfo ii = toSkImageInfo(sii);
1049
1050 return self->readPixels(ii, pixels, dstRowBytes, srcX, srcY);
Kevin Lubicka064c282019-04-04 09:28:53 -04001051 }), allow_raw_pointers());
Kevin Lubick217056c2018-09-20 17:39:31 -04001052
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001053 class_<SkMaskFilter>("SkMaskFilter")
1054 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<SkMaskFilter>");
1055
Kevin Lubick217056c2018-09-20 17:39:31 -04001056 class_<SkPaint>("SkPaint")
1057 .constructor<>()
1058 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
1059 SkPaint p(self);
1060 return p;
1061 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001062 .function("getBlendMode", &SkPaint::getBlendMode)
Kevin Lubickee91c072019-03-29 10:39:52 -04001063 .function("getColor", &SkPaint::getColor)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001064 .function("getFilterQuality", &SkPaint::getFilterQuality)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001065 .function("getStrokeCap", &SkPaint::getStrokeCap)
1066 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001067 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
1068 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
Kevin Lubick217056c2018-09-20 17:39:31 -04001069 .function("setAntiAlias", &SkPaint::setAntiAlias)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001070 .function("setBlendMode", &SkPaint::setBlendMode)
Mike Reeddc2b98f2019-05-20 11:47:49 -04001071 .function("setColor", optional_override([](SkPaint& self, SkColor c) {
1072 self.setColor(c);
1073 }))
1074 .function("setColorf", optional_override([](SkPaint& self,
1075 float r, float g, float b, float a) {
1076 self.setColor({r, g, b, a});
1077 }))
Kevin Lubickd3729342019-09-12 11:11:25 -04001078 .function("setColorFilter", &SkPaint::setColorFilter)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001079 .function("setFilterQuality", &SkPaint::setFilterQuality)
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001080 .function("setMaskFilter", &SkPaint::setMaskFilter)
Kevin Lubick217056c2018-09-20 17:39:31 -04001081 .function("setPathEffect", &SkPaint::setPathEffect)
1082 .function("setShader", &SkPaint::setShader)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001083 .function("setStrokeCap", &SkPaint::setStrokeCap)
1084 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001085 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
1086 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
Kevin Lubickec4903d2019-01-14 08:36:08 -05001087 .function("setStyle", &SkPaint::setStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001088
1089 class_<SkPathEffect>("SkPathEffect")
1090 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>");
1091
Kevin Lubick217056c2018-09-20 17:39:31 -04001092 class_<SkPath>("SkPath")
1093 .constructor<>()
1094 .constructor<const SkPath&>()
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001095 .function("_addArc", &ApplyAddArc)
Kevin Lubick217056c2018-09-20 17:39:31 -04001096 // interface.js has 3 overloads of addPath
Kevin Lubicke384df42019-08-26 15:48:09 -04001097 .function("_addOval", &ApplyAddOval)
Kevin Lubick217056c2018-09-20 17:39:31 -04001098 .function("_addPath", &ApplyAddPath)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001099 // interface.js has 4 overloads of addRect
1100 .function("_addRect", &ApplyAddRect)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001101 // interface.js has 4 overloads of addRoundRect
1102 .function("_addRoundRect", &ApplyAddRoundRect)
Kevin Lubick217056c2018-09-20 17:39:31 -04001103 .function("_arcTo", &ApplyArcTo)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001104 .function("_arcTo", &ApplyArcToAngle)
Kevin Lubicke384df42019-08-26 15:48:09 -04001105 .function("_arcTo", &ApplyAddArcToArcSize)
Kevin Lubick217056c2018-09-20 17:39:31 -04001106 .function("_close", &ApplyClose)
1107 .function("_conicTo", &ApplyConicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001108 .function("countPoints", &SkPath::countPoints)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001109 .function("contains", &SkPath::contains)
Kevin Lubick217056c2018-09-20 17:39:31 -04001110 .function("_cubicTo", &ApplyCubicTo)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001111 .function("getPoint", &SkPath::getPoint)
Kevin Lubick1646e7d2018-12-07 13:03:08 -05001112 .function("isEmpty", &SkPath::isEmpty)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001113 .function("isVolatile", &SkPath::isVolatile)
Kevin Lubick217056c2018-09-20 17:39:31 -04001114 .function("_lineTo", &ApplyLineTo)
1115 .function("_moveTo", &ApplyMoveTo)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001116 .function("reset", &ApplyReset)
1117 .function("rewind", &ApplyRewind)
Kevin Lubick217056c2018-09-20 17:39:31 -04001118 .function("_quadTo", &ApplyQuadTo)
Kevin Lubick2b79d1c2018-12-14 16:10:38 -05001119 .function("setIsVolatile", &SkPath::setIsVolatile)
Kevin Lubick1a05fce2018-11-20 12:51:16 -05001120 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
Kevin Lubick217056c2018-09-20 17:39:31 -04001121
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001122 // PathEffects
1123 .function("_dash", &ApplyDash)
1124 .function("_trim", &ApplyTrim)
1125 .function("_stroke", &ApplyStroke)
1126
1127 // PathOps
1128 .function("_simplify", &ApplySimplify)
1129 .function("_op", &ApplyPathOp)
1130
1131 // Exporting
1132 .function("toSVGString", &ToSVGString)
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001133 .function("toCmds", &ToCmds)
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001134
Kevin Lubick217056c2018-09-20 17:39:31 -04001135 .function("setFillType", &SkPath::setFillType)
1136 .function("getFillType", &SkPath::getFillType)
1137 .function("getBounds", &SkPath::getBounds)
1138 .function("computeTightBounds", &SkPath::computeTightBounds)
1139 .function("equals", &Equals)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001140 .function("copy", &CopyPath)
1141#ifdef SK_DEBUG
1142 .function("dump", select_overload<void() const>(&SkPath::dump))
1143 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
1144#endif
1145 ;
Kevin Lubick217056c2018-09-20 17:39:31 -04001146
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001147 class_<SkPathMeasure>("SkPathMeasure")
1148 .constructor<const SkPath&, bool, SkScalar>()
1149 .function("getLength", &SkPathMeasure::getLength)
1150 .function("getPosTan", optional_override([](SkPathMeasure& self,
1151 SkScalar distance) -> PosTan {
1152 SkPoint p{0, 0};
1153 SkVector v{0, 0};
1154 if (!self.getPosTan(distance, &p, &v)) {
1155 SkDebugf("zero-length path in getPosTan\n");
1156 }
1157 return PosTan{p.x(), p.y(), v.x(), v.y()};
1158 }))
1159 .function("isClosed", &SkPathMeasure::isClosed)
1160 .function("nextContour", &SkPathMeasure::nextContour);
1161
Kevin Lubickcc13fd32019-04-05 13:00:01 -04001162 class_<SkPictureRecorder>("SkPictureRecorder")
1163 .constructor<>()
1164 .function("beginRecording", optional_override([](SkPictureRecorder& self,
1165 const SkRect& bounds) -> SkCanvas* {
1166 return self.beginRecording(bounds, nullptr, 0);
1167 }), allow_raw_pointers())
1168 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
1169 -> sk_sp<SkPicture> {
1170 return self.finishRecordingAsPicture(0);
1171 }), allow_raw_pointers());
1172
1173 class_<SkPicture>("SkPicture")
1174 .smart_ptr<sk_sp<SkPicture>>("sk_sp<SkPicture>")
1175 // The serialized format of an SkPicture (informally called an "skp"), is not something
1176 // that clients should ever rely on. It is useful when filing bug reports, but that's
1177 // about it. The format may change at anytime and no promises are made for backwards
1178 // or forward compatibility.
1179 .function("DEBUGONLY_serialize", optional_override([](SkPicture& self) -> sk_sp<SkData> {
1180 // Emscripten doesn't play well with optional arguments, which we don't
1181 // want to expose anyway.
1182 return self.serialize();
1183 }), allow_raw_pointers());
1184
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001185 class_<SkShader>("SkShader")
1186 .smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>");
1187
Kevin Lubick217056c2018-09-20 17:39:31 -04001188 class_<SkSurface>("SkSurface")
1189 .smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
Greg Danielbae71212019-03-01 15:24:35 -05001190 .function("_flush", select_overload<void()>(&SkSurface::flush))
Kevin Lubick543f3522019-03-08 10:04:28 -05001191 .function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
1192 .function("height", &SkSurface::height)
Mike Reed114bde82018-11-21 09:12:09 -05001193 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
1194 .function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
Kevin Lubick543f3522019-03-08 10:04:28 -05001195 .function("makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1196 return self.makeSurface(toSkImageInfo(sii));
1197 }), allow_raw_pointers())
1198 .function("width", &SkSurface::width);
Kevin Lubick217056c2018-09-20 17:39:31 -04001199
Kevin Lubick61887c72019-09-26 13:20:50 -04001200#ifndef SK_NO_FONTS
Kevin Lubickec4903d2019-01-14 08:36:08 -05001201 class_<SkTextBlob>("SkTextBlob")
1202 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<SkTextBlob>>")
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001203 .class_function("_MakeFromRSXform", optional_override([](uintptr_t /* char* */ sptr,
1204 size_t strBtyes,
1205 uintptr_t /* SkRSXform* */ xptr,
1206 const SkFont& font,
1207 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
1208 // See comment above for uintptr_t explanation
1209 const char* str = reinterpret_cast<const char*>(sptr);
1210 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
1211
1212 return SkTextBlob::MakeFromRSXform(str, strBtyes, xforms, font, encoding);
1213 }), allow_raw_pointers())
Kevin Lubick543f3522019-03-08 10:04:28 -05001214 .class_function("_MakeFromText", optional_override([](uintptr_t /* char* */ sptr,
1215 size_t len, const SkFont& font,
1216 SkTextEncoding encoding)->sk_sp<SkTextBlob> {
Kevin Lubickec4903d2019-01-14 08:36:08 -05001217 // See comment above for uintptr_t explanation
1218 const char* str = reinterpret_cast<const char*>(sptr);
1219 return SkTextBlob::MakeFromText(str, len, font, encoding);
1220 }), allow_raw_pointers());
1221
Kevin Lubickddd0a332018-12-12 10:35:13 -05001222 class_<SkTypeface>("SkTypeface")
1223 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<SkTypeface>");
Kevin Lubick61887c72019-09-26 13:20:50 -04001224#endif
Kevin Lubickddd0a332018-12-12 10:35:13 -05001225
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001226 class_<SkVertices>("SkVertices")
1227 .smart_ptr<sk_sp<SkVertices>>("sk_sp<SkVertices>")
1228 .function("_applyBones", optional_override([](SkVertices& self, uintptr_t /* Bone* */ bptr, int boneCount)->sk_sp<SkVertices> {
1229 // See comment above for uintptr_t explanation
1230 const Bone* bones = reinterpret_cast<const Bone*>(bptr);
1231 return self.applyBones(bones, boneCount);
1232 }))
1233 .function("bounds", &SkVertices::bounds)
1234 .function("mode", &SkVertices::mode)
1235 .function("uniqueID", &SkVertices::uniqueID)
Kevin Lubick12c0e502018-11-28 12:51:56 -05001236#ifdef SK_DEBUG
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001237 .function("dumpPositions", optional_override([](SkVertices& self)->void {
1238 auto pos = self.positions();
1239 for(int i = 0; i< self.vertexCount(); i++) {
1240 SkDebugf("position[%d] = (%f, %f)\n", i, pos[i].x(), pos[i].y());
1241 }
1242 }))
Kevin Lubick12c0e502018-11-28 12:51:56 -05001243#endif
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001244 .function("vertexCount", &SkVertices::vertexCount);
1245
Kevin Lubickd6ba7252019-06-03 14:38:05 -04001246 // Not intended to be called directly by clients
1247 class_<SkVertices::Builder>("_SkVerticesBuilder")
1248 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
1249 .function("boneIndices", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneIndices* */{
1250 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1251 return reinterpret_cast<uintptr_t>(self.boneIndices());
1252 }))
1253 .function("boneWeights", optional_override([](SkVertices::Builder& self)->uintptr_t /* BoneWeights* */{
1254 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1255 return reinterpret_cast<uintptr_t>(self.boneWeights());
1256 }))
1257 .function("colors", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkColor* */{
1258 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1259 return reinterpret_cast<uintptr_t>(self.colors());
1260 }))
1261 .function("detach", &SkVertices::Builder::detach)
1262 .function("indices", optional_override([](SkVertices::Builder& self)->uintptr_t /* uint16_t* */{
1263 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1264 return reinterpret_cast<uintptr_t>(self.indices());
1265 }))
1266 .function("positions", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1267 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1268 return reinterpret_cast<uintptr_t>(self.positions());
1269 }))
1270 .function("texCoords", optional_override([](SkVertices::Builder& self)->uintptr_t /* SkPoint* */{
1271 // Emscripten won't let us return bare pointers, but we can return ints just fine.
1272 return reinterpret_cast<uintptr_t>(self.texCoords());
1273 }));
1274
Kevin Lubickea905ec2018-11-30 14:05:58 -05001275 enum_<SkAlphaType>("AlphaType")
1276 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
1277 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
1278 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001279
1280 enum_<SkBlendMode>("BlendMode")
1281 .value("Clear", SkBlendMode::kClear)
1282 .value("Src", SkBlendMode::kSrc)
1283 .value("Dst", SkBlendMode::kDst)
1284 .value("SrcOver", SkBlendMode::kSrcOver)
1285 .value("DstOver", SkBlendMode::kDstOver)
1286 .value("SrcIn", SkBlendMode::kSrcIn)
1287 .value("DstIn", SkBlendMode::kDstIn)
1288 .value("SrcOut", SkBlendMode::kSrcOut)
1289 .value("DstOut", SkBlendMode::kDstOut)
1290 .value("SrcATop", SkBlendMode::kSrcATop)
1291 .value("DstATop", SkBlendMode::kDstATop)
1292 .value("Xor", SkBlendMode::kXor)
1293 .value("Plus", SkBlendMode::kPlus)
1294 .value("Modulate", SkBlendMode::kModulate)
1295 .value("Screen", SkBlendMode::kScreen)
1296 .value("Overlay", SkBlendMode::kOverlay)
1297 .value("Darken", SkBlendMode::kDarken)
1298 .value("Lighten", SkBlendMode::kLighten)
1299 .value("ColorDodge", SkBlendMode::kColorDodge)
1300 .value("ColorBurn", SkBlendMode::kColorBurn)
1301 .value("HardLight", SkBlendMode::kHardLight)
1302 .value("SoftLight", SkBlendMode::kSoftLight)
1303 .value("Difference", SkBlendMode::kDifference)
1304 .value("Exclusion", SkBlendMode::kExclusion)
1305 .value("Multiply", SkBlendMode::kMultiply)
1306 .value("Hue", SkBlendMode::kHue)
1307 .value("Saturation", SkBlendMode::kSaturation)
1308 .value("Color", SkBlendMode::kColor)
1309 .value("Luminosity", SkBlendMode::kLuminosity);
Kevin Lubick217056c2018-09-20 17:39:31 -04001310
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001311 enum_<SkBlurStyle>("BlurStyle")
1312 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
1313 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
1314 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
1315 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
Kevin Lubick217056c2018-09-20 17:39:31 -04001316
Kevin Lubickeb2f6b02018-11-29 15:07:02 -05001317 enum_<SkClipOp>("ClipOp")
1318 .value("Difference", SkClipOp::kDifference)
1319 .value("Intersect", SkClipOp::kIntersect);
1320
Kevin Lubickea905ec2018-11-30 14:05:58 -05001321 enum_<SkColorType>("ColorType")
1322 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
1323 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
1324 .value("ARGB_4444", SkColorType::kARGB_4444_SkColorType)
1325 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
1326 .value("RGB_888x", SkColorType::kRGB_888x_SkColorType)
1327 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
1328 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
1329 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
1330 .value("Gray_8", SkColorType::kGray_8_SkColorType)
1331 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
Robert Phillipsd470e1b2019-09-04 15:05:35 -04001332 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType)
Robert Phillipsea1b30b2019-09-19 16:05:48 -04001333 .value("R8G8_unorm", SkColorType::kR8G8_unorm_SkColorType)
1334 .value("A16_unorm", SkColorType::kA16_unorm_SkColorType)
1335 .value("R16G16_unorm", SkColorType::kR16G16_unorm_SkColorType)
1336 .value("A16_float", SkColorType::kA16_float_SkColorType)
1337 .value("R16G16_float", SkColorType::kR16G16_float_SkColorType)
1338 .value("R16G16B16A16_unorm", SkColorType::kR16G16B16A16_unorm_SkColorType);
Kevin Lubickea905ec2018-11-30 14:05:58 -05001339
Kevin Lubick217056c2018-09-20 17:39:31 -04001340 enum_<SkPath::FillType>("FillType")
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001341 .value("Winding", SkPath::FillType::kWinding_FillType)
1342 .value("EvenOdd", SkPath::FillType::kEvenOdd_FillType)
1343 .value("InverseWinding", SkPath::FillType::kInverseWinding_FillType)
1344 .value("InverseEvenOdd", SkPath::FillType::kInverseEvenOdd_FillType);
1345
Kevin Lubick0a1293c2018-12-03 12:31:04 -05001346 enum_<SkFilterQuality>("FilterQuality")
1347 .value("None", SkFilterQuality::kNone_SkFilterQuality)
1348 .value("Low", SkFilterQuality::kLow_SkFilterQuality)
1349 .value("Medium", SkFilterQuality::kMedium_SkFilterQuality)
1350 .value("High", SkFilterQuality::kHigh_SkFilterQuality);
1351
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001352 enum_<SkEncodedImageFormat>("ImageFormat")
1353 .value("PNG", SkEncodedImageFormat::kPNG)
1354 .value("JPEG", SkEncodedImageFormat::kJPEG);
1355
1356 enum_<SkPaint::Style>("PaintStyle")
1357 .value("Fill", SkPaint::Style::kFill_Style)
1358 .value("Stroke", SkPaint::Style::kStroke_Style)
1359 .value("StrokeAndFill", SkPaint::Style::kStrokeAndFill_Style);
1360
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001361 enum_<SkPathOp>("PathOp")
1362 .value("Difference", SkPathOp::kDifference_SkPathOp)
1363 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
1364 .value("Union", SkPathOp::kUnion_SkPathOp)
1365 .value("XOR", SkPathOp::kXOR_SkPathOp)
1366 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
1367
Kevin Lubickb9db3902018-11-26 11:47:54 -05001368 enum_<SkPaint::Cap>("StrokeCap")
1369 .value("Butt", SkPaint::Cap::kButt_Cap)
1370 .value("Round", SkPaint::Cap::kRound_Cap)
1371 .value("Square", SkPaint::Cap::kSquare_Cap);
1372
1373 enum_<SkPaint::Join>("StrokeJoin")
1374 .value("Miter", SkPaint::Join::kMiter_Join)
1375 .value("Round", SkPaint::Join::kRound_Join)
1376 .value("Bevel", SkPaint::Join::kBevel_Join);
1377
Kevin Lubickec4903d2019-01-14 08:36:08 -05001378 enum_<SkTextEncoding>("TextEncoding")
1379 .value("UTF8", SkTextEncoding::kUTF8)
1380 .value("UTF16", SkTextEncoding::kUTF16)
1381 .value("UTF32", SkTextEncoding::kUTF32)
1382 .value("GlyphID", SkTextEncoding::kGlyphID);
Kevin Lubickb9db3902018-11-26 11:47:54 -05001383
Mike Reed5c5de212019-04-03 16:51:47 -04001384 enum_<SkTileMode>("TileMode")
1385 .value("Clamp", SkTileMode::kClamp)
1386 .value("Repeat", SkTileMode::kRepeat)
1387 .value("Mirror", SkTileMode::kMirror)
Mike Reed5c5de212019-04-03 16:51:47 -04001388 .value("Decal", SkTileMode::kDecal);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001389
1390 enum_<SkVertices::VertexMode>("VertexMode")
1391 .value("Triangles", SkVertices::VertexMode::kTriangles_VertexMode)
1392 .value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
Kevin Lubickb9db3902018-11-26 11:47:54 -05001393 .value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001394
Kevin Lubick217056c2018-09-20 17:39:31 -04001395
1396 // A value object is much simpler than a class - it is returned as a JS
1397 // object and does not require delete().
1398 // https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
Kevin Lubick1ba9c4d2019-02-22 10:04:06 -05001399 value_object<ShapedTextOpts>("ShapedTextOpts")
1400 .field("font", &ShapedTextOpts::font)
1401 .field("leftToRight", &ShapedTextOpts::leftToRight)
1402 .field("text", &ShapedTextOpts::text)
1403 .field("width", &ShapedTextOpts::width);
1404
Kevin Lubick217056c2018-09-20 17:39:31 -04001405 value_object<SkRect>("SkRect")
1406 .field("fLeft", &SkRect::fLeft)
1407 .field("fTop", &SkRect::fTop)
1408 .field("fRight", &SkRect::fRight)
1409 .field("fBottom", &SkRect::fBottom);
1410
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001411 value_object<SimpleRRect>("SkRRect")
1412 .field("rect", &SimpleRRect::rect)
Kevin Lubick7d644e12019-09-11 14:22:22 -04001413 .field("rx1", &SimpleRRect::rx1)
1414 .field("ry1", &SimpleRRect::ry1)
1415 .field("rx2", &SimpleRRect::rx2)
1416 .field("ry2", &SimpleRRect::ry2)
1417 .field("rx3", &SimpleRRect::rx3)
1418 .field("ry3", &SimpleRRect::ry3)
1419 .field("rx4", &SimpleRRect::rx4)
1420 .field("ry4", &SimpleRRect::ry4);
Kevin Lubick2e5fe352019-09-03 12:59:06 -04001421
Mike Reed114bde82018-11-21 09:12:09 -05001422 value_object<SkIRect>("SkIRect")
1423 .field("fLeft", &SkIRect::fLeft)
1424 .field("fTop", &SkIRect::fTop)
1425 .field("fRight", &SkIRect::fRight)
1426 .field("fBottom", &SkIRect::fBottom);
1427
Kevin Lubick50f377e2019-09-11 15:23:00 -04001428 value_object<TonalColors>("TonalColors")
1429 .field("ambient", &TonalColors::ambientColor)
1430 .field("spot", &TonalColors::spotColor);
1431
Kevin Lubickea905ec2018-11-30 14:05:58 -05001432 value_object<SimpleImageInfo>("SkImageInfo")
1433 .field("width", &SimpleImageInfo::width)
1434 .field("height", &SimpleImageInfo::height)
1435 .field("colorType", &SimpleImageInfo::colorType)
1436 .field("alphaType", &SimpleImageInfo::alphaType);
1437
Kevin Lubick217056c2018-09-20 17:39:31 -04001438 // SkPoints can be represented by [x, y]
1439 value_array<SkPoint>("SkPoint")
1440 .element(&SkPoint::fX)
1441 .element(&SkPoint::fY);
1442
Kevin Lubick61ef7b22018-11-27 13:26:59 -05001443 // SkPoint3s can be represented by [x, y, z]
1444 value_array<SkPoint3>("SkPoint3")
1445 .element(&SkPoint3::fX)
1446 .element(&SkPoint3::fY)
1447 .element(&SkPoint3::fZ);
1448
Kevin Lubickd3cfbca2019-03-15 15:36:29 -04001449 // PosTan can be represented by [px, py, tx, ty]
1450 value_array<PosTan>("PosTan")
1451 .element(&PosTan::px)
1452 .element(&PosTan::py)
1453 .element(&PosTan::tx)
1454 .element(&PosTan::ty);
1455
Kevin Lubick217056c2018-09-20 17:39:31 -04001456 // {"w": Number, "h", Number}
1457 value_object<SkSize>("SkSize")
1458 .field("w", &SkSize::fWidth)
1459 .field("h", &SkSize::fHeight);
1460
1461 value_object<SkISize>("SkISize")
1462 .field("w", &SkISize::fWidth)
1463 .field("h", &SkISize::fHeight);
1464
Kevin Lubickec4903d2019-01-14 08:36:08 -05001465 value_object<StrokeOpts>("StrokeOpts")
1466 .field("width", &StrokeOpts::width)
1467 .field("miter_limit", &StrokeOpts::miter_limit)
1468 .field("join", &StrokeOpts::join)
1469 .field("cap", &StrokeOpts::cap)
1470 .field("precision", &StrokeOpts::precision);
1471
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001472 // Allows clients to supply a 1D array of 9 elements and the bindings
1473 // will automatically turn it into a 3x3 2D matrix.
1474 // e.g. path.transform([0,1,2,3,4,5,6,7,8])
1475 // This is likely simpler for the client than exposing SkMatrix
1476 // directly and requiring them to do a lot of .delete().
1477 value_array<SimpleMatrix>("SkMatrix")
1478 .element(&SimpleMatrix::scaleX)
1479 .element(&SimpleMatrix::skewX)
1480 .element(&SimpleMatrix::transX)
1481
1482 .element(&SimpleMatrix::skewY)
1483 .element(&SimpleMatrix::scaleY)
1484 .element(&SimpleMatrix::transY)
1485
1486 .element(&SimpleMatrix::pers0)
1487 .element(&SimpleMatrix::pers1)
1488 .element(&SimpleMatrix::pers2);
1489
Kevin Lubickee91c072019-03-29 10:39:52 -04001490 constant("TRANSPARENT", SK_ColorTRANSPARENT);
1491 constant("RED", SK_ColorRED);
1492 constant("BLUE", SK_ColorBLUE);
1493 constant("YELLOW", SK_ColorYELLOW);
1494 constant("CYAN", SK_ColorCYAN);
1495 constant("BLACK", SK_ColorBLACK);
1496 constant("WHITE", SK_ColorWHITE);
Kevin Lubickb5ae3b52018-11-03 07:51:19 -04001497 // TODO(?)
1498
Kevin Lubickda3d8ac2019-01-07 11:08:55 -05001499 constant("MOVE_VERB", MOVE);
1500 constant("LINE_VERB", LINE);
1501 constant("QUAD_VERB", QUAD);
1502 constant("CONIC_VERB", CONIC);
1503 constant("CUBIC_VERB", CUBIC);
1504 constant("CLOSE_VERB", CLOSE);
Kevin Lubick217056c2018-09-20 17:39:31 -04001505}