[canvaskit] Add error callback for runtime effect constructor
It would otherwise be difficult/tedious/not-backwards-compatible to return the RuntimeEffect AND the error message. Change-Id: I9bdbafb653398ccbb72e6e762ec4b6af294f9110 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/365483 Reviewed-by: Joe Gregorio <jcgregorio@google.com>
This commit is contained in:
parent
1db274d0b9
commit
70b6729a05
@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- `getShadowLocalBounds()` to estimate the bounds of the shadows drawn by `Canvas.drawShadow`.
|
||||
- compile.sh now takes "no_matrix", which will omit the helper JS to deal with 3x3, 4x4 and
|
||||
SkColorMatrix (in case clients have logic to deal with that themselves).
|
||||
- `CanvasKit.RuntimeEffect.Make` now takes an optional callback function that will be called
|
||||
with any compilation error.
|
||||
|
||||
### Breaking
|
||||
- `MakeImprovedNoise` is removed.
|
||||
|
@ -656,6 +656,9 @@ function rectangleTests(CK: CanvasKit) {
|
||||
function runtimeEffectTests(CK: CanvasKit) {
|
||||
const rt = CK.RuntimeEffect.Make('not real sksl code'); // $ExpectType RuntimeEffect | null
|
||||
if (!rt) return;
|
||||
const rt2 = CK.RuntimeEffect.Make('not real sksl code', (err) => {
|
||||
console.log(err);
|
||||
});
|
||||
const someMatr = CK.Matrix.translated(2, 60);
|
||||
const s1 = rt.makeShader([0, 1]); // $ExpectType Shader
|
||||
const s2 = rt.makeShader([0, 1], true, someMatr); // $ExpectType Shader
|
||||
|
4
modules/canvaskit/canvaskit/types/index.d.ts
vendored
4
modules/canvaskit/canvaskit/types/index.d.ts
vendored
@ -3101,8 +3101,10 @@ export interface RuntimeEffectFactory {
|
||||
/**
|
||||
* Compiles a RuntimeEffect from the given shader code.
|
||||
* @param sksl - Source code for a shader written in SkSL
|
||||
* @param callback - will be called with any compilation error. If not provided, errors will
|
||||
* be printed to console.log().
|
||||
*/
|
||||
Make(sksl: string): RuntimeEffect | null;
|
||||
Make(sksl: string, callback?: (err: string) => void): RuntimeEffect | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1674,11 +1674,13 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
#ifdef SK_INCLUDE_RUNTIME_EFFECT
|
||||
class_<SkRuntimeEffect>("RuntimeEffect")
|
||||
.smart_ptr<sk_sp<SkRuntimeEffect>>("sk_sp<RuntimeEffect>")
|
||||
.class_function("Make", optional_override([](std::string sksl)->sk_sp<SkRuntimeEffect> {
|
||||
.class_function("_Make", optional_override([](std::string sksl,
|
||||
emscripten::val errHandler
|
||||
)->sk_sp<SkRuntimeEffect> {
|
||||
SkString s(sksl.c_str(), sksl.length());
|
||||
auto [effect, errorText] = SkRuntimeEffect::Make(s);
|
||||
if (!effect) {
|
||||
SkDebugf("Runtime effect failed to compile:\n%s\n", errorText.c_str());
|
||||
errHandler.call<void>("onError", val(errorText.c_str()));
|
||||
return nullptr;
|
||||
}
|
||||
return effect;
|
||||
|
@ -166,10 +166,14 @@ var CanvasKit = {
|
||||
},
|
||||
|
||||
RuntimeEffect: {
|
||||
// public API (from C++ bindings)
|
||||
// public API (from JS bindings)
|
||||
Make: function() {},
|
||||
|
||||
// private API
|
||||
prototype: {
|
||||
makeShader: function() {},
|
||||
makeShaderWithChildren: function() {},
|
||||
},
|
||||
// private API (from C++ bindings)
|
||||
_Make: function() {},
|
||||
_makeShader: function() {},
|
||||
_makeShaderWithChildren: function() {},
|
||||
},
|
||||
|
@ -1,5 +1,20 @@
|
||||
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
|
||||
CanvasKit._extraInitializations.push(function() {
|
||||
|
||||
// sksl is the shader code.
|
||||
// errorCallback is a function that will be called with an error string if the
|
||||
// effect cannot be made. If not provided, the error will be logged.
|
||||
CanvasKit.RuntimeEffect.Make = function(sksl, errorCallback) {
|
||||
// The easiest way to pass a function into C++ code is to wrap it in an object and
|
||||
// treat it as an emscripten::val on the other side.
|
||||
var callbackObj = {
|
||||
'onError': errorCallback || function(err) {
|
||||
console.log('RuntimeEffect error', err);
|
||||
},
|
||||
};
|
||||
return CanvasKit.RuntimeEffect._Make(sksl, callbackObj);
|
||||
};
|
||||
|
||||
CanvasKit.RuntimeEffect.prototype.makeShader = function(floats, isOpaque, localMatrix) {
|
||||
// We don't need to free these floats because they will become owned by the shader.
|
||||
var fptr = copy1dArray(floats, "HEAPF32");
|
||||
|
@ -70,6 +70,15 @@ half4 main(float2 p) {
|
||||
testRTShader('rtshader_spiral_translated', done, CanvasKit.Matrix.translated(-200, 100));
|
||||
});
|
||||
|
||||
it('can provide a error handler for compilation errors', () => {
|
||||
let error = '';
|
||||
const spiral = CanvasKit.RuntimeEffect.Make(`invalid sksl code, I hope`, (e) => {
|
||||
error = e;
|
||||
});
|
||||
expect(spiral).toBeFalsy();
|
||||
expect(error).toContain('error');
|
||||
});
|
||||
|
||||
const loadBrick = fetch(
|
||||
'/assets/brickwork-texture.jpg')
|
||||
.then((response) => response.arrayBuffer());
|
||||
|
Loading…
Reference in New Issue
Block a user