Flutter Engine
The Flutter Engine
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
241 int width;
246};
247
249 return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType,
251}
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());
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,
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) {
443 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
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) {
450 auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize : SkPath::ArcSize::kLarge_ArcSize;
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
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
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
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
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 }
763 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
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 }
778 SkStrokeRec rec(SkStrokeRec::InitStyle::kHairline_InitStyle);
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
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
885}
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<>
896 }
897
898 template<>
900 }
901
902#ifndef CK_NO_FONTS
903 template<>
905 }
906
907 template<>
909 }
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(GrRecordingContext* ctx,
980 skgpu::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 // These textures are unlikely to actually have mipmaps generated (we might even be on
992 // WebGL 1, where Skia doesn't support mipmapping at all). Therefore, we ignore any request
993 // for mipmapping here. See: b/338095525
994 auto backendTexture = GrBackendTextures::MakeGL(
995 fInfo.width(), fInfo.height(), skgpu::Mipmapped::kNo, glInfo);
996
997 // In order to bind the image source to the texture, makeTexture has changed which
998 // texture is "in focus" for the WebGL context.
1000 return std::make_unique<ExternalWebGLTexture>(
1001 backendTexture, glInfo.fID, emscripten_webgl_get_current_context());
1002 }
1003
1004private:
1005 JSObject fCallback;
1006};
1007
1008// callbackObj has two functions in it, one to create a texture "makeTexture" and one to clean up
1009// the underlying texture source "freeSrc". This way, we can create WebGL textures for each
1010// surface/WebGLContext that the image is used on (we cannot share WebGLTextures across contexts).
1011sk_sp<SkImage> MakeImageFromGenerator(SimpleImageInfo ii, JSObject callbackObj) {
1012 auto gen = std::make_unique<WebGLTextureImageGenerator>(toSkImageInfo(ii), callbackObj);
1014}
1015#endif // CK_ENABLE_WEBGL
1016
1017
1019 sk_sp<SkImage> img,
1021 int quality) {
1022 sk_sp<SkData> data = nullptr;
1025 opts.fQuality = quality;
1026 data = SkJpegEncoder::Encode(dContext, img.get(), opts);
1027 } else if (fmt == SkEncodedImageFormat::kPNG) {
1028 data = SkPngEncoder::Encode(dContext, img.get(), {});
1029 } else {
1031 if (quality >= 100) {
1033 opts.fQuality = 75; // This is effort to compress
1034 } else {
1036 opts.fQuality = quality;
1037 }
1038 data = SkWebpEncoder::Encode(dContext, img.get(), opts);
1039 }
1040 if (!data) {
1041 return emscripten::val::null();
1042 }
1043 return toBytes(data);
1044}
1045
1047#ifdef ENABLE_GPU
1048 constant("gpu", true);
1049 function("_MakeGrContext", &MakeGrContext);
1050#endif // ENABLE_GPU
1051
1052#ifdef CK_ENABLE_WEBGL
1053 constant("webgl", true);
1054 function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>)>(&MakeOnScreenGLSurface));
1055 function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>, int, int)>(&MakeOnScreenGLSurface));
1056 function("_MakeRenderTargetWH", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int)>(&MakeRenderTarget));
1057 function("_MakeRenderTargetII", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, SimpleImageInfo)>(&MakeRenderTarget));
1058#endif // CK_ENABLE_WEBGL
1059
1060#ifdef CK_ENABLE_WEBGPU
1061 constant("webgpu", true);
1062 function("_MakeGPUTextureSurface", &MakeGPUTextureSurface);
1063#endif // CK_ENABLE_WEBGPU
1064
1065 function("getDecodeCacheLimitBytes", &SkResourceCache::GetTotalByteLimit);
1066 function("setDecodeCacheLimitBytes", &SkResourceCache::SetTotalByteLimit);
1067 function("getDecodeCacheUsedBytes" , &SkResourceCache::GetTotalBytesUsed);
1068
1069 function("_computeTonalColors", &computeTonalColors);
1070 function("_decodeAnimatedImage", optional_override([](WASMPointerU8 iptr,
1072 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
1073 auto bytes = SkData::MakeFromMalloc(imgData, length);
1074 auto codec = DecodeImageData(bytes);
1075 if (codec == nullptr) {
1076 return nullptr;
1077 }
1078 auto aCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
1079 if (aCodec == nullptr) {
1080 return nullptr;
1081 }
1082
1083 return SkAnimatedImage::Make(std::move(aCodec));
1084 }), allow_raw_pointers());
1085 function("_decodeImage", optional_override([](WASMPointerU8 iptr,
1086 size_t length)->sk_sp<SkImage> {
1087 uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
1088 auto bytes = SkData::MakeFromMalloc(imgData, length);
1089 auto codec = DecodeImageData(bytes);
1090 if (codec == nullptr) {
1091 return nullptr;
1092 }
1093 return std::get<0>(codec->getImage());
1094 }), allow_raw_pointers());
1095
1096 // These won't be called directly, there are corresponding JS helpers to deal with arrays.
1097 function("_MakeImage", optional_override([](SimpleImageInfo ii,
1098 WASMPointerU8 pPtr, int plen,
1099 size_t rowBytes)->sk_sp<SkImage> {
1100 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1102 sk_sp<SkData> pixelData = SkData::MakeFromMalloc(pixels, plen);
1103
1104 return SkImages::RasterFromData(info, pixelData, rowBytes);
1105 }), allow_raw_pointers());
1106
1107 function("_getShadowLocalBounds", optional_override([](
1108 WASMPointerF32 ctmPtr, const SkPath& path,
1109 WASMPointerF32 zPlaneParamPtr, WASMPointerF32 lightPosPtr,
1110 SkScalar lightRadius, uint32_t flags, WASMPointerF32 outPtr) -> bool {
1111 SkMatrix ctm;
1112 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(ctmPtr);
1113 ctm.set9(nineMatrixValues);
1114 const SkVector3* zPlaneParams = reinterpret_cast<const SkVector3*>(zPlaneParamPtr);
1115 const SkVector3* lightPos = reinterpret_cast<const SkVector3*>(lightPosPtr);
1116 SkRect* outputBounds = reinterpret_cast<SkRect*>(outPtr);
1117 return SkShadowUtils::GetLocalBounds(ctm, path, *zPlaneParams, *lightPos, lightRadius,
1118 flags, outputBounds);
1119 }));
1120
1121#ifdef CK_SERIALIZE_SKP
1122 function("_MakePicture", optional_override([](WASMPointerU8 dPtr,
1123 size_t bytes)->sk_sp<SkPicture> {
1124 uint8_t* d = reinterpret_cast<uint8_t*>(dPtr);
1126
1127#ifndef CK_NO_FONTS
1128 // Be sure we can process the data stored when serializing the SkPicture.
1129 static SkOnce once;
1130 once([] {
1133 });
1134#endif
1135
1136 SkDeserialProcs dp;
1137 dp.fImageDataProc = [](sk_sp<SkData> bytes, std::optional<SkAlphaType> at, void* ctx) -> sk_sp<SkImage> {
1138 auto codec = DecodeImageData(bytes);
1139 if (codec == nullptr) {
1140 return nullptr;
1141 }
1142 SkImageInfo info = codec->getInfo();
1143 if (at.has_value()) {
1144 info = info.makeAlphaType(*at);
1145 } else if (kUnpremul_SkAlphaType == info.alphaType()) {
1146 // Otherwise, prefer premul over unpremul (this produces better filtering in general)
1147 info = info.makeAlphaType(kPremul_SkAlphaType);
1148 }
1149 return std::get<0>(codec->getImage(info));
1150 };
1151
1152 return SkPicture::MakeFromData(data.get(), nullptr);
1153 }), allow_raw_pointers());
1154#endif
1155
1156#ifdef ENABLE_GPU
1157 class_<GrDirectContext>("GrDirectContext")
1158 .smart_ptr<sk_sp<GrDirectContext>>("sk_sp<GrDirectContext>")
1159 .function("_getResourceCacheLimitBytes",
1160 optional_override([](GrDirectContext& self)->size_t {
1161 int maxResources = 0;// ignored
1162 size_t currMax = 0;
1163 self.getResourceCacheLimits(&maxResources, &currMax);
1164 return currMax;
1165 }))
1166 .function("_getResourceCacheUsageBytes",
1167 optional_override([](GrDirectContext& self)->size_t {
1168 int usedResources = 0;// ignored
1169 size_t currUsage = 0;
1170 self.getResourceCacheUsage(&usedResources, &currUsage);
1171 return currUsage;
1172 }))
1173 .function("_releaseResourcesAndAbandonContext",
1175 .function("_setResourceCacheLimitBytes",
1176 optional_override([](GrDirectContext& self, size_t maxResourceBytes)->void {
1177 int maxResources = 0;
1178 size_t currMax = 0; // ignored
1179 self.getResourceCacheLimits(&maxResources, &currMax);
1180 self.setResourceCacheLimits(maxResources, maxResourceBytes);
1181 }));
1182#endif // ENABLE_GPU
1183#ifdef CK_ENABLE_WEBGL
1184 // This allows us to give the C++ code a JS callback to delete textures that
1185 // have been passed in via makeImageFromTexture and makeImageFromTextureSource.
1186 function("_setTextureCleanup", optional_override([](JSObject callbackObj)->void {
1187 textureCleanup = callbackObj;
1188 }));
1189#endif
1190
1191 class_<SkAnimatedImage>("AnimatedImage")
1192 .smart_ptr<sk_sp<SkAnimatedImage>>("sk_sp<AnimatedImage>")
1193 .function("currentFrameDuration", &SkAnimatedImage::currentFrameDuration)
1194 .function("decodeNextFrame", &SkAnimatedImage::decodeNextFrame)
1195 .function("getFrameCount", &SkAnimatedImage::getFrameCount)
1196 .function("getRepetitionCount", &SkAnimatedImage::getRepetitionCount)
1197 .function("height", optional_override([](SkAnimatedImage& self)->int32_t {
1198 // getBounds returns an SkRect, but internally, the width and height are ints.
1199 return SkScalarFloorToInt(self.getBounds().height());
1200 }))
1201 .function("makeImageAtCurrentFrame", &SkAnimatedImage::getCurrentFrame)
1202 .function("reset", &SkAnimatedImage::reset)
1203 .function("width", optional_override([](SkAnimatedImage& self)->int32_t {
1204 return SkScalarFloorToInt(self.getBounds().width());
1205 }));
1206
1207 class_<SkBlender>("Blender")
1208 .smart_ptr<sk_sp<SkBlender>>("sk_sp<Blender>")
1209 .class_function("Mode", &SkBlender::Mode);
1210
1211 class_<SkCanvas>("Canvas")
1212 .constructor<>()
1213 .constructor<SkScalar,SkScalar>()
1214 .function("_clear", optional_override([](SkCanvas& self, WASMPointerF32 cPtr) {
1215 self.clear(ptrToSkColor4f(cPtr));
1216 }))
1217 .function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
1218 .function("_clipRRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr, SkClipOp op, bool doAntiAlias) {
1219 self.clipRRect(ptrToSkRRect(fPtr), op, doAntiAlias);
1220 }))
1221 .function("_clipRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr, SkClipOp op, bool doAntiAlias) {
1222 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1223 self.clipRect(*rect, op, doAntiAlias);
1224 }))
1225 .function("_concat", optional_override([](SkCanvas& self, WASMPointerF32 mPtr) {
1226 //TODO(skbug.com/10108): make the JS side be column major.
1227 const SkScalar* sixteenMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1228 SkM44 m = SkM44::RowMajor(sixteenMatrixValues);
1229 self.concat(m);
1230 }))
1231 .function("_drawArc", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1233 bool useCenter, const SkPaint& paint) {
1234 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1235 self.drawArc(*oval, startAngle, sweepAngle, useCenter, paint);
1236 }))
1237 .function("_drawAtlasOptions", optional_override([](SkCanvas& self,
1238 const sk_sp<SkImage>& atlas, WASMPointerF32 xptr,
1239 WASMPointerF32 rptr, WASMPointerU32 cptr, int count,
1240 SkBlendMode mode, SkFilterMode filter, SkMipmapMode mipmap,
1241 const SkPaint* paint)->void {
1242 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
1243 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
1244 const SkColor* colors = nullptr;
1245 if (cptr) {
1246 colors = reinterpret_cast<const SkColor*>(cptr);
1247 }
1248 SkSamplingOptions sampling(filter, mipmap);
1249 self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
1250 nullptr, paint);
1251 }), allow_raw_pointers())
1252 .function("_drawAtlasCubic", optional_override([](SkCanvas& self,
1253 const sk_sp<SkImage>& atlas, WASMPointerF32 xptr,
1254 WASMPointerF32 rptr, WASMPointerU32 cptr, int count,
1255 SkBlendMode mode, float B, float C, const SkPaint* paint)->void {
1256 const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
1257 const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
1258 const SkColor* colors = nullptr;
1259 if (cptr) {
1260 colors = reinterpret_cast<const SkColor*>(cptr);
1261 }
1263 self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
1264 nullptr, paint);
1265 }), allow_raw_pointers())
1266 .function("_drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
1267 .function("_drawColor", optional_override([](SkCanvas& self, WASMPointerF32 cPtr) {
1268 self.drawColor(ptrToSkColor4f(cPtr));
1269 }))
1270 .function("_drawColor", optional_override([](SkCanvas& self, WASMPointerF32 cPtr, SkBlendMode mode) {
1271 self.drawColor(ptrToSkColor4f(cPtr), mode);
1272 }))
1273 .function("_drawColorInt", optional_override([](SkCanvas& self, SkColor color, SkBlendMode mode) {
1274 self.drawColor(color, mode);
1275 }))
1276 .function("_drawDRRect", optional_override([](SkCanvas& self, WASMPointerF32 outerPtr,
1277 WASMPointerF32 innerPtr, const SkPaint& paint) {
1278 self.drawDRRect(ptrToSkRRect(outerPtr), ptrToSkRRect(innerPtr), paint);
1279 }))
1280 .function("_drawGlyphs", optional_override([](SkCanvas& self,
1281 int count,
1283 WASMPointerF32 positions,
1284 float x, float y,
1285 const SkFont& font,
1286 const SkPaint& paint)->void {
1287 self.drawGlyphs(count,
1288 reinterpret_cast<const uint16_t*>(glyphs),
1289 reinterpret_cast<const SkPoint*>(positions),
1290 {x, y}, font, paint);
1291 }))
1292 // TODO: deprecate this version, and require sampling
1293 .function("_drawImage", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1294 SkScalar x, SkScalar y, const SkPaint* paint) {
1295 self.drawImage(image.get(), x, y, SkSamplingOptions(), paint);
1296 }), allow_raw_pointers())
1297 .function("_drawImageCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
1298 SkScalar left, SkScalar top,
1299 float B, float C, // See SkSamplingOptions.h for docs.
1300 const SkPaint* paint)->void {
1301 self.drawImage(img.get(), left, top, SkSamplingOptions({B, C}), paint);
1302 }), allow_raw_pointers())
1303 .function("_drawImageOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
1304 SkScalar left, SkScalar top,
1305 SkFilterMode filter, SkMipmapMode mipmap,
1306 const SkPaint* paint)->void {
1307 self.drawImage(img.get(), left, top, {filter, mipmap}, paint);
1308 }), allow_raw_pointers())
1309
1310 .function("_drawImageNine", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1311 WASMPointerU32 centerPtr, WASMPointerF32 dstPtr,
1312 SkFilterMode filter, const SkPaint* paint)->void {
1313 const SkIRect* center = reinterpret_cast<const SkIRect*>(centerPtr);
1314 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1315
1316 self.drawImageNine(image.get(), *center, *dst, filter, paint);
1317 }), allow_raw_pointers())
1318 // TODO: deprecate this version, and require sampling
1319 .function("_drawImageRect", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1320 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1321 const SkPaint* paint, bool fastSample)->void {
1322 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1323 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1324 self.drawImageRect(image, *src, *dst, SkSamplingOptions(), paint,
1327 }), allow_raw_pointers())
1328 .function("_drawImageRectCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1329 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1330 float B, float C, // See SkSamplingOptions.h for docs.
1331 const SkPaint* paint)->void {
1332 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1333 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1334 auto constraint = SkCanvas::kStrict_SrcRectConstraint; // TODO: get from caller
1335 self.drawImageRect(image.get(), *src, *dst, SkSamplingOptions({B, C}), paint, constraint);
1336 }), allow_raw_pointers())
1337 .function("_drawImageRectOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
1338 WASMPointerF32 srcPtr, WASMPointerF32 dstPtr,
1339 SkFilterMode filter, SkMipmapMode mipmap,
1340 const SkPaint* paint)->void {
1341 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1342 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1343 auto constraint = SkCanvas::kStrict_SrcRectConstraint; // TODO: get from caller
1344 self.drawImageRect(image.get(), *src, *dst, {filter, mipmap}, paint, constraint);
1345 }), allow_raw_pointers())
1346 .function("_drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
1347 .function("_drawOval", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1348 const SkPaint& paint)->void {
1349 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1350 self.drawOval(*oval, paint);
1351 }))
1352 .function("_drawPaint", &SkCanvas::drawPaint)
1353#ifdef CK_INCLUDE_PARAGRAPH
1354 .function("_drawParagraph", optional_override([](SkCanvas& self, skia::textlayout::Paragraph* p,
1355 SkScalar x, SkScalar y) {
1356 p->paint(&self, x, y);
1357 }), allow_raw_pointers())
1358#endif
1359 .function("_drawPath", &SkCanvas::drawPath)
1360 .function("_drawPatch", optional_override([](SkCanvas& self,
1361 WASMPointerF32 cubics,
1365 const SkPaint& paint)->void {
1366 self.drawPatch(reinterpret_cast<const SkPoint*>(cubics),
1367 reinterpret_cast<const SkColor*>(colors),
1368 reinterpret_cast<const SkPoint*>(texs),
1369 mode, paint);
1370 }))
1371 // Of note, picture is *not* what is colloquially thought of as a "picture", what we call
1372 // a bitmap. An SkPicture is a series of draw commands.
1373 .function("_drawPicture", select_overload<void (const sk_sp<SkPicture>&)>(&SkCanvas::drawPicture))
1374 .function("_drawPoints", optional_override([](SkCanvas& self, SkCanvas::PointMode mode,
1375 WASMPointerF32 pptr,
1376 int count, SkPaint& paint)->void {
1377 const SkPoint* pts = reinterpret_cast<const SkPoint*>(pptr);
1378 self.drawPoints(mode, count, pts, paint);
1379 }))
1380 .function("_drawRRect",optional_override([](SkCanvas& self, WASMPointerF32 fPtr, const SkPaint& paint) {
1381 self.drawRRect(ptrToSkRRect(fPtr), paint);
1382 }))
1383 .function("_drawRect", optional_override([](SkCanvas& self, WASMPointerF32 fPtr,
1384 const SkPaint& paint)->void {
1385 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1386 self.drawRect(*rect, paint);
1387 }))
1388 .function("_drawRect4f", optional_override([](SkCanvas& self, SkScalar left, SkScalar top,
1389 SkScalar right, SkScalar bottom,
1390 const SkPaint& paint)->void {
1391 const SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
1392 self.drawRect(rect, paint);
1393 }))
1394 .function("_drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
1395 WASMPointerF32 zPlaneParamPtr,
1396 WASMPointerF32 lightPosPtr,
1397 SkScalar lightRadius,
1398 WASMPointerF32 ambientColorPtr,
1399 WASMPointerF32 spotColorPtr,
1400 uint32_t flags) {
1401 const SkVector3* zPlaneParams = reinterpret_cast<const SkVector3*>(zPlaneParamPtr);
1402 const SkVector3* lightPos = reinterpret_cast<const SkVector3*>(lightPosPtr);
1403
1404 SkShadowUtils::DrawShadow(&self, path, *zPlaneParams, *lightPos, lightRadius,
1405 ptrToSkColor4f(ambientColorPtr).toSkColor(),
1406 ptrToSkColor4f(spotColorPtr).toSkColor(),
1407 flags);
1408 }))
1409#ifndef CK_NO_FONTS
1410 .function("_drawSimpleText", optional_override([](SkCanvas& self, WASMPointerU8 sptr,
1411 size_t len, SkScalar x, SkScalar y, const SkFont& font,
1412 const SkPaint& paint) {
1413 const char* str = reinterpret_cast<const char*>(sptr);
1414
1415 self.drawSimpleText(str, len, SkTextEncoding::kUTF8, x, y, font, paint);
1416 }))
1417 .function("_drawTextBlob", select_overload<void (const sk_sp<SkTextBlob>&, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawTextBlob))
1418#endif
1419 .function("_drawVertices", select_overload<void (const sk_sp<SkVertices>&, SkBlendMode, const SkPaint&)>(&SkCanvas::drawVertices))
1420
1421 .function("_getDeviceClipBounds", optional_override([](const SkCanvas& self, WASMPointerI32 iPtr) {
1422 SkIRect* outputRect = reinterpret_cast<SkIRect*>(iPtr);
1423 if (!outputRect) {
1424 return; // output pointer cannot be null
1425 }
1426 self.getDeviceClipBounds(outputRect);
1427 }))
1428 // 4x4 matrix functions
1429 // Just like with getTotalMatrix, we allocate the buffer for the 16 floats to go in from
1430 // interface.js, so it can also free them when its done.
1431 .function("_getLocalToDevice", optional_override([](const SkCanvas& self, WASMPointerF32 mPtr) {
1432 SkScalar* sixteenMatrixValues = reinterpret_cast<SkScalar*>(mPtr);
1433 if (!sixteenMatrixValues) {
1434 return; // matrix cannot be null
1435 }
1436 SkM44 m = self.getLocalToDevice();
1437 m.getRowMajor(sixteenMatrixValues);
1438 }))
1439 .function("getSaveCount", &SkCanvas::getSaveCount)
1440 // We allocate room for the matrix from the JS side and free it there so as to not have
1441 // an awkward moment where we malloc something here and "just know" to free it on the
1442 // JS side.
1443 .function("_getTotalMatrix", optional_override([](const SkCanvas& self, WASMPointerU8 mPtr) {
1444 SkScalar* nineMatrixValues = reinterpret_cast<SkScalar*>(mPtr);
1445 if (!nineMatrixValues) {
1446 return; // matrix cannot be null
1447 }
1448 SkMatrix m = self.getTotalMatrix();
1449 m.get9(nineMatrixValues);
1450 }))
1451 .function("_makeSurface", optional_override([](SkCanvas& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
1452 return self.makeSurface(toSkImageInfo(sii), nullptr);
1453 }), allow_raw_pointers())
1454
1455 .function("_readPixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
1456 WASMPointerU8 pPtr,
1457 size_t dstRowBytes, int srcX, int srcY) {
1458 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1459 SkImageInfo dstInfo = toSkImageInfo(di);
1460
1461 return self.readPixels(dstInfo, pixels, dstRowBytes, srcX, srcY);
1462 }), allow_raw_pointers())
1463 .function("restore", &SkCanvas::restore)
1464 .function("restoreToCount", &SkCanvas::restoreToCount)
1465 .function("rotate", select_overload<void (SkScalar, SkScalar, SkScalar)>(&SkCanvas::rotate))
1466 .function("save", &SkCanvas::save)
1467 .function("_saveLayer", optional_override([](SkCanvas& self, const SkPaint* p, WASMPointerF32 fPtr,
1469 SkRect* bounds = reinterpret_cast<SkRect*>(fPtr);
1470 return self.saveLayer(SkCanvas::SaveLayerRec(bounds, p, backdrop, flags));
1471 }), allow_raw_pointers())
1472 .function("saveLayerPaint", optional_override([](SkCanvas& self, const SkPaint p)->int {
1473 return self.saveLayer(SkCanvas::SaveLayerRec(nullptr, &p, 0));
1474 }))
1475 .function("scale", &SkCanvas::scale)
1476 .function("skew", &SkCanvas::skew)
1477 .function("translate", &SkCanvas::translate)
1478 .function("_writePixels", optional_override([](SkCanvas& self, SimpleImageInfo di,
1479 WASMPointerU8 pPtr,
1480 size_t srcRowBytes, int dstX, int dstY) {
1481 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1482 SkImageInfo dstInfo = toSkImageInfo(di);
1483
1484 return self.writePixels(dstInfo, pixels, srcRowBytes, dstX, dstY);
1485 }));
1486
1487 class_<SkColorFilter>("ColorFilter")
1488 .smart_ptr<sk_sp<SkColorFilter>>("sk_sp<ColorFilter>>")
1489 .class_function("_MakeBlend", optional_override([](WASMPointerF32 cPtr, SkBlendMode mode,
1491 return SkColorFilters::Blend(ptrToSkColor4f(cPtr), colorSpace, mode);
1492 }))
1493 .class_function("MakeCompose", &SkColorFilters::Compose)
1494 .class_function("MakeLerp", &SkColorFilters::Lerp)
1495 .class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
1496 .class_function("_makeMatrix", optional_override([](WASMPointerF32 fPtr) {
1497 float* twentyFloats = reinterpret_cast<float*>(fPtr);
1498 return SkColorFilters::Matrix(twentyFloats);
1499 }))
1500 .class_function("MakeSRGBToLinearGamma", &SkColorFilters::SRGBToLinearGamma)
1501 .class_function("MakeLuma", &SkLumaColorFilter::Make);
1502
1503 class_<SkContourMeasureIter>("ContourMeasureIter")
1504 .constructor<const SkPath&, bool, SkScalar>()
1506
1507 class_<SkContourMeasure>("ContourMeasure")
1508 .smart_ptr<sk_sp<SkContourMeasure>>("sk_sp<ContourMeasure>>")
1509 .function("_getPosTan", optional_override([](SkContourMeasure& self,
1511 WASMPointerF32 oPtr) -> void {
1512 SkPoint* pointAndVector = reinterpret_cast<SkPoint*>(oPtr);
1513 if (!self.getPosTan(distance, pointAndVector, pointAndVector + 1)) {
1514 SkDebugf("zero-length path in getPosTan\n");
1515 }
1516 }))
1517 .function("getSegment", optional_override([](SkContourMeasure& self, SkScalar startD,
1518 SkScalar stopD, bool startWithMoveTo) -> SkPath {
1519 SkPath p;
1520 bool ok = self.getSegment(startD, stopD, &p, startWithMoveTo);
1521 if (ok) {
1522 return p;
1523 }
1524 return SkPath();
1525 }))
1526 .function("isClosed", &SkContourMeasure::isClosed)
1527 .function("length", &SkContourMeasure::length);
1528
1529#ifndef CK_NO_FONTS
1530 class_<SkFont>("Font")
1531 .constructor<>()
1532 .constructor<sk_sp<SkTypeface>>()
1533 .constructor<sk_sp<SkTypeface>, SkScalar>()
1534 .constructor<sk_sp<SkTypeface>, SkScalar, SkScalar, SkScalar>()
1535 .function("_getGlyphWidthBounds", optional_override([](SkFont& self, WASMPointerU16 gPtr,
1536 int numGlyphs, WASMPointerF32 wPtr,
1537 WASMPointerF32 rPtr,
1538 SkPaint* paint) {
1539 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
1540 // On the JS side only one of these is set at a time for easier ergonomics.
1541 SkRect* outputRects = reinterpret_cast<SkRect*>(rPtr);
1542 SkScalar* outputWidths = reinterpret_cast<SkScalar*>(wPtr);
1543 self.getWidthsBounds(glyphs, numGlyphs, outputWidths, outputRects, paint);
1544 }), allow_raw_pointers())
1545 .function("_getGlyphIDs", optional_override([](SkFont& self, WASMPointerU8 sptr,
1546 size_t strLen, size_t expectedCodePoints,
1547 WASMPointerU16 iPtr) -> int {
1548 char* str = reinterpret_cast<char*>(sptr);
1549 SkGlyphID* glyphIDs = reinterpret_cast<SkGlyphID*>(iPtr);
1550
1551 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
1552 glyphIDs, expectedCodePoints);
1553 return actualCodePoints;
1554 }))
1555 .function("getMetrics", optional_override([](SkFont& self) -> JSObject {
1556 SkFontMetrics fm;
1557 self.getMetrics(&fm);
1558
1559 JSObject j = emscripten::val::object();
1560 j.set("ascent", fm.fAscent);
1561 j.set("descent", fm.fDescent);
1562 j.set("leading", fm.fLeading);
1564 const float rect[] = {
1565 fm.fXMin, fm.fTop, fm.fXMax, fm.fBottom
1566 };
1567 j.set("bounds", MakeTypedArray(4, rect));
1568 }
1569 return j;
1570 }))
1571 .function("_getGlyphIntercepts", optional_override([](SkFont& self,
1572 WASMPointerU16 gPtr, size_t numGlyphs, bool ownGlyphs,
1573 WASMPointerF32 pPtr, size_t numPos, bool ownPos,
1574 float top, float bottom) -> Float32Array {
1575 JSSpan<uint16_t> glyphs(gPtr, numGlyphs, ownGlyphs);
1576 JSSpan<float> pos (pPtr, numPos, ownPos);
1577 if (glyphs.size() > (pos.size() >> 1)) {
1578 return emscripten::val("Not enough x,y position pairs for glyphs");
1579 }
1580 auto sects = self.getIntercepts(glyphs.data(), SkToInt(glyphs.size()),
1581 (const SkPoint*)pos.data(), top, bottom);
1582 return MakeTypedArray(sects.size(), (const float*)sects.data());
1583 }), allow_raw_pointers())
1584 .function("getScaleX", &SkFont::getScaleX)
1585 .function("getSize", &SkFont::getSize)
1586 .function("getSkewX", &SkFont::getSkewX)
1587 .function("isEmbolden", &SkFont::isEmbolden)
1588 .function("getTypeface", &SkFont::getTypeface, allow_raw_pointers())
1589 .function("setEdging", &SkFont::setEdging)
1590 .function("setEmbeddedBitmaps", &SkFont::setEmbeddedBitmaps)
1591 .function("setHinting", &SkFont::setHinting)
1592 .function("setLinearMetrics", &SkFont::setLinearMetrics)
1593 .function("setScaleX", &SkFont::setScaleX)
1594 .function("setSize", &SkFont::setSize)
1595 .function("setSkewX", &SkFont::setSkewX)
1596 .function("setEmbolden", &SkFont::setEmbolden)
1597 .function("setSubpixel", &SkFont::setSubpixel)
1598 .function("setTypeface", &SkFont::setTypeface, allow_raw_pointers());
1599
1600 class_<SkFontMgr>("FontMgr")
1601 .smart_ptr<sk_sp<SkFontMgr>>("sk_sp<FontMgr>")
1602 .class_function("_fromData", optional_override([](WASMPointerU32 dPtr,
1603 WASMPointerU32 sPtr,
1604 int numFonts)->sk_sp<SkFontMgr> {
1605 auto datas = reinterpret_cast<const uint8_t**>(dPtr);
1606 auto sizes = reinterpret_cast<const size_t*>(sPtr);
1607
1608 std::unique_ptr<sk_sp<SkData>[]> skdatas(new sk_sp<SkData>[numFonts]);
1609 for (int i = 0; i < numFonts; ++i) {
1610 skdatas[i] = SkData::MakeFromMalloc(datas[i], sizes[i]);
1611 }
1612
1613 return SkFontMgr_New_Custom_Data(SkSpan(skdatas.get(), numFonts));
1614 }), allow_raw_pointers())
1615 .function("countFamilies", &SkFontMgr::countFamilies)
1616 .function("getFamilyName", optional_override([](SkFontMgr& self, int index)->JSString {
1617 if (index < 0 || index >= self.countFamilies()) {
1618 return emscripten::val::null();
1619 }
1620 SkString s;
1621 self.getFamilyName(index, &s);
1622 return emscripten::val(s.c_str());
1623 }))
1624 .function("matchFamilyStyle", optional_override([](SkFontMgr& self, std::string name, emscripten::val jsFontStyle)->sk_sp<SkTypeface> {
1625 auto weight = SkFontStyle::Weight(jsFontStyle["weight"].isUndefined() ? SkFontStyle::kNormal_Weight : jsFontStyle["weight"].as<int>());
1626 auto width = SkFontStyle::Width(jsFontStyle["width"].isUndefined() ? SkFontStyle::kNormal_Width : jsFontStyle["width"].as<int>());
1627 auto slant = SkFontStyle::Slant(jsFontStyle["slant"].isUndefined() ? SkFontStyle::kUpright_Slant : static_cast<SkFontStyle::Slant>(jsFontStyle["slant"].as<int>()));
1628
1629 SkFontStyle style(weight, width, slant);
1630
1631 return self.matchFamilyStyle(name.c_str(), style);
1632 }), allow_raw_pointers())
1633#ifdef SK_DEBUG
1634 .function("dumpFamilies", optional_override([](SkFontMgr& self) {
1635 int numFam = self.countFamilies();
1636 SkDebugf("There are %d font families\n", numFam);
1637 for (int i = 0 ; i< numFam; i++) {
1638 SkString s;
1639 self.getFamilyName(i, &s);
1640 SkDebugf("\t%s\n", s.c_str());
1641 }
1642 }))
1643#endif
1644 .function("_makeTypefaceFromData", optional_override([](SkFontMgr& self,
1645 WASMPointerU8 fPtr,
1646 int flen)->sk_sp<SkTypeface> {
1647 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
1648 sk_sp<SkData> fontData = SkData::MakeFromMalloc(font, flen);
1649
1650 return self.makeFromData(fontData);
1651 }), allow_raw_pointers());
1652#endif // CK_NO_FONTS
1653
1654 class_<SkImage>("Image")
1655 .smart_ptr<sk_sp<SkImage>>("sk_sp<Image>")
1656#ifdef CK_ENABLE_WEBGL
1657 .class_function("_makeFromGenerator", &MakeImageFromGenerator)
1658#endif
1659 // Note that this needs to be cleaned up with delete().
1660 .function("getColorSpace", optional_override([](sk_sp<SkImage> self)->sk_sp<SkColorSpace> {
1661 return self->imageInfo().refColorSpace();
1662 }), allow_raw_pointers())
1663 .function("getImageInfo", optional_override([](sk_sp<SkImage> self)->JSObject {
1664 // We cannot return a SimpleImageInfo because the colorspace object would be leaked.
1665 JSObject result = emscripten::val::object();
1666 SkImageInfo ii = self->imageInfo();
1667 result.set("alphaType", ii.alphaType());
1668 result.set("colorType", ii.colorType());
1669 result.set("height", ii.height());
1670 result.set("width", ii.width());
1671 return result;
1672 }))
1673 .function("height", &SkImage::height)
1674 .function("_encodeToBytes", optional_override([](sk_sp<SkImage> self,
1676 int quality) -> Uint8Array {
1677 return encodeImage(nullptr, self, fmt, quality);
1678 }))
1679#if defined(ENABLE_GPU)
1680 .function("_encodeToBytes", optional_override([](sk_sp<SkImage> self,
1682 int quality,
1683 GrDirectContext* dContext) -> Uint8Array {
1684 return encodeImage(dContext, self, fmt, quality);
1685 }), allow_raw_pointers())
1686#endif
1687 .function("makeCopyWithDefaultMipmaps", optional_override([](sk_sp<SkImage> self)->sk_sp<SkImage> {
1688 return self->withDefaultMipmaps();
1689 }))
1690 .function("_makeShaderCubic", optional_override([](sk_sp<SkImage> self,
1691 SkTileMode tx, SkTileMode ty,
1692 float B, float C, // See SkSamplingOptions.h for docs.
1693 WASMPointerF32 mPtr)->sk_sp<SkShader> {
1694 OptionalMatrix localMatrix(mPtr);
1695 return self->makeShader(tx, ty, SkSamplingOptions({B, C}), mPtr ? &localMatrix
1696 : nullptr);
1697 }), allow_raw_pointers())
1698 .function("_makeShaderOptions", optional_override([](sk_sp<SkImage> self,
1699 SkTileMode tx, SkTileMode ty,
1700 SkFilterMode filter, SkMipmapMode mipmap,
1701 WASMPointerF32 mPtr)->sk_sp<SkShader> {
1702 OptionalMatrix localMatrix(mPtr);
1703 return self->makeShader(tx, ty, {filter, mipmap}, mPtr ? &localMatrix : nullptr);
1704 }), allow_raw_pointers())
1705#if defined(ENABLE_GPU)
1706 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1708 size_t dstRowBytes, int srcX, int srcY,
1709 GrDirectContext* dContext)->bool {
1710 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1711 SkImageInfo ii = toSkImageInfo(sii);
1712 return self->readPixels(dContext, ii, pixels, dstRowBytes, srcX, srcY);
1713 }), allow_raw_pointers())
1714#endif
1715 .function("_readPixels", optional_override([](sk_sp<SkImage> self,
1717 size_t dstRowBytes, int srcX, int srcY)->bool {
1718 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
1719 SkImageInfo ii = toSkImageInfo(sii);
1720 return self->readPixels(nullptr, ii, pixels, dstRowBytes, srcX, srcY);
1721 }), allow_raw_pointers())
1722 .function("width", &SkImage::width);
1723
1724 class_<SkImageFilter>("ImageFilter")
1725 .smart_ptr<sk_sp<SkImageFilter>>("sk_sp<ImageFilter>")
1726 .function("_getOutputBounds", optional_override([](const SkImageFilter& self, WASMPointerF32 bPtr, WASMPointerF32 mPtr, WASMPointerU32 oPtr)->void {
1727 SkRect* rect = reinterpret_cast<SkRect*>(bPtr);
1728 OptionalMatrix ctm(mPtr);
1729 SkIRect* output = reinterpret_cast<SkIRect*>(oPtr);
1730 output[0] = self.filterBounds(ctm.mapRect(*rect).roundOut(), ctm, SkImageFilter::kForward_MapDirection);
1731 }))
1732 .class_function("MakeBlend", optional_override([](SkBlendMode mode, sk_sp<SkImageFilter> background,
1733 sk_sp<SkImageFilter> foreground)->sk_sp<SkImageFilter> {
1734 return SkImageFilters::Blend(mode, background, foreground);
1735 }))
1736 .class_function("MakeBlur", optional_override([](SkScalar sigmaX, SkScalar sigmaY,
1737 SkTileMode tileMode, sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1738 return SkImageFilters::Blur(sigmaX, sigmaY, tileMode, input);
1739 }))
1740 .class_function("MakeColorFilter", optional_override([](sk_sp<SkColorFilter> cf,
1741 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1742 return SkImageFilters::ColorFilter(cf, input);
1743 }))
1744 .class_function("MakeCompose", &SkImageFilters::Compose)
1745 .class_function("MakeDilate", optional_override([](SkScalar radiusX, SkScalar radiusY,
1746 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1747 return SkImageFilters::Dilate(radiusX, radiusY, input);
1748 }))
1749 .class_function("MakeDisplacementMap", optional_override([](SkColorChannel xChannelSelector,
1750 SkColorChannel yChannelSelector,
1751 SkScalar scale, sk_sp<SkImageFilter> displacement,
1753 return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector,
1754 scale, displacement, color);
1755 }))
1756 .class_function("MakeShader", optional_override([](sk_sp<SkShader> shader)->sk_sp<SkImageFilter> {
1757 return SkImageFilters::Shader(shader);
1758 }))
1759 .class_function("_MakeDropShadow", optional_override([](SkScalar dx, SkScalar dy,
1760 SkScalar sigmaX, SkScalar sigmaY,
1762 SkColor4f c = ptrToSkColor4f(cPtr);
1763 return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, c.toSkColor(), input);
1764 }))
1765 .class_function("_MakeDropShadowOnly", optional_override([](SkScalar dx, SkScalar dy,
1766 SkScalar sigmaX, SkScalar sigmaY,
1768 SkColor4f c = ptrToSkColor4f(cPtr);
1769 return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, c.toSkColor(), input);
1770 }))
1771 .class_function("MakeErode", optional_override([](SkScalar radiusX, SkScalar radiusY,
1772 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1773 return SkImageFilters::Erode(radiusX, radiusY, input);
1774 }))
1775 .class_function("_MakeImageCubic", optional_override([](sk_sp<SkImage> image,
1776 float B, float C,
1777 WASMPointerF32 srcPtr,
1778 WASMPointerF32 dstPtr
1779 )->sk_sp<SkImageFilter> {
1780 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1781 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1782 if (src && dst) {
1784 }
1786 }))
1787 .class_function("_MakeImageOptions", optional_override([](sk_sp<SkImage> image,
1788 SkFilterMode fm,
1789 SkMipmapMode mm,
1790 WASMPointerF32 srcPtr,
1791 WASMPointerF32 dstPtr
1792 )->sk_sp<SkImageFilter> {
1793 const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
1794 const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
1795 if (src && dst) {
1797 }
1799 }))
1800 .class_function("_MakeMatrixTransformCubic",
1801 optional_override([](WASMPointerF32 mPtr, float B, float C,
1802 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1803 OptionalMatrix matr(mPtr);
1804 return SkImageFilters::MatrixTransform(matr, SkSamplingOptions({B, C}), input);
1805 }))
1806 .class_function("_MakeMatrixTransformOptions",
1807 optional_override([](WASMPointerF32 mPtr, SkFilterMode fm, SkMipmapMode mm,
1808 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1809 OptionalMatrix matr(mPtr);
1810 return SkImageFilters::MatrixTransform(matr, SkSamplingOptions(fm, mm), input);
1811 }))
1812 .class_function("MakeOffset", optional_override([](SkScalar dx, SkScalar dy,
1813 sk_sp<SkImageFilter> input)->sk_sp<SkImageFilter> {
1814 return SkImageFilters::Offset(dx, dy, input);
1815 }));
1816
1817 class_<SkMaskFilter>("MaskFilter")
1818 .smart_ptr<sk_sp<SkMaskFilter>>("sk_sp<MaskFilter>")
1819 .class_function("MakeBlur", optional_override([](SkBlurStyle style, SkScalar sigma, bool respectCTM)->sk_sp<SkMaskFilter> {
1820 // Adds a little helper because emscripten doesn't expose default params.
1821 return SkMaskFilter::MakeBlur(style, sigma, respectCTM);
1822 }), allow_raw_pointers());
1823
1824 class_<SkPaint>("Paint")
1825 .constructor<>()
1826 .function("copy", optional_override([](const SkPaint& self)->SkPaint {
1827 SkPaint p(self);
1828 return p;
1829 }))
1830 // provide an allocated place to put the returned color
1831 .function("_getColor", optional_override([](SkPaint& self, WASMPointerF32 cPtr)->void {
1832 const SkColor4f& c = self.getColor4f();
1833 float* fourFloats = reinterpret_cast<float*>(cPtr);
1834 memcpy(fourFloats, c.vec(), 4 * sizeof(SkScalar));
1835 }))
1836 .function("getStrokeCap", &SkPaint::getStrokeCap)
1837 .function("getStrokeJoin", &SkPaint::getStrokeJoin)
1838 .function("getStrokeMiter", &SkPaint::getStrokeMiter)
1839 .function("getStrokeWidth", &SkPaint::getStrokeWidth)
1840 .function("setAntiAlias", &SkPaint::setAntiAlias)
1841 .function("setAlphaf", &SkPaint::setAlphaf)
1842 .function("setBlendMode", &SkPaint::setBlendMode)
1843 .function("setBlender", &SkPaint::setBlender)
1844 .function("_setColor", optional_override([](SkPaint& self, WASMPointerF32 cPtr,
1845 sk_sp<SkColorSpace> colorSpace) {
1846 self.setColor(ptrToSkColor4f(cPtr), colorSpace.get());
1847 }))
1848 .function("setColorInt", optional_override([](SkPaint& self, SkColor color) {
1849 self.setColor(SkColor4f::FromColor(color), nullptr);
1850 }))
1851 .function("setColorInt", optional_override([](SkPaint& self, SkColor color,
1852 sk_sp<SkColorSpace> colorSpace) {
1853 self.setColor(SkColor4f::FromColor(color), colorSpace.get());
1854 }))
1855 .function("setColorFilter", &SkPaint::setColorFilter)
1856 .function("setDither", &SkPaint::setDither)
1857 .function("setImageFilter", &SkPaint::setImageFilter)
1858 .function("setMaskFilter", &SkPaint::setMaskFilter)
1859 .function("setPathEffect", &SkPaint::setPathEffect)
1860 .function("setShader", &SkPaint::setShader)
1861 .function("setStrokeCap", &SkPaint::setStrokeCap)
1862 .function("setStrokeJoin", &SkPaint::setStrokeJoin)
1863 .function("setStrokeMiter", &SkPaint::setStrokeMiter)
1864 .function("setStrokeWidth", &SkPaint::setStrokeWidth)
1865 .function("setStyle", &SkPaint::setStyle);
1866
1867 class_<SkColorSpace>("ColorSpace")
1868 .smart_ptr<sk_sp<SkColorSpace>>("sk_sp<ColorSpace>")
1869 .class_function("Equals", optional_override([](sk_sp<SkColorSpace> a, sk_sp<SkColorSpace> b)->bool {
1870 return SkColorSpace::Equals(a.get(), b.get());
1871 }))
1872 // These are private because they are to be called once in interface.js to
1873 // avoid clients having to delete the returned objects.
1874 .class_function("_MakeSRGB", &SkColorSpace::MakeSRGB)
1875 .class_function("_MakeDisplayP3", optional_override([]()->sk_sp<SkColorSpace> {
1877 }))
1878 .class_function("_MakeAdobeRGB", optional_override([]()->sk_sp<SkColorSpace> {
1880 }));
1881
1882 class_<SkPathEffect>("PathEffect")
1883 .smart_ptr<sk_sp<SkPathEffect>>("sk_sp<PathEffect>")
1884 .class_function("MakeCorner", &SkCornerPathEffect::Make)
1885 .class_function("_MakeDash", optional_override([](WASMPointerF32 cptr, int count,
1887 const float* intervals = reinterpret_cast<const float*>(cptr);
1888 return SkDashPathEffect::Make(intervals, count, phase);
1889 }), allow_raw_pointers())
1890 .class_function("MakeDiscrete", &SkDiscretePathEffect::Make)
1891 .class_function("_MakeLine2D", optional_override([](SkScalar width,
1892 WASMPointerF32 mPtr)->sk_sp<SkPathEffect> {
1894 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1895 matrix.set9(nineMatrixValues);
1897 }), allow_raw_pointers())
1898 .class_function("MakePath1D", &SkPath1DPathEffect::Make)
1899 .class_function("_MakePath2D", optional_override([](WASMPointerF32 mPtr,
1900 SkPath path)->sk_sp<SkPathEffect> {
1902 const SkScalar* nineMatrixValues = reinterpret_cast<const SkScalar*>(mPtr);
1903 matrix.set9(nineMatrixValues);
1905 }), allow_raw_pointers());
1906
1907 // TODO(kjlubick, reed) Make SkPath immutable and only creatable via a factory/builder.
1908 class_<SkPath>("Path")
1909 .constructor<>()
1910#ifdef CK_INCLUDE_PATHOPS
1911 .class_function("MakeFromOp", &MakePathFromOp)
1912#endif
1913 .class_function("MakeFromSVGString", &MakePathFromSVGString)
1914 .class_function("MakeFromPathInterpolation", &MakePathFromInterpolation)
1915 .class_function("CanInterpolate", &CanInterpolate)
1916 .class_function("_MakeFromCmds", &MakePathFromCmds)
1917 .class_function("_MakeFromVerbsPointsWeights", &MakePathFromVerbsPointsWeights)
1918 .function("_addArc", optional_override([](SkPath& self,
1919 WASMPointerF32 fPtr,
1921 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1922 self.addArc(*oval, startAngle, sweepAngle);
1923 }))
1924 .function("_addOval", optional_override([](SkPath& self,
1925 WASMPointerF32 fPtr,
1926 bool ccw, unsigned start)->void {
1927 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1929 }))
1930 .function("_addCircle", optional_override([](SkPath& self,
1931 SkScalar x,
1932 SkScalar y,
1933 SkScalar r,
1934 bool ccw)->void {
1935 self.addCircle(x, y, r, ccw ? SkPathDirection::kCCW : SkPathDirection::kCW);
1936 }))
1937 // interface.js has 3 overloads of addPath
1938 .function("_addPath", &ApplyAddPath)
1939 .function("_addPoly", optional_override([](SkPath& self,
1940 WASMPointerF32 fPtr,
1941 int count, bool close)->void {
1942 const SkPoint* pts = reinterpret_cast<const SkPoint*>(fPtr);
1943 self.addPoly(pts, count, close);
1944 }))
1945 .function("_addRect", optional_override([](SkPath& self,
1946 WASMPointerF32 fPtr,
1947 bool ccw)->void {
1948 const SkRect* rect = reinterpret_cast<const SkRect*>(fPtr);
1950 }))
1951 .function("_addRRect", optional_override([](SkPath& self,
1952 WASMPointerF32 fPtr,
1953 bool ccw)->void {
1955 }))
1956 .function("_addVerbsPointsWeights", &PathAddVerbsPointsWeights)
1957 .function("_arcToOval", optional_override([](SkPath& self,
1959 SkScalar sweepAngle, bool forceMoveTo)->void {
1960 const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
1961 self.arcTo(*oval, startAngle, sweepAngle, forceMoveTo);
1962 }))
1963 .function("_arcToRotated", &ApplyArcToArcSize)
1964 .function("_arcToTangent", ApplyArcToTangent)
1965 .function("_close", &ApplyClose)
1966 .function("_conicTo", &ApplyConicTo)
1967 .function("countPoints", &SkPath::countPoints)
1968 .function("contains", &SkPath::contains)
1969 .function("_cubicTo", &ApplyCubicTo)
1970 .function("_getPoint", optional_override([](SkPath& self, int index,
1971 WASMPointerF32 oPtr)->void {
1972 SkPoint* output = reinterpret_cast<SkPoint*>(oPtr);
1973 *output = self.getPoint(index);
1974 }))
1975 .function("isEmpty", &SkPath::isEmpty)
1976 .function("isVolatile", &SkPath::isVolatile)
1977 .function("_lineTo", &ApplyLineTo)
1978 .function("_moveTo", &ApplyMoveTo)
1979 .function("_quadTo", &ApplyQuadTo)
1980 .function("_rArcTo", &ApplyRArcToArcSize)
1981 .function("_rConicTo", &ApplyRConicTo)
1982 .function("_rCubicTo", &ApplyRCubicTo)
1983 .function("_rLineTo", &ApplyRLineTo)
1984 .function("_rMoveTo", &ApplyRMoveTo)
1985 .function("_rQuadTo", &ApplyRQuadTo)
1986 .function("reset", &ApplyReset)
1987 .function("rewind", &ApplyRewind)
1988 .function("setIsVolatile", &SkPath::setIsVolatile)
1989 .function("_transform", select_overload<void(SkPath&, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar, SkScalar)>(&ApplyTransform))
1990
1991 // PathEffects
1992 .function("_dash", &ApplyDash)
1993 .function("_trim", &ApplyTrim)
1994 .function("_stroke", &ApplyStroke)
1995
1996#ifdef CK_INCLUDE_PATHOPS
1997 // PathOps
1998 .function("_simplify", &ApplySimplify)
1999 .function("_op", &ApplyPathOp)
2000 .function("makeAsWinding", &MakeAsWinding)
2001#endif
2002 // Exporting
2003 .function("toSVGString", &ToSVGString)
2004 .function("toCmds", &ToCmds)
2005
2006 .function("setFillType", select_overload<void(SkPathFillType)>(&SkPath::setFillType))
2007 .function("getFillType", &SkPath::getFillType)
2008 .function("_getBounds", optional_override([](SkPath& self,
2009 WASMPointerF32 fPtr)->void {
2010 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2011 output[0] = self.getBounds();
2012 }))
2013 .function("_computeTightBounds", optional_override([](SkPath& self,
2014 WASMPointerF32 fPtr)->void {
2015 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2016 output[0] = self.computeTightBounds();
2017 }))
2018 .function("equals", &Equals)
2019 .function("copy", &CopyPath)
2020#ifdef SK_DEBUG
2021 .function("dump", select_overload<void() const>(&SkPath::dump))
2022 .function("dumpHex", select_overload<void() const>(&SkPath::dumpHex))
2023#endif
2024 ;
2025
2027 class_<SkPictureRecorder>("PictureRecorder")
2028 .constructor<>()
2029 .function("_beginRecording", optional_override([](SkPictureRecorder& self,
2030 WASMPointerF32 fPtr,
2031 bool computeBounds) -> SkCanvas* {
2032 SkRect* bounds = reinterpret_cast<SkRect*>(fPtr);
2033 return self.beginRecording(*bounds, computeBounds ? &bbhFactory : nullptr);
2034 }), allow_raw_pointers())
2035 .function("finishRecordingAsPicture", optional_override([](SkPictureRecorder& self)
2036 -> sk_sp<SkPicture> {
2037 return self.finishRecordingAsPicture();
2038 }), allow_raw_pointers());
2039
2040 class_<SkPicture>("Picture")
2041 .smart_ptr<sk_sp<SkPicture>>("sk_sp<Picture>")
2042 .function("_makeShader", optional_override([](SkPicture& self,
2045 OptionalMatrix localMatrix(mPtr);
2046 SkRect* tileRect = reinterpret_cast<SkRect*>(rPtr);
2047 return self.makeShader(tmx, tmy, mode, mPtr ? &localMatrix : nullptr, tileRect);
2048 }), allow_raw_pointers())
2049 .function("_cullRect", optional_override([](SkPicture& self,
2050 WASMPointerF32 fPtr)->void {
2051 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2052 output[0] = self.cullRect();
2053 }))
2054 .function("approximateBytesUsed", &SkPicture::approximateBytesUsed)
2055#ifdef CK_SERIALIZE_SKP
2056 // The serialized format of an SkPicture (informally called an "skp"), is not something
2057 // that clients should ever rely on. The format may change at anytime and no promises
2058 // are made for backwards or forward compatibility.
2059 .function("serialize", optional_override([](SkPicture& self) -> Uint8Array {
2060 // We want to make sure we always save the underlying data of the Typeface to the
2061 // SkPicture. By default, the data for "system" fonts is not saved, just an identifier
2062 // (e.g. the family name and style). We do not want the user to have to supply a
2063 // FontMgr with the correct fonts by name when deserializing, so we choose to always
2064 // serialize the underlying data. This makes the SKPs a bit bigger, but easier to use.
2065 SkSerialProcs sp;
2067 sp.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
2068 return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
2069 };
2070
2071 sk_sp<SkData> data = self.serialize(&sp);
2072 if (!data) {
2073 return emscripten::val::null();
2074 }
2075 return toBytes(data);
2076 }), allow_raw_pointers())
2077#endif
2078 ;
2079
2080 class_<SkShader>("Shader")
2081 .smart_ptr<sk_sp<SkShader>>("sk_sp<Shader>")
2082 .class_function("MakeBlend", select_overload<sk_sp<SkShader>(SkBlendMode, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Blend))
2083 .class_function("_MakeColor",
2084 optional_override([](WASMPointerF32 cPtr, sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2085 return SkShaders::Color(ptrToSkColor4f(cPtr), colorSpace);
2086 })
2087 )
2088 .class_function("MakeFractalNoise", optional_override([](
2089 SkScalar baseFreqX, SkScalar baseFreqY,
2090 int numOctaves, SkScalar seed,
2091 int tileW, int tileH)->sk_sp<SkShader> {
2092 // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
2093 SkISize tileSize = SkISize::Make(tileW, tileH);
2094 return SkShaders::MakeFractalNoise(baseFreqX, baseFreqY, numOctaves, seed, &tileSize);
2095 }))
2096 // Here and in other gradient functions, cPtr is a pointer to an array of data
2097 // representing colors. whether this is an array of SkColor or SkColor4f is indicated
2098 // by the colorType argument. Only RGBA_8888 and RGBA_F32 are accepted.
2099 .class_function("_MakeLinearGradient", optional_override([](
2100 WASMPointerF32 fourFloatsPtr,
2102 WASMPointerF32 pPtr,
2103 int count, SkTileMode mode, uint32_t flags,
2104 WASMPointerF32 mPtr,
2105 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2106 const SkPoint* points = reinterpret_cast<const SkPoint*>(fourFloatsPtr);
2107 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2108 OptionalMatrix localMatrix(mPtr);
2109
2111 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2112 return SkGradientShader::MakeLinear(points, colors, colorSpace, positions, count,
2113 mode, flags,
2114 mPtr ? &localMatrix : nullptr);
2116 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2117 return SkGradientShader::MakeLinear(points, colors, positions, count,
2118 mode, flags,
2119 mPtr ? &localMatrix : nullptr);
2120 }
2121 SkDebugf("%d is not an accepted colorType\n", colorType);
2122 return nullptr;
2123 }), allow_raw_pointers())
2124 .class_function("_MakeRadialGradient", optional_override([](
2125 SkScalar cx, SkScalar cy, SkScalar radius,
2127 WASMPointerF32 pPtr,
2128 int count, SkTileMode mode, uint32_t flags,
2129 WASMPointerF32 mPtr,
2130 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2131 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2132 OptionalMatrix localMatrix(mPtr);
2134 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2135 return SkGradientShader::MakeRadial({cx, cy}, radius, colors, colorSpace,
2136 positions, count, mode, flags,
2137 mPtr ? &localMatrix : nullptr);
2139 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2140 return SkGradientShader::MakeRadial({cx, cy}, radius, colors, positions,
2141 count, mode, flags,
2142 mPtr ? &localMatrix : nullptr);
2143 }
2144 SkDebugf("%d is not an accepted colorType\n", colorType);
2145 return nullptr;
2146 }), allow_raw_pointers())
2147 .class_function("_MakeSweepGradient", optional_override([](SkScalar cx, SkScalar cy,
2149 WASMPointerF32 pPtr,
2150 int count, SkTileMode mode,
2151 SkScalar startAngle, SkScalar endAngle,
2152 uint32_t flags,
2153 WASMPointerF32 mPtr,
2154 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2155 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2156 OptionalMatrix localMatrix(mPtr);
2158 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2159 return SkGradientShader::MakeSweep(cx, cy, colors, colorSpace, positions, count,
2160 mode, startAngle, endAngle, flags,
2161 mPtr ? &localMatrix : nullptr);
2163 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2164 return SkGradientShader::MakeSweep(cx, cy, colors, positions, count,
2165 mode, startAngle, endAngle, flags,
2166 mPtr ? &localMatrix : nullptr);
2167 }
2168 SkDebugf("%d is not an accepted colorType\n", colorType);
2169 return nullptr;
2170 }), allow_raw_pointers())
2171 .class_function("MakeTurbulence", optional_override([](
2172 SkScalar baseFreqX, SkScalar baseFreqY,
2173 int numOctaves, SkScalar seed,
2174 int tileW, int tileH)->sk_sp<SkShader> {
2175 // if tileSize is empty (e.g. tileW <= 0 or tileH <= 0, it will be ignored.
2176 SkISize tileSize = SkISize::Make(tileW, tileH);
2177 return SkShaders::MakeTurbulence(baseFreqX, baseFreqY, numOctaves, seed, &tileSize);
2178 }))
2179 .class_function("_MakeTwoPointConicalGradient", optional_override([](
2180 WASMPointerF32 fourFloatsPtr,
2181 SkScalar startRadius, SkScalar endRadius,
2183 WASMPointerF32 pPtr,
2184 int count, SkTileMode mode, uint32_t flags,
2185 WASMPointerF32 mPtr,
2186 sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
2187 const SkPoint* startAndEnd = reinterpret_cast<const SkPoint*>(fourFloatsPtr);
2188 const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
2189 OptionalMatrix localMatrix(mPtr);
2190
2192 const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
2193 return SkGradientShader::MakeTwoPointConical(startAndEnd[0], startRadius,
2194 startAndEnd[1], endRadius,
2195 colors, colorSpace, positions, count, mode,
2196 flags,
2197 mPtr ? &localMatrix : nullptr);
2199 const SkColor* colors = reinterpret_cast<const SkColor*>(cPtr);
2200 return SkGradientShader::MakeTwoPointConical(startAndEnd[0],
2201 startRadius,
2202 startAndEnd[1],
2203 endRadius,
2204 colors,
2205 positions,
2206 count,
2207 mode,
2208 flags,
2209 mPtr ? &localMatrix : nullptr);
2210 }
2211 SkDebugf("%d is not an accepted colorType\n", colorType);
2212 return nullptr;
2213 }), allow_raw_pointers());
2214
2215#ifdef CK_INCLUDE_RUNTIME_EFFECT
2216 class_<SkSL::DebugTrace>("DebugTrace")
2217 .smart_ptr<sk_sp<SkSL::DebugTrace>>("sk_sp<DebugTrace>")
2218 .function("writeTrace", optional_override([](SkSL::DebugTrace& self) -> std::string {
2219 SkDynamicMemoryWStream wstream;
2220 self.writeTrace(&wstream);
2221 sk_sp<SkData> trace = wstream.detachAsData();
2222 return std::string(reinterpret_cast<const char*>(trace->bytes()), trace->size());
2223 }));
2224
2225 value_object<SkRuntimeEffect::TracedShader>("TracedShader")
2226 .field("shader", &SkRuntimeEffect::TracedShader::shader)
2227 .field("debugTrace", &SkRuntimeEffect::TracedShader::debugTrace);
2228
2229 class_<SkRuntimeEffect>("RuntimeEffect")
2230 .smart_ptr<sk_sp<SkRuntimeEffect>>("sk_sp<RuntimeEffect>")
2231 .class_function("_Make", optional_override([](std::string sksl,
2232 emscripten::val errHandler
2234 SkString s(sksl.c_str(), sksl.length());
2235 auto [effect, errorText] = SkRuntimeEffect::MakeForShader(s);
2236 if (!effect) {
2237 errHandler.call<void>("onError", val(errorText.c_str()));
2238 return nullptr;
2239 }
2240 return effect;
2241 }))
2242 .class_function("_MakeForBlender", optional_override([](std::string sksl,
2243 emscripten::val errHandler
2244 )->sk_sp<SkRuntimeEffect> {
2245 SkString s(sksl.c_str(), sksl.length());
2246 auto [effect, errorText] = SkRuntimeEffect::MakeForBlender(s);
2247 if (!effect) {
2248 errHandler.call<void>("onError", val(errorText.c_str()));
2249 return nullptr;
2250 }
2251 return effect;
2252 }))
2253 .class_function("MakeTraced", optional_override([](
2254 sk_sp<SkShader> shader,
2255 int traceCoordX,
2256 int traceCoordY) -> SkRuntimeEffect::TracedShader {
2257 return SkRuntimeEffect::MakeTraced(shader, SkIPoint::Make(traceCoordX, traceCoordY));
2258 }))
2259 .function("_makeShader", optional_override([](SkRuntimeEffect& self,
2260 WASMPointerF32 fPtr,
2261 size_t fLen,
2262 bool shouldOwnUniforms,
2263 WASMPointerF32 mPtr)->sk_sp<SkShader> {
2264 void* uniformData = reinterpret_cast<void*>(fPtr);
2265 castUniforms(uniformData, fLen, self);
2266 sk_sp<SkData> uniforms;
2267 if (shouldOwnUniforms) {
2268 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2269 } else {
2270 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2271 }
2272
2273 OptionalMatrix localMatrix(mPtr);
2274 return self.makeShader(uniforms, nullptr, 0, mPtr ? &localMatrix : nullptr);
2275 }))
2276 .function("_makeShaderWithChildren", optional_override([](SkRuntimeEffect& self,
2277 WASMPointerF32 fPtr,
2278 size_t fLen,
2279 bool shouldOwnUniforms,
2280 WASMPointerU32 cPtrs,
2281 size_t cLen,
2282 WASMPointerF32 mPtr)->sk_sp<SkShader> {
2283 void* uniformData = reinterpret_cast<void*>(fPtr);
2284 castUniforms(uniformData, fLen, self);
2285 sk_sp<SkData> uniforms;
2286 if (shouldOwnUniforms) {
2287 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2288 } else {
2289 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2290 }
2291
2292 sk_sp<SkShader>* children = new sk_sp<SkShader>[cLen];
2293 SkShader** childrenPtrs = reinterpret_cast<SkShader**>(cPtrs);
2294 for (size_t i = 0; i < cLen; i++) {
2295 // This bare pointer was already part of an sk_sp (owned outside of here),
2296 // so we want to ref the new sk_sp so makeShader doesn't clean it up.
2297 children[i] = sk_ref_sp<SkShader>(childrenPtrs[i]);
2298 }
2299 OptionalMatrix localMatrix(mPtr);
2300 auto s = self.makeShader(uniforms, children, cLen, mPtr ? &localMatrix : nullptr);
2301 delete[] children;
2302 return s;
2303 }))
2304 .function("_makeBlender", optional_override([](SkRuntimeEffect& self,
2305 WASMPointerF32 fPtr,
2306 size_t fLen,
2307 bool shouldOwnUniforms)->sk_sp<SkBlender> {
2308 void* uniformData = reinterpret_cast<void*>(fPtr);
2309 castUniforms(uniformData, fLen, self);
2310 sk_sp<SkData> uniforms;
2311 if (shouldOwnUniforms) {
2312 uniforms = SkData::MakeFromMalloc(uniformData, fLen);
2313 } else {
2314 uniforms = SkData::MakeWithoutCopy(uniformData, fLen);
2315 }
2316
2317 return self.makeBlender(uniforms, {});
2318 }))
2319 .function("getUniformCount", optional_override([](SkRuntimeEffect& self)->int {
2320 return self.uniforms().size();
2321 }))
2322 .function("getUniformFloatCount", optional_override([](SkRuntimeEffect& self)->int {
2323 return self.uniformSize() / sizeof(float);
2324 }))
2325 .function("getUniformName", optional_override([](SkRuntimeEffect& self, int i)->JSString {
2326 auto it = self.uniforms().begin() + i;
2327 return emscripten::val(std::string(it->name).c_str());
2328 }))
2329 .function("getUniform", optional_override([](SkRuntimeEffect& self, int i)->RuntimeEffectUniform {
2330 auto it = self.uniforms().begin() + i;
2331 RuntimeEffectUniform su = fromUniform(*it);
2332 return su;
2333 }));
2334
2335 value_object<RuntimeEffectUniform>("RuntimeEffectUniform")
2336 .field("columns", &RuntimeEffectUniform::columns)
2337 .field("rows", &RuntimeEffectUniform::rows)
2338 .field("slot", &RuntimeEffectUniform::slot)
2339 .field("isInteger", &RuntimeEffectUniform::isInteger);
2340
2341 constant("rt_effect", true);
2342#endif
2343
2344 class_<SkSurface>("Surface")
2345 .smart_ptr<sk_sp<SkSurface>>("sk_sp<Surface>")
2346 .class_function("_makeRasterDirect", optional_override([](const SimpleImageInfo ii,
2347 WASMPointerU8 pPtr,
2348 size_t rowBytes)->sk_sp<SkSurface> {
2349 uint8_t* pixels = reinterpret_cast<uint8_t*>(pPtr);
2350 SkImageInfo imageInfo = toSkImageInfo(ii);
2351 return SkSurfaces::WrapPixels(imageInfo, pixels, rowBytes, nullptr);
2352 }), allow_raw_pointers())
2353 .function("_flush", optional_override([](SkSurface& self) {
2354#ifdef CK_ENABLE_WEBGL
2356#endif
2357 }))
2358 .function("_getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
2359 .function("imageInfo", optional_override([](SkSurface& self)->SimpleImageInfo {
2360 const auto& ii = self.imageInfo();
2361 return {ii.width(), ii.height(), ii.colorType(), ii.alphaType(), ii.refColorSpace()};
2362 }))
2363 .function("height", &SkSurface::height)
2364#ifdef CK_ENABLE_WEBGL
2365 .function("_makeImageFromTexture", optional_override([](SkSurface& self,
2366 uint32_t webglHandle, uint32_t texHandle,
2367 SimpleImageInfo ii)->sk_sp<SkImage> {
2368 auto releaseCtx = new TextureReleaseContext{webglHandle, texHandle};
2369 GrGLTextureInfo gti = {GR_GL_TEXTURE_2D, texHandle,
2370 GR_GL_RGBA8}; // TODO(kjlubick) look at ii for this
2372 auto dContext = GrAsDirectContext(self.getCanvas()->recordingContext());
2373
2374 return SkImages::BorrowTextureFrom(dContext,
2375 gbt,
2377 ii.colorType,
2378 ii.alphaType,
2379 ii.colorSpace,
2380 deleteJSTexture,
2381 releaseCtx);
2382 }))
2383#endif // CK_ENABLE_WEBGL
2384#ifdef CK_ENABLE_WEBGPU
2385 .function("_replaceBackendTexture", optional_override([](SkSurface& self,
2386 uint32_t texHandle, uint32_t texFormat,
2387 int width, int height) {
2388 return ReplaceBackendTexture(self, texHandle, texFormat, width, height);
2389 }))
2390#endif // CK_ENABLE_WEBGPU
2391 .function("_makeImageSnapshot", optional_override([](SkSurface& self, WASMPointerU32 iPtr)->sk_sp<SkImage> {
2392 SkIRect* bounds = reinterpret_cast<SkIRect*>(iPtr);
2393 if (!bounds) {
2394 return self.makeImageSnapshot();
2395 }
2396 return self.makeImageSnapshot(*bounds);
2397 }))
2398 .function("_makeSurface", optional_override([](SkSurface& self, SimpleImageInfo sii)->sk_sp<SkSurface> {
2399 return self.makeSurface(toSkImageInfo(sii));
2400 }), allow_raw_pointers())
2401#ifdef ENABLE_GPU
2402 .function("reportBackendTypeIsGPU", optional_override([](SkSurface& self) -> bool {
2403 return self.getCanvas()->recordingContext() != nullptr;
2404 }))
2405 .function("sampleCnt", optional_override([](SkSurface& self)->int {
2406 auto backendRT = SkSurfaces::GetBackendRenderTarget(
2408 return (backendRT.isValid()) ? backendRT.sampleCnt() : 0;
2409 }))
2410 .function("_resetContext",optional_override([](SkSurface& self)->void {
2412 }))
2413#else
2414 .function("reportBackendTypeIsGPU", optional_override([](SkSurface& self) -> bool {
2415 return false;
2416 }))
2417#endif
2418 .function("width", &SkSurface::width);
2419
2420#ifndef CK_NO_FONTS
2421 class_<SkTextBlob>("TextBlob")
2422 .smart_ptr<sk_sp<SkTextBlob>>("sk_sp<TextBlob>")
2423 .class_function("_MakeFromRSXform", optional_override([](WASMPointerU8 sptr,
2424 size_t strBtyes,
2425 WASMPointerF32 xptr,
2426 const SkFont& font)->sk_sp<SkTextBlob> {
2427 const char* str = reinterpret_cast<const char*>(sptr);
2428 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
2429
2431 }), allow_raw_pointers())
2432 .class_function("_MakeFromRSXformGlyphs", optional_override([](WASMPointerU16 gPtr,
2433 size_t byteLen,
2434 WASMPointerF32 xptr,
2435 const SkFont& font)->sk_sp<SkTextBlob> {
2436 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
2437 const SkRSXform* xforms = reinterpret_cast<const SkRSXform*>(xptr);
2438
2440 }), allow_raw_pointers())
2441 .class_function("_MakeFromText", optional_override([](WASMPointerU8 sptr,
2442 size_t len, const SkFont& font)->sk_sp<SkTextBlob> {
2443 const char* str = reinterpret_cast<const char*>(sptr);
2445 }), allow_raw_pointers())
2446 .class_function("_MakeFromGlyphs", optional_override([](WASMPointerU16 gPtr,
2447 size_t byteLen, const SkFont& font)->sk_sp<SkTextBlob> {
2448 const SkGlyphID* glyphs = reinterpret_cast<const SkGlyphID*>(gPtr);
2450 }), allow_raw_pointers());
2451
2452 class_<SkTypeface>("Typeface")
2453 .smart_ptr<sk_sp<SkTypeface>>("sk_sp<Typeface>")
2454 .class_function("GetDefault", optional_override([]()->sk_sp<SkTypeface> {
2455#if defined(CK_EMBED_FONT)
2456 if (SK_EMBEDDED_FONTS.count == 0) {
2457 return nullptr;
2458 }
2459 static sk_sp<SkTypeface> default_face;
2460 static SkOnce once;
2461 once([] {
2462 const SkEmbeddedResource& fontEntry = SK_EMBEDDED_FONTS.entries[0];
2463 auto stream = std::make_unique<SkMemoryStream>(fontEntry.data, fontEntry.size, false);
2464 default_face = SkTypeface_FreeType::MakeFromStream(std::move(stream), SkFontArguments());
2465 });
2466 return default_face;
2467#else
2468 return nullptr;
2469#endif
2470 }), allow_raw_pointers())
2471 .class_function("_MakeTypefaceFromData", optional_override([](
2472 WASMPointerU8 fPtr, int flen)->sk_sp<SkTypeface> {
2473 uint8_t* font = reinterpret_cast<uint8_t*>(fPtr);
2474 std::unique_ptr<SkMemoryStream> stream(new SkMemoryStream());
2475 stream->setMemoryOwned(font, flen);
2477 }), allow_raw_pointers())
2478 .function("_getGlyphIDs", optional_override([](SkTypeface& self, WASMPointerU8 sptr,
2479 size_t strLen, size_t expectedCodePoints,
2480 WASMPointerU16 iPtr) -> int {
2481 char* str = reinterpret_cast<char*>(sptr);
2482 SkGlyphID* glyphIDs = reinterpret_cast<SkGlyphID*>(iPtr);
2483
2484 int actualCodePoints = self.textToGlyphs(str, strLen, SkTextEncoding::kUTF8,
2485 glyphIDs, expectedCodePoints);
2486 return actualCodePoints;
2487 }));
2488#endif
2489
2490 class_<SkVertices>("Vertices")
2491 .smart_ptr<sk_sp<SkVertices>>("sk_sp<Vertices>")
2492 .function("_bounds", optional_override([](SkVertices& self,
2493 WASMPointerF32 fPtr)->void {
2494 SkRect* output = reinterpret_cast<SkRect*>(fPtr);
2495 output[0] = self.bounds();
2496 }))
2497 .function("uniqueID", &SkVertices::uniqueID);
2498
2499 // Not intended to be called directly by clients
2500 class_<SkVertices::Builder>("_VerticesBuilder")
2501 .constructor<SkVertices::VertexMode, int, int, uint32_t>()
2502 .function("colors", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2503 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2504 return reinterpret_cast<WASMPointerF32>(self.colors());
2505 }))
2506 .function("detach", &SkVertices::Builder::detach)
2507 .function("indices", optional_override([](SkVertices::Builder& self)->WASMPointerU16{
2508 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2509 return reinterpret_cast<WASMPointerU16>(self.indices());
2510 }))
2511 .function("positions", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2512 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2513 return reinterpret_cast<WASMPointerF32>(self.positions());
2514 }))
2515 .function("texCoords", optional_override([](SkVertices::Builder& self)->WASMPointerF32{
2516 // Emscripten won't let us return bare pointers, but we can return ints just fine.
2517 return reinterpret_cast<WASMPointerF32>(self.texCoords());
2518 }));
2519
2520 enum_<SkAlphaType>("AlphaType")
2521 .value("Opaque", SkAlphaType::kOpaque_SkAlphaType)
2522 .value("Premul", SkAlphaType::kPremul_SkAlphaType)
2523 .value("Unpremul", SkAlphaType::kUnpremul_SkAlphaType);
2524
2525 enum_<SkBlendMode>("BlendMode")
2526 .value("Clear", SkBlendMode::kClear)
2527 .value("Src", SkBlendMode::kSrc)
2528 .value("Dst", SkBlendMode::kDst)
2529 .value("SrcOver", SkBlendMode::kSrcOver)
2530 .value("DstOver", SkBlendMode::kDstOver)
2531 .value("SrcIn", SkBlendMode::kSrcIn)
2532 .value("DstIn", SkBlendMode::kDstIn)
2533 .value("SrcOut", SkBlendMode::kSrcOut)
2534 .value("DstOut", SkBlendMode::kDstOut)
2535 .value("SrcATop", SkBlendMode::kSrcATop)
2536 .value("DstATop", SkBlendMode::kDstATop)
2537 .value("Xor", SkBlendMode::kXor)
2538 .value("Plus", SkBlendMode::kPlus)
2539 .value("Modulate", SkBlendMode::kModulate)
2540 .value("Screen", SkBlendMode::kScreen)
2541 .value("Overlay", SkBlendMode::kOverlay)
2542 .value("Darken", SkBlendMode::kDarken)
2543 .value("Lighten", SkBlendMode::kLighten)
2544 .value("ColorDodge", SkBlendMode::kColorDodge)
2545 .value("ColorBurn", SkBlendMode::kColorBurn)
2546 .value("HardLight", SkBlendMode::kHardLight)
2547 .value("SoftLight", SkBlendMode::kSoftLight)
2548 .value("Difference", SkBlendMode::kDifference)
2549 .value("Exclusion", SkBlendMode::kExclusion)
2550 .value("Multiply", SkBlendMode::kMultiply)
2551 .value("Hue", SkBlendMode::kHue)
2552 .value("Saturation", SkBlendMode::kSaturation)
2553 .value("Color", SkBlendMode::kColor)
2554 .value("Luminosity", SkBlendMode::kLuminosity);
2555
2556 enum_<SkBlurStyle>("BlurStyle")
2557 .value("Normal", SkBlurStyle::kNormal_SkBlurStyle)
2558 .value("Solid", SkBlurStyle::kSolid_SkBlurStyle)
2559 .value("Outer", SkBlurStyle::kOuter_SkBlurStyle)
2560 .value("Inner", SkBlurStyle::kInner_SkBlurStyle);
2561
2562 enum_<SkClipOp>("ClipOp")
2563 .value("Difference", SkClipOp::kDifference)
2564 .value("Intersect", SkClipOp::kIntersect);
2565
2566 enum_<SkColorChannel>("ColorChannel")
2567 .value("Red", SkColorChannel::kR)
2568 .value("Green", SkColorChannel::kG)
2569 .value("Blue", SkColorChannel::kB)
2570 .value("Alpha", SkColorChannel::kA);
2571
2572 enum_<SkColorType>("ColorType")
2573 .value("Alpha_8", SkColorType::kAlpha_8_SkColorType)
2574 .value("RGB_565", SkColorType::kRGB_565_SkColorType)
2575 .value("RGBA_8888", SkColorType::kRGBA_8888_SkColorType)
2576 .value("BGRA_8888", SkColorType::kBGRA_8888_SkColorType)
2577 .value("RGBA_1010102", SkColorType::kRGBA_1010102_SkColorType)
2578 .value("RGB_101010x", SkColorType::kRGB_101010x_SkColorType)
2579 .value("Gray_8", SkColorType::kGray_8_SkColorType)
2580 .value("RGBA_F16", SkColorType::kRGBA_F16_SkColorType)
2581 .value("RGBA_F32", SkColorType::kRGBA_F32_SkColorType);
2582
2583 enum_<SkPathFillType>("FillType")
2584 .value("Winding", SkPathFillType::kWinding)
2585 .value("EvenOdd", SkPathFillType::kEvenOdd);
2586
2587 enum_<SkFilterMode>("FilterMode")
2588 .value("Nearest", SkFilterMode::kNearest)
2589 .value("Linear", SkFilterMode::kLinear);
2590
2591 // Only used to control the encode function.
2592 // TODO(kjlubick): compile these out when the appropriate encoder is disabled.
2593 enum_<SkEncodedImageFormat>("ImageFormat")
2594 .value("PNG", SkEncodedImageFormat::kPNG)
2595 .value("JPEG", SkEncodedImageFormat::kJPEG)
2596 .value("WEBP", SkEncodedImageFormat::kWEBP);
2597
2598 enum_<SkMipmapMode>("MipmapMode")
2599 .value("None", SkMipmapMode::kNone)
2600 .value("Nearest", SkMipmapMode::kNearest)
2601 .value("Linear", SkMipmapMode::kLinear);
2602
2603 enum_<SkPaint::Style>("PaintStyle")
2604 .value("Fill", SkPaint::Style::kFill_Style)
2605 .value("Stroke", SkPaint::Style::kStroke_Style);
2606
2607 enum_<SkPath1DPathEffect::Style>("Path1DEffect")
2608 .value("Translate", SkPath1DPathEffect::Style::kTranslate_Style)
2609 .value("Rotate", SkPath1DPathEffect::Style::kRotate_Style)
2610 .value("Morph", SkPath1DPathEffect::Style::kMorph_Style);
2611
2612#ifdef CK_INCLUDE_PATHOPS
2613 enum_<SkPathOp>("PathOp")
2614 .value("Difference", SkPathOp::kDifference_SkPathOp)
2615 .value("Intersect", SkPathOp::kIntersect_SkPathOp)
2616 .value("Union", SkPathOp::kUnion_SkPathOp)
2617 .value("XOR", SkPathOp::kXOR_SkPathOp)
2618 .value("ReverseDifference", SkPathOp::kReverseDifference_SkPathOp);
2619#endif
2620
2621 enum_<SkCanvas::PointMode>("PointMode")
2622 .value("Points", SkCanvas::PointMode::kPoints_PointMode)
2623 .value("Lines", SkCanvas::PointMode::kLines_PointMode)
2624 .value("Polygon", SkCanvas::PointMode::kPolygon_PointMode);
2625
2626 enum_<SkPaint::Cap>("StrokeCap")
2627 .value("Butt", SkPaint::Cap::kButt_Cap)
2628 .value("Round", SkPaint::Cap::kRound_Cap)
2629 .value("Square", SkPaint::Cap::kSquare_Cap);
2630
2631 enum_<SkPaint::Join>("StrokeJoin")
2632 .value("Miter", SkPaint::Join::kMiter_Join)
2633 .value("Round", SkPaint::Join::kRound_Join)
2634 .value("Bevel", SkPaint::Join::kBevel_Join);
2635
2636#ifndef CK_NO_FONTS
2637 enum_<SkFontHinting>("FontHinting")
2638 .value("None", SkFontHinting::kNone)
2639 .value("Slight", SkFontHinting::kSlight)
2640 .value("Normal", SkFontHinting::kNormal)
2641 .value("Full", SkFontHinting::kFull);
2642
2643 enum_<SkFont::Edging>("FontEdging")
2644#ifndef CK_NO_ALIAS_FONT
2645 .value("Alias", SkFont::Edging::kAlias)
2646#endif
2647 .value("AntiAlias", SkFont::Edging::kAntiAlias)
2648 .value("SubpixelAntiAlias", SkFont::Edging::kSubpixelAntiAlias);
2649#endif
2650
2651 enum_<SkTileMode>("TileMode")
2652 .value("Clamp", SkTileMode::kClamp)
2653 .value("Repeat", SkTileMode::kRepeat)
2654 .value("Mirror", SkTileMode::kMirror)
2655 .value("Decal", SkTileMode::kDecal);
2656
2657 enum_<SkVertices::VertexMode>("VertexMode")
2658 .value("Triangles", SkVertices::VertexMode::kTriangles_VertexMode)
2659 .value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
2660 .value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
2661
2662 // A value object is much simpler than a class - it is returned as a JS
2663 // object and does not require delete().
2664 // https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
2665
2666 value_object<SimpleImageInfo>("ImageInfo")
2667 .field("width", &SimpleImageInfo::width)
2668 .field("height", &SimpleImageInfo::height)
2669 .field("colorType", &SimpleImageInfo::colorType)
2670 .field("alphaType", &SimpleImageInfo::alphaType)
2671 .field("colorSpace", &SimpleImageInfo::colorSpace);
2672
2673 value_object<StrokeOpts>("StrokeOpts")
2674 .field("width", &StrokeOpts::width)
2675 .field("miter_limit", &StrokeOpts::miter_limit)
2676 .field("join", &StrokeOpts::join)
2677 .field("cap", &StrokeOpts::cap)
2678 .field("precision", &StrokeOpts::precision);
2679
2680 constant("MOVE_VERB", MOVE);
2681 constant("LINE_VERB", LINE);
2682 constant("QUAD_VERB", QUAD);
2683 constant("CONIC_VERB", CONIC);
2684 constant("CUBIC_VERB", CUBIC);
2685 constant("CLOSE_VERB", CLOSE);
2686
2687 constant("SaveLayerInitWithPrevious", (int)SkCanvas::SaveLayerFlagsSet::kInitWithPrevious_SaveLayerFlag);
2688 constant("SaveLayerF16ColorType", (int)SkCanvas::SaveLayerFlagsSet::kF16ColorType);
2689
2690 constant("ShadowTransparentOccluder", (int)SkShadowFlags::kTransparentOccluder_ShadowFlag);
2691 constant("ShadowGeometricOnly", (int)SkShadowFlags::kGeometricOnly_ShadowFlag);
2692 constant("ShadowDirectionalLight", (int)SkShadowFlags::kDirectionalLight_ShadowFlag);
2693
2694#ifdef CK_INCLUDE_PARAGRAPH
2695 constant("_GlyphRunFlags_isWhiteSpace", (int)skia::textlayout::Paragraph::kWhiteSpace_VisitorFlag);
2696#endif
2697}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
int count
Definition: FontMgrTest.cpp:50
#define GR_GL_RGBA8
Definition: GrGLDefines.h:524
#define GR_GL_TEXTURE_2D
Definition: GrGLDefines.h:152
#define GR_GL_RGBA16F
Definition: GrGLDefines.h:527
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
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
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
Definition: SkShadowUtils.h:31
@ kGeometricOnly_ShadowFlag
Definition: SkShadowUtils.h:29
@ kTransparentOccluder_ShadowFlag
Definition: SkShadowUtils.h:27
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
static void copy(void *dst, const uint8_t *src, int width, int bpp, int deltaSrc, int offset, const SkPMColor ctable[])
Definition: SkSwizzler.cpp:31
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
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
int currentFrameDuration()
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:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void drawPaint(const SkPaint &paint)
Definition: SkCanvas.cpp:1668
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
@ 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:431
void rotate(SkScalar degrees)
Definition: SkCanvas.cpp:1300
void restoreToCount(int saveCount)
Definition: SkCanvas.cpp:478
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1456
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
void drawPicture(const SkPicture *picture)
Definition: SkCanvas.h:1961
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
Definition: SkCanvas.cpp:1720
void skew(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1312
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
Definition: SkCanvas.cpp:2484
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
Definition: SkCanvas.cpp:2707
static sk_sp< SkColorFilter > Compose(const sk_sp< SkColorFilter > &outer, sk_sp< SkColorFilter > inner)
Definition: SkColorFilter.h:92
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)
bool isSRGB() const
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
const uint8_t * bytes() const
Definition: SkData.h:43
static sk_sp< SkData > MakeFromMalloc(const void *data, size_t length)
Definition: SkData.cpp:107
size_t size() const
Definition: SkData.h:30
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
Definition: SkFont.h:35
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={})
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
Definition: SkMatrix.cpp:1141
Definition: SkOnce.h:22
SkScalar getStrokeMiter() const
Definition: SkPaint.h:318
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
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
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)
Definition: SkPath.h:59
SkPath & rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc, SkPathDirection sweep, SkScalar dx, SkScalar dy)
Definition: SkPath.cpp:1431
bool isEmpty() const
Definition: SkPath.cpp:416
int countPoints() const
Definition: SkPath.cpp:535
SkPath & arcTo(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo)
Definition: SkPath.cpp:1220
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:1506
bool isVolatile() const
Definition: SkPath.h:350
void dump() const
Definition: SkPath.h:1734
bool isInterpolatable(const SkPath &compare) const
Definition: SkPath.cpp:243
bool interpolate(const SkPath &ending, SkScalar weight, SkPath *out) const
Definition: SkPath.cpp:250
SkPath & setIsVolatile(bool isVolatile)
Definition: SkPath.h:370
@ kExtend_AddPathMode
Definition: SkPath.h:1293
@ kAppend_AddPathMode
Definition: SkPath.h:1286
void dumpHex() const
Definition: SkPath.h:1735
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkPath.cpp:1711
bool contains(SkScalar x, SkScalar y) const
Definition: SkPath.cpp:3118
static sk_sp< SkPicture > MakeFromData(const SkData *data, const SkDeserialProcs *procs=nullptr)
Definition: SkPicture.cpp:160
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
SkSpan< const Uniform > uniforms() 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)
@ kDiscard_ContentChangeMode
discards surface on change
Definition: SkSurface.h:204
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
int width() const
Definition: SkSurface.h:178
int height() const
Definition: SkSurface.h:184
@ kFlushRead
back-end object is readable
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.cpp:788
static sk_sp< SkTextBlob > MakeFromRSXform(const void *text, size_t byteLength, const SkRSXform xform[], const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.cpp:831
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
Definition: SkTypeface.cpp:202
static void Register(FactoryId id, sk_sp< SkTypeface >(*make)(std::unique_ptr< SkStreamAsset >, const SkFontArguments &))
Definition: SkTypeface.cpp:196
SkFourByteTag FactoryId
Definition: SkTypeface.h:335
sk_sp< SkVertices > detach()
Definition: SkVertices.cpp:146
uint32_t uniqueID() const
Definition: SkVertices.h:97
T * get() const
Definition: SkRefCnt.h:303
const Paint & paint
Definition: color_source.cc:38
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248
DlColor color
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
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
static sk_sp< GrDirectContext > MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
Definition: gm_bindings.cpp:69
#define B
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_sp< const GrGLInterface >, const GrContextOptions &)
SK_API sk_sp< const GrGLInterface > MakeWebGL()
SK_API bool IsBmp(const void *, size_t)
Definition: SkBmpCodec.cpp:670
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
Definition: SkBmpCodec.cpp:674
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)
Definition: SkIcoCodec.cpp:413
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
Definition: SkIcoCodec.cpp:417
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
Definition: SkColorSpace.h:77
static constexpr skcms_Matrix3x3 kDisplayP3
Definition: SkColorSpace.h:87
static constexpr skcms_TransferFunction k2Dot2
Definition: SkColorSpace.h:48
static constexpr skcms_TransferFunction kSRGB
Definition: SkColorSpace.h:45
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_sp< const SkImage > atlas
Definition: SkRecords.h:331
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
PODArray< SkRect > texs
Definition: SkRecords.h:333
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< const SkImageFilter > backdrop
Definition: SkRecords.h:191
SkRect oval
Definition: SkRecords.h:249
PODArray< SkRSXform > xforms
Definition: SkRecords.h:332
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
PODArray< SkColor > colors
Definition: SkRecords.h:276
SkSamplingOptions sampling
Definition: SkRecords.h:337
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
SK_API sk_sp< SkShader > Color(SkColor)
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)
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 The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
font
Font Metadata and Metrics.
Definition: gen.py:1
dst
Definition: cp.py:12
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
SK_API void FlushAndSubmit(sk_sp< SkSurface >)
SK_API std::unique_ptr< Context > MakeDawn(const DawnBackendContext &, const ContextOptions &)
Mipmapped
Definition: GpuTypes.h:53
SkSamplingOptions(SkFilterMode::kLinear))
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
Definition: SkPathUtils.cpp:23
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
GrGLuint fID
Definition: GrGLTypes.h:182
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 ...
Definition: SkFontMetrics.h:53
SkScalar fLeading
distance to add between lines, typically positive or zero
Definition: SkFontMetrics.h:57
SkScalar fBottom
greatest extent below origin of any glyph bounding box, typically positive; deprecated with variable ...
Definition: SkFontMetrics.h:56
uint32_t fFlags
FontMetricsFlags indicating which metrics are valid.
Definition: SkFontMetrics.h:52
SkScalar fAscent
distance to reserve above baseline, typically negative
Definition: SkFontMetrics.h:54
@ kBoundsInvalid_Flag
set if fTop, fBottom, fXMin, fXMax invalid
Definition: SkFontMetrics.h:49
SkScalar fDescent
distance to reserve below baseline, typically positive
Definition: SkFontMetrics.h:55
SkScalar fXMin
greatest extent to left of origin of any glyph bounding box, typically negative; deprecated with vari...
Definition: SkFontMetrics.h:60
SkScalar fXMax
greatest extent to right of origin of any glyph bounding box, typically positive; deprecated with var...
Definition: SkFontMetrics.h:61
static constexpr SkIPoint Make(int32_t x, int32_t y)
Definition: SkPoint_impl.h:38
Definition: SkRect.h:32
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
int width() const
Definition: SkImageInfo.h:365
static SkImageInfo MakeN32(int width, int height, SkAlphaType at)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkAlphaType alphaType() const
Definition: SkImageInfo.h:375
SkColorType colorType() const
Definition: SkImageInfo.h:373
int height() const
Definition: SkImageInfo.h:371
static sk_sp< SkColorFilter > Make()
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
sk_sp< SkSL::DebugTrace > debugTrace
SkSerialImageProc fImageProc
Definition: SkSerialProcs.h:90
SkSerialTypefaceProc fTypefaceProc
Definition: SkSerialProcs.h:93
Compression fCompression
Definition: SkWebpEncoder.h:43
SkPaint::Join join
SkPaint::Cap cap
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63