Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
canvaskit_bindings.cpp
Go to the documentation of this file.
1/*
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
20#include "include/core/SkData.h"
25#include "include/core/SkM44.h"
28#include "include/core/SkPath.h"
66#include "src/core/SkPathPriv.h"
70
72#include <emscripten.h>
73#include <emscripten/bind.h>
74#include <emscripten/html5.h>
75
76#if defined(CK_ENABLE_WEBGL) || defined(CK_ENABLE_WEBGPU)
77#define ENABLE_GPU
78#endif
79
80#ifdef ENABLE_GPU
87#endif // ENABLE_GPU
88
89#ifdef CK_ENABLE_WEBGL
91#include "include/gpu/GrTypes.h"
101
102#include <GLES2/gl2.h>
103#endif // CK_ENABLE_WEBGL
104
105#ifdef CK_ENABLE_WEBGPU
106#include <emscripten/html5_webgpu.h>
107#include <webgpu/webgpu.h>
108#include <webgpu/webgpu_cpp.h>
109#endif // CK_ENABLE_WEBGPU
110
111#ifndef CK_NO_FONTS
112#include "include/core/SkFont.h"
117#ifdef CK_INCLUDE_PARAGRAPH
119#endif // CK_INCLUDE_PARAGRAPH
120#endif // CK_NO_FONTS
121
122#ifdef CK_INCLUDE_PATHOPS
124#endif
125
126#if defined(CK_INCLUDE_RUNTIME_EFFECT)
128#endif
129
130#ifndef CK_NO_FONTS
132#endif
133
134#if defined(CK_EMBED_FONT)
135struct SkEmbeddedResource { const uint8_t* data; size_t size; };
137extern "C" const SkEmbeddedResourceHeader SK_EMBEDDED_FONTS;
138#endif
139
140#if defined(GR_TEST_UTILS)
141#error "This define should not be set, as it brings in test-only things and bloats codesize."
142#endif
143
144#if defined(SK_CODEC_DECODES_BMP)
146#endif
147#if defined(SK_CODEC_DECODES_GIF)
149#endif
150#if defined(SK_CODEC_DECODES_ICO)
152#endif
153#if defined(SK_CODEC_DECODES_JPEG)
155#endif
156#if defined(SK_CODEC_DECODES_PNG)
158#endif
159#if defined(SK_CODEC_DECODES_WBMP)
161#endif
162#if defined(SK_CODEC_DECODES_WEBP)
164#endif
165
166// We'd like clients to be able to compile in as many or few codecs as they want (e.g. codesize)
167std::unique_ptr<SkCodec> DecodeImageData(sk_sp<SkData> data) {
168 if (data == nullptr) {
169 return nullptr;
170 }
171 // These codecs are arbitrarily ordered in alphabetical order.
172#if defined(SK_CODEC_DECODES_BMP)
173 if (SkBmpDecoder::IsBmp(data->data(), data->size())) {
174 return SkBmpDecoder::Decode(data, nullptr);
175 }
176#endif
177#if defined(SK_CODEC_DECODES_GIF)
178 if (SkGifDecoder::IsGif(data->data(), data->size())) {
179 return SkGifDecoder::Decode(data, nullptr);
180 }
181#endif
182#if defined(SK_CODEC_DECODES_ICO)
183 if (SkIcoDecoder::IsIco(data->data(), data->size())) {
184 return SkIcoDecoder::Decode(data, nullptr);
185 }
186#endif
187#if defined(SK_CODEC_DECODES_JPEG)
188 if (SkJpegDecoder::IsJpeg(data->data(), data->size())) {
189 return SkJpegDecoder::Decode(data, nullptr);
190 }
191#endif
192#if defined(SK_CODEC_DECODES_PNG)
193 if (SkPngDecoder::IsPng(data->data(), data->size())) {
194 return SkPngDecoder::Decode(data, nullptr);
195 }
196#endif
197#if defined(SK_CODEC_DECODES_WBMP)
198 if (SkWbmpDecoder::IsWbmp(data->data(), data->size())) {
199 return SkWbmpDecoder::Decode(data, nullptr);
200 }
201#endif
202#if defined(SK_CODEC_DECODES_WEBP)
203 if (SkWebpDecoder::IsWebp(data->data(), data->size())) {
204 return SkWebpDecoder::Decode(data, nullptr);
205 }
206#endif
207 return nullptr;
208}
209
212 if (mPtr) {
213 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
214 this->set9(nineMatrixValues);
215 }
216 }
217};
218
220 float* fourFloats = reinterpret_cast<float*>(cPtr);
222 memcpy(&color, fourFloats, 4 * sizeof(float));
223 return color;
224}
225
227 // In order, these floats should be 4 floats for the rectangle
228 // (left, top, right, bottom) and then 8 floats for the radii
229 // (upper left, upper right, lower right, lower left).
230 const SkScalar* twelveFloats = reinterpret_cast<const SkScalar*>(fPtr);
231 const SkRect rect = reinterpret_cast<const SkRect*>(twelveFloats)[0];
232 const SkVector* radiiValues = reinterpret_cast<const SkVector*>(twelveFloats + 4);
233
234 SkRRect rr;
235 rr.setRectRadii(rect, radiiValues);
236 return rr;
237}
238
239// Surface creation structs and helpers
247
252
253#ifdef CK_ENABLE_WEBGL
254
255// Set the pixel format based on the colortype.
256// These degrees of freedom are removed from canvaskit only to keep the interface simpler.
257struct ColorSettings {
258 ColorSettings(sk_sp<SkColorSpace> colorSpace) {
259 if (colorSpace == nullptr || colorSpace->isSRGB()) {
261 pixFormat = GR_GL_RGBA8;
262 } else {
264 pixFormat = GR_GL_RGBA16F;
265 }
266 }
268 GrGLenum pixFormat;
269};
270
272 // We assume that any calls we make to GL for the remainder of this function will go to the
273 // desired WebGL Context.
274 // setup interface.
275 auto interface = GrGLInterfaces::MakeWebGL();
276 // setup context
277 return GrDirectContexts::MakeGL(interface);
278}
279
280sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrDirectContext> dContext, int width, int height,
281 sk_sp<SkColorSpace> colorSpace, int sampleCnt, int stencil) {
282 // WebGL should already be clearing the color and stencil buffers, but do it again here to
283 // ensure Skia receives them in the expected state.
284 glBindFramebuffer(GL_FRAMEBUFFER, 0);
285 glClearColor(0, 0, 0, 0);
286 glClearStencil(0);
287 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
289
290 // The on-screen canvas is FBO 0. Wrap it in a Skia render target so Skia can render to it.
292 info.fFBOID = 0;
293
294 if (!colorSpace) {
295 colorSpace = SkColorSpace::MakeSRGB();
296 }
297
298 const auto colorSettings = ColorSettings(colorSpace);
299 info.fFormat = colorSettings.pixFormat;
300 auto target = GrBackendRenderTargets::MakeGL(width, height, sampleCnt, stencil, info);
302 target,
304 colorSettings.colorType,
305 colorSpace,
306 nullptr));
307 return surface;
308}
309
310sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrDirectContext> dContext, int width, int height,
311 sk_sp<SkColorSpace> colorSpace) {
312 GrGLint sampleCnt;
313 glGetIntegerv(GL_SAMPLES, &sampleCnt);
314
315 GrGLint stencil;
316 glGetIntegerv(GL_STENCIL_BITS, &stencil);
317
318 return MakeOnScreenGLSurface(dContext, width, height, colorSpace, sampleCnt, stencil);
319}
320
321sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrDirectContext> dContext, int width, int height) {
324
327 info,
328 0,
330 nullptr,
331 true));
332 return surface;
333}
334
335sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrDirectContext> dContext, SimpleImageInfo sii) {
338 toSkImageInfo(sii),
339 0,
341 nullptr,
342 true));
343 return surface;
344}
345#endif // CK_ENABLE_WEBGL
346
347#ifdef CK_ENABLE_WEBGPU
348
351 wgpu::Device device = wgpu::Device::Acquire(emscripten_webgpu_get_device());
352 return GrDirectContext::MakeDawn(device, options);
353}
354
355sk_sp<SkSurface> MakeGPUTextureSurface(sk_sp<GrDirectContext> dContext,
356 uint32_t textureHandle, uint32_t textureFormat,
357 int width, int height, sk_sp<SkColorSpace> colorSpace) {
358 if (!colorSpace) {
359 colorSpace = SkColorSpace::MakeSRGB();
360 }
361
362 wgpu::TextureFormat format = static_cast<wgpu::TextureFormat>(textureFormat);
363 wgpu::Texture texture(emscripten_webgpu_import_texture(textureHandle));
364 emscripten_webgpu_release_js_handle(textureHandle);
365
366 // GrDawnRenderTargetInfo currently only supports a 1-mip TextureView.
367 constexpr uint32_t mipLevelCount = 1;
368 constexpr uint32_t sampleCount = 1;
369
370 GrDawnTextureInfo info;
371 info.fTexture = texture;
372 info.fFormat = format;
373 info.fLevelCount = mipLevelCount;
374
377 dContext.get(),
378 target,
380 sampleCount,
381 colorSpace->isSRGB() ? kRGBA_8888_SkColorType : kRGBA_F16_SkColorType,
382 colorSpace,
383 nullptr);
384}
385
386bool ReplaceBackendTexture(SkSurface& surface, uint32_t textureHandle, uint32_t textureFormat,
387 int width, int height) {
388 wgpu::TextureFormat format = static_cast<wgpu::TextureFormat>(textureFormat);
389 wgpu::Texture texture(emscripten_webgpu_import_texture(textureHandle));
390 emscripten_webgpu_release_js_handle(textureHandle);
391
392 GrDawnTextureInfo info;
393 info.fTexture = texture;
394 info.fFormat = format;
395 info.fLevelCount = 1;
396
397 // Use kDiscard_ContentChangeMode to discard the contents of the old backing texture. This not
398 // only avoids an unnecessary blit, we also don't support copying the contents of a swapchain
399 // texture due to the default GPUCanvasConfiguration usage bits we used when configuring the
400 // GPUCanvasContext in JS.
401 //
402 // The default usage bits only contain GPUTextureUsage.RENDER_ATTACHMENT. To support a copy we
403 // would need to also set GPUTextureUsage.TEXTURE_BINDING (to sample it in a shader) or
404 // GPUTextureUsage.COPY_SRC (for a copy command).
405 //
406 // See https://www.w3.org/TR/webgpu/#namespacedef-gputextureusage and
407 // https://www.w3.org/TR/webgpu/#dictdef-gpucanvasconfiguration.
409 return surface.replaceBackendTexture(target, kTopLeft_GrSurfaceOrigin,
411}
412
413#endif // CK_ENABLE_WEBGPU
414
415//========================================================================================
416// Path things
417//========================================================================================
418
419// All these Apply* methods are simple wrappers to avoid returning an object.
420// The default WASM bindings produce code that will leak if a return value
421// isn't assigned to a JS variable and has delete() called on it.
422// These Apply methods, combined with the smarter binding code allow for chainable
423// commands that don't leak if the return value is ignored (i.e. when used intuitively).
424void ApplyAddPath(SkPath& orig, const SkPath& newPath,
425 SkScalar scaleX, SkScalar skewX, SkScalar transX,
426 SkScalar skewY, SkScalar scaleY, SkScalar transY,
427 SkScalar pers0, SkScalar pers1, SkScalar pers2,
428 bool extendPath) {
429 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
430 skewY , scaleY, transY,
431 pers0 , pers1 , pers2);
432 orig.addPath(newPath, m, extendPath ? SkPath::kExtend_AddPathMode :
434}
435
437 SkScalar radius) {
438 p.arcTo(x1, y1, x2, y2, radius);
439}
440
441void ApplyArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
442 bool useSmallArc, bool ccw, SkScalar x, SkScalar y) {
444 auto sweep = ccw ? SkPathDirection::kCCW : SkPathDirection::kCW;
445 orig.arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y);
446}
447
448void ApplyRArcToArcSize(SkPath& orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate,
449 bool useSmallArc, bool ccw, SkScalar dx, SkScalar dy) {
451 auto sweep = ccw ? SkPathDirection::kCCW : SkPathDirection::kCW;
452 orig.rArcTo(rx, ry, xAxisRotate, arcSize, sweep, dx, dy);
453}
454
456 p.close();
457}
458
460 SkScalar w) {
461 p.conicTo(x1, y1, x2, y2, w);
462}
463
465 SkScalar w) {
466 p.rConicTo(dx1, dy1, dx2, dy2, w);
467}
468
470 SkScalar x3, SkScalar y3) {
471 p.cubicTo(x1, y1, x2, y2, x3, y3);
472}
473
475 SkScalar dx3, SkScalar dy3) {
476 p.rCubicTo(dx1, dy1, dx2, dy2, dx3, dy3);
477}
478
480 p.lineTo(x, y);
481}
482
484 p.rLineTo(dx, dy);
485}
486
488 p.moveTo(x, y);
489}
490
492 p.rMoveTo(dx, dy);
493}
494
496 p.reset();
497}
498
500 p.rewind();
501}
502
504 p.quadTo(x1, y1, x2, y2);
505}
506
507void ApplyRQuadTo(SkPath& p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2) {
508 p.rQuadTo(dx1, dy1, dx2, dy2);
509}
510
512 SkScalar scaleX, SkScalar skewX, SkScalar transX,
513 SkScalar skewY, SkScalar scaleY, SkScalar transY,
514 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
515 SkMatrix m = SkMatrix::MakeAll(scaleX, skewX , transX,
516 skewY , scaleY, transY,
517 pers0 , pers1 , pers2);
518 orig.transform(m);
519}
520
521#ifdef CK_INCLUDE_PATHOPS
522bool ApplySimplify(SkPath& path) {
523 return Simplify(path, &path);
524}
525
526bool ApplyPathOp(SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
527 return Op(pathOne, pathTwo, op, &pathOne);
528}
529
530SkPathOrNull MakePathFromOp(const SkPath& pathOne, const SkPath& pathTwo, SkPathOp op) {
531 SkPath out;
532 if (Op(pathOne, pathTwo, op, &out)) {
533 return emscripten::val(out);
534 }
535 return emscripten::val::null();
536}
537
538SkPathOrNull MakeAsWinding(const SkPath& self) {
539 SkPath out;
540 if (AsWinding(self, &out)) {
541 return emscripten::val(out);
542 }
543 return emscripten::val::null();
544}
545#endif
546
548 return emscripten::val(SkParsePath::ToSVGString(path).c_str());
549}
550
552 SkPath path;
553 if (SkParsePath::FromSVGString(str.c_str(), &path)) {
554 return emscripten::val(path);
555 }
556 return emscripten::val::null();
557}
558
559bool CanInterpolate(const SkPath& path1, const SkPath& path2) {
561}
562
564 SkPath out;
565 bool succeed = path1.interpolate(path2, weight, &out);
566 if (succeed) {
567 return emscripten::val(out);
568 }
569 return emscripten::val::null();
570}
571
573 SkPath copy(a);
574 return copy;
575}
576
577bool Equals(const SkPath& a, const SkPath& b) {
578 return a == b;
579}
580
581// =================================================================================
582// Creating/Exporting Paths with cmd arrays
583// =================================================================================
584
585static const int MOVE = 0;
586static const int LINE = 1;
587static const int QUAD = 2;
588static const int CONIC = 3;
589static const int CUBIC = 4;
590static const int CLOSE = 5;
591
593 std::vector<SkScalar> cmds;
594 for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
595 switch (verb) {
597 cmds.insert(cmds.end(), {MOVE, pts[0].x(), pts[0].y()});
598 break;
600 cmds.insert(cmds.end(), {LINE, pts[1].x(), pts[1].y()});
601 break;
603 cmds.insert(cmds.end(), {QUAD, pts[1].x(), pts[1].y(), pts[2].x(), pts[2].y()});
604 break;
606 cmds.insert(cmds.end(), {CONIC,
607 pts[1].x(), pts[1].y(),
608 pts[2].x(), pts[2].y(), *w});
609 break;
611 cmds.insert(cmds.end(), {CUBIC,
612 pts[1].x(), pts[1].y(),
613 pts[2].x(), pts[2].y(),
614 pts[3].x(), pts[3].y()});
615 break;
617 cmds.push_back(CLOSE);
618 break;
619 }
620 }
621 return MakeTypedArray(cmds.size(), (const float*)cmds.data());
622}
623
625 const auto* cmds = reinterpret_cast<const float*>(cptr);
626 SkPath path;
627 float x1, y1, x2, y2, x3, y3;
628
629 // if there are not enough arguments, bail with the path we've constructed so far.
630 #define CHECK_NUM_ARGS(n) \
631 if ((i + n) > numCmds) { \
632 SkDebugf("Not enough args to match the verbs. Saw %d commands\n", numCmds); \
633 return emscripten::val::null(); \
634 }
635
636 for(int i = 0; i < numCmds;){
637 switch (sk_float_floor2int(cmds[i++])) {
638 case MOVE:
640 x1 = cmds[i++]; y1 = cmds[i++];
641 path.moveTo(x1, y1);
642 break;
643 case LINE:
645 x1 = cmds[i++]; y1 = cmds[i++];
646 path.lineTo(x1, y1);
647 break;
648 case QUAD:
650 x1 = cmds[i++]; y1 = cmds[i++];
651 x2 = cmds[i++]; y2 = cmds[i++];
652 path.quadTo(x1, y1, x2, y2);
653 break;
654 case CONIC:
656 x1 = cmds[i++]; y1 = cmds[i++];
657 x2 = cmds[i++]; y2 = cmds[i++];
658 x3 = cmds[i++]; // weight
659 path.conicTo(x1, y1, x2, y2, x3);
660 break;
661 case CUBIC:
663 x1 = cmds[i++]; y1 = cmds[i++];
664 x2 = cmds[i++]; y2 = cmds[i++];
665 x3 = cmds[i++]; y3 = cmds[i++];
666 path.cubicTo(x1, y1, x2, y2, x3, y3);
667 break;
668 case CLOSE:
669 path.close();
670 break;
671 default:
672 SkDebugf(" path: UNKNOWN command %f, aborting dump...\n", cmds[i-1]);
673 return emscripten::val::null();
674 }
675 }
676
677 #undef CHECK_NUM_ARGS
678
679 return emscripten::val(path);
680}
681
682void PathAddVerbsPointsWeights(SkPath& path, WASMPointerU8 verbsPtr, int numVerbs,
683 WASMPointerF32 ptsPtr, int numPts,
684 WASMPointerF32 wtsPtr, int numWts) {
685 const uint8_t* verbs = reinterpret_cast<const uint8_t*>(verbsPtr);
686 const float* pts = reinterpret_cast<const float*>(ptsPtr);
687 const float* weights = reinterpret_cast<const float*>(wtsPtr);
688
689 #define CHECK_NUM_POINTS(n) \
690 if ((ptIdx + n) > numPts) { \
691 SkDebugf("Not enough points to match the verbs. Saw %d points\n", numPts); \
692 return; \
693 }
694 #define CHECK_NUM_WEIGHTS(n) \
695 if ((wtIdx + n) > numWts) { \
696 SkDebugf("Not enough weights to match the verbs. Saw %d weights\n", numWts); \
697 return; \
698 }
699
700 path.incReserve(numPts);
701 int ptIdx = 0;
702 int wtIdx = 0;
703 for (int v = 0; v < numVerbs; ++v) {
704 switch (verbs[v]) {
705 case MOVE:
707 path.moveTo(pts[ptIdx], pts[ptIdx+1]);
708 ptIdx += 2;
709 break;
710 case LINE:
712 path.lineTo(pts[ptIdx], pts[ptIdx+1]);
713 ptIdx += 2;
714 break;
715 case QUAD:
717 path.quadTo(pts[ptIdx], pts[ptIdx+1], pts[ptIdx+2], pts[ptIdx+3]);
718 ptIdx += 4;
719 break;
720 case CONIC:
723 path.conicTo(pts[ptIdx], pts[ptIdx+1], pts[ptIdx+2], pts[ptIdx+3],
724 weights[wtIdx]);
725 ptIdx += 4;
726 wtIdx++;
727 break;
728 case CUBIC:
730 path.cubicTo(pts[ptIdx ], pts[ptIdx+1],
731 pts[ptIdx+2], pts[ptIdx+3],
732 pts[ptIdx+4], pts[ptIdx+5]);
733 ptIdx += 6;
734 break;
735 case CLOSE:
736 path.close();
737 break;
738 }
739 }
740 #undef CHECK_NUM_POINTS
741 #undef CHECK_NUM_WEIGHTS
742}
743
745 WASMPointerF32 ptsPtr, int numPts,
746 WASMPointerF32 wtsPtr, int numWts) {
747 SkPath path;
748 PathAddVerbsPointsWeights(path, verbsPtr, numVerbs, ptsPtr, numPts, wtsPtr, numWts);
749 return path;
750}
751
752//========================================================================================
753// Path Effects
754//========================================================================================
755
756bool ApplyDash(SkPath& path, SkScalar on, SkScalar off, SkScalar phase) {
757 SkScalar intervals[] = { on, off };
758 auto pe = SkDashPathEffect::Make(intervals, 2, phase);
759 if (!pe) {
760 SkDebugf("Invalid args to dash()\n");
761 return false;
762 }
764 if (pe->filterPath(&path, path, &rec, nullptr)) {
765 return true;
766 }
767 SkDebugf("Could not make dashed path\n");
768 return false;
769}
770
771bool ApplyTrim(SkPath& path, SkScalar startT, SkScalar stopT, bool isComplement) {
773 auto pe = SkTrimPathEffect::Make(startT, stopT, mode);
774 if (!pe) {
775 SkDebugf("Invalid args to trim(): startT and stopT must be in [0,1]\n");
776 return false;
777 }
779 if (pe->filterPath(&path, path, &rec, nullptr)) {
780 return true;
781 }
782 SkDebugf("Could not trim path\n");
783 return false;
784}
785
787 // Default values are set in interface.js which allows clients
788 // to set any number of them. Otherwise, the binding code complains if
789 // any are omitted.
795};
796
797bool ApplyStroke(SkPath& path, StrokeOpts opts) {
798 SkPaint p;
799 p.setStyle(SkPaint::kStroke_Style);
800 p.setStrokeCap(opts.cap);
801 p.setStrokeJoin(opts.join);
802 p.setStrokeWidth(opts.width);
803 p.setStrokeMiter(opts.miter_limit);
804
805 return skpathutils::FillPathWithPaint(path, p, &path, nullptr, opts.precision);
806}
807
808// This function is private, we call it in interface.js
810 // private methods accepting colors take pointers to floats already copied into wasm memory.
811 float* ambiFloats = reinterpret_cast<float*>(cPtrAmbi);
812 float* spotFloats = reinterpret_cast<float*>(cPtrSpot);
813 SkColor4f ambiColor = { ambiFloats[0], ambiFloats[1], ambiFloats[2], ambiFloats[3]};
814 SkColor4f spotColor = { spotFloats[0], spotFloats[1], spotFloats[2], spotFloats[3]};
815
816 // This function takes SkColor
817 SkColor resultAmbi, resultSpot;
819 ambiColor.toSkColor(), spotColor.toSkColor(),
820 &resultAmbi, &resultSpot);
821
822 // Convert back to color4f
823 const SkColor4f ambi4f = SkColor4f::FromColor(resultAmbi);
824 const SkColor4f spot4f = SkColor4f::FromColor(resultSpot);
825
826 // Re-use the caller's allocated memory to hold the result.
827 memcpy(ambiFloats, ambi4f.vec(), 4 * sizeof(SkScalar));
828 memcpy(spotFloats, spot4f.vec(), 4 * sizeof(SkScalar));
829}
830
831#ifdef CK_INCLUDE_RUNTIME_EFFECT
832struct RuntimeEffectUniform {
833 int columns;
834 int rows;
835 int slot; // the index into the uniforms array that this uniform begins.
836 bool isInteger;
837};
838
839RuntimeEffectUniform fromUniform(const SkRuntimeEffect::Uniform& u) {
840 RuntimeEffectUniform su;
841 su.rows = u.count; // arrayLength
842 su.columns = 1;
843 su.isInteger = false;
845 switch (u.type) {
846 case Type::kFloat: break;
847 case Type::kFloat2: su.columns = 2; break;
848 case Type::kFloat3: su.columns = 3; break;
849 case Type::kFloat4: su.columns = 4; break;
850 case Type::kFloat2x2: su.columns = 2; su.rows *= 2; break;
851 case Type::kFloat3x3: su.columns = 3; su.rows *= 3; break;
852 case Type::kFloat4x4: su.columns = 4; su.rows *= 4; break;
853 case Type::kInt: su.isInteger = true; break;
854 case Type::kInt2: su.columns = 2; su.isInteger = true; break;
855 case Type::kInt3: su.columns = 3; su.isInteger = true; break;
856 case Type::kInt4: su.columns = 4; su.isInteger = true; break;
857 }
858 su.slot = u.offset / sizeof(float);
859 return su;
860}
861
862void castUniforms(void* data, size_t dataLen, const SkRuntimeEffect& effect) {
863 if (dataLen != effect.uniformSize()) {
864 // Incorrect number of uniforms. Our code below could read/write off the end of the buffer.
865 // However, shader creation is going to fail anyway, so just do nothing.
866 return;
867 }
868
869 float* fltData = reinterpret_cast<float*>(data);
870 for (const auto& u : effect.uniforms()) {
871 RuntimeEffectUniform reu = fromUniform(u);
872 if (reu.isInteger) {
873 // The SkSL is expecting integers in the uniform data
874 for (int i = 0; i < reu.columns * reu.rows; ++i) {
875 int numAsInt = static_cast<int>(fltData[reu.slot + i]);
876 fltData[reu.slot + i] = SkBits2Float(numAsInt);
877 }
878 }
879 }
880}
881#endif
882
886
887// These objects have private destructors / delete methods - I don't think
888// we need to do anything other than tell emscripten to do nothing.
889namespace emscripten {
890 namespace internal {
891 template<typename ClassType>
892 void raw_destructor(ClassType*);
893
894 template<>
897
898 template<>
901
902#ifndef CK_NO_FONTS
903 template<>
906
907 template<>
910#endif
911 }
912}
913
914// toBytes returns a Uint8Array that has a copy of the data in the given SkData.
916 // By making the copy using the JS transliteration, we don't risk the SkData object being
917 // cleaned up before we make the copy.
918 return emscripten::val(
919 // https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#memory-views
920 typed_memory_view(data->size(), data->bytes())
921 ).call<Uint8Array>("slice"); // slice with no args makes a copy of the memory view.
922}
923
924#ifdef CK_ENABLE_WEBGL
925// We need to call into the JS side of things to free webGL contexts. This object will be called
926// with _setTextureCleanup after CanvasKit loads. The object will have one attribute,
927// a function called deleteTexture that takes two ints.
928JSObject textureCleanup = emscripten::val::null();
929
930struct TextureReleaseContext {
931 // This refers to which webgl context, i.e. which surface, owns the texture. We need this
932 // to route the deleteTexture to the right context.
933 uint32_t webglHandle;
934 // This refers to the index of the texture in the complete list of textures.
935 uint32_t texHandle;
936};
937
938void deleteJSTexture(SkImages::ReleaseContext rc) {
939 auto ctx = reinterpret_cast<TextureReleaseContext*>(rc);
940 textureCleanup.call<void>("deleteTexture", ctx->webglHandle, ctx->texHandle);
941 delete ctx;
942}
943
944class ExternalWebGLTexture : public GrExternalTexture {
945public:
946 ExternalWebGLTexture(GrBackendTexture backendTexture, uint32_t textureHandle, EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context) :
947 fBackendTexture(backendTexture), fWebglHandle(context), fTextureHandle(textureHandle) {}
948
950 return fBackendTexture;
951 }
952
953 void dispose() override {
954 textureCleanup.call<void>("deleteTexture", fWebglHandle, fTextureHandle);
955 }
956private:
957 GrBackendTexture fBackendTexture;
958
959 // This refers to which webgl context, i.e. which surface, owns the texture. We need this
960 // to route the deleteTexture to the right context.
961 uint32_t fWebglHandle;
962 // This refers to the index of the texture in the complete list of textures.
963 uint32_t fTextureHandle;
964};
965
966class WebGLTextureImageGenerator : public GrExternalTextureGenerator {
967public:
968 WebGLTextureImageGenerator(SkImageInfo ii, JSObject callbackObj):
970 fCallback(callbackObj) {}
971
972 ~WebGLTextureImageGenerator() override {
973 // This cleans up the associated TextureSource that is used to make the texture
974 // (i.e. "makeTexture" below). We expect this destructor to be called when the
975 // SkImage that this Generator belongs to is destroyed.
976 fCallback.call<void>("freeSrc");
977 }
978
979 std::unique_ptr<GrExternalTexture> generateExternalTexture(
980 GrRecordingContext* ctx, skgpu::Mipmapped mipmapped) override {
981 GrGLTextureInfo glInfo;
982
983 // This callback is defined in webgl.js
984 glInfo.fID = fCallback.call<uint32_t>("makeTexture");
985
986 // The format and target should match how we make the texture on the JS side
987 // See the implementation of the makeTexture function.
988 glInfo.fFormat = GR_GL_RGBA8;
989 glInfo.fTarget = GR_GL_TEXTURE_2D;
990
991 auto backendTexture =
992 GrBackendTextures::MakeGL(fInfo.width(), fInfo.height(), mipmapped, glInfo);
993
994 // In order to bind the image source to the texture, makeTexture has changed which
995 // texture is "in focus" for the WebGL context.
997 return std::make_unique<ExternalWebGLTexture>(
998 backendTexture, glInfo.fID, emscripten_webgl_get_current_context());
999 }
1000
1001private:
1002 JSObject fCallback;
1003};
1004
1005// callbackObj has two functions in it, one to create a texture "makeTexture" and one to clean up
1006// the underlying texture source "freeSrc". This way, we can create WebGL textures for each
1007// surface/WebGLContext that the image is used on (we cannot share WebGLTextures across contexts).
1008sk_sp<SkImage> MakeImageFromGenerator(SimpleImageInfo ii, JSObject callbackObj) {
1009 auto gen = std::make_unique<WebGLTextureImageGenerator>(toSkImageInfo(ii), callbackObj);
1011}
1012#endif // CK_ENABLE_WEBGL
1013
1014
1016 sk_sp<SkImage> img,
1018 int quality) {
1019 sk_sp<SkData> data = nullptr;
1022 opts.fQuality = quality;
1023 data = SkJpegEncoder::Encode(dContext, img.get(), opts);
1024 } else if (fmt == SkEncodedImageFormat::kPNG) {
1025 data = SkPngEncoder::Encode(dContext, img.get(), {});
1026 } else {
1028 if (quality >= 100) {
1030 opts.fQuality = 75; // This is effort to compress
1031 } else {
1033 opts.fQuality = quality;
1034 }
1035 data = SkWebpEncoder::Encode(dContext, img.get(), opts);
1036 }
1037 if (!data) {
1038 return emscripten::val::null();
1039 }
1040 return toBytes(data);
1041}
1042
1044#ifdef ENABLE_GPU
1045 constant("gpu", true);
1046 function("_MakeGrContext", &MakeGrContext);
1047#endif // ENABLE_GPU
1048
1049#ifdef CK_ENABLE_WEBGL
1050 constant("webgl", true);
1051 function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>)>(&MakeOnScreenGLSurface));
1052 function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>, int, int)>(&MakeOnScreenGLSurface));
1053 function("_MakeRenderTargetWH", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int)>(&MakeRenderTarget));
1054 function("_MakeRenderTargetII", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, SimpleImageInfo)>(&MakeRenderTarget));
1055#endif // CK_ENABLE_WEBGL
1056
1057#ifdef CK_ENABLE_WEBGPU
1058 constant("webgpu", true);
1059 function("_MakeGPUTextureSurface", &MakeGPUTextureSurface);
1060#endif // CK_ENABLE_WEBGPU
1061
1062 function("getDecodeCacheLimitBytes", &SkResourceCache::GetTotalByteLimit);
1063 function("setDecodeCacheLimitBytes", &SkResourceCache::SetTotalByteLimit);
1064 function("getDecodeCacheUsedBytes" , &SkResourceCache::GetTotalBytesUsed);
1065
1066 function("_computeTonalColors", &computeTonalColors);
1067 function("_decodeAnimatedImage", optional_override([](WASMPointerU8 iptr,
1069 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
1070 auto bytes = SkData::MakeFromMalloc(imgData, length);
1071 auto codec = DecodeImageData(bytes);
1072 if (codec == nullptr) {
1073 return nullptr;
1074 }
1075 auto aCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
1076 if (aCodec == nullptr) {
1077 return nullptr;
1078 }
1079
1080 return SkAnimatedImage::Make(std::move(aCodec));
1081 }), allow_raw_pointers());
1082 function("_decodeImage", optional_override([](WASMPointerU8 iptr,
1083 size_t length)->sk_sp<SkImage> {
1084 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
1085 auto bytes = SkData::MakeFromMalloc(imgData, length);
1086 auto codec = DecodeImageData(bytes);
1087 if (codec == nullptr) {
1088 return nullptr;
1089 }
1090 return std::get<0>(codec->getImage());
1091 }), allow_raw_pointers());
1092
1093 // These won't be called directly, there are corresponding JS helpers to deal with arrays.
1094 function("_MakeImage", optional_override([](SimpleImageInfo ii,
1095 WASMPointerU8 pPtr, int plen,
1096 size_t rowBytes)->sk_sp<SkImage> {
1097 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1099 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
1100
1101 return SkImages::RasterFromData(info, pixelData, rowBytes);
1102 }), allow_raw_pointers());
1103
1104 function("_getShadowLocalBounds", optional_override([](
1105 WASMPointerF32 ctmPtr, const SkPath& path,
1106 WASMPointerF32 zPlaneParamPtr, WASMPointerF32 lightPosPtr,
1107 SkScalar lightRadius, uint32_t flags, WASMPointerF32 outPtr) -> bool {
1108 SkMatrix ctm;
1109 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(ctmPtr);
1110 ctm.set9(nineMatrixValues);
1111 const SkVector3* zPlaneParams = reinterpret_cast<const SkVector3*>(zPlaneParamPtr);
1112 const SkVector3* lightPos = reinterpret_cast<const SkVector3*>(lightPosPtr);
1113 SkRect* outputBounds = reinterpret_cast<SkRect*>(outPtr);
1114 return SkShadowUtils::GetLocalBounds(ctm, path, *zPlaneParams, *lightPos, lightRadius,
1115 flags, outputBounds);
1116 }));
1117
1118#ifdef CK_SERIALIZE_SKP
1119 function("_MakePicture", optional_override([](WASMPointerU8 dPtr,
1120 size_t bytes)->sk_sp<SkPicture> {
1121 uint8_t* d = reinterpret_cast<uint8_t*>(dPtr);
1122 sk_sp<SkData> data = SkData::MakeFromMalloc(d, bytes);
1123
1124#ifndef CK_NO_FONTS
1125 // Be sure we can process the data stored when serializing the SkPicture.
1126 static SkOnce once;
1127 once([] {
1130 });
1131#endif
1132
1133 SkDeserialProcs dp;
1134 dp.fImageDataProc = [](sk_sp<SkData> bytes, std::optional<SkAlphaType> at, void* ctx) -> sk_sp<SkImage> {
1135 auto codec = DecodeImageData(bytes);
1136 if (codec == nullptr) {
1137 return nullptr;
1138 }
1139 SkImageInfo info = codec->getInfo();
1140 if (at.has_value()) {
1141 info = info.makeAlphaType(*at);
1142 } else if (kUnpremul_SkAlphaType == info.alphaType()) {
1143 // Otherwise, prefer premul over unpremul (this produces better filtering in general)
1145 }
1146 return std::get<0>(codec->getImage(info));
1147 };
1148
1149 return SkPicture::MakeFromData(data.get(), nullptr);
1150 }), allow_raw_pointers());
1151#endif
1152
1153#ifdef ENABLE_GPU
1154 class_<GrDirectContext>("GrDirectContext")
1155 .smart_ptr<sk_sp<GrDirectContext>>("sk_sp<GrDirectContext>")
1156 .function("_getResourceCacheLimitBytes",
1157 optional_override([](GrDirectContext& self)->size_t {
1158 int maxResources = 0;// ignored
1159 size_t currMax = 0;
1160 self.getResourceCacheLimits(&maxResources, &currMax);
1161 return currMax;
1162 }))
1163 .function("_getResourceCacheUsageBytes",
1164 optional_override([](GrDirectContext& self)->size_t {
1165 int usedResources = 0;// ignored
1166 size_t currUsage = 0;
1167 self.getResourceCacheUsage(&usedResources, &currUsage);
1168 return currUsage;
1169 }))
1170 .function("_releaseResourcesAndAbandonContext",
1172 .function("_setResourceCacheLimitBytes",
1173 optional_override([](GrDirectContext& self, size_t maxResourceBytes)->void {
1174 int maxResources = 0;
1175 size_t currMax = 0; // ignored
1176 self.getResourceCacheLimits(&maxResources, &currMax);
1177 self.setResourceCacheLimits(maxResources, maxResourceBytes);
1178 }));
1179#endif // ENABLE_GPU
1180#ifdef CK_ENABLE_WEBGL
1181 // This allows us to give the C++ code a JS callback to delete textures that
1182 // have been passed in via makeImageFromTexture and makeImageFromTextureSource.
1183 function("_setTextureCleanup", optional_override([](JSObject callbackObj)->void {
1184 textureCleanup = callbackObj;
1185 }));
1186#endif
1187
1188 class_<SkAnimatedImage>("AnimatedImage")
1189 .smart_ptr<sk_sp<SkAnimatedImage>>("sk_sp<AnimatedImage>")
1190 .function("currentFrameDuration", &SkAnimatedImage::currentFrameDuration)
1191 .function("decodeNextFrame", &SkAnimatedImage::decodeNextFrame)
1192 .function("getFrameCount", &SkAnimatedImage::getFrameCount)
1193 .function("getRepetitionCount", &SkAnimatedImage::getRepetitionCount)
1194 .function("height", optional_override([](SkAnimatedImage& self)->int32_t {
1195 // getBounds returns an SkRect, but internally, the width and height are ints.
1196 return SkScalarFloorToInt(self.getBounds().height());
1197 }))
1198 .function("makeImageAtCurrentFrame", &SkAnimatedImage::getCurrentFrame)
1199 .function("reset", &SkAnimatedImage::reset)
1200 .function("width", optional_override([](SkAnimatedImage& self)->int32_t {
1201 return SkScalarFloorToInt(self.getBounds().width());
1202 }));
1203
1204 class_<SkBlender>("Blender")
1205 .smart_ptr<sk_sp<SkBlender>>("sk_sp<Blender>")
1206 .class_function("Mode", &SkBlender::Mode);
1207
1208 class_<SkCanvas>("Canvas")
1209 .constructor<>()
1210 .constructor<SkScalar,SkScalar>()
1211 .function("_clear", optional_override([](SkCanvas& self, WASMPointerF32 cPtr) {
1212 self.clear(ptrToSkColor4f(cPtr));
1213 }))
1214 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
1215 .function("_clipRRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr, SkClipOp op, bool doAntiAlias) {
1216 self.clipRRect(ptrToSkRRect(fPtr), op, doAntiAlias);
1217 }))
1218 .function("_clipRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr, SkClipOp op, bool doAntiAlias) {
1219 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1220 self.clipRect(*rect, op, doAntiAlias);
1221 }))
1222 .function("_concat", optional_override([](SkCanvas& self, WASMPointerF32 mPtr) {
1223 //TODO(skbug.com/10108): make the JS side be column major.
1224 const SkScalar* sixteenMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1225 SkM44 m = SkM44::RowMajor(sixteenMatrixValues);
1226 self.concat(m);
1227 }))
1228 .function("_drawArc", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1229 SkScalar startAngle, SkScalar sweepAngle,
1230 bool useCenter, const SkPaint& paint) {
1231 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1232 self.drawArc(*oval, startAngle, sweepAngle, useCenter, paint);
1233 }))
1234 .function("_drawAtlasOptions", optional_override([](SkCanvas& self,
1235 const sk_sp<SkImage>& atlas, WASMPointerF32 xptr,
1236 WASMPointerF32 rptr, WASMPointerU32 cptr, int count,
1237 SkBlendMode mode, SkFilterMode filter, SkMipmapMode mipmap,
1238 const SkPaint* paint)->void {
1239 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
1240 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
1241 const SkColor* colors = nullptr;
1242 if (cptr) {
1243 colors = reinterpret_cast<const SkColor*>(cptr);
1244 }
1245 SkSamplingOptions sampling(filter, mipmap);
1246 self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
1247 nullptr, paint);
1248 }), allow_raw_pointers())
1249 .function("_drawAtlasCubic", optional_override([](SkCanvas& self,
1250 const sk_sp<SkImage>& atlas, WASMPointerF32 xptr,
1251 WASMPointerF32 rptr, WASMPointerU32 cptr, int count,
1252 SkBlendMode mode, float B, float C, const SkPaint* paint)->void {
1253 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
1254 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
1255 const SkColor* colors = nullptr;
1256 if (cptr) {
1257 colors = reinterpret_cast<const SkColor*>(cptr);
1258 }
1259 SkSamplingOptions sampling({B, C});
1260 self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
1261 nullptr, paint);
1262 }), allow_raw_pointers())
1263 .function("_drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
1264 .function("_drawColor", optional_override([](SkCanvas& self, WASMPointerF32 cPtr) {
1265 self.drawColor(ptrToSkColor4f(cPtr));
1266 }))
1267 .function("_drawColor", optional_override([](SkCanvas& self, WASMPointerF32 cPtr, SkBlendMode mode) {
1268 self.drawColor(ptrToSkColor4f(cPtr), mode);
1269 }))
1270 .function("_drawColorInt", optional_override([](SkCanvas& self, SkColor color, SkBlendMode mode) {
1271 self.drawColor(color, mode);
1272 }))
1273 .function("_drawDRRect", optional_override([](SkCanvas& self, WASMPointerF32 outerPtr,
1274 WASMPointerF32 innerPtr, const SkPaint& paint) {
1275 self.drawDRRect(ptrToSkRRect(outerPtr), ptrToSkRRect(innerPtr), paint);
1276 }))
1277 .function("_drawGlyphs", optional_override([](SkCanvas& self,
1278 int count,
1280 WASMPointerF32 positions,
1281 float x, float y,
1282 const SkFont& font,
1283 const SkPaint& paint)->void {
1284 self.drawGlyphs(count,
1285 reinterpret_cast<const uint16_t*>(glyphs),
1286 reinterpret_cast<const SkPoint*>(positions),
1287 {x, y}, font, paint);
1288 }))
1289 // TODO: deprecate this version, and require sampling
1290 .function("_drawImage", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1291 SkScalar x, SkScalar y, const SkPaint* paint) {
1292 self.drawImage(image.get(), x, y, SkSamplingOptions(), paint);
1293 }), allow_raw_pointers())
1294 .function("_drawImageCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
1295 SkScalar left, SkScalar top,
1296 float B, float C, // See SkSamplingOptions.h for docs.
1297 const SkPaint* paint)->void {
1298 self.drawImage(img.get(), left, top, SkSamplingOptions({B, C}), paint);
1299 }), allow_raw_pointers())
1300 .function("_drawImageOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
1301 SkScalar left, SkScalar top,
1302 SkFilterMode filter, SkMipmapMode mipmap,
1303 const SkPaint* paint)->void {
1304 self.drawImage(img.get(), left, top, {filter, mipmap}, paint);
1305 }), allow_raw_pointers())
1306
1307 .function("_drawImageNine", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1308 WASMPointerU32 centerPtr, WASMPointerF32 dstPtr,
1309 SkFilterMode filter, const SkPaint* paint)->void {
1310 const SkIRect* center = reinterpret_cast<const SkIRect*>(centerPtr);
1311 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1312
1313 self.drawImageNine(image.get(), *center, *dst, filter, paint);
1314 }), allow_raw_pointers())
1315 // TODO: deprecate this version, and require sampling
1316 .function("_drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1317 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1318 const SkPaint* paint, bool fastSample)->void {
1319 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1320 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1321 self.drawImageRect(image, *src, *dst, SkSamplingOptions(), paint,
1324 }), allow_raw_pointers())
1325 .function("_drawImageRectCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1326 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1327 float B, float C, // See SkSamplingOptions.h for docs.
1328 const SkPaint* paint)->void {
1329 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1330 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1331 auto constraint = SkCanvas::kStrict_SrcRectConstraint; // TODO: get from caller
1332 self.drawImageRect(image.get(), *src, *dst, SkSamplingOptions({B, C}), paint, constraint);
1333 }), allow_raw_pointers())
1334 .function("_drawImageRectOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1335 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1336 SkFilterMode filter, SkMipmapMode mipmap,
1337 const SkPaint* paint)->void {
1338 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1339 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1340 auto constraint = SkCanvas::kStrict_SrcRectConstraint; // TODO: get from caller
1341 self.drawImageRect(image.get(), *src, *dst, {filter, mipmap}, paint, constraint);
1342 }), allow_raw_pointers())
1343 .function("_drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
1344 .function("_drawOval", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1345 const SkPaint& paint)->void {
1346 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1347 self.drawOval(*oval, paint);
1348 }))
1349 .function("_drawPaint", &SkCanvas::drawPaint)
1350#ifdef CK_INCLUDE_PARAGRAPH
1351 .function("_drawParagraph", optional_override([](SkCanvas& self, skia::textlayout::Paragraph* p,
1352 SkScalar x, SkScalar y) {
1353 p->paint(&self, x, y);
1354 }), allow_raw_pointers())
1355#endif
1356 .function("_drawPath", &SkCanvas::drawPath)
1357 .function("_drawPatch", optional_override([](SkCanvas& self,
1358 WASMPointerF32 cubics,
1359 WASMPointerU32 colors,
1360 WASMPointerF32 texs,
1361 SkBlendMode mode,
1362 const SkPaint& paint)->void {
1363 self.drawPatch(reinterpret_cast<const SkPoint*>(cubics),
1364 reinterpret_cast<const SkColor*>(colors),
1365 reinterpret_cast<const SkPoint*>(texs),
1366 mode, paint);
1367 }))
1368 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
1369 // a bitmap. An SkPicture is a series of draw commands.
1370 .function("_drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
1371 .function("_drawPoints", optional_override([](SkCanvas& self, SkCanvas::PointMode mode,
1372 WASMPointerF32 pptr,
1373 int count, SkPaint& paint)->void {
1374 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
1375 self.drawPoints(mode, count, pts, paint);
1376 }))
1377 .function("_drawRRect",optional_override([](SkCanvas& self, WASMPointerF32 fPtr, const SkPaint& paint) {
1378 self.drawRRect(ptrToSkRRect(fPtr), paint);
1379 }))
1380 .function("_drawRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1381 const SkPaint& paint)->void {
1382 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1383 self.drawRect(*rect, paint);
1384 }))
1385 .function("_drawRect4f", optional_override([](SkCanvas& self, SkScalar left, SkScalar top,
1386 SkScalar right, SkScalar bottom,
1387 const SkPaint& paint)->void {
1388 const SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
1389 self.drawRect(rect, paint);
1390 }))
1391 .function("_drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
1392 WASMPointerF32 zPlaneParamPtr,
1393 WASMPointerF32 lightPosPtr,
1394 SkScalar lightRadius,
1395 WASMPointerF32 ambientColorPtr,
1396 WASMPointerF32 spotColorPtr,
1397 uint32_t flags) {
1398 const SkVector3* zPlaneParams = reinterpret_cast<const SkVector3*>(zPlaneParamPtr);
1399 const SkVector3* lightPos = reinterpret_cast<const SkVector3*>(lightPosPtr);
1400
1401 SkShadowUtils::DrawShadow(&self, path, *zPlaneParams, *lightPos, lightRadius,
1402 ptrToSkColor4f(ambientColorPtr).toSkColor(),
1403 ptrToSkColor4f(spotColorPtr).toSkColor(),
1404 flags);
1405 }))
1406#ifndef CK_NO_FONTS
1407 .function("_drawSimpleText", optional_override([](SkCanvas& self, WASMPointerU8 sptr,
1408 size_t len, SkScalar x, SkScalar y, const SkFont& font,
1409 const SkPaint& paint) {
1410 const char* str = reinterpret_cast<const char*>(sptr);
1411
1412 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
1413 }))
1414 .function("_drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
1415#endif
1416 .function("_drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
1417
1418 .function("_getDeviceClipBounds", optional_override([](const SkCanvas& self, WASMPointerI32 iPtr) {
1419 SkIRect* outputRect = reinterpret_cast<SkIRect*>(iPtr);
1420 if (!outputRect) {
1421 return; // output pointer cannot be null
1422 }
1423 self.getDeviceClipBounds(outputRect);
1424 }))
1425 // 4x4 matrix functions
1426 // Just like with getTotalMatrix, we allocate the buffer for the 16 floats to go in from
1427 // interface.js, so it can also free them when its done.
1428 .function("_getLocalToDevice", optional_override([](const SkCanvas& self, WASMPointerF32 mPtr) {
1429 SkScalar* sixteenMatrixValues = reinterpret_cast<SkScalar*>(mPtr);
1430 if (!sixteenMatrixValues) {
1431 return; // matrix cannot be null
1432 }
1433 SkM44 m = self.getLocalToDevice();
1434 m.getRowMajor(sixteenMatrixValues);
1435 }))
1436 .function("getSaveCount", &SkCanvas::getSaveCount)
1437 // We allocate room for the matrix from the JS side and free it there so as to not have
1438 // an awkward moment where we malloc something here and "just know" to free it on the
1439 // JS side.
1440 .function("_getTotalMatrix", optional_override([](const SkCanvas& self, WASMPointerU8 mPtr) {
1441 SkScalar* nineMatrixValues = reinterpret_cast<SkScalar*>(mPtr);
1442 if (!nineMatrixValues) {
1443 return; // matrix cannot be null
1444 }
1445 SkMatrix m = self.getTotalMatrix();
1446 m.get9(nineMatrixValues);
1447 }))
1448 .function("_makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1449 return self.makeSurface(toSkImageInfo(sii), nullptr);
1450 }), allow_raw_pointers())
1451
1452 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
1453 WASMPointerU8 pPtr,
1454 size_t dstRowBytes, int srcX, int srcY) {
1455 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1456 SkImageInfo dstInfo = toSkImageInfo(di);
1457
1458 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
1459 }), allow_raw_pointers())
1460 .function("restore", &SkCanvas::restore)
1461 .function("restoreToCount", &SkCanvas::restoreToCount)
1462 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
1463 .function("save", &SkCanvas::save)
1464 .function("_saveLayer", optional_override([](SkCanvas& self, const SkPaint* p, WASMPointerF32 fPtr,
1465 const SkImageFilter* backdrop, SkCanvas::SaveLayerFlags flags)->int {
1466 SkRect* bounds = reinterpret_cast<SkRect*>(fPtr);
1467 return self.saveLayer(SkCanvas::SaveLayerRec(bounds, p, backdrop, flags));
1468 }), allow_raw_pointers())
1469 .function("saveLayerPaint", optional_override([](SkCanvas& self, const SkPaint p)->int {
1470 return self.saveLayer(SkCanvas::SaveLayerRec(nullptr, &p, 0));
1471 }))
1472 .function("scale", &SkCanvas::scale)
1473 .function("skew", &SkCanvas::skew)
1474 .function("translate", &SkCanvas::translate)
1475 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
1476 WASMPointerU8 pPtr,
1477 size_t srcRowBytes, int dstX, int dstY) {
1478 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1479 SkImageInfo dstInfo = toSkImageInfo(di);
1480
1481 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
1482 }));
1483
1484 class_<SkColorFilter>("ColorFilter")
1485 .smart_ptr<sk_sp<SkColorFilter>>("sk_sp<ColorFilter>>")
1486 .class_function("_MakeBlend", optional_override([](WASMPointerF32 cPtr, SkBlendMode mode,
1488 return SkColorFilters::Blend(ptrToSkColor4f(cPtr), colorSpace, mode);
1489 }))
1490 .class_function("MakeCompose", &SkColorFilters::Compose)
1491 .class_function("MakeLerp", &SkColorFilters::Lerp)
1492 .class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
1493 .class_function("_makeMatrix", optional_override([](WASMPointerF32 fPtr) {
1494 float* twentyFloats = reinterpret_cast<float*>(fPtr);
1495 return SkColorFilters::Matrix(twentyFloats);
1496 }))
1497 .class_function("MakeSRGBToLinearGamma", &SkColorFilters::SRGBToLinearGamma)
1498 .class_function("MakeLuma", &SkLumaColorFilter::Make);
1499
1500 class_<SkContourMeasureIter>("ContourMeasureIter")
1501 .constructor<const SkPath&, bool, SkScalar>()
1503
1504 class_<SkContourMeasure>("ContourMeasure")
1505 .smart_ptr<sk_sp<SkContourMeasure>>("sk_sp<ContourMeasure>>")
1506 .function("_getPosTan", optional_override([](SkContourMeasure& self,
1507 SkScalar distance,
1508 WASMPointerF32 oPtr) -> void {
1509 SkPoint* pointAndVector = reinterpret_cast<SkPoint*>(oPtr);
1510 if (!self.getPosTan(distance, pointAndVector, pointAndVector + 1)) {
1511 SkDebugf("zero-length path in getPosTan\n");
1512 }
1513 }))
1514 .function("getSegment", optional_override([](SkContourMeasure& self, SkScalar startD,
1515 SkScalar stopD, bool startWithMoveTo) -> SkPath {
1516 SkPath p;
1517 bool ok = self.getSegment(startD, stopD, &p, startWithMoveTo);
1518 if (ok) {
1519 return p;
1520 }
1521 return SkPath();
1522 }))
1523 .function("isClosed", &SkContourMeasure::isClosed)
1524 .function("length", &SkContourMeasure::length);
1525
1526#ifndef CK_NO_FONTS
1527 class_<SkFont>("Font")
1528 .constructor<>()
1529 .constructor<sk_sp<SkTypeface>>()
1530 .constructor<sk_sp<SkTypeface>, SkScalar>()
1531 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
1532 .function("_getGlyphWidthBounds", optional_override([](SkFont& self, WASMPointerU16 gPtr,
1533 int numGlyphs, WASMPointerF32 wPtr,
1534 WASMPointerF32 rPtr,
1535 SkPaint* paint) {
1536 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
1537 // On the JS side only one of these is set at a time for easier ergonomics.
1538 SkRect* outputRects = reinterpret_cast<SkRect*>(rPtr);
1539 SkScalar* outputWidths = reinterpret_cast<SkScalar*>(wPtr);
1540 self.getWidthsBounds(glyphs, numGlyphs, outputWidths, outputRects, paint);
1541 }), allow_raw_pointers())
1542 .function("_getGlyphIDs", optional_override([](SkFont& self, WASMPointerU8 sptr,
1543 size_t strLen, size_t expectedCodePoints,
1544 WASMPointerU16 iPtr) -> int {
1545 char* str = reinterpret_cast<char*>(sptr);
1546 SkGlyphID* glyphIDs = reinterpret_cast<SkGlyphID*>(iPtr);
1547
1548 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
1549 glyphIDs, expectedCodePoints);
1550 return actualCodePoints;
1551 }))
1552 .function("getMetrics", optional_override([](SkFont& self) -> JSObject {
1553 SkFontMetrics fm;
1554 self.getMetrics(&fm);
1555
1556 JSObject j = emscripten::val::object();
1557 j.set("ascent", fm.fAscent);
1558 j.set("descent", fm.fDescent);
1559 j.set("leading", fm.fLeading);
1561 const float rect[] = {
1562 fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom
1563 };
1564 j.set("bounds", MakeTypedArray(4, rect));
1565 }
1566 return j;
1567 }))
1568 .function("_getGlyphIntercepts", optional_override([](SkFont& self,
1569 WASMPointerU16 gPtr, size_t numGlyphs, bool ownGlyphs,
1570 WASMPointerF32 pPtr, size_t numPos, bool ownPos,
1571 float top, float bottom) -> Float32Array {
1572 JSSpan<uint16_t> glyphs(gPtr, numGlyphs, ownGlyphs);
1573 JSSpan<float> pos (pPtr, numPos, ownPos);
1574 if (glyphs.size() > (pos.size() >> 1)) {
1575 return emscripten::val("Not enough x,y position pairs for glyphs");
1576 }
1577 auto sects = self.getIntercepts(glyphs.data(), SkToInt(glyphs.size()),
1578 (const SkPoint*)pos.data(), top, bottom);
1579 return MakeTypedArray(sects.size(), (const float*)sects.data());
1580 }), allow_raw_pointers())
1581 .function("getScaleX", &SkFont::getScaleX)
1582 .function("getSize", &SkFont::getSize)
1583 .function("getSkewX", &SkFont::getSkewX)
1584 .function("isEmbolden", &SkFont::isEmbolden)
1585 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
1586 .function("setEdging", &SkFont::setEdging)
1587 .function("setEmbeddedBitmaps", &SkFont::setEmbeddedBitmaps)
1588 .function("setHinting", &SkFont::setHinting)
1589 .function("setLinearMetrics", &SkFont::setLinearMetrics)
1590 .function("setScaleX", &SkFont::setScaleX)
1591 .function("setSize", &SkFont::setSize)
1592 .function("setSkewX", &SkFont::setSkewX)
1593 .function("setEmbolden", &SkFont::setEmbolden)
1594 .function("setSubpixel", &SkFont::setSubpixel)
1595 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
1596
1597 class_<SkFontMgr>("FontMgr")
1598 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<FontMgr>")
1599 .class_function("_fromData", optional_override([](WASMPointerU32 dPtr,
1600 WASMPointerU32 sPtr,
1601 int numFonts)->sk_sp<SkFontMgr> {
1602 auto datas = reinterpret_cast<const uint8_t**>(dPtr);
1603 auto sizes = reinterpret_cast<const size_t*>(sPtr);
1604
1605 std::unique_ptr<sk_sp<SkData>[]> skdatas(new sk_sp<SkData>[numFonts]);
1606 for (int i = 0; i < numFonts; ++i) {
1607 skdatas[i] = SkData::MakeFromMalloc(datas[i], sizes[i]);
1608 }
1609
1610 return SkFontMgr_New_Custom_Data(SkSpan(skdatas.get(), numFonts));
1611 }), allow_raw_pointers())
1612 .function("countFamilies", &SkFontMgr::countFamilies)
1613 .function("getFamilyName", optional_override([](SkFontMgr& self, int index)->JSString {
1614 if (index < 0 || index >= self.countFamilies()) {
1615 return emscripten::val::null();
1616 }
1617 SkString s;
1618 self.getFamilyName(index, &s);
1619 return emscripten::val(s.c_str());
1620 }))
1621 .function("matchFamilyStyle", optional_override([](SkFontMgr& self, std::string name, emscripten::val jsFontStyle)->sk_sp<SkTypeface> {
1622 auto weight = SkFontStyle::Weight(jsFontStyle["weight"].isUndefined() ? SkFontStyle::kNormal_Weight : jsFontStyle["weight"].as<int>());
1623 auto width = SkFontStyle::Width(jsFontStyle["width"].isUndefined() ? SkFontStyle::kNormal_Width : jsFontStyle["width"].as<int>());
1624 auto slant = SkFontStyle::Slant(jsFontStyle["slant"].isUndefined() ? SkFontStyle::kUpright_Slant : static_cast<SkFontStyle::Slant>(jsFontStyle["slant"].as<int>()));
1625
1626 SkFontStyle style(weight, width, slant);
1627
1628 return self.matchFamilyStyle(name.c_str(), style);
1629 }), allow_raw_pointers())
1630#ifdef SK_DEBUG
1631 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
1632 int numFam = self.countFamilies();
1633 SkDebugf("There are %d font families\n", numFam);
1634 for (int i = 0 ; i< numFam; i++) {
1635 SkString s;
1636 self.getFamilyName(i, &s);
1637 SkDebugf("\t%s\n", s.c_str());
1638 }
1639 }))
1640#endif
1641 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
1642 WASMPointerU8 fPtr,
1643 int flen)->sk_sp<SkTypeface> {
1644 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
1645 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
1646
1647 return self.makeFromData(fontData);
1648 }), allow_raw_pointers());
1649#endif // CK_NO_FONTS
1650
1651 class_<SkImage>("Image")
1652 .smart_ptr<sk_sp<SkImage>>("sk_sp<Image>")
1653#ifdef CK_ENABLE_WEBGL
1654 .class_function("_makeFromGenerator", &MakeImageFromGenerator)
1655#endif
1656 // Note that this needs to be cleaned up with delete().
1657 .function("getColorSpace", optional_override([](sk_sp<SkImage> self)->sk_sp<SkColorSpace> {
1658 return self->imageInfo().refColorSpace();
1659 }), allow_raw_pointers())
1660 .function("getImageInfo", optional_override([](sk_sp<SkImage> self)->JSObject {
1661 // We cannot return a SimpleImageInfo because the colorspace object would be leaked.
1662 JSObject result = emscripten::val::object();
1663 SkImageInfo ii = self->imageInfo();
1664 result.set("alphaType", ii.alphaType());
1665 result.set("colorType", ii.colorType());
1666 result.set("height", ii.height());
1667 result.set("width", ii.width());
1668 return result;
1669 }))
1670 .function("height", &SkImage::height)
1671 .function("_encodeToBytes", optional_override([](sk_sp<SkImage> self,
1673 int quality) -> Uint8Array {
1674 return encodeImage(nullptr, self, fmt, quality);
1675 }))
1676#if defined(ENABLE_GPU)
1677 .function("_encodeToBytes", optional_override([](sk_sp<SkImage> self,
1679 int quality,
1680 GrDirectContext* dContext) -> Uint8Array {
1681 return encodeImage(dContext, self, fmt, quality);
1682 }), allow_raw_pointers())
1683#endif
1684 .function("makeCopyWithDefaultMipmaps", optional_override([](sk_sp<SkImage> self)->sk_sp<SkImage> {
1685 return self->withDefaultMipmaps();
1686 }))
1687 .function("_makeShaderCubic", optional_override([](sk_sp<SkImage> self,
1688 SkTileMode tx, SkTileMode ty,
1689 float B, float C, // See SkSamplingOptions.h for docs.
1690 WASMPointerF32 mPtr)->sk_sp<SkShader> {
1691 OptionalMatrix localMatrix(mPtr);
1692 return self->makeShader(tx, ty, SkSamplingOptions({B, C}), mPtr ? &localMatrix
1693 : nullptr);
1694 }), allow_raw_pointers())
1695 .function("_makeShaderOptions", optional_override([](sk_sp<SkImage> self,
1696 SkTileMode tx, SkTileMode ty,
1697 SkFilterMode filter, SkMipmapMode mipmap,
1698 WASMPointerF32 mPtr)->sk_sp<SkShader> {
1699 OptionalMatrix localMatrix(mPtr);
1700 return self->makeShader(tx, ty, {filter, mipmap}, mPtr ? &localMatrix : nullptr);
1701 }), allow_raw_pointers())
1702#if defined(ENABLE_GPU)
1703 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1705 size_t dstRowBytes, int srcX, int srcY,
1706 GrDirectContext* dContext)->bool {
1707 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1708 SkImageInfo ii = toSkImageInfo(sii);
1709 return self->readPixels(dContext, ii, pixels, dstRowBytes, srcX, srcY);
1710 }), allow_raw_pointers())
1711#endif
1712 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1714 size_t dstRowBytes, int srcX, int srcY)->bool {
1715 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1716 SkImageInfo ii = toSkImageInfo(sii);
1717 return self->readPixels(nullptr, ii, pixels, dstRowBytes, srcX, srcY);
1718 }), allow_raw_pointers())
1719 .function("width", &SkImage::width);
1720
1721 class_<SkImageFilter>("ImageFilter")
1722 .smart_ptr<sk_sp<SkImageFilter>>("sk_sp<ImageFilter>")
1723 .function("_getOutputBounds", optional_override([](const SkImageFilter& self, WASMPointerF32 bPtr, WASMPointerF32 mPtr, WASMPointerU32 oPtr)->void {
1724 SkRect* rect = reinterpret_cast<SkRect*>(bPtr);
1725 OptionalMatrix ctm(mPtr);
1726 SkIRect* output = reinterpret_cast<SkIRect*>(oPtr);
1727 output[0] = self.filterBounds(ctm.mapRect(*rect).roundOut(), ctm, SkImageFilter::kForward_MapDirection);
1728 }))
1729 .class_function("MakeBlend", optional_override([](SkBlendMode mode, sk_sp<SkImageFilter> background,
1730 sk_sp<SkImageFilter> foreground)->sk_sp<SkImageFilter> {
1731 return SkImageFilters::Blend(mode, background, foreground);
1732 }))
1733 .class_function("MakeBlur", optional_override([](SkScalar sigmaX, SkScalar sigmaY,
1734 SkTileMode tileMode, sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1735 return SkImageFilters::Blur(sigmaX, sigmaY, tileMode, input);
1736 }))
1737 .class_function("MakeColorFilter", optional_override([](sk_sp<SkColorFilter> cf,
1738 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1739 return SkImageFilters::ColorFilter(cf, input);
1740 }))
1741 .class_function("MakeCompose", &SkImageFilters::Compose)
1742 .class_function("MakeDilate", optional_override([](SkScalar radiusX, SkScalar radiusY,
1743 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1744 return SkImageFilters::Dilate(radiusX, radiusY, input);
1745 }))
1746 .class_function("MakeDisplacementMap", optional_override([](SkColorChannel xChannelSelector,
1747 SkColorChannel yChannelSelector,
1748 SkScalar scale, sk_sp<SkImageFilter> displacement,
1750 return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector,
1751 scale, displacement, color);
1752 }))
1753 .class_function("MakeShader", optional_override([](sk_sp<SkShader> shader)->sk_sp<SkImageFilter> {
1754 return SkImageFilters::Shader(shader);
1755 }))
1756 .class_function("_MakeDropShadow", optional_override([](SkScalar dx, SkScalar dy,
1757 SkScalar sigmaX, SkScalar sigmaY,
1759 SkColor4f c = ptrToSkColor4f(cPtr);
1760 return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, c.toSkColor(), input);
1761 }))
1762 .class_function("_MakeDropShadowOnly", optional_override([](SkScalar dx, SkScalar dy,
1763 SkScalar sigmaX, SkScalar sigmaY,
1765 SkColor4f c = ptrToSkColor4f(cPtr);
1766 return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, c.toSkColor(), input);
1767 }))
1768 .class_function("MakeErode", optional_override([](SkScalar radiusX, SkScalar radiusY,
1769 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1770 return SkImageFilters::Erode(radiusX, radiusY, input);
1771 }))
1772 .class_function("_MakeImageCubic", optional_override([](sk_sp<SkImage> image,
1773 float B, float C,
1774 WASMPointerF32 srcPtr,
1775 WASMPointerF32 dstPtr
1776 )->sk_sp<SkImageFilter> {
1777 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1778 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1779 if (src && dst) {
1780 return SkImageFilters::Image(image, *src, *dst, SkSamplingOptions({B, C}));
1781 }
1783 }))
1784 .class_function("_MakeImageOptions", optional_override([](sk_sp<SkImage> image,
1785 SkFilterMode fm,
1786 SkMipmapMode mm,
1787 WASMPointerF32 srcPtr,
1788 WASMPointerF32 dstPtr
1789 )->sk_sp<SkImageFilter> {
1790 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1791 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1792 if (src && dst) {
1793 return SkImageFilters::Image(image, *src, *dst, SkSamplingOptions(fm, mm));
1794 }
1796 }))
1797 .class_function("_MakeMatrixTransformCubic",
1798 optional_override([](WASMPointerF32 mPtr, float B, float C,
1799 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1800 OptionalMatrix matr(mPtr);
1801 return SkImageFilters::MatrixTransform(matr, SkSamplingOptions({B, C}), input);
1802 }))
1803 .class_function("_MakeMatrixTransformOptions",
1804 optional_override([](WASMPointerF32 mPtr, SkFilterMode fm, SkMipmapMode mm,
1805 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1806 OptionalMatrix matr(mPtr);
1807 return SkImageFilters::MatrixTransform(matr, SkSamplingOptions(fm, mm), input);
1808 }))
1809 .class_function("MakeOffset", optional_override([](SkScalar dx, SkScalar dy,
1810 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1811 return SkImageFilters::Offset(dx, dy, input);
1812 }));
1813
1814 class_<SkMaskFilter>("MaskFilter")
1815 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<MaskFilter>")
1816 .class_function("MakeBlur", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
1817 // Adds a little helper because emscripten doesn't expose default params.
1818 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
1819 }), allow_raw_pointers());
1820
1821 class_<SkPaint>("Paint")
1822 .constructor<>()
1823 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
1824 SkPaint p(self);
1825 return p;
1826 }))
1827 // provide an allocated place to put the returned color
1828 .function("_getColor", optional_override([](SkPaint& self, WASMPointerF32 cPtr)->void {
1829 const SkColor4f& c = self.getColor4f();
1830 float* fourFloats = reinterpret_cast<float*>(cPtr);
1831 memcpy(fourFloats, c.vec(), 4 * sizeof(SkScalar));
1832 }))
1833 .function("getStrokeCap", &SkPaint::getStrokeCap)
1834 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
1835 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
1836 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
1837 .function("setAntiAlias", &SkPaint::setAntiAlias)
1838 .function("setAlphaf", &SkPaint::setAlphaf)
1839 .function("setBlendMode", &SkPaint::setBlendMode)
1840 .function("setBlender", &SkPaint::setBlender)
1841 .function("_setColor", optional_override([](SkPaint& self, WASMPointerF32 cPtr,
1842 sk_sp<SkColorSpace> colorSpace) {
1843 self.setColor(ptrToSkColor4f(cPtr), colorSpace.get());
1844 }))
1845 .function("setColorInt", optional_override([](SkPaint& self, SkColor color) {
1846 self.setColor(SkColor4f::FromColor(color), nullptr);
1847 }))
1848 .function("setColorInt", optional_override([](SkPaint& self, SkColor color,
1849 sk_sp<SkColorSpace> colorSpace) {
1850 self.setColor(SkColor4f::FromColor(color), colorSpace.get());
1851 }))
1852 .function("setColorFilter", &SkPaint::setColorFilter)
1853 .function("setDither", &SkPaint::setDither)
1854 .function("setImageFilter", &SkPaint::setImageFilter)
1855 .function("setMaskFilter", &SkPaint::setMaskFilter)
1856 .function("setPathEffect", &SkPaint::setPathEffect)
1857 .function("setShader", &SkPaint::setShader)
1858 .function("setStrokeCap", &SkPaint::setStrokeCap)
1859 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
1860 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
1861 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
1862 .function("setStyle", &SkPaint::setStyle);
1863
1864 class_<SkColorSpace>("ColorSpace")
1865 .smart_ptr<sk_sp<SkColorSpace>>("sk_sp<ColorSpace>")
1866 .class_function("Equals", optional_override([](sk_sp<SkColorSpace> a, sk_sp<SkColorSpace> b)->bool {
1867 return SkColorSpace::Equals(a.get(), b.get());
1868 }))
1869 // These are private because they are to be called once in interface.js to
1870 // avoid clients having to delete the returned objects.
1871 .class_function("_MakeSRGB", &SkColorSpace::MakeSRGB)
1872 .class_function("_MakeDisplayP3", optional_override([]()->sk_sp<SkColorSpace> {
1874 }))
1875 .class_function("_MakeAdobeRGB", optional_override([]()->sk_sp<SkColorSpace> {
1877 }));
1878
1879 class_<SkPathEffect>("PathEffect")
1880 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<PathEffect>")
1881 .class_function("MakeCorner", &SkCornerPathEffect::Make)
1882 .class_function("_MakeDash", optional_override([](WASMPointerF32 cptr, int count,
1884 const float* intervals = reinterpret_cast<const float*>(cptr);
1885 return SkDashPathEffect::Make(intervals, count, phase);
1886 }), allow_raw_pointers())
1887 .class_function("MakeDiscrete", &SkDiscretePathEffect::Make)
1888 .class_function("_MakeLine2D", optional_override([](SkScalar width,
1889 WASMPointerF32 mPtr)->sk_sp<SkPathEffect> {
1890 SkMatrix matrix;
1891 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1892 matrix.set9(nineMatrixValues);
1893 return SkLine2DPathEffect::Make(width, matrix);
1894 }), allow_raw_pointers())
1895 .class_function("MakePath1D", &SkPath1DPathEffect::Make)
1896 .class_function("_MakePath2D", optional_override([](WASMPointerF32 mPtr,
1897 SkPath path)->sk_sp<SkPathEffect> {
1898 SkMatrix matrix;
1899 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1900 matrix.set9(nineMatrixValues);
1901 return SkPath2DPathEffect::Make(matrix, path);
1902 }), allow_raw_pointers());
1903
1904 // TODO(kjlubick, reed) Make SkPath immutable and only creatable via a factory/builder.
1905 class_<SkPath>("Path")
1906 .constructor<>()
1907#ifdef CK_INCLUDE_PATHOPS
1908 .class_function("MakeFromOp", &MakePathFromOp)
1909#endif
1910 .class_function("MakeFromSVGString", &MakePathFromSVGString)
1911 .class_function("MakeFromPathInterpolation", &MakePathFromInterpolation)
1912 .class_function("CanInterpolate", &CanInterpolate)
1913 .class_function("_MakeFromCmds", &MakePathFromCmds)
1914 .class_function("_MakeFromVerbsPointsWeights", &MakePathFromVerbsPointsWeights)
1915 .function("_addArc", optional_override([](SkPath& self,
1916 WASMPointerF32 fPtr,
1917 SkScalar startAngle, SkScalar sweepAngle)->void {
1918 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1919 self.addArc(*oval, startAngle, sweepAngle);
1920 }))
1921 .function("_addOval", optional_override([](SkPath& self,
1922 WASMPointerF32 fPtr,
1923 bool ccw, unsigned start)->void {
1924 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1925 self.addOval(*oval, ccw ? SkPathDirection::kCCW : SkPathDirection::kCW, start);
1926 }))
1927 .function("_addCircle", optional_override([](SkPath& self,
1928 SkScalar x,
1929 SkScalar y,
1930 SkScalar r,
1931 bool ccw)->void {
1932 self.addCircle(x, y, r, ccw ? SkPathDirection::kCCW : SkPathDirection::kCW);
1933 }))
1934 // interface.js has 3 overloads of addPath
1935 .function("_addPath", &ApplyAddPath)
1936 .function("_addPoly", optional_override([](SkPath& self,
1937 WASMPointerF32 fPtr,
1938 int count, bool close)->void {
1939 const SkPoint* pts = reinterpret_cast<const SkPoint*>(fPtr);
1940 self.addPoly(pts, count, close);
1941 }))
1942 .function("_addRect", optional_override([](SkPath& self,
1943 WASMPointerF32 fPtr,
1944 bool ccw)->void {
1945 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1946 self.addRect(*rect, ccw ? SkPathDirection::kCCW : SkPathDirection::kCW);
1947 }))
1948 .function("_addRRect", optional_override([](SkPath& self,
1949 WASMPointerF32 fPtr,
1950 bool ccw)->void {
1952 }))
1953 .function("_addVerbsPointsWeights", &PathAddVerbsPointsWeights)
1954 .function("_arcToOval", optional_override([](SkPath& self,
1955 WASMPointerF32 fPtr, SkScalar startAngle,
1956 SkScalar sweepAngle, bool forceMoveTo)->void {
1957 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1958 self.arcTo(*oval, startAngle, sweepAngle, forceMoveTo);
1959 }))
1960 .function("_arcToRotated", &ApplyArcToArcSize)
1961 .function("_arcToTangent", ApplyArcToTangent)
1962 .function("_close", &ApplyClose)
1963 .function("_conicTo", &ApplyConicTo)
1964 .function("countPoints", &SkPath::countPoints)
1965 .function("contains", &SkPath::contains)
1966 .function("_cubicTo", &ApplyCubicTo)
1967 .function("_getPoint", optional_override([](SkPath& self, int index,
1968 WASMPointerF32 oPtr)->void {
1969 SkPoint* output = reinterpret_cast<SkPoint*>(oPtr);
1970 *output = self.getPoint(index);
1971 }))
1972 .function("isEmpty", &SkPath::isEmpty)
1973 .function("isVolatile", &SkPath::isVolatile)
1974 .function("_lineTo", &ApplyLineTo)
1975 .function("_moveTo", &ApplyMoveTo)
1976 .function("_quadTo", &ApplyQuadTo)
1977 .function("_rArcTo", &ApplyRArcToArcSize)
1978 .function("_rConicTo", &ApplyRConicTo)
1979 .function("_rCubicTo", &ApplyRCubicTo)
1980 .function("_rLineTo", &ApplyRLineTo)
1981 .function("_rMoveTo", &ApplyRMoveTo)
1982 .function("_rQuadTo", &ApplyRQuadTo)
1983 .function("reset", &ApplyReset)
1984 .function("rewind", &ApplyRewind)
1985 .function("setIsVolatile", &SkPath::setIsVolatile)
1986 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
1987
1988 // PathEffects
1989 .function("_dash", &ApplyDash)
1990 .function("_trim", &ApplyTrim)
1991 .function("_stroke", &ApplyStroke)
1992
1993#ifdef CK_INCLUDE_PATHOPS
1994 // PathOps
1995 .function("_simplify", &ApplySimplify)
1996 .function("_op", &ApplyPathOp)
1997 .function("makeAsWinding", &MakeAsWinding)
1998#endif
1999 // Exporting
2000 .function("toSVGString", &ToSVGString)
2001 .function("toCmds", &ToCmds)
2002
2003 .function("setFillType", select_overload<void(SkPathFillType)>(&SkPath::setFillType))
2004 .function("getFillType", &SkPath::getFillType)
2005 .function("_getBounds", optional_override([](SkPath& self,
2006 WASMPointerF32 fPtr)->void {
2007 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2008 output[0] = self.getBounds();
2009 }))
2010 .function("_computeTightBounds", optional_override([](SkPath& self,
2011 WASMPointerF32 fPtr)->void {
2012 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2013 output[0] = self.computeTightBounds();
2014 }))
2015 .function("equals", &Equals)
2016 .function("copy", &CopyPath)
2017#ifdef SK_DEBUG
2018 .function("dump", select_overload<void() const>(&SkPath::dump))
2019 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
2020#endif
2021 ;
2022
2024 class_<SkPictureRecorder>("PictureRecorder")
2025 .constructor<>()
2026 .function("_beginRecording", optional_override([](SkPictureRecorder& self,
2027 WASMPointerF32 fPtr,
2028 bool computeBounds) -> SkCanvas* {
2029 SkRect* bounds = reinterpret_cast<SkRect*>(fPtr);
2030 return self.beginRecording(*bounds, computeBounds ? &bbhFactory : nullptr);
2031 }), allow_raw_pointers())
2032 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
2033 -> sk_sp<SkPicture> {
2034 return self.finishRecordingAsPicture();
2035 }), allow_raw_pointers());
2036
2037 class_<SkPicture>("Picture")
2038 .smart_ptr<sk_sp<SkPicture>>("sk_sp<Picture>")
2039 .function("_makeShader", optional_override([](SkPicture& self,
2042 OptionalMatrix localMatrix(mPtr);
2043 SkRect* tileRect = reinterpret_cast<SkRect*>(rPtr);
2044 return self.makeShader(tmx, tmy, mode, mPtr ? &localMatrix : nullptr, tileRect);
2045 }), allow_raw_pointers())
2046 .function("_cullRect", optional_override([](SkPicture& self,
2047 WASMPointerF32 fPtr)->void {
2048 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2049 output[0] = self.cullRect();
2050 }))
2051 .function("approximateBytesUsed", &SkPicture::approximateBytesUsed)
2052#ifdef CK_SERIALIZE_SKP
2053 // The serialized format of an SkPicture (informally called an "skp"), is not something
2054 // that clients should ever rely on. The format may change at anytime and no promises
2055 // are made for backwards or forward compatibility.
2056 .function("serialize", optional_override([](SkPicture& self) -> Uint8Array {
2057 // We want to make sure we always save the underlying data of the Typeface to the
2058 // SkPicture. By default, the data for "system" fonts is not saved, just an identifier
2059 // (e.g. the family name and style). We do not want the user to have to supply a
2060 // FontMgr with the correct fonts by name when deserializing, so we choose to always
2061 // serialize the underlying data. This makes the SKPs a bit bigger, but easier to use.
2062 SkSerialProcs sp;
2064 sp.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
2065 return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
2066 };
2067
2068 sk_sp<SkData> data = self.serialize(&sp);
2069 if (!data) {
2070 return emscripten::val::null();
2071 }
2072 return toBytes(data);
2073 }), allow_raw_pointers())
2074#endif
2075 ;
2076
2077 class_<SkShader>("Shader")
2078 .smart_ptr<sk_sp<SkShader>>("sk_sp<Shader>")
2079 .class_function("MakeBlend", select_overload<sk_sp<SkShader>(SkBlendMode, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Blend))
2080 .class_function("_MakeColor",
2081 optional_override([](WASMPointerF32 cPtr, sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2082 return SkShaders::Color(ptrToSkColor4f(cPtr), colorSpace);
2083 })
2084 )
2085 .class_function("MakeFractalNoise", optional_override([](
2086 SkScalar baseFreqX, SkScalar baseFreqY,
2087 int numOctaves, SkScalar seed,
2088 int tileW, int tileH)->sk_sp<SkShader> {
2089 // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
2090 SkISize tileSize = SkISize::Make(tileW, tileH);
2091 return SkShaders::MakeFractalNoise(baseFreqX, baseFreqY, numOctaves, seed, &tileSize);
2092 }))
2093 // Here and in other gradient functions, cPtr is a pointer to an array of data
2094 // representing colors. whether this is an array of SkColor or SkColor4f is indicated
2095 // by the colorType argument. Only RGBA_8888 and RGBA_F32 are accepted.
2096 .class_function("_MakeLinearGradient", optional_override([](
2097 WASMPointerF32 fourFloatsPtr,
2099 WASMPointerF32 pPtr,
2100 int count, SkTileMode mode, uint32_t flags,
2101 WASMPointerF32 mPtr,
2102 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2103 const SkPoint* points = reinterpret_cast<const SkPoint*>(fourFloatsPtr);
2104 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2105 OptionalMatrix localMatrix(mPtr);
2106
2108 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2109 return SkGradientShader::MakeLinear(points, colors, colorSpace, positions, count,
2110 mode, flags,
2111 mPtr ? &localMatrix : nullptr);
2113 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2114 return SkGradientShader::MakeLinear(points, colors, positions, count,
2115 mode, flags,
2116 mPtr ? &localMatrix : nullptr);
2117 }
2118 SkDebugf("%d is not an accepted colorType\n", colorType);
2119 return nullptr;
2120 }), allow_raw_pointers())
2121 .class_function("_MakeRadialGradient", optional_override([](
2122 SkScalar cx, SkScalar cy, SkScalar radius,
2124 WASMPointerF32 pPtr,
2125 int count, SkTileMode mode, uint32_t flags,
2126 WASMPointerF32 mPtr,
2127 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2128 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2129 OptionalMatrix localMatrix(mPtr);
2131 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2132 return SkGradientShader::MakeRadial({cx, cy}, radius, colors, colorSpace,
2133 positions, count, mode, flags,
2134 mPtr ? &localMatrix : nullptr);
2136 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2137 return SkGradientShader::MakeRadial({cx, cy}, radius, colors, positions,
2138 count, mode, flags,
2139 mPtr ? &localMatrix : nullptr);
2140 }
2141 SkDebugf("%d is not an accepted colorType\n", colorType);
2142 return nullptr;
2143 }), allow_raw_pointers())
2144 .class_function("_MakeSweepGradient", optional_override([](SkScalar cx, SkScalar cy,
2146 WASMPointerF32 pPtr,
2147 int count, SkTileMode mode,
2148 SkScalar startAngle, SkScalar endAngle,
2149 uint32_t flags,
2150 WASMPointerF32 mPtr,
2151 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2152 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2153 OptionalMatrix localMatrix(mPtr);
2155 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2156 return SkGradientShader::MakeSweep(cx, cy, colors, colorSpace, positions, count,
2157 mode, startAngle, endAngle, flags,
2158 mPtr ? &localMatrix : nullptr);
2160 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2161 return SkGradientShader::MakeSweep(cx, cy, colors, positions, count,
2162 mode, startAngle, endAngle, flags,
2163 mPtr ? &localMatrix : nullptr);
2164 }
2165 SkDebugf("%d is not an accepted colorType\n", colorType);
2166 return nullptr;
2167 }), allow_raw_pointers())
2168 .class_function("MakeTurbulence", optional_override([](
2169 SkScalar baseFreqX, SkScalar baseFreqY,
2170 int numOctaves, SkScalar seed,
2171 int tileW, int tileH)->sk_sp<SkShader> {
2172 // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
2173 SkISize tileSize = SkISize::Make(tileW, tileH);
2174 return SkShaders::MakeTurbulence(baseFreqX, baseFreqY, numOctaves, seed, &tileSize);
2175 }))
2176 .class_function("_MakeTwoPointConicalGradient", optional_override([](
2177 WASMPointerF32 fourFloatsPtr,
2178 SkScalar startRadius, SkScalar endRadius,
2180 WASMPointerF32 pPtr,
2181 int count, SkTileMode mode, uint32_t flags,
2182 WASMPointerF32 mPtr,
2183 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2184 const SkPoint* startAndEnd = reinterpret_cast<const SkPoint*>(fourFloatsPtr);
2185 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2186 OptionalMatrix localMatrix(mPtr);
2187
2189 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2190 return SkGradientShader::MakeTwoPointConical(startAndEnd[0], startRadius,
2191 startAndEnd[1], endRadius,
2192 colors, colorSpace, positions, count, mode,
2193 flags,
2194 mPtr ? &localMatrix : nullptr);
2196 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2197 return SkGradientShader::MakeTwoPointConical(startAndEnd[0],
2198 startRadius,
2199 startAndEnd[1],
2200 endRadius,
2201 colors,
2202 positions,
2203 count,
2204 mode,
2205 flags,
2206 mPtr ? &localMatrix : nullptr);
2207 }
2208 SkDebugf("%d is not an accepted colorType\n", colorType);
2209 return nullptr;
2210 }), allow_raw_pointers());
2211
2212#ifdef CK_INCLUDE_RUNTIME_EFFECT
2213 class_<SkSL::DebugTrace>("DebugTrace")
2214 .smart_ptr<sk_sp<SkSL::DebugTrace>>("sk_sp<DebugTrace>")
2215 .function("writeTrace", optional_override([](SkSL::DebugTrace& self) -> std::string {
2216 SkDynamicMemoryWStream wstream;
2217 self.writeTrace(&wstream);
2218 sk_sp<SkData> trace = wstream.detachAsData();
2219 return std::string(reinterpret_cast<const char*>(trace->bytes()), trace->size());
2220 }));
2221
2222 value_object<SkRuntimeEffect::TracedShader>("TracedShader")
2223 .field("shader", &SkRuntimeEffect::TracedShader::shader)
2224 .field("debugTrace", &SkRuntimeEffect::TracedShader::debugTrace);
2225
2226 class_<SkRuntimeEffect>("RuntimeEffect")
2227 .smart_ptr<sk_sp<SkRuntimeEffect>>("sk_sp<RuntimeEffect>")
2228 .class_function("_Make", optional_override([](std::string sksl,
2229 emscripten::val errHandler
2231 SkString s(sksl.c_str(), sksl.length());
2232 auto [effect, errorText] = SkRuntimeEffect::MakeForShader(s);
2233 if (!effect) {
2234 errHandler.call<void>("onError", val(errorText.c_str()));
2235 return nullptr;
2236 }
2237 return effect;
2238 }))
2239 .class_function("_MakeForBlender", optional_override([](std::string sksl,
2240 emscripten::val errHandler
2241 )->sk_sp<SkRuntimeEffect> {
2242 SkString s(sksl.c_str(), sksl.length());
2243 auto [effect, errorText] = SkRuntimeEffect::MakeForBlender(s);
2244 if (!effect) {
2245 errHandler.call<void>("onError", val(errorText.c_str()));
2246 return nullptr;
2247 }
2248 return effect;
2249 }))
2250 .class_function("MakeTraced", optional_override([](
2251 sk_sp<SkShader> shader,
2252 int traceCoordX,
2253 int traceCoordY) -> SkRuntimeEffect::TracedShader {
2254 return SkRuntimeEffect::MakeTraced(shader, SkIPoint::Make(traceCoordX, traceCoordY));
2255 }))
2256 .function("_makeShader", optional_override([](SkRuntimeEffect& self,
2257 WASMPointerF32 fPtr,
2258 size_t fLen,
2259 bool shouldOwnUniforms,
2260 WASMPointerF32 mPtr)->sk_sp<SkShader> {
2261 void* uniformData = reinterpret_cast<void*>(fPtr);
2262 castUniforms(uniformData, fLen, self);
2263 sk_sp<SkData> uniforms;
2264 if (shouldOwnUniforms) {
2265 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2266 } else {
2267 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2268 }
2269
2270 OptionalMatrix localMatrix(mPtr);
2271 return self.makeShader(uniforms, nullptr, 0, mPtr ? &localMatrix : nullptr);
2272 }))
2273 .function("_makeShaderWithChildren", optional_override([](SkRuntimeEffect& self,
2274 WASMPointerF32 fPtr,
2275 size_t fLen,
2276 bool shouldOwnUniforms,
2277 WASMPointerU32 cPtrs,
2278 size_t cLen,
2279 WASMPointerF32 mPtr)->sk_sp<SkShader> {
2280 void* uniformData = reinterpret_cast<void*>(fPtr);
2281 castUniforms(uniformData, fLen, self);
2282 sk_sp<SkData> uniforms;
2283 if (shouldOwnUniforms) {
2284 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2285 } else {
2286 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2287 }
2288
2289 sk_sp<SkShader>* children = new sk_sp<SkShader>[cLen];
2290 SkShader** childrenPtrs = reinterpret_cast<SkShader**>(cPtrs);
2291 for (size_t i = 0; i < cLen; i++) {
2292 // This bare pointer was already part of an sk_sp (owned outside of here),
2293 // so we want to ref the new sk_sp so makeShader doesn't clean it up.
2294 children[i] = sk_ref_sp<SkShader>(childrenPtrs[i]);
2295 }
2296 OptionalMatrix localMatrix(mPtr);
2297 auto s = self.makeShader(uniforms, children, cLen, mPtr ? &localMatrix : nullptr);
2298 delete[] children;
2299 return s;
2300 }))
2301 .function("_makeBlender", optional_override([](SkRuntimeEffect& self,
2302 WASMPointerF32 fPtr,
2303 size_t fLen,
2304 bool shouldOwnUniforms)->sk_sp<SkBlender> {
2305 void* uniformData = reinterpret_cast<void*>(fPtr);
2306 castUniforms(uniformData, fLen, self);
2307 sk_sp<SkData> uniforms;
2308 if (shouldOwnUniforms) {
2309 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2310 } else {
2311 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2312 }
2313
2314 return self.makeBlender(uniforms, {});
2315 }))
2316 .function("getUniformCount", optional_override([](SkRuntimeEffect& self)->int {
2317 return self.uniforms().size();
2318 }))
2319 .function("getUniformFloatCount", optional_override([](SkRuntimeEffect& self)->int {
2320 return self.uniformSize() / sizeof(float);
2321 }))
2322 .function("getUniformName", optional_override([](SkRuntimeEffect& self, int i)->JSString {
2323 auto it = self.uniforms().begin() + i;
2324 return emscripten::val(std::string(it->name).c_str());
2325 }))
2326 .function("getUniform", optional_override([](SkRuntimeEffect& self, int i)->RuntimeEffectUniform {
2327 auto it = self.uniforms().begin() + i;
2328 RuntimeEffectUniform su = fromUniform(*it);
2329 return su;
2330 }));
2331
2332 value_object<RuntimeEffectUniform>("RuntimeEffectUniform")
2333 .field("columns", &RuntimeEffectUniform::columns)
2334 .field("rows", &RuntimeEffectUniform::rows)
2335 .field("slot", &RuntimeEffectUniform::slot)
2336 .field("isInteger", &RuntimeEffectUniform::isInteger);
2337
2338 constant("rt_effect", true);
2339#endif
2340
2341 class_<SkSurface>("Surface")
2342 .smart_ptr<sk_sp<SkSurface>>("sk_sp<Surface>")
2343 .class_function("_makeRasterDirect", optional_override([](const SimpleImageInfo ii,
2344 WASMPointerU8 pPtr,
2345 size_t rowBytes)->sk_sp<SkSurface> {
2346 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
2347 SkImageInfo imageInfo = toSkImageInfo(ii);
2348 return SkSurfaces::WrapPixels(imageInfo, pixels, rowBytes, nullptr);
2349 }), allow_raw_pointers())
2350 .function("_flush", optional_override([](SkSurface& self) {
2351#ifdef CK_ENABLE_WEBGL
2353#endif
2354 }))
2355 .function("_getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
2356 .function("imageInfo", optional_override([](SkSurface& self)->SimpleImageInfo {
2357 const auto& ii = self.imageInfo();
2358 return {ii.width(), ii.height(), ii.colorType(), ii.alphaType(), ii.refColorSpace()};
2359 }))
2360 .function("height", &SkSurface::height)
2361#ifdef CK_ENABLE_WEBGL
2362 .function("_makeImageFromTexture", optional_override([](SkSurface& self,
2363 uint32_t webglHandle, uint32_t texHandle,
2364 SimpleImageInfo ii)->sk_sp<SkImage> {
2365 auto releaseCtx = new TextureReleaseContext{webglHandle, texHandle};
2366 GrGLTextureInfo gti = {GR_GL_TEXTURE_2D, texHandle,
2367 GR_GL_RGBA8}; // TODO(kjlubick) look at ii for this
2368 auto gbt = GrBackendTextures::MakeGL(ii.width, ii.height, skgpu::Mipmapped::kNo, gti);
2369 auto dContext = GrAsDirectContext(self.getCanvas()->recordingContext());
2370
2371 return SkImages::BorrowTextureFrom(dContext,
2372 gbt,
2374 ii.colorType,
2375 ii.alphaType,
2376 ii.colorSpace,
2377 deleteJSTexture,
2378 releaseCtx);
2379 }))
2380#endif // CK_ENABLE_WEBGL
2381#ifdef CK_ENABLE_WEBGPU
2382 .function("_replaceBackendTexture", optional_override([](SkSurface& self,
2383 uint32_t texHandle, uint32_t texFormat,
2384 int width, int height) {
2385 return ReplaceBackendTexture(self, texHandle, texFormat, width, height);
2386 }))
2387#endif // CK_ENABLE_WEBGPU
2388 .function("_makeImageSnapshot", optional_override([](SkSurface& self, WASMPointerU32 iPtr)->sk_sp<SkImage> {
2389 SkIRect* bounds = reinterpret_cast<SkIRect*>(iPtr);
2390 if (!bounds) {
2391 return self.makeImageSnapshot();
2392 }
2393 return self.makeImageSnapshot(*bounds);
2394 }))
2395 .function("_makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
2396 return self.makeSurface(toSkImageInfo(sii));
2397 }), allow_raw_pointers())
2398#ifdef ENABLE_GPU
2399 .function("reportBackendTypeIsGPU", optional_override([](SkSurface& self) -> bool {
2400 return self.getCanvas()->recordingContext() != nullptr;
2401 }))
2402 .function("sampleCnt", optional_override([](SkSurface& self)->int {
2403 auto backendRT = SkSurfaces::GetBackendRenderTarget(
2404 &self, SkSurfaces::BackendHandleAccess::kFlushRead);
2405 return (backendRT.isValid()) ? backendRT.sampleCnt() : 0;
2406 }))
2407 .function("_resetContext",optional_override([](SkSurface& self)->void {
2409 }))
2410#else
2411 .function("reportBackendTypeIsGPU", optional_override([](SkSurface& self) -> bool {
2412 return false;
2413 }))
2414#endif
2415 .function("width", &SkSurface::width);
2416
2417#ifndef CK_NO_FONTS
2418 class_<SkTextBlob>("TextBlob")
2419 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<TextBlob>")
2420 .class_function("_MakeFromRSXform", optional_override([](WASMPointerU8 sptr,
2421 size_t strBtyes,
2422 WASMPointerF32 xptr,
2423 const SkFont& font)->sk_sp<SkTextBlob> {
2424 const char* str = reinterpret_cast<const char*>(sptr);
2425 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
2426
2427 return SkTextBlob::MakeFromRSXform(str, strBtyes, xforms, font, SkTextEncoding::kUTF8);
2428 }), allow_raw_pointers())
2429 .class_function("_MakeFromRSXformGlyphs", optional_override([](WASMPointerU16 gPtr,
2430 size_t byteLen,
2431 WASMPointerF32 xptr,
2432 const SkFont& font)->sk_sp<SkTextBlob> {
2433 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
2434 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
2435
2436 return SkTextBlob::MakeFromRSXform(glyphs, byteLen, xforms, font, SkTextEncoding::kGlyphID);
2437 }), allow_raw_pointers())
2438 .class_function("_MakeFromText", optional_override([](WASMPointerU8 sptr,
2439 size_t len, const SkFont& font)->sk_sp<SkTextBlob> {
2440 const char* str = reinterpret_cast<const char*>(sptr);
2441 return SkTextBlob::MakeFromText(str, len, font, SkTextEncoding::kUTF8);
2442 }), allow_raw_pointers())
2443 .class_function("_MakeFromGlyphs", optional_override([](WASMPointerU16 gPtr,
2444 size_t byteLen, const SkFont& font)->sk_sp<SkTextBlob> {
2445 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
2447 }), allow_raw_pointers());
2448
2449 class_<SkTypeface>("Typeface")
2450 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<Typeface>")
2451 .class_function("GetDefault", optional_override([]()->sk_sp<SkTypeface> {
2452#if defined(CK_EMBED_FONT)
2453 if (SK_EMBEDDED_FONTS.count == 0) {
2454 return nullptr;
2455 }
2456 static sk_sp<SkTypeface> default_face;
2457 static SkOnce once;
2458 once([] {
2459 const SkEmbeddedResource& fontEntry = SK_EMBEDDED_FONTS.entries[0];
2460 auto stream = std::make_unique<SkMemoryStream>(fontEntry.data, fontEntry.size, false);
2461 default_face = SkTypeface_FreeType::MakeFromStream(std::move(stream), SkFontArguments());
2462 });
2463 return default_face;
2464#else
2465 return nullptr;
2466#endif
2467 }), allow_raw_pointers())
2468 .class_function("_MakeTypefaceFromData", optional_override([](
2469 WASMPointerU8 fPtr, int flen)->sk_sp<SkTypeface> {
2470 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
2471 std::unique_ptr<SkMemoryStream> stream(new SkMemoryStream());
2472 stream->setMemoryOwned(font, flen);
2473 return SkTypeface_FreeType::MakeFromStream(std::move(stream), SkFontArguments());
2474 }), allow_raw_pointers())
2475 .function("_getGlyphIDs", optional_override([](SkTypeface& self, WASMPointerU8 sptr,
2476 size_t strLen, size_t expectedCodePoints,
2477 WASMPointerU16 iPtr) -> int {
2478 char* str = reinterpret_cast<char*>(sptr);
2479 SkGlyphID* glyphIDs = reinterpret_cast<SkGlyphID*>(iPtr);
2480
2481 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
2482 glyphIDs, expectedCodePoints);
2483 return actualCodePoints;
2484 }));
2485#endif
2486
2487 class_<SkVertices>("Vertices")
2488 .smart_ptr<sk_sp<SkVertices>>("sk_sp<Vertices>")
2489 .function("_bounds", optional_override([](SkVertices& self,
2490 WASMPointerF32 fPtr)->void {
2491 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2492 output[0] = self.bounds();
2493 }))
2494 .function("uniqueID", &SkVertices::uniqueID);
2495
2496 // Not intended to be called directly by clients
2497 class_<SkVertices::Builder>("_VerticesBuilder")
2498 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
2499 .function("colors", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2500 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2501 return reinterpret_cast<WASMPointerF32>(self.colors());
2502 }))
2503 .function("detach", &SkVertices::Builder::detach)
2504 .function("indices", optional_override([](SkVertices::Builder& self)->WASMPointerU16{
2505 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2506 return reinterpret_cast<WASMPointerU16>(self.indices());
2507 }))
2508 .function("positions", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2509 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2510 return reinterpret_cast<WASMPointerF32>(self.positions());
2511 }))
2512 .function("texCoords", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2513 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2514 return reinterpret_cast<WASMPointerF32>(self.texCoords());
2515 }));
2516
2517 enum_<SkAlphaType>("AlphaType")
2518 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
2519 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
2520 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
2521
2522 enum_<SkBlendMode>("BlendMode")
2523 .value("Clear", SkBlendMode::kClear)
2524 .value("Src", SkBlendMode::kSrc)
2525 .value("Dst", SkBlendMode::kDst)
2526 .value("SrcOver", SkBlendMode::kSrcOver)
2527 .value("DstOver", SkBlendMode::kDstOver)
2528 .value("SrcIn", SkBlendMode::kSrcIn)
2529 .value("DstIn", SkBlendMode::kDstIn)
2530 .value("SrcOut", SkBlendMode::kSrcOut)
2531 .value("DstOut", SkBlendMode::kDstOut)
2532 .value("SrcATop", SkBlendMode::kSrcATop)
2533 .value("DstATop", SkBlendMode::kDstATop)
2534 .value("Xor", SkBlendMode::kXor)
2535 .value("Plus", SkBlendMode::kPlus)
2536 .value("Modulate", SkBlendMode::kModulate)
2537 .value("Screen", SkBlendMode::kScreen)
2538 .value("Overlay", SkBlendMode::kOverlay)
2539 .value("Darken", SkBlendMode::kDarken)
2540 .value("Lighten", SkBlendMode::kLighten)
2541 .value("ColorDodge", SkBlendMode::kColorDodge)
2542 .value("ColorBurn", SkBlendMode::kColorBurn)
2543 .value("HardLight", SkBlendMode::kHardLight)
2544 .value("SoftLight", SkBlendMode::kSoftLight)
2545 .value("Difference", SkBlendMode::kDifference)
2546 .value("Exclusion", SkBlendMode::kExclusion)
2547 .value("Multiply", SkBlendMode::kMultiply)
2548 .value("Hue", SkBlendMode::kHue)
2549 .value("Saturation", SkBlendMode::kSaturation)
2550 .value("Color", SkBlendMode::kColor)
2551 .value("Luminosity", SkBlendMode::kLuminosity);
2552
2553 enum_<SkBlurStyle>("BlurStyle")
2554 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
2555 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
2556 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
2557 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
2558
2559 enum_<SkClipOp>("ClipOp")
2560 .value("Difference", SkClipOp::kDifference)
2561 .value("Intersect", SkClipOp::kIntersect);
2562
2563 enum_<SkColorChannel>("ColorChannel")
2564 .value("Red", SkColorChannel::kR)
2565 .value("Green", SkColorChannel::kG)
2566 .value("Blue", SkColorChannel::kB)
2567 .value("Alpha", SkColorChannel::kA);
2568
2569 enum_<SkColorType>("ColorType")
2570 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
2571 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
2572 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
2573 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
2574 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
2575 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
2576 .value("Gray_8", SkColorType::kGray_8_SkColorType)
2577 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
2578 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType);
2579
2580 enum_<SkPathFillType>("FillType")
2581 .value("Winding", SkPathFillType::kWinding)
2582 .value("EvenOdd", SkPathFillType::kEvenOdd);
2583
2584 enum_<SkFilterMode>("FilterMode")
2585 .value("Nearest", SkFilterMode::kNearest)
2586 .value("Linear", SkFilterMode::kLinear);
2587
2588 // Only used to control the encode function.
2589 // TODO(kjlubick): compile these out when the appropriate encoder is disabled.
2590 enum_<SkEncodedImageFormat>("ImageFormat")
2591 .value("PNG", SkEncodedImageFormat::kPNG)
2592 .value("JPEG", SkEncodedImageFormat::kJPEG)
2593 .value("WEBP", SkEncodedImageFormat::kWEBP);
2594
2595 enum_<SkMipmapMode>("MipmapMode")
2596 .value("None", SkMipmapMode::kNone)
2597 .value("Nearest", SkMipmapMode::kNearest)
2598 .value("Linear", SkMipmapMode::kLinear);
2599
2600 enum_<SkPaint::Style>("PaintStyle")
2601 .value("Fill", SkPaint::Style::kFill_Style)
2602 .value("Stroke", SkPaint::Style::kStroke_Style);
2603
2604 enum_<SkPath1DPathEffect::Style>("Path1DEffect")
2608
2609#ifdef CK_INCLUDE_PATHOPS
2610 enum_<SkPathOp>("PathOp")
2611 .value("Difference", SkPathOp::kDifference_SkPathOp)
2612 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
2613 .value("Union", SkPathOp::kUnion_SkPathOp)
2614 .value("XOR", SkPathOp::kXOR_SkPathOp)
2615 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
2616#endif
2617
2618 enum_<SkCanvas::PointMode>("PointMode")
2621 .value("Polygon", SkCanvas::PointMode::kPolygon_PointMode);
2622
2623 enum_<SkPaint::Cap>("StrokeCap")
2624 .value("Butt", SkPaint::Cap::kButt_Cap)
2625 .value("Round", SkPaint::Cap::kRound_Cap)
2626 .value("Square", SkPaint::Cap::kSquare_Cap);
2627
2628 enum_<SkPaint::Join>("StrokeJoin")
2629 .value("Miter", SkPaint::Join::kMiter_Join)
2630 .value("Round", SkPaint::Join::kRound_Join)
2631 .value("Bevel", SkPaint::Join::kBevel_Join);
2632
2633#ifndef CK_NO_FONTS
2634 enum_<SkFontHinting>("FontHinting")
2635 .value("None", SkFontHinting::kNone)
2636 .value("Slight", SkFontHinting::kSlight)
2637 .value("Normal", SkFontHinting::kNormal)
2638 .value("Full", SkFontHinting::kFull);
2639
2640 enum_<SkFont::Edging>("FontEdging")
2641#ifndef CK_NO_ALIAS_FONT
2642 .value("Alias", SkFont::Edging::kAlias)
2643#endif
2644 .value("AntiAlias", SkFont::Edging::kAntiAlias)
2645 .value("SubpixelAntiAlias", SkFont::Edging::kSubpixelAntiAlias);
2646#endif
2647
2648 enum_<SkTileMode>("TileMode")
2649 .value("Clamp", SkTileMode::kClamp)
2650 .value("Repeat", SkTileMode::kRepeat)
2651 .value("Mirror", SkTileMode::kMirror)
2652 .value("Decal", SkTileMode::kDecal);
2653
2654 enum_<SkVertices::VertexMode>("VertexMode")
2658
2659 // A value object is much simpler than a class - it is returned as a JS
2660 // object and does not require delete().
2661 // https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
2662
2663 value_object<SimpleImageInfo>("ImageInfo")
2664 .field("width", &SimpleImageInfo::width)
2665 .field("height", &SimpleImageInfo::height)
2666 .field("colorType", &SimpleImageInfo::colorType)
2667 .field("alphaType", &SimpleImageInfo::alphaType)
2668 .field("colorSpace", &SimpleImageInfo::colorSpace);
2669
2670 value_object<StrokeOpts>("StrokeOpts")
2671 .field("width", &StrokeOpts::width)
2672 .field("miter_limit", &StrokeOpts::miter_limit)
2673 .field("join", &StrokeOpts::join)
2674 .field("cap", &StrokeOpts::cap)
2675 .field("precision", &StrokeOpts::precision);
2676
2677 constant("MOVE_VERB", MOVE);
2678 constant("LINE_VERB", LINE);
2679 constant("QUAD_VERB", QUAD);
2680 constant("CONIC_VERB", CONIC);
2681 constant("CUBIC_VERB", CUBIC);
2682 constant("CLOSE_VERB", CLOSE);
2683
2684 constant("SaveLayerInitWithPrevious", (int)SkCanvas::SaveLayerFlagsSet::kInitWithPrevious_SaveLayerFlag);
2685 constant("SaveLayerF16ColorType", (int)SkCanvas::SaveLayerFlagsSet::kF16ColorType);
2686
2687 constant("ShadowTransparentOccluder", (int)SkShadowFlags::kTransparentOccluder_ShadowFlag);
2688 constant("ShadowGeometricOnly", (int)SkShadowFlags::kGeometricOnly_ShadowFlag);
2689 constant("ShadowDirectionalLight", (int)SkShadowFlags::kDirectionalLight_ShadowFlag);
2690
2691#ifdef CK_INCLUDE_PARAGRAPH
2692 constant("_GlyphRunFlags_isWhiteSpace", (int)skia::textlayout::Paragraph::kWhiteSpace_VisitorFlag);
2693#endif
2694}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
uint16_t glyphs[5]
int count
#define GR_GL_RGBA8
#define GR_GL_TEXTURE_2D
#define GR_GL_RGBA16F
int GrGLint
Definition GrGLTypes.h:108
unsigned int GrGLenum
Definition GrGLTypes.h:102
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
@ kBottomLeft_GrSurfaceOrigin
Definition GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition GrTypes.h:148
@ kTextureBinding_GrGLBackendState
Definition GrTypes.h:159
@ kMisc_GrGLBackendState
Definition GrTypes.h:169
@ kRenderTarget_GrGLBackendState
Definition GrTypes.h:157
static const int points[]
SkPoint pos
SkColor4f color
static SkPath path1()
static SkPath path2()
kUnpremul_SkAlphaType
SkAlphaType
Definition SkAlphaType.h:26
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
@ kUnpremul_SkAlphaType
pixel components are independent of alpha
Definition SkAlphaType.h:30
SkBlendMode
Definition SkBlendMode.h:38
@ kSrcOut
r = s * (1-da)
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kSaturation
saturation of source with hue and luminosity of destination
@ kColorBurn
darken destination to reflect source
@ kPlus
r = min(s + d, 1)
@ kLighten
rc = s + d - min(s*da, d*sa), ra = kSrcOver
@ kHue
hue of source with saturation and luminosity of destination
@ kDstIn
r = d * sa
@ kModulate
r = s*d
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kColorDodge
brighten destination to reflect source
@ kScreen
r = s + d - s*d
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
@ kLuminosity
luminosity of source with hue and saturation of destination
@ kSoftLight
lighten or darken, depending on source
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOverlay
multiply or screen, depending on destination
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOver
r = d + (1-da)*s
@ kColor
hue and saturation of source with luminosity of destination
@ kHardLight
multiply or screen, depending on source
@ kDstOut
r = d * (1-sa)
@ kDarken
rc = s + d - max(s*da, d*sa), ra = kSrcOver
@ kSrcIn
r = s * da
@ kClear
r = 0
SkBlurStyle
Definition SkBlurTypes.h:11
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
Definition SkBlurTypes.h:14
@ kSolid_SkBlurStyle
solid inside, fuzzy outside
Definition SkBlurTypes.h:13
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
Definition SkBlurTypes.h:15
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition SkBlurTypes.h:12
SkClipOp
Definition SkClipOp.h:13
SkColorType
Definition SkColorType.h:19
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition SkColorType.h:26
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition SkColorType.h:21
@ kRGB_101010x_SkColorType
pixel with 10 bits each for red, green, blue; in 32-bit word
Definition SkColorType.h:29
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition SkColorType.h:35
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition SkColorType.h:22
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition SkColorType.h:40
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition SkColorType.h:27
uint32_t SkColor
Definition SkColor.h:37
SkColorChannel
Definition SkColor.h:228
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SkEncodedImageFormat
static float SkBits2Float(uint32_t bits)
Definition SkFloatBits.h:48
#define sk_float_floor2int(x)
SK_API sk_sp< SkFontMgr > SkFontMgr_New_Custom_Data(SkSpan< sk_sp< SkData > >)
@ kNormal
glyph outlines modified to improve constrast
@ kNone
glyph outlines unchanged
@ kSlight
minimal modification to improve constrast
@ kFull
modifies glyph outlines for maximum constrast
@ kUTF8
uses bytes to represent UTF-8 or ASCII
@ kGlyphID
uses two byte words to represent glyph indices
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static bool ok(int result)
#define SK_DEBUG
bool SK_API AsWinding(const SkPath &path, SkPath *result)
SkPathOp
Definition SkPathOps.h:22
@ kReverseDifference_SkPathOp
subtract the first path from the op path
Definition SkPathOps.h:27
@ kDifference_SkPathOp
subtract the op path from the first path
Definition SkPathOps.h:23
@ kIntersect_SkPathOp
intersect the two paths
Definition SkPathOps.h:24
@ kUnion_SkPathOp
union (inclusive-or) the two paths
Definition SkPathOps.h:25
@ kXOR_SkPathOp
exclusive-or the two paths
Definition SkPathOps.h:26
bool SK_API Simplify(const SkPath &path, SkPath *result)
SkPathFillType
Definition SkPathTypes.h:11
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
SkFilterMode
SkMipmapMode
#define SkScalarFloorToInt(x)
Definition SkScalar.h:35
@ kDirectionalLight_ShadowFlag
@ kGeometricOnly_ShadowFlag
@ kTransparentOccluder_ShadowFlag
SkTileMode
Definition SkTileMode.h:13
constexpr int SkToInt(S x)
Definition SkTo.h:29
uint16_t SkGlyphID
Definition SkTypes.h:179
static SkScalar center(float pos0, float pos1)
emscripten::val JSObject
Definition WasmCommon.h:28
uintptr_t WASMPointerU8
Definition WasmCommon.h:46
emscripten::val SkPathOrNull
Definition WasmCommon.h:30
emscripten::val JSString
Definition WasmCommon.h:29
uintptr_t WASMPointerU16
Definition WasmCommon.h:47
uintptr_t WASMPointerU32
Definition WasmCommon.h:48
uintptr_t WASMPointerI32
Definition WasmCommon.h:45
uintptr_t WASMPointerF32
Definition WasmCommon.h:44
TypedArray MakeTypedArray(int count, const T src[])
Definition WasmCommon.h:72
emscripten::val Float32Array
Definition WasmCommon.h:35
emscripten::val Uint8Array
Definition WasmCommon.h:32
Type::kYUV Type::kRGBA() int(0.7 *637)
SkColor4f ptrToSkColor4f(WASMPointerF32 cPtr)
void ApplyReset(SkPath &p)
void ApplyTransform(SkPath &orig, SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
bool ApplyStroke(SkPath &path, StrokeOpts opts)
static const int CLOSE
SkImageInfo toSkImageInfo(const SimpleImageInfo &sii)
void ApplyRMoveTo(SkPath &p, SkScalar dx, SkScalar dy)
void ApplyRQuadTo(SkPath &p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2)
void PathAddVerbsPointsWeights(SkPath &path, WASMPointerU8 verbsPtr, int numVerbs, WASMPointerF32 ptsPtr, int numPts, WASMPointerF32 wtsPtr, int numWts)
void ApplyClose(SkPath &p)
void ApplyRewind(SkPath &p)
SkPathOrNull MakePathFromCmds(WASMPointerF32 cptr, int numCmds)
#define CHECK_NUM_WEIGHTS(n)
void ApplyRCubicTo(SkPath &p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar dx3, SkScalar dy3)
void ApplyRArcToArcSize(SkPath &orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate, bool useSmallArc, bool ccw, SkScalar dx, SkScalar dy)
void ApplyRConicTo(SkPath &p, SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, SkScalar w)
sk_sp< SkData > alwaysSaveTypefaceBytes(SkTypeface *face, void *)
void ApplyCubicTo(SkPath &p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
void ApplyArcToTangent(SkPath &p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius)
void ApplyMoveTo(SkPath &p, SkScalar x, SkScalar y)
static const int QUAD
SkPathOrNull MakePathFromSVGString(std::string str)
void ApplyConicTo(SkPath &p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
void ApplyAddPath(SkPath &orig, const SkPath &newPath, SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2, bool extendPath)
void ApplyArcToArcSize(SkPath &orig, SkScalar rx, SkScalar ry, SkScalar xAxisRotate, bool useSmallArc, bool ccw, SkScalar x, SkScalar y)
static const int CUBIC
SkRRect ptrToSkRRect(WASMPointerF32 fPtr)
SkPathOrNull MakePathFromInterpolation(const SkPath &path1, const SkPath &path2, SkScalar weight)
EMSCRIPTEN_BINDINGS(Skia)
bool ApplyDash(SkPath &path, SkScalar on, SkScalar off, SkScalar phase)
Uint8Array toBytes(sk_sp< SkData > data)
static const int MOVE
JSString ToSVGString(const SkPath &path)
#define CHECK_NUM_POINTS(n)
static Uint8Array encodeImage(GrDirectContext *dContext, sk_sp< SkImage > img, SkEncodedImageFormat fmt, int quality)
static const int LINE
Float32Array ToCmds(const SkPath &path)
#define CHECK_NUM_ARGS(n)
SkPath MakePathFromVerbsPointsWeights(WASMPointerU8 verbsPtr, int numVerbs, WASMPointerF32 ptsPtr, int numPts, WASMPointerF32 wtsPtr, int numWts)
void ApplyQuadTo(SkPath &p, SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2)
void ApplyRLineTo(SkPath &p, SkScalar dx, SkScalar dy)
bool Equals(const SkPath &a, const SkPath &b)
bool CanInterpolate(const SkPath &path1, const SkPath &path2)
bool ApplyTrim(SkPath &path, SkScalar startT, SkScalar stopT, bool isComplement)
void computeTonalColors(WASMPointerF32 cPtrAmbi, WASMPointerF32 cPtrSpot)
static const int CONIC
std::unique_ptr< SkCodec > DecodeImageData(sk_sp< SkData > data)
SkPath CopyPath(const SkPath &a)
void ApplyLineTo(SkPath &p, SkScalar x, SkScalar y)
void resetContext(uint32_t state=kAll_GrBackendState)
void releaseResourcesAndAbandonContext()
virtual std::unique_ptr< GrExternalTexture > generateExternalTexture(GrRecordingContext *, skgpu::Mipmapped)=0
virtual void dispose()=0
virtual GrBackendTexture getBackendTexture()=0
static std::unique_ptr< SkAndroidCodec > MakeFromCodec(std::unique_ptr< SkCodec >)
static sk_sp< SkAnimatedImage > Make(std::unique_ptr< SkAndroidCodec >, const SkImageInfo &info, SkIRect cropRect, sk_sp< SkPicture > postProcess)
int getFrameCount() const
sk_sp< SkImage > getCurrentFrame()
int getRepetitionCount() const
static sk_sp< SkBlender > Mode(SkBlendMode mode)
uint32_t SaveLayerFlags
Definition SkCanvas.h:677
void restore()
Definition SkCanvas.cpp:465
void translate(SkScalar dx, SkScalar dy)
void drawPaint(const SkPaint &paint)
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition SkCanvas.h:1542
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition SkCanvas.h:1543
int getSaveCount() const
Definition SkCanvas.cpp:435
void rotate(SkScalar degrees)
void restoreToCount(int saveCount)
Definition SkCanvas.cpp:482
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
@ kF16ColorType
Definition SkCanvas.h:674
@ kInitWithPrevious_SaveLayerFlag
initializes with previous contents
Definition SkCanvas.h:672
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
@ kLines_PointMode
draw each pair of points as a line segment
Definition SkCanvas.h:1242
@ kPolygon_PointMode
draw the array of points as a open polygon
Definition SkCanvas.h:1243
@ kPoints_PointMode
draw each point separately
Definition SkCanvas.h:1241
void skew(SkScalar sx, SkScalar sy)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
static sk_sp< SkColorFilter > Compose(const sk_sp< SkColorFilter > &outer, sk_sp< SkColorFilter > inner)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorFilter > SRGBToLinearGamma()
static sk_sp< SkColorFilter > Lerp(float t, sk_sp< SkColorFilter > dst, sk_sp< SkColorFilter > src)
static sk_sp< SkColorFilter > LinearToSRGBGamma()
static bool Equals(const SkColorSpace *, const SkColorSpace *)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
sk_sp< SkContourMeasure > next()
SkScalar length() const
bool isClosed() const
static sk_sp< SkPathEffect > Make(SkScalar radius)
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
static sk_sp< SkData > MakeWithoutCopy(const void *data, size_t length)
Definition SkData.h:116
static sk_sp< SkData > MakeFromMalloc(const void *data, size_t length)
Definition SkData.cpp:107
static sk_sp< SkPathEffect > Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist=0)
sk_sp< SkData > detachAsData()
Definition SkStream.cpp:707
int countFamilies() const
Definition SkFontMgr.cpp:93
void setSubpixel(bool subpixel)
Definition SkFont.cpp:109
bool isEmbolden() const
Definition SkFont.h:126
void setScaleX(SkScalar scaleX)
Definition SkFont.cpp:132
void setLinearMetrics(bool linearMetrics)
Definition SkFont.cpp:112
SkTypeface * getTypeface() const
Definition SkFont.h:208
void setTypeface(sk_sp< SkTypeface > tf)
Definition SkFont.cpp:90
SkScalar getSize() const
Definition SkFont.h:217
void setEdging(Edging edging)
Definition SkFont.cpp:121
void setSize(SkScalar textSize)
Definition SkFont.cpp:129
SkScalar getScaleX() const
Definition SkFont.h:224
SkScalar getSkewX() const
Definition SkFont.h:231
void setSkewX(SkScalar skewX)
Definition SkFont.cpp:135
void setHinting(SkFontHinting hintingLevel)
Definition SkFont.cpp:125
@ kAntiAlias
may have transparent pixels on glyph edges
@ kAlias
no transparent pixels on glyph edges
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
void setEmbolden(bool embolden)
Definition SkFont.cpp:115
void setEmbeddedBitmaps(bool embeddedBitmaps)
Definition SkFont.cpp:106
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, SkScalar startAngle, SkScalar endAngle, uint32_t flags, const SkMatrix *localMatrix)
static sk_sp< SkShader > MakeRadial(const SkPoint &center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkImageFilter > ColorFilter(sk_sp< SkColorFilter > cf, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DropShadow(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Erode(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DropShadowOnly(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DisplacementMap(SkColorChannel xChannelSelector, SkColorChannel yChannelSelector, SkScalar scale, sk_sp< SkImageFilter > displacement, sk_sp< SkImageFilter > color, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Compose(sk_sp< SkImageFilter > outer, sk_sp< SkImageFilter > inner)
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
static sk_sp< SkImageFilter > MatrixTransform(const SkMatrix &matrix, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input)
static sk_sp< SkImageFilter > Blend(SkBlendMode mode, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground=nullptr, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Offset(SkScalar dx, SkScalar dy, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Shader(sk_sp< SkShader > shader, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Dilate(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
sk_sp< SkImage > withDefaultMipmaps() const
Definition SkImage.cpp:305
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
static sk_sp< SkPathEffect > Make(SkScalar width, const SkMatrix &matrix)
Definition SkM44.h:150
static SkM44 RowMajor(const SkScalar r[16])
Definition SkM44.h:212
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
Definition SkMatrix.h:179
SkMatrix & set9(const SkScalar buffer[9])
Definition SkMatrix.cpp:51
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
SkScalar getStrokeMiter() const
Definition SkPaint.h:318
@ kRound_Cap
adds circle
Definition SkPaint.h:335
@ kButt_Cap
no stroke extension
Definition SkPaint.h:334
@ kSquare_Cap
adds square
Definition SkPaint.h:336
void setStyle(Style style)
Definition SkPaint.cpp:105
void setStrokeMiter(SkScalar miter)
Definition SkPaint.cpp:169
void setAntiAlias(bool aa)
Definition SkPaint.h:170
void setDither(bool dither)
Definition SkPaint.h:182
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
void setStrokeCap(Cap cap)
Definition SkPaint.cpp:179
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
void setStrokeJoin(Join join)
Definition SkPaint.cpp:189
void setMaskFilter(sk_sp< SkMaskFilter > maskFilter)
void setShader(sk_sp< SkShader > shader)
void setPathEffect(sk_sp< SkPathEffect > pathEffect)
SkScalar getStrokeWidth() const
Definition SkPaint.h:300
@ kRound_Join
adds circle
Definition SkPaint.h:360
@ kMiter_Join
extends to miter limit
Definition SkPaint.h:359
@ kBevel_Join
connects outside edges
Definition SkPaint.h:361
void setBlendMode(SkBlendMode mode)
Definition SkPaint.cpp:151
Cap getStrokeCap() const
Definition SkPaint.h:372
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
void setBlender(sk_sp< SkBlender > blender)
Definition SkPaint.cpp:155
Join getStrokeJoin() const
Definition SkPaint.h:383
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
void setAlphaf(float a)
Definition SkPaint.cpp:130
static SkString ToSVGString(const SkPath &, PathEncoding=PathEncoding::Absolute)
static bool FromSVGString(const char str[], SkPath *)
static sk_sp< SkPathEffect > Make(const SkPath &path, SkScalar advance, SkScalar phase, Style)
static sk_sp< SkPathEffect > Make(const SkMatrix &matrix, const SkPath &path)
SkPath & rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, SkScalar dx, SkScalar dy)
Definition SkPath.cpp:1367
bool isEmpty() const
Definition SkPath.cpp:406
int countPoints() const
Definition SkPath.cpp:525
SkPath & arcTo(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
Definition SkPath.cpp:1156
SkPathFillType getFillType() const
Definition SkPath.h:230
void setFillType(SkPathFillType ft)
Definition SkPath.h:235
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition SkPath.cpp:1442
bool isVolatile() const
Definition SkPath.h:350
void dump() const
Definition SkPath.h:1726
bool isInterpolatable(const SkPath &compare) const
Definition SkPath.cpp:241
bool interpolate(const SkPath &ending, SkScalar weight, SkPath *out) const
Definition SkPath.cpp:248
SkPath & setIsVolatile(bool isVolatile)
Definition SkPath.h:370
@ kSmall_ArcSize
smaller of arc pair
Definition SkPath.h:924
@ kLarge_ArcSize
larger of arc pair
Definition SkPath.h:925
@ kExtend_AddPathMode
Definition SkPath.h:1285
@ kAppend_AddPathMode
Definition SkPath.h:1278
void dumpHex() const
Definition SkPath.h:1727
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition SkPath.cpp:1647
bool contains(SkScalar x, SkScalar y) const
Definition SkPath.cpp:3054
static sk_sp< SkPicture > MakeFromData(const SkData *data, const SkDeserialProcs *procs=nullptr)
virtual size_t approximateBytesUsed() const =0
void setRectRadii(const SkRect &rect, const SkVector radii[4])
Definition SkRRect.cpp:189
static size_t GetTotalBytesUsed()
static size_t GetTotalByteLimit()
static size_t SetTotalByteLimit(size_t newLimit)
size_t uniformSize() const
static Result MakeForBlender(SkString sksl, const Options &)
static Result MakeForShader(SkString sksl, const Options &)
static TracedShader MakeTraced(sk_sp< SkShader > shader, const SkIPoint &traceCoord)
static void DrawShadow(SkCanvas *canvas, const SkPath &path, const SkPoint3 &zPlaneParams, const SkPoint3 &lightPos, SkScalar lightRadius, SkColor ambientColor, SkColor spotColor, uint32_t flags=SkShadowFlags::kNone_ShadowFlag)
static bool GetLocalBounds(const SkMatrix &ctm, const SkPath &path, const SkPoint3 &zPlaneParams, const SkPoint3 &lightPos, SkScalar lightRadius, uint32_t flags, SkRect *bounds)
static void ComputeTonalColors(SkColor inAmbientColor, SkColor inSpotColor, SkColor *outAmbientColor, SkColor *outSpotColor)
@ kHairline_InitStyle
Definition SkStrokeRec.h:25
@ kDiscard_ContentChangeMode
discards surface on change
Definition SkSurface.h:204
SkCanvas * getCanvas()
Definition SkSurface.cpp:82
int width() const
Definition SkSurface.h:178
sk_sp< SkSurface > makeSurface(const SkImageInfo &imageInfo)
int height() const
Definition SkSurface.h:184
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
static sk_sp< SkTextBlob > MakeFromRSXform(const void *text, size_t byteLength, const SkRSXform xform[], const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
static sk_sp< SkPathEffect > Make(SkScalar startT, SkScalar stopT, Mode=Mode::kNormal)
static sk_sp< SkTypeface > MakeFromStream(std::unique_ptr< SkStreamAsset >, const SkFontArguments &)
void serialize(SkWStream *, SerializeBehavior=SerializeBehavior::kIncludeDataIfLocal) const
static void Register(FactoryId id, sk_sp< SkTypeface >(*make)(std::unique_ptr< SkStreamAsset >, const SkFontArguments &))
SkFourByteTag FactoryId
Definition SkTypeface.h:335
sk_sp< SkVertices > detach()
uint32_t uniqueID() const
Definition SkVertices.h:97
@ kTriangleStrip_VertexMode
Definition SkVertices.h:32
@ kTriangleFan_VertexMode
Definition SkVertices.h:33
@ kTriangles_VertexMode
Definition SkVertices.h:31
T * get() const
Definition SkRefCnt.h:303
const Paint & paint
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
VkDevice device
Definition main.cc:53
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct s
struct MyStruct a[10]
FlutterSemanticsFlag flags
GAsyncResult * result
uint32_t uint32_t * format
uint32_t * target
Dart_NativeFunction function
Definition fuchsia.cc:51
const char * name
Definition fuchsia.cc:50
static sk_sp< GrDirectContext > MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
size_t length
SkRTreeFactory bbhFactory
Definition picture.cpp:14
FlTexture * texture
double y
double x
SK_API GrBackendRenderTarget MakeGL(int width, int height, int sampleCnt, int stencilBits, const GrGLFramebufferInfo &glInfo)
SK_API GrBackendTexture MakeGL(int width, int height, skgpu::Mipmapped, const GrGLTextureInfo &glInfo, std::string_view label={})
SK_API sk_sp< GrDirectContext > MakeGL()
SK_API sk_sp< const GrGLInterface > MakeWebGL()
SK_API bool IsBmp(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsGif(const void *, size_t)
SK_API bool IsIco(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API sk_sp< SkImage > DeferredFromTextureGenerator(std::unique_ptr< GrTextureGenerator > gen)
SK_API sk_sp< SkImage > RasterFromData(const SkImageInfo &info, sk_sp< SkData > pixels, size_t rowBytes)
void * ReleaseContext
Definition SkImage.h:50
SK_API sk_sp< SkImage > BorrowTextureFrom(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API bool IsJpeg(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
static constexpr skcms_Matrix3x3 kAdobeRGB
static constexpr skcms_Matrix3x3 kDisplayP3
static constexpr skcms_TransferFunction k2Dot2
static constexpr skcms_TransferFunction kSRGB
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsPng(const void *, size_t)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
SK_API sk_sp< SkShader > MakeTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, int numOctaves, SkScalar seed, const SkISize *tileSize=nullptr)
SK_API sk_sp< SkShader > MakeFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, int numOctaves, SkScalar seed, const SkISize *tileSize=nullptr)
SK_API sk_sp< SkSurface > WrapPixels(const SkImageInfo &imageInfo, void *pixels, size_t rowBytes, const SkSurfaceProps *surfaceProps=nullptr)
SK_API sk_sp< SkSurface > WrapBackendRenderTarget(GrRecordingContext *context, const GrBackendRenderTarget &backendRenderTarget, GrSurfaceOrigin origin, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, RenderTargetReleaseProc releaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API GrBackendRenderTarget GetBackendRenderTarget(SkSurface *, BackendHandleAccess)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
SK_API bool IsWbmp(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsWebp(const void *, size_t)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
Definition copy.py:1
void raw_destructor< SkTextBlob >(SkTextBlob *ptr)
void raw_destructor(ClassType *)
void raw_destructor< SkTypeface >(SkTypeface *ptr)
void raw_destructor< SkVertices >(SkVertices *ptr)
void raw_destructor< SkContourMeasure >(SkContourMeasure *ptr)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
Definition gen.py:1
SK_API void FlushAndSubmit(sk_sp< SkSurface >)
Mipmapped
Definition GpuTypes.h:53
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
static SkString fmt(SkColor4f c)
Definition p3.cpp:43
bool EMSCRIPTEN_KEEPALIVE ApplySimplify(SkPath &path)
bool EMSCRIPTEN_KEEPALIVE ApplyPathOp(SkPath &pathOne, const SkPath &pathTwo, SkPathOp op)
SkTileMode tmy
SkTileMode tmx
SkScalar w
int32_t height
int32_t width
const Scalar scale
GrGLenum fFormat
Definition GrGLTypes.h:183
GrGLenum fTarget
Definition GrGLTypes.h:181
OptionalMatrix(WASMPointerF32 mPtr)
sk_sp< SkColorSpace > colorSpace
SkDeserialImageFromDataProc fImageDataProc
const SkEmbeddedResource * entries
SkScalar fTop
greatest extent above origin of any glyph bounding box, typically negative; deprecated with variable ...
SkScalar fLeading
distance to add between lines, typically positive or zero
SkScalar fBottom
greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable ...
uint32_t fFlags
FontMetricsFlags indicating which metrics are valid.
SkScalar fAscent
distance to reserve above baseline, typically negative
@ kBoundsInvalid_Flag
set if fTop, fBottom, fXMin, fXMax invalid
SkScalar fDescent
distance to reserve below baseline, typically positive
SkScalar fXMin
greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with vari...
SkScalar fXMax
greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with var...
static constexpr SkIPoint Make(int32_t x, int32_t y)
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
int width() const
static SkImageInfo MakeN32(int width, int height, SkAlphaType at)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkAlphaType alphaType() const
SkColorType colorType() const
int height() const
static sk_sp< SkColorFilter > Make()
static SkRGBA4f FromColor(SkColor color)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition SkRect.h:646
sk_sp< SkSL::DebugTrace > debugTrace
SkSerialImageProc fImageProc
SkSerialTypefaceProc fTypefaceProc
SkPaint::Join join