Pass 4f colors to private functions with float pointers
Change-Id: I4534a246c37870750298d39edcbc869781dc1008 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/286880 Commit-Queue: Nathaniel Nifong <nifong@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
parent
d16e322f02
commit
1bedbeb081
@ -22,23 +22,4 @@ using SkPathOrNull = emscripten::val;
|
||||
using Uint8Array = emscripten::val;
|
||||
using Float32Array = emscripten::val;
|
||||
|
||||
// A struct used for binding the TypedArray colors passed to to canvaskit functions.
|
||||
// Canvaskit functions returning colors return a Float32Array, which looks the same
|
||||
// on the javascript side.
|
||||
struct SimpleColor4f {
|
||||
// A sensible but noticeable default value to let you know you've called the
|
||||
// default constructor.
|
||||
float r = 1.0;
|
||||
float g = 0.0;
|
||||
float b = 1.0;
|
||||
float a = 1.0;
|
||||
|
||||
SkColor4f toSkColor4f() const {
|
||||
return SkColor4f({r, g, b, a});
|
||||
};
|
||||
SkColor toSkColor() const {
|
||||
return toSkColor4f().toSkColor();
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -97,10 +97,9 @@ struct OptionalMatrix : SkMatrix {
|
||||
}
|
||||
};
|
||||
|
||||
SimpleColor4f toSimpleColor4f(const SkColor4f c) {
|
||||
SimpleColor4f color {
|
||||
c.fR, c.fG, c.fB, c.fA,
|
||||
};
|
||||
SkColor4f ptrToSkColor4f(uintptr_t /* float* */ cPtr) {
|
||||
float* fourFloats = reinterpret_cast<float*>(cPtr);
|
||||
SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3] };
|
||||
return color;
|
||||
}
|
||||
|
||||
@ -623,19 +622,27 @@ SkRRect toRRect(const SimpleRRect& r) {
|
||||
return rr;
|
||||
}
|
||||
|
||||
struct TonalColors {
|
||||
SimpleColor4f ambientColor;
|
||||
SimpleColor4f spotColor;
|
||||
};
|
||||
// This function is private, we call it in interface.js
|
||||
void computeTonalColors(uintptr_t cPtrAmbi /* float * */, uintptr_t cPtrSpot /* float * */) {
|
||||
// private methods accepting colors take pointers to floats already copied into wasm memory.
|
||||
float* ambiFloats = reinterpret_cast<float*>(cPtrAmbi);
|
||||
float* spotFloats = reinterpret_cast<float*>(cPtrSpot);
|
||||
SkColor4f ambiColor = { ambiFloats[0], ambiFloats[1], ambiFloats[2], ambiFloats[3]};
|
||||
SkColor4f spotColor = { spotFloats[0], spotFloats[1], spotFloats[2], spotFloats[3]};
|
||||
|
||||
TonalColors computeTonalColors(const TonalColors& in) {SkColor resultAmbient, resultSpot;
|
||||
// This function takes SkColor
|
||||
SkColor resultAmbi, resultSpot;
|
||||
SkShadowUtils::ComputeTonalColors(
|
||||
in.ambientColor.toSkColor(), in.spotColor.toSkColor(),
|
||||
&resultAmbient, &resultSpot);
|
||||
TonalColors out;
|
||||
out.ambientColor = toSimpleColor4f(SkColor4f::FromColor(resultAmbient));
|
||||
out.spotColor = toSimpleColor4f(SkColor4f::FromColor(resultSpot));
|
||||
return out;
|
||||
ambiColor.toSkColor(), spotColor.toSkColor(),
|
||||
&resultAmbi, &resultSpot);
|
||||
|
||||
// Convert back to color4f
|
||||
const SkColor4f ambi4f = SkColor4f::FromColor(resultAmbi);
|
||||
const SkColor4f spot4f = SkColor4f::FromColor(resultSpot);
|
||||
|
||||
// Re-use the caller's allocated memory to hold the result.
|
||||
memcpy(ambiFloats, ambi4f.vec(), 4 * sizeof(SkScalar));
|
||||
memcpy(spotFloats, spot4f.vec(), 4 * sizeof(SkScalar));
|
||||
}
|
||||
|
||||
// These objects have private destructors / delete methods - I don't think
|
||||
@ -695,7 +702,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
function("setDecodeCacheLimitBytes", &SkResourceCache::SetTotalByteLimit);
|
||||
function("getDecodeCacheUsedBytes" , &SkResourceCache::GetTotalBytesUsed);
|
||||
|
||||
function("computeTonalColors", &computeTonalColors);
|
||||
function("_computeTonalColors", &computeTonalColors);
|
||||
function("_decodeAnimatedImage", optional_override([](uintptr_t /* uint8_t* */ iptr,
|
||||
size_t length)->sk_sp<SkAnimatedImage> {
|
||||
uint8_t* imgData = reinterpret_cast<uint8_t*>(iptr);
|
||||
@ -853,8 +860,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
|
||||
class_<SkCanvas>("SkCanvas")
|
||||
.constructor<>()
|
||||
.function("clear", optional_override([](SkCanvas& self, SimpleColor4f c) {
|
||||
self.clear(c.toSkColor());
|
||||
.function("_clear", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr) {
|
||||
self.clear(ptrToSkColor4f(cPtr).toSkColor());
|
||||
}))
|
||||
.function("clipPath", select_overload<void (const SkPath&, SkClipOp, bool)>(&SkCanvas::clipPath))
|
||||
.function("clipRRect", optional_override([](SkCanvas& self, const SimpleRRect& r, SkClipOp op, bool doAntiAlias) {
|
||||
@ -886,11 +893,11 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
self.drawAtlas(atlas, dstXforms, srcRects, colors, count, mode, nullptr, paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("drawCircle", select_overload<void (SkScalar, SkScalar, SkScalar, const SkPaint& paint)>(&SkCanvas::drawCircle))
|
||||
.function("drawColor", optional_override([](SkCanvas& self, SimpleColor4f c) {
|
||||
self.drawColor(c.toSkColor());
|
||||
.function("_drawColor", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr) {
|
||||
self.drawColor(ptrToSkColor4f(cPtr).toSkColor());
|
||||
}))
|
||||
.function("drawColor", optional_override([](SkCanvas& self, SimpleColor4f c, SkBlendMode mode) {
|
||||
self.drawColor(c.toSkColor(), mode);
|
||||
.function("_drawColor", optional_override([](SkCanvas& self, uintptr_t /* float* */ cPtr, SkBlendMode mode) {
|
||||
self.drawColor(ptrToSkColor4f(cPtr).toSkColor(), mode);
|
||||
}))
|
||||
.function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
|
||||
self.drawDRRect(toRRect(o), toRRect(i), paint);
|
||||
@ -937,13 +944,16 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
}))
|
||||
.function("drawRect", &SkCanvas::drawRect)
|
||||
.function("drawRoundRect", &SkCanvas::drawRoundRect)
|
||||
.function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
|
||||
.function("_drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
|
||||
const SkPoint3& zPlaneParams,
|
||||
const SkPoint3& lightPos, SkScalar lightRadius,
|
||||
SimpleColor4f ambientColor, SimpleColor4f spotColor,
|
||||
uintptr_t /* float* */ ambientColorPtr,
|
||||
uintptr_t /* float* */ spotColorPtr,
|
||||
uint32_t flags) {
|
||||
SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
|
||||
ambientColor.toSkColor(), spotColor.toSkColor(), flags);
|
||||
ptrToSkColor4f(ambientColorPtr).toSkColor(),
|
||||
ptrToSkColor4f(spotColorPtr).toSkColor(),
|
||||
flags);
|
||||
}))
|
||||
#ifndef SK_NO_FONTS
|
||||
.function("_drawShapedText", &drawShapedText)
|
||||
@ -1025,8 +1035,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
|
||||
class_<SkColorFilter>("SkColorFilter")
|
||||
.smart_ptr<sk_sp<SkColorFilter>>("sk_sp<SkColorFilter>>")
|
||||
.class_function("MakeBlend", optional_override([](SimpleColor4f c, SkBlendMode mode)->sk_sp<SkColorFilter> {
|
||||
return SkColorFilters::Blend(c.toSkColor(), mode);
|
||||
.class_function("_MakeBlend", optional_override([](uintptr_t /* float* */ cPtr, SkBlendMode mode)->sk_sp<SkColorFilter> {
|
||||
return SkColorFilters::Blend(ptrToSkColor4f(cPtr).toSkColor(), mode);
|
||||
}))
|
||||
.class_function("MakeCompose", &SkColorFilters::Compose)
|
||||
.class_function("MakeLerp", &SkColorFilters::Lerp)
|
||||
@ -1216,10 +1226,11 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
return p;
|
||||
}))
|
||||
.function("getBlendMode", &SkPaint::getBlendMode)
|
||||
.function("getColor", optional_override([](SkPaint& self)->Float32Array {
|
||||
const SimpleColor4f& c = toSimpleColor4f(self.getColor4f());
|
||||
const float array[4] = {c.r, c.g, c.b, c.a};
|
||||
return Float32Array(typed_memory_view(4, array));
|
||||
// provide an allocated place to put the returned color
|
||||
.function("_getColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr)->void {
|
||||
const SkColor4f& c = self.getColor4f();
|
||||
float* fourFloats = reinterpret_cast<float*>(cPtr);
|
||||
memcpy(fourFloats, c.vec(), 4 * sizeof(SkScalar));
|
||||
}))
|
||||
.function("getFilterQuality", &SkPaint::getFilterQuality)
|
||||
.function("getStrokeCap", &SkPaint::getStrokeCap)
|
||||
@ -1229,8 +1240,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.function("setAntiAlias", &SkPaint::setAntiAlias)
|
||||
.function("setAlphaf", &SkPaint::setAlphaf)
|
||||
.function("setBlendMode", &SkPaint::setBlendMode)
|
||||
.function("setColor", optional_override([](SkPaint& self, SimpleColor4f c) {
|
||||
self.setColor({c.r, c.g, c.b, c.a});
|
||||
.function("_setColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr) {
|
||||
self.setColor(ptrToSkColor4f(cPtr));
|
||||
}))
|
||||
.function("setColorFilter", &SkPaint::setColorFilter)
|
||||
.function("setFilterQuality", &SkPaint::setFilterQuality)
|
||||
@ -1376,9 +1387,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
class_<SkShader>("SkShader")
|
||||
.smart_ptr<sk_sp<SkShader>>("sk_sp<SkShader>")
|
||||
.class_function("Blend", select_overload<sk_sp<SkShader>(SkBlendMode, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Blend))
|
||||
.class_function("Color",
|
||||
optional_override([](SimpleColor4f c)->sk_sp<SkShader> {
|
||||
return SkShaders::Color(c.toSkColor4f(), SkColorSpace::MakeSRGB());
|
||||
.class_function("_Color",
|
||||
optional_override([](uintptr_t /* float* */ cPtr)->sk_sp<SkShader> {
|
||||
return SkShaders::Color(ptrToSkColor4f(cPtr), SkColorSpace::MakeSRGB());
|
||||
})
|
||||
)
|
||||
.class_function("Lerp", select_overload<sk_sp<SkShader>(float, sk_sp<SkShader>, sk_sp<SkShader>)>(&SkShaders::Lerp));
|
||||
@ -1651,10 +1662,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.field("fRight", &SkIRect::fRight)
|
||||
.field("fBottom", &SkIRect::fBottom);
|
||||
|
||||
value_object<TonalColors>("TonalColors")
|
||||
.field("ambient", &TonalColors::ambientColor)
|
||||
.field("spot", &TonalColors::spotColor);
|
||||
|
||||
value_object<SimpleImageInfo>("SkImageInfo")
|
||||
.field("width", &SimpleImageInfo::width)
|
||||
.field("height", &SimpleImageInfo::height)
|
||||
@ -1695,13 +1702,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
.field("cap", &StrokeOpts::cap)
|
||||
.field("precision", &StrokeOpts::precision);
|
||||
|
||||
value_array<SimpleColor4f>("SkColor4f")
|
||||
.element(&SimpleColor4f::r)
|
||||
.element(&SimpleColor4f::g)
|
||||
.element(&SimpleColor4f::b)
|
||||
.element(&SimpleColor4f::a);
|
||||
|
||||
|
||||
constant("MOVE_VERB", MOVE);
|
||||
constant("LINE_VERB", LINE);
|
||||
constant("QUAD_VERB", QUAD);
|
||||
|
@ -60,7 +60,6 @@ var CanvasKit = {
|
||||
MakeWebGLCanvasSurface: function() {},
|
||||
/** @return {TypedArray} */
|
||||
Malloc: function() {},
|
||||
/** @return {TonalColors} */
|
||||
computeTonalColors: function() {},
|
||||
currentContext: function() {},
|
||||
getColorComponents: function() {},
|
||||
@ -74,6 +73,7 @@ var CanvasKit = {
|
||||
|
||||
// private API (i.e. things declared in the bindings that we use
|
||||
// in the pre-js file)
|
||||
_computeTonalColors: function() {},
|
||||
_MakeImage: function() {},
|
||||
_MakeLinearGradientShader: function() {},
|
||||
_MakePathFromCmds: function() {},
|
||||
@ -104,6 +104,12 @@ var CanvasKit = {
|
||||
setResourceCacheLimitBytes: function() {},
|
||||
},
|
||||
|
||||
ManagedAnimation: {
|
||||
prototype: {
|
||||
setColor: function() {},
|
||||
},
|
||||
},
|
||||
|
||||
Paragraph: {
|
||||
// public API (from C++ bindings)
|
||||
didExceedMaxLines: function() {},
|
||||
@ -123,6 +129,21 @@ var CanvasKit = {
|
||||
_getRectsForRange: function() {},
|
||||
},
|
||||
|
||||
ParagraphBuilder: {
|
||||
Make: function() {},
|
||||
addText: function() {},
|
||||
build: function() {},
|
||||
pop: function() {},
|
||||
|
||||
prototype: {
|
||||
pushStyle: function() {},
|
||||
},
|
||||
|
||||
// private API
|
||||
_Make: function() {},
|
||||
_pushStyle: function() {},
|
||||
},
|
||||
|
||||
SkRuntimeEffect: {
|
||||
// public API (from C++ bindings)
|
||||
Make: function() {},
|
||||
@ -154,14 +175,12 @@ var CanvasKit = {
|
||||
|
||||
SkCanvas: {
|
||||
// public API (from C++ bindings)
|
||||
clear: function() {},
|
||||
clipPath: function() {},
|
||||
clipRRect: function() {},
|
||||
clipRect: function() {},
|
||||
drawAnimatedImage: function() {},
|
||||
drawArc: function() {},
|
||||
drawCircle: function() {},
|
||||
drawColor: function() {},
|
||||
drawDRRect: function() {},
|
||||
drawImage: function() {},
|
||||
drawImageNine: function() {},
|
||||
@ -175,7 +194,6 @@ var CanvasKit = {
|
||||
drawRRect: function() {},
|
||||
drawRect: function() {},
|
||||
drawRoundRect: function() {},
|
||||
drawShadow: function() {},
|
||||
drawText: function() {},
|
||||
drawTextBlob: function() {},
|
||||
drawVertices: function() {},
|
||||
@ -191,10 +209,19 @@ var CanvasKit = {
|
||||
skew: function() {},
|
||||
translate: function() {},
|
||||
|
||||
prototype: {
|
||||
clear: function() {},
|
||||
drawColor: function() {},
|
||||
drawShadow: function() {},
|
||||
},
|
||||
|
||||
// private API
|
||||
_clear: function() {},
|
||||
_concat: function() {},
|
||||
_drawAtlas: function() {},
|
||||
_drawColor: function() {},
|
||||
_drawPoints: function() {},
|
||||
_drawShadow: function() {},
|
||||
_drawSimpleText: function() {},
|
||||
_getLocalToCamera: function() {},
|
||||
_getLocalToDevice: function() {},
|
||||
@ -214,6 +241,7 @@ var CanvasKit = {
|
||||
MakeMatrix: function() {},
|
||||
MakeSRGBToLinearGamma: function() {},
|
||||
// private API (from C++ bindings)
|
||||
_MakeBlend: function() {},
|
||||
_makeMatrix: function() {},
|
||||
},
|
||||
|
||||
@ -329,7 +357,6 @@ var CanvasKit = {
|
||||
getStrokeWidth: function() {},
|
||||
setAntiAlias: function() {},
|
||||
setBlendMode: function() {},
|
||||
setColor: function() {},
|
||||
setFilterQuality: function() {},
|
||||
setImageFilter: function() {},
|
||||
setMaskFilter: function() {},
|
||||
@ -341,8 +368,14 @@ var CanvasKit = {
|
||||
setStrokeWidth: function() {},
|
||||
setStyle: function() {},
|
||||
|
||||
prototype: {
|
||||
setColor: function() {},
|
||||
},
|
||||
|
||||
// Private API
|
||||
delete: function() {},
|
||||
_getColor: function() {},
|
||||
_setColor: function() {},
|
||||
},
|
||||
|
||||
SkPathEffect: {
|
||||
@ -472,6 +505,9 @@ var CanvasKit = {
|
||||
MakeRadialGradient: function() {},
|
||||
MakeTwoPointConicalGradient: function() {},
|
||||
MakeSweepGradient: function() {},
|
||||
|
||||
// private API (from C++ bindings)
|
||||
_Color: function() {},
|
||||
},
|
||||
|
||||
SkSurface: {
|
||||
|
@ -351,6 +351,16 @@ function copy4x4MatrixFromWasm(matrPtr) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// copies the four floats at the given pointer in a js Float32Array
|
||||
function copyColorFromWasm(colorPtr) {
|
||||
var rv = new Float32Array(4);
|
||||
for (var i = 0; i < 4; i++) {
|
||||
rv[i] = CanvasKit.HEAPF32[colorPtr/4 + i]; // divide by 4 to "cast" to float.
|
||||
}
|
||||
CanvasKit._free(colorPtr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Caching the Float32Arrays can save having to reallocate them
|
||||
// over and over again.
|
||||
var Float32ArrayCache = {};
|
||||
|
@ -852,6 +852,13 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Accepts an array of four numbers in the range of 0-1 representing a 4f color
|
||||
CanvasKit.SkCanvas.prototype.clear = function (color4f) {
|
||||
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
|
||||
this._clear(cPtr);
|
||||
CanvasKit._free(cPtr);
|
||||
}
|
||||
|
||||
// concat takes a 3x2, a 3x3, or a 4x4 matrix and upscales it (if needed) to 4x4. This is because
|
||||
// under the hood, SkCanvas uses a 4x4 matrix.
|
||||
CanvasKit.SkCanvas.prototype.concat = function(matr) {
|
||||
@ -866,7 +873,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
// atlas is an SkImage, e.g. from CanvasKit.MakeImageFromEncoded
|
||||
// srcRects and dstXforms should be CanvasKit.SkRectBuilder and CanvasKit.RSXFormBuilder
|
||||
// or just arrays of floats in groups of 4.
|
||||
// colors, if provided, should be a CanvasKit.SkColorBuilder or array of CanvasKit.SimpleColor4f
|
||||
// colors, if provided, should be a CanvasKit.SkColorBuilder or array of float colors (arrays of 4 floats)
|
||||
CanvasKit.SkCanvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
|
||||
/*optional*/ blendMode, colors) {
|
||||
if (!atlas || !paint || !srcRects || !dstXforms) {
|
||||
@ -902,7 +909,7 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
} else {
|
||||
if (!isCanvasKitColor(colors[0])) {
|
||||
SkDebug('DrawAtlas color argument expected to be CanvasKit.SkRectBuilder or array of ' +
|
||||
'CanvasKit.SimpleColor4f, but got '+colors);
|
||||
'float arrays, but got '+colors);
|
||||
return;
|
||||
}
|
||||
// convert here
|
||||
@ -926,6 +933,16 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawColor = function (color4f, mode) {
|
||||
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
|
||||
if (mode !== undefined) {
|
||||
this._drawColor(cPtr, mode);
|
||||
} else {
|
||||
this._drawColor(cPtr);
|
||||
}
|
||||
CanvasKit._free(cPtr);
|
||||
}
|
||||
|
||||
// points is either an array of [x, y] where x and y are numbers or
|
||||
// a typed array from Malloc where the even indices will be treated
|
||||
// as x coordinates and the odd indices will be treated as y coordinates.
|
||||
@ -945,6 +962,14 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
CanvasKit._free(ptr);
|
||||
}
|
||||
|
||||
CanvasKit.SkCanvas.prototype.drawShadow = function(path, zPlaneParams, lightPos, lightRadius, ambientColor, spotColor, flags) {
|
||||
var ambiPtr = copy1dArray(ambientColor, CanvasKit.HEAPF32);
|
||||
var spotPtr = copy1dArray(spotColor, CanvasKit.HEAPF32);
|
||||
this._drawShadow(path, zPlaneParams, lightPos, lightRadius, ambiPtr, spotPtr, flags);
|
||||
CanvasKit._free(ambiPtr);
|
||||
CanvasKit._free(spotPtr);
|
||||
}
|
||||
|
||||
// getLocalToDevice returns a 4x4 matrix.
|
||||
CanvasKit.SkCanvas.prototype.getLocalToDevice = function() {
|
||||
var matrPtr = CanvasKit._malloc(16 * 4); // allocate space for the matrix
|
||||
@ -1023,6 +1048,13 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
return ok;
|
||||
}
|
||||
|
||||
CanvasKit.SkColorFilter.MakeBlend = function(color4f, mode) {
|
||||
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
|
||||
var result = CanvasKit.SkColorFilter._MakeBlend(cPtr, mode);
|
||||
CanvasKit._free(cPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
// colorMatrix is an SkColorMatrix (e.g. Float32Array of length 20)
|
||||
CanvasKit.SkColorFilter.MakeMatrix = function(colorMatrix) {
|
||||
if (!colorMatrix || colorMatrix.length !== 20) {
|
||||
@ -1043,6 +1075,18 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
return imgF;
|
||||
}
|
||||
|
||||
CanvasKit.SkPaint.prototype.getColor = function() {
|
||||
var cPtr = CanvasKit._malloc(16); // 4 floats, 4 bytes each
|
||||
this._getColor(cPtr);
|
||||
return copyColorFromWasm(cPtr);
|
||||
}
|
||||
|
||||
CanvasKit.SkPaint.prototype.setColor = function(color4f) {
|
||||
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
|
||||
this._setColor(cPtr);
|
||||
CanvasKit._free(cPtr);
|
||||
}
|
||||
|
||||
CanvasKit.SkSurface.prototype.captureFrameAsSkPicture = function(drawFrame) {
|
||||
// Set up SkPictureRecorder
|
||||
var spr = new CanvasKit.SkPictureRecorder();
|
||||
@ -1104,6 +1148,13 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
return dpe;
|
||||
}
|
||||
|
||||
CanvasKit.SkShader.Color = function(color4f) {
|
||||
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
|
||||
var result = CanvasKit.SkShader._Color(cPtr);
|
||||
CanvasKit._free(cPtr);
|
||||
return result;
|
||||
}
|
||||
|
||||
CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags) {
|
||||
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
|
||||
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
|
||||
@ -1184,6 +1235,23 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
}
|
||||
}; // end CanvasKit.onRuntimeInitialized, that is, anything changing prototypes or dynamic.
|
||||
|
||||
// Accepts an object holding two canvaskit colors.
|
||||
// {
|
||||
// ambient: {r, g, b, a},
|
||||
// spot: {r, g, b, a},
|
||||
// }
|
||||
// Returns the same format
|
||||
CanvasKit.computeTonalColors = function(tonalColors) {
|
||||
var cPtrAmbi = copy1dArray(tonalColors['ambient'], CanvasKit.HEAPF32);
|
||||
var cPtrSpot = copy1dArray(tonalColors['spot'], CanvasKit.HEAPF32);
|
||||
this._computeTonalColors(cPtrAmbi, cPtrSpot);
|
||||
var result = {
|
||||
'ambient': copyColorFromWasm(cPtrAmbi),
|
||||
'spot': copyColorFromWasm(cPtrSpot),
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CanvasKit.LTRBRect = function(l, t, r, b) {
|
||||
return {
|
||||
fLeft: l,
|
||||
@ -1269,7 +1337,7 @@ CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType) {
|
||||
return CanvasKit._MakeImage(info, pptr, pixels.length, width * bytesPerPixel);
|
||||
}
|
||||
|
||||
// colors is an array of SimpleColor4f
|
||||
// colors is an array of float color arrays
|
||||
CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
|
||||
indices, isVolatile) {
|
||||
// Default isVolitile to true if not set
|
||||
|
@ -15,6 +15,7 @@ module.exports = function(config) {
|
||||
'../../modules/pathkit/perf/perfReporter.js',
|
||||
'canvaskit/bin/canvaskit.js',
|
||||
'tests/canvaskitinit.js',
|
||||
'tests/util.js',
|
||||
'perf/*.bench.js'
|
||||
],
|
||||
|
||||
|
@ -68,6 +68,7 @@
|
||||
if (!isCanvasKitColor(s['color'])) {
|
||||
s['color'] = CanvasKit.BLACK;
|
||||
}
|
||||
|
||||
s['foregroundColor'] = s['foregroundColor'] || CanvasKit.TRANSPARENT;
|
||||
s['backgroundColor'] = s['backgroundColor'] || CanvasKit.TRANSPARENT;
|
||||
s['decoration'] = s['decoration'] || 0;
|
||||
@ -108,5 +109,41 @@
|
||||
}
|
||||
return copy1dArray(sPtrs, CanvasKit.HEAPU32);
|
||||
}
|
||||
|
||||
function copyColors(textStyle) {
|
||||
// these two color fields were arrays, but will set to WASM pointers before we pass this
|
||||
// object over the WASM interface.
|
||||
textStyle['colorPtr'] = copy1dArray(textStyle['color'], CanvasKit.HEAPF32);
|
||||
textStyle['foregroundColorPtr'] = nullptr; // nullptr is 0, from helper.js
|
||||
textStyle['backgroundColorPtr'] = nullptr;
|
||||
|
||||
if (isCanvasKitColor(textStyle['foregroundColor']) && textStyle['foregroundColor'][3] > 0) {
|
||||
textStyle['foregroundColorPtr'] = copy1dArray(textStyle['foregroundColor'], CanvasKit.HEAPF32);
|
||||
}
|
||||
if (isCanvasKitColor(textStyle['backgroundColor']) && textStyle['backgroundColor'][3] > 0) {
|
||||
textStyle['backgroundColorPtr'] = copy1dArray(textStyle['backgroundColor'], CanvasKit.HEAPF32);
|
||||
}
|
||||
return textStyle;
|
||||
}
|
||||
|
||||
function freeColors(textStyle) {
|
||||
CanvasKit._free(textStyle['colorPtr']);
|
||||
CanvasKit._free(textStyle['foregroundColorPtr']);
|
||||
CanvasKit._free(textStyle['backgroundColorPtr']);
|
||||
}
|
||||
|
||||
CanvasKit.ParagraphBuilder.Make = function(paragraphStyle, fontManager) {
|
||||
paragraphStyle['textStyle'] = copyColors(paragraphStyle['textStyle']);
|
||||
|
||||
var result = CanvasKit.ParagraphBuilder._Make(paragraphStyle, fontManager);
|
||||
freeColors(paragraphStyle['textStyle']);
|
||||
return result;
|
||||
}
|
||||
|
||||
CanvasKit.ParagraphBuilder.prototype.pushStyle = function(textStyle) {
|
||||
var tmpStyle = copyColors(textStyle);
|
||||
this._pushStyle(tmpStyle);
|
||||
freeColors(tmpStyle);
|
||||
}
|
||||
});
|
||||
}(Module)); // When this file is loaded in, the high level object is "Module";
|
@ -27,6 +27,12 @@ using namespace emscripten;
|
||||
|
||||
namespace para = skia::textlayout;
|
||||
|
||||
SkColor4f toSkColor4f(uintptr_t /* float* */ cPtr) {
|
||||
float* fourFloats = reinterpret_cast<float*>(cPtr);
|
||||
SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3] };
|
||||
return color;
|
||||
}
|
||||
|
||||
struct SimpleFontStyle {
|
||||
SkFontStyle::Slant slant;
|
||||
SkFontStyle::Weight weight;
|
||||
@ -34,9 +40,9 @@ struct SimpleFontStyle {
|
||||
};
|
||||
|
||||
struct SimpleTextStyle {
|
||||
SimpleColor4f color;
|
||||
SimpleColor4f foregroundColor;
|
||||
SimpleColor4f backgroundColor;
|
||||
uintptr_t /* float* */ colorPtr;
|
||||
uintptr_t /* float* */ foregroundColorPtr;
|
||||
uintptr_t /* float* */ backgroundColorPtr;
|
||||
uint8_t decoration;
|
||||
SkScalar decorationThickness;
|
||||
SkScalar fontSize;
|
||||
@ -50,20 +56,18 @@ para::TextStyle toTextStyle(const SimpleTextStyle& s) {
|
||||
para::TextStyle ts;
|
||||
|
||||
// textstyle.color doesn't support a 4f color, however the foreground and background fields below do.
|
||||
ts.setColor(s.color.toSkColor());
|
||||
ts.setColor(toSkColor4f(s.colorPtr).toSkColor());
|
||||
|
||||
// Emscripten will not allow a value_object to have an unset field, however
|
||||
// It is functionally important that these paints be unset when no value was provided.
|
||||
// paragraph.js defaults these colors to transparent in that case and we use that signal here.
|
||||
if (s.foregroundColor.a > 0) {
|
||||
if (s.foregroundColorPtr) {
|
||||
SkPaint p1;
|
||||
p1.setColor4f(s.foregroundColor.toSkColor4f());
|
||||
p1.setColor4f(toSkColor4f(s.foregroundColorPtr));
|
||||
ts.setForegroundColor(p1);
|
||||
}
|
||||
|
||||
if (s.backgroundColor.a > 0) {
|
||||
if (s.backgroundColorPtr) {
|
||||
SkPaint p2;
|
||||
p2.setColor4f(s.backgroundColor.toSkColor4f());
|
||||
p2.setColor4f(toSkColor4f(s.backgroundColorPtr));
|
||||
ts.setBackgroundColor(p2);
|
||||
}
|
||||
|
||||
@ -178,7 +182,7 @@ EMSCRIPTEN_BINDINGS(Paragraph) {
|
||||
.function("layout", ¶::ParagraphImpl::layout);
|
||||
|
||||
class_<para::ParagraphBuilderImpl>("ParagraphBuilder")
|
||||
.class_function("Make", optional_override([](SimpleParagraphStyle style,
|
||||
.class_function("_Make", optional_override([](SimpleParagraphStyle style,
|
||||
sk_sp<SkFontMgr> fontMgr)-> para::ParagraphBuilderImpl {
|
||||
auto fc = sk_make_sp<para::FontCollection>();
|
||||
fc->setDefaultFontManager(fontMgr);
|
||||
@ -191,7 +195,7 @@ EMSCRIPTEN_BINDINGS(Paragraph) {
|
||||
}))
|
||||
.function("build", ¶::ParagraphBuilderImpl::Build, allow_raw_pointers())
|
||||
.function("pop", ¶::ParagraphBuilderImpl::pop)
|
||||
.function("pushStyle", optional_override([](para::ParagraphBuilderImpl& self,
|
||||
.function("_pushStyle", optional_override([](para::ParagraphBuilderImpl& self,
|
||||
SimpleTextStyle textStyle) {
|
||||
auto ts = toTextStyle(textStyle);
|
||||
self.pushStyle(ts);
|
||||
@ -275,9 +279,9 @@ EMSCRIPTEN_BINDINGS(Paragraph) {
|
||||
.field("textStyle", &SimpleParagraphStyle::textStyle);
|
||||
|
||||
value_object<SimpleTextStyle>("TextStyle")
|
||||
.field("color", &SimpleTextStyle::color)
|
||||
.field("foregroundColor", &SimpleTextStyle::foregroundColor)
|
||||
.field("backgroundColor", &SimpleTextStyle::backgroundColor)
|
||||
.field("colorPtr", &SimpleTextStyle::colorPtr)
|
||||
.field("foregroundColorPtr", &SimpleTextStyle::foregroundColorPtr)
|
||||
.field("backgroundColorPtr", &SimpleTextStyle::backgroundColorPtr)
|
||||
.field("decoration", &SimpleTextStyle::decoration)
|
||||
.field("decorationThickness", &SimpleTextStyle::decorationThickness)
|
||||
.field("_fontFamilies", &SimpleTextStyle::fontFamilies)
|
||||
|
70
modules/canvaskit/perf/canvas.bench.js
Normal file
70
modules/canvaskit/perf/canvas.bench.js
Normal file
@ -0,0 +1,70 @@
|
||||
describe('Basic Canvas ops', () => {
|
||||
|
||||
let container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
|
||||
beforeEach(async () => {
|
||||
container.innerHTML = `
|
||||
<canvas width=600 height=600 id=test></canvas>`;
|
||||
await LoadCanvasKit;
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
container.innerHTML = '';
|
||||
});
|
||||
|
||||
it('can draw 100 colored regions', () => {
|
||||
function setup(ctx) {
|
||||
ctx.surface = CanvasKit.MakeCanvasSurface('test');
|
||||
ctx.canvas = ctx.surface.getCanvas();
|
||||
};
|
||||
|
||||
function test(ctx) {
|
||||
for (let i=0; i<100; i++) {
|
||||
ctx.canvas.save();
|
||||
ctx.canvas.clipRect(CanvasKit.LTRBRect(i, i, i+100, i+100),
|
||||
CanvasKit.ClipOp.Intersect, false);
|
||||
ctx.canvas.drawColor(CanvasKit.Color4f(1-i/100, 1.0, i/100, 1.0),
|
||||
CanvasKit.BlendMode.SrcOver);
|
||||
ctx.canvas.restore();
|
||||
}
|
||||
ctx.surface.flush();
|
||||
};
|
||||
|
||||
function teardown(ctx) {
|
||||
ctx.surface.delete();
|
||||
};
|
||||
|
||||
benchmarkAndReport('canvas_drawColor', setup, test, teardown);
|
||||
});
|
||||
|
||||
it('can draw a shadow with tonal colors', () => {
|
||||
function setup(ctx) {
|
||||
ctx.surface = CanvasKit.MakeCanvasSurface('test');
|
||||
ctx.canvas = ctx.surface.getCanvas();
|
||||
};
|
||||
|
||||
const input = {
|
||||
ambient: CanvasKit.Color4f(0.2, 0.1, 0.3, 0.5),
|
||||
spot: CanvasKit.Color4f(0.8, 0.8, 0.9, 0.9),
|
||||
};
|
||||
const lightRadius = 30;
|
||||
const flags = 0;
|
||||
const lightPos = [250,150,300];
|
||||
const zPlaneParams = [0,0,1];
|
||||
const path = starPath(CanvasKit);
|
||||
|
||||
function test(ctx) {
|
||||
const out = CanvasKit.computeTonalColors(input);
|
||||
ctx.canvas.drawShadow(path, zPlaneParams, lightPos, lightRadius,
|
||||
out.ambient, out.spot, flags);
|
||||
ctx.surface.flush();
|
||||
};
|
||||
|
||||
function teardown(ctx) {
|
||||
ctx.surface.delete();
|
||||
};
|
||||
|
||||
benchmarkAndReport('canvas_drawShadow', setup, test, teardown);
|
||||
});
|
||||
});
|
@ -52,3 +52,16 @@ CanvasKit.MakeManagedAnimation = function(json, assets) {
|
||||
|
||||
return anim;
|
||||
};
|
||||
|
||||
(function(CanvasKit){
|
||||
CanvasKit._extraInitializations = CanvasKit._extraInitializations || [];
|
||||
CanvasKit._extraInitializations.push(function() {
|
||||
|
||||
CanvasKit.ManagedAnimation.prototype.setColor = function(key, color) {
|
||||
var cPtr = copy1dArray(color, CanvasKit.HEAPF32);
|
||||
this._setColor(key, cPtr);
|
||||
CanvasKit._free(cPtr);
|
||||
}
|
||||
|
||||
});
|
||||
}(Module)); // When this file is loaded in, the high level object is "Module";
|
@ -220,8 +220,10 @@ EMSCRIPTEN_BINDINGS(Skottie) {
|
||||
.function("render" , select_overload<void(SkCanvas*) const>(&ManagedAnimation::render), allow_raw_pointers())
|
||||
.function("render" , select_overload<void(SkCanvas*, const SkRect&) const>
|
||||
(&ManagedAnimation::render), allow_raw_pointers())
|
||||
.function("setColor" , optional_override([](ManagedAnimation& self, const std::string& key, SimpleColor4f c) {
|
||||
self.setColor(key, c.toSkColor());
|
||||
.function("_setColor" , optional_override([](ManagedAnimation& self, const std::string& key, uintptr_t /* float* */ cPtr) {
|
||||
float* fourFloats = reinterpret_cast<float*>(cPtr);
|
||||
SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3] };
|
||||
self.setColor(key, color.toSkColor());
|
||||
}))
|
||||
.function("setOpacity", &ManagedAnimation::setOpacity)
|
||||
.function("getMarkers", &ManagedAnimation::getMarkers)
|
||||
|
Loading…
Reference in New Issue
Block a user