Switch to using a Float32Array (bound as value array) for color.

Change-Id: I1bcca931954b1399c79f4074a3d57a68847ac785
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/276757
Commit-Queue: Nathaniel Nifong <nifong@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
This commit is contained in:
Nathaniel Nifong 2020-03-24 09:08:37 -04:00 committed by Skia Commit-Bot
parent e5ca6ba2c8
commit 4e79b6730d
15 changed files with 434 additions and 165 deletions

View File

@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- CanvasKit colors are now represented with a TypedArray of four floats.
### Removed
- SkPaint.setColorf is obsolete and removed. setColor accepts a CanvasKit color which is
always composed of floats.
## [0.14.0] - 2020-03-18
### Added

View File

@ -1,24 +0,0 @@
/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef WasmAliases_DEFINED
#define WasmAliases_DEFINED
#include <emscripten.h>
#include <emscripten/bind.h>
using namespace emscripten;
// Self-documenting types
using JSArray = emscripten::val;
using JSObject = emscripten::val;
using JSString = emscripten::val;
using SkPathOrNull = emscripten::val;
using Uint8Array = emscripten::val;
using Float32Array = emscripten::val;
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright 2019 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef WasmCommon_DEFINED
#define WasmCommon_DEFINED
#include <emscripten.h>
#include <emscripten/bind.h>
#include "include/core/SkColor.h"
using namespace emscripten;
// Self-documenting types
using JSArray = emscripten::val;
using JSObject = emscripten::val;
using JSString = emscripten::val;
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 {
float r, g, b, a;
SkColor4f toSkColor4f() const {
return SkColor4f({r, g, b, a});
};
SkColor toSkColor() const {
return toSkColor4f().toSkColor();
};
};
#endif

View File

@ -55,7 +55,7 @@
#include <iostream>
#include <string>
#include "modules/canvaskit/WasmAliases.h"
#include "modules/canvaskit/WasmCommon.h"
#include <emscripten.h>
#include <emscripten/bind.h>
@ -134,6 +134,13 @@ SimpleM44 toSimpleM44(const SkM44& sm) {
return m;
}
SimpleColor4f toSimpleColor4f(const SkColor4f c) {
SimpleColor4f color {
c.fR, c.fG, c.fB, c.fA,
};
return color;
}
// Surface creation structs and helpers
struct SimpleImageInfo {
int width;
@ -668,14 +675,17 @@ SkRRect toRRect(const SimpleRRect& r) {
}
struct TonalColors {
SkColor ambientColor;
SkColor spotColor;
SimpleColor4f ambientColor;
SimpleColor4f spotColor;
};
TonalColors computeTonalColors(const TonalColors& in) {
TonalColors computeTonalColors(const TonalColors& in) {SkColor resultAmbient, resultSpot;
SkShadowUtils::ComputeTonalColors(
in.ambientColor.toSkColor(), in.spotColor.toSkColor(),
&resultAmbient, &resultSpot);
TonalColors out;
SkShadowUtils::ComputeTonalColors(in.ambientColor, in.spotColor,
&out.ambientColor, &out.spotColor);
out.ambientColor = toSimpleColor4f(SkColor4f::FromColor(resultAmbient));
out.spotColor = toSimpleColor4f(SkColor4f::FromColor(resultSpot));
return out;
}
@ -792,28 +802,29 @@ EMSCRIPTEN_BINDINGS(Skia) {
return SkImage::MakeRasterData(info, pixelData, rowBytes);
}), allow_raw_pointers());
function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
SkPoint points[] = { start, end };
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
return SkGradientShader::MakeLinear(points, colors, positions, count,
// TODO(nifong): do not assume color space. Support and test wide gamut color gradients
return SkGradientShader::MakeLinear(points, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, flags, nullptr);
}), allow_raw_pointers());
function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
const SimpleMatrix& lm)->sk_sp<SkShader> {
SkPoint points[] = { start, end };
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
SkMatrix localMatrix = toSkMatrix(lm);
return SkGradientShader::MakeLinear(points, colors, positions, count,
return SkGradientShader::MakeLinear(points, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, flags, &localMatrix);
}), allow_raw_pointers());
#ifdef SK_SERIALIZE_SKP
@ -827,89 +838,89 @@ EMSCRIPTEN_BINDINGS(Skia) {
}), allow_raw_pointers());
#endif
function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
return SkGradientShader::MakeRadial(center, radius, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, flags, nullptr);
}), allow_raw_pointers());
function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
const SimpleMatrix& lm)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
SkMatrix localMatrix = toSkMatrix(lm);
return SkGradientShader::MakeRadial(center, radius, colors, positions, count,
return SkGradientShader::MakeRadial(center, radius, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, flags, &localMatrix);
}), allow_raw_pointers());
function("_MakeSweepGradientShader", optional_override([](SkScalar cx, SkScalar cy,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode,
SkScalar startAngle, SkScalar endAngle,
uint32_t flags,
const SimpleMatrix& lm)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
SkMatrix localMatrix = toSkMatrix(lm);
return SkGradientShader::MakeSweep(cx, cy, colors, positions, count,
return SkGradientShader::MakeSweep(cx, cy, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, startAngle, endAngle, flags,
&localMatrix);
}), allow_raw_pointers());
function("_MakeSweepGradientShader", optional_override([](SkScalar cx, SkScalar cy,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, uint32_t flags,
const SimpleMatrix& lm)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
SkMatrix localMatrix = toSkMatrix(lm);
return SkGradientShader::MakeSweep(cx, cy, colors, positions, count,
return SkGradientShader::MakeSweep(cx, cy, colors, SkColorSpace::MakeSRGB(), positions, count,
flags, &localMatrix);
}), allow_raw_pointers());
function("_MakeSweepGradientShader", optional_override([](SkScalar cx, SkScalar cy,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
return SkGradientShader::MakeSweep(cx, cy, colors, positions, count);
return SkGradientShader::MakeSweep(cx, cy, colors, SkColorSpace::MakeSRGB(), positions, count);
}), allow_raw_pointers());
function("_MakeTwoPointConicalGradientShader", optional_override([](
SkPoint start, SkScalar startRadius,
SkPoint end, SkScalar endRadius,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
colors, positions, count, mode,
colors, SkColorSpace::MakeSRGB(), positions, count, mode,
flags, nullptr);
}), allow_raw_pointers());
function("_MakeTwoPointConicalGradientShader", optional_override([](
SkPoint start, SkScalar startRadius,
SkPoint end, SkScalar endRadius,
uintptr_t /* SkColor* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
const SimpleMatrix& lm)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor* colors = reinterpret_cast<const SkColor*> (cPtr);
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
SkMatrix localMatrix = toSkMatrix(lm);
return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
colors, positions, count, mode,
colors, SkColorSpace::MakeSRGB(), positions, count, mode,
flags, &localMatrix);
}), allow_raw_pointers());
@ -953,7 +964,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkCanvas>("SkCanvas")
.constructor<>()
.function("clear", &SkCanvas::clear)
.function("clear", optional_override([](SkCanvas& self, SimpleColor4f c) {
self.clear(c.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) {
self.clipRRect(toRRect(r), op, doAntiAlias);
@ -963,6 +976,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
self.concat(toSkMatrix(m));
}))
.function("drawArc", &SkCanvas::drawArc)
// _drawAtlas takes an SkColor, unlike most private functions handling color.
// This is because it takes an array of colors. Converting it on the Javascript side allows
// an allocation to be avoided here.
.function("_drawAtlas", optional_override([](SkCanvas& self,
const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
@ -977,7 +993,12 @@ 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", &SkCanvas::drawColor)
.function("drawColor", optional_override([](SkCanvas& self, SimpleColor4f c) {
self.drawColor(c.toSkColor());
}))
.function("drawColor", optional_override([](SkCanvas& self, SimpleColor4f c, SkBlendMode mode) {
self.drawColor(c.toSkColor(), mode);
}))
.function("drawDRRect",optional_override([](SkCanvas& self, const SimpleRRect& o, const SimpleRRect& i, const SkPaint& paint) {
self.drawDRRect(toRRect(o), toRRect(i), paint);
}))
@ -1026,10 +1047,10 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("drawShadow", optional_override([](SkCanvas& self, const SkPath& path,
const SkPoint3& zPlaneParams,
const SkPoint3& lightPos, SkScalar lightRadius,
SkColor ambientColor, SkColor spotColor,
SimpleColor4f ambientColor, SimpleColor4f spotColor,
uint32_t flags) {
SkShadowUtils::DrawShadow(&self, path, zPlaneParams, lightPos, lightRadius,
ambientColor, spotColor, flags);
ambientColor.toSkColor(), spotColor.toSkColor(), flags);
}))
#ifndef SK_NO_FONTS
.function("_drawShapedText", &drawShapedText)
@ -1111,7 +1132,9 @@ EMSCRIPTEN_BINDINGS(Skia) {
class_<SkColorFilter>("SkColorFilter")
.smart_ptr<sk_sp<SkColorFilter>>("sk_sp<SkColorFilter>>")
.class_function("MakeBlend", &SkColorFilters::Blend)
.class_function("MakeBlend", optional_override([](SimpleColor4f c, SkBlendMode mode)->sk_sp<SkColorFilter> {
return SkColorFilters::Blend(c.toSkColor(), mode);
}))
.class_function("MakeCompose", &SkColorFilters::Compose)
.class_function("MakeLerp", &SkColorFilters::Lerp)
.class_function("MakeLinearToSRGBGamma", &SkColorFilters::LinearToSRGBGamma)
@ -1305,7 +1328,11 @@ EMSCRIPTEN_BINDINGS(Skia) {
return p;
}))
.function("getBlendMode", &SkPaint::getBlendMode)
.function("getColor", &SkPaint::getColor)
.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));
}))
.function("getFilterQuality", &SkPaint::getFilterQuality)
.function("getStrokeCap", &SkPaint::getStrokeCap)
.function("getStrokeJoin", &SkPaint::getStrokeJoin)
@ -1314,12 +1341,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("setAntiAlias", &SkPaint::setAntiAlias)
.function("setAlphaf", &SkPaint::setAlphaf)
.function("setBlendMode", &SkPaint::setBlendMode)
.function("setColor", optional_override([](SkPaint& self, SkColor c) {
self.setColor(c);
}))
.function("setColorf", optional_override([](SkPaint& self,
float r, float g, float b, float a) {
self.setColor({r, g, b, a});
.function("setColor", optional_override([](SkPaint& self, SimpleColor4f c) {
self.setColor({c.r, c.g, c.b, c.a});
}))
.function("setColorFilter", &SkPaint::setColorFilter)
.function("setFilterQuality", &SkPaint::setFilterQuality)
@ -1472,7 +1495,11 @@ EMSCRIPTEN_BINDINGS(Skia) {
auto m = toSkMatrix(sm);
return SkShaders::Blend(mode, dst, src, &m);
}))
.class_function("Color", select_overload<sk_sp<SkShader>(SkColor)>(&SkShaders::Color))
.class_function("Color",
optional_override([](SimpleColor4f c)->sk_sp<SkShader> {
return SkShaders::Color(c.toSkColor4f(), SkColorSpace::MakeSRGB());
})
)
.class_function("_Lerp", optional_override([](float t, sk_sp<SkShader> dst, sk_sp<SkShader> src)->sk_sp<SkShader> {
return SkShaders::Lerp(t, dst, src, nullptr);
}))
@ -1747,6 +1774,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
.field("text", &ShapedTextOpts::text)
.field("width", &ShapedTextOpts::width);
#endif
value_object<SkRect>("SkRect")
.field("fLeft", &SkRect::fLeft)
.field("fTop", &SkRect::fTop)
@ -1838,16 +1866,15 @@ EMSCRIPTEN_BINDINGS(Skia) {
.element(&SimpleM44::m8).element(&SimpleM44::m9).element(&SimpleM44::m10).element(&SimpleM44::m11)
.element(&SimpleM44::m12).element(&SimpleM44::m13).element(&SimpleM44::m14).element(&SimpleM44::m15);
constant("TRANSPARENT", SK_ColorTRANSPARENT);
constant("RED", SK_ColorRED);
constant("GREEN", SK_ColorGREEN);
constant("BLUE", SK_ColorBLUE);
constant("MAGENTA", SK_ColorMAGENTA);
constant("YELLOW", SK_ColorYELLOW);
constant("CYAN", SK_ColorCYAN);
constant("BLACK", SK_ColorBLACK);
constant("WHITE", SK_ColorWHITE);
// TODO(?)
// TODO(nifong): emscripten will allow functions taking this to accept either an array
// or a typed array, but functions returning it always produce arrays. If possible
// make them return a Float32Array
value_array<SimpleColor4f>("SkColor4f")
.element(&SimpleColor4f::r)
.element(&SimpleColor4f::g)
.element(&SimpleColor4f::b)
.element(&SimpleColor4f::a);
constant("MOVE_VERB", MOVE);
constant("LINE_VERB", LINE);

View File

@ -25,6 +25,7 @@
var CanvasKit = {
// public API (i.e. things we declare in the pre-js file or in the cpp bindings)
Color: function() {},
Color4f: function() {},
/** @return {CanvasKit.SkRect} */
LTRBRect: function() {},
/** @return {CanvasKit.SkRect} */

View File

@ -4,34 +4,53 @@ function clamp(c) {
return Math.round(Math.max(0, Math.min(c || 0, 255)));
}
// Colors are just a 32 bit number with 8 bits each of a, r, g, b
// The API is the same as CSS's representation of color rgba(), that is
// Constructs a Color with the same API as CSS's rgba(), that is
// r,g,b are 0-255, and a is 0.0 to 1.0.
// if a is omitted, it will be assumed to be 1.0
// Internally, Colors are a TypedArray of four unpremultiplied 32-bit floats: a, r, g, b
// In order to construct one with more precision or in a wider gamut, use
// CanvasKit.Color4f
CanvasKit.Color = function(r, g, b, a) {
if (a === undefined) {
a = 1;
}
// The >>> 0 converts the signed int to an unsigned int. Skia's
// SkColor object is an unsigned int.
// https://stackoverflow.com/a/14891172
return ((clamp(a*255) << 24) | (clamp(r) << 16) | (clamp(g) << 8) | (clamp(b) << 0)) >>> 0;
return CanvasKit.Color4f(clamp(r)/255, clamp(g)/255, clamp(b)/255, a);
}
// returns [r, g, b, a] from a color
// Construct a 4-float color.
// Opaque if opacity is omitted.
CanvasKit.Color4f = function(r, g, b, a) {
if (a === undefined) {
a = 1;
}
return Float32Array.of(r, g, b, a);
}
CanvasKit.TRANSPARENT = CanvasKit.Color4f(0, 0, 0, 0);
CanvasKit.BLACK = CanvasKit.Color4f(0, 0, 0, 1);
CanvasKit.WHITE = CanvasKit.Color4f(1, 1, 1, 1);
CanvasKit.RED = CanvasKit.Color4f(1, 0, 0, 1);
CanvasKit.GREEN = CanvasKit.Color4f(0, 1, 0, 1);
CanvasKit.BLUE = CanvasKit.Color4f(0, 0, 1, 1);
CanvasKit.YELLOW = CanvasKit.Color4f(1, 1, 0, 1);
CanvasKit.CYAN = CanvasKit.Color4f(0, 1, 1, 1);
CanvasKit.MAGENTA = CanvasKit.Color4f(1, 0, 1, 1);
// returns a css style [r, g, b, a] from a CanvasKit.Color
// where r, g, b are returned as ints in the range [0, 255]
// where a is scaled between 0 and 1.0
CanvasKit.getColorComponents = function(color) {
return [
(color >> 16) & 0xFF,
(color >> 8) & 0xFF,
(color >> 0) & 0xFF,
((color >> 24) & 0xFF) / 255,
]
Math.floor(color[0]*255),
Math.floor(color[1]*255),
Math.floor(color[2]*255),
color[3]
];
}
// parseColorString takes in a CSS color value and returns a CanvasKit.Color
// (which is just a 32 bit integer, 8 bits per channel). An optional colorMap
// may be provided which maps custom strings to values (e.g. {'springgreen':4278255487}).
// (which is an array of 4 floats in RGBA order). An optional colorMap
// may be provided which maps custom strings to values.
// In the CanvasKit canvas2d shim layer, we provide this map for processing
// canvas2d calls, but not here for code size reasons.
CanvasKit.parseColorString = function(colorStr, colorMap) {
@ -88,6 +107,26 @@ CanvasKit.parseColorString = function(colorStr, colorMap) {
return CanvasKit.BLACK;
}
function isCanvasKitColor(ob) {
if (!ob) {
return false;
}
return (ob.constructor === Float32Array && ob.length === 4);
}
// Warning information is lost by this conversion
function toUint32Color(c) {
return ((clamp(c[3]*255) << 24) | (clamp(c[0]*255) << 16) | (clamp(c[1]*255) << 8) | (clamp(c[2]*255) << 0)) >>> 0;
}
function uIntColorToCanvasKitColor(c) {
return CanvasKit.Color(
(c >> 16) & 0xFF,
(c >> 8) & 0xFF,
(c >> 0) & 0xFF,
((c >> 24) & 0xFF) / 255
);
}
function valueOrPercent(aStr) {
if (aStr === undefined) {
return 1; // default to opaque.
@ -100,16 +139,10 @@ function valueOrPercent(aStr) {
}
CanvasKit.multiplyByAlpha = function(color, alpha) {
if (alpha === 1) {
return color;
}
// extract as int from 0 to 255
var a = (color >> 24) & 0xFF;
a *= alpha;
// mask off the old alpha
color &= 0xFFFFFF;
// back to unsigned int to match SkColor.
return (clamp(a) << 24 | color) >>> 0;
// make a copy of the color so the function remains pure.
var result = color.slice();
result[3] = Math.max(0, Math.min(result[3] * alpha, 1));
return result;
}
function radiansToDegrees(rad) {

View File

@ -79,7 +79,7 @@ function CanvasRenderingContext2D(skcanvas) {
Object.defineProperty(this, 'fillStyle', {
enumerable: true,
get: function() {
if (Number.isInteger(this._fillStyle)) {
if (isCanvasKitColor(this._fillStyle)) {
return colorToString(this._fillStyle);
}
return this._fillStyle;
@ -632,7 +632,7 @@ function CanvasRenderingContext2D(skcanvas) {
this._fillPaint = function() {
var paint = this._paint.copy();
paint.setStyle(CanvasKit.PaintStyle.Fill);
if (Number.isInteger(this._fillStyle)) {
if (isCanvasKitColor(this._fillStyle)) {
var alphaColor = CanvasKit.multiplyByAlpha(this._fillStyle, this._globalAlpha);
paint.setColor(alphaColor);
} else {
@ -1047,7 +1047,7 @@ function CanvasRenderingContext2D(skcanvas) {
this._strokePaint = function() {
var paint = this._paint.copy();
paint.setStyle(CanvasKit.PaintStyle.Stroke);
if (Number.isInteger(this._strokeStyle)) {
if (isCanvasKitColor(this._strokeStyle)) {
var alphaColor = CanvasKit.multiplyByAlpha(this._strokeStyle, this._globalAlpha);
paint.setColor(alphaColor);
} else {

View File

@ -7,7 +7,158 @@
// the map, which saves (a tiny amount of) startup time
// and (a small amount of) code size.
/* @dict */
var colorMap = {'aliceblue':4293982463,'antiquewhite':4294634455,'aqua':4278255615,'aquamarine':4286578644,'azure':4293984255,'beige':4294309340,'bisque':4294960324,'black':4278190080,'blanchedalmond':4294962125,'blue':4278190335,'blueviolet':4287245282,'brown':4289014314,'burlywood':4292786311,'cadetblue':4284456608,'chartreuse':4286578432,'chocolate':4291979550,'coral':4294934352,'cornflowerblue':4284782061,'cornsilk':4294965468,'crimson':4292613180,'cyan':4278255615,'darkblue':4278190219,'darkcyan':4278225803,'darkgoldenrod':4290283019,'darkgray':4289309097,'darkgreen':4278215680,'darkgrey':4289309097,'darkkhaki':4290623339,'darkmagenta':4287299723,'darkolivegreen':4283788079,'darkorange':4294937600,'darkorchid':4288230092,'darkred':4287299584,'darksalmon':4293498490,'darkseagreen':4287609999,'darkslateblue':4282924427,'darkslategray':4281290575,'darkslategrey':4281290575,'darkturquoise':4278243025,'darkviolet':4287889619,'deeppink':4294907027,'deepskyblue':4278239231,'dimgray':4285098345,'dimgrey':4285098345,'dodgerblue':4280193279,'firebrick':4289864226,'floralwhite':4294966000,'forestgreen':4280453922,'fuchsia':4294902015,'gainsboro':4292664540,'ghostwhite':4294506751,'gold':4294956800,'goldenrod':4292519200,'gray':4286611584,'green':4278222848,'greenyellow':4289593135,'grey':4286611584,'honeydew':4293984240,'hotpink':4294928820,'indianred':4291648604,'indigo':4283105410,'ivory':4294967280,'khaki':4293977740,'lavender':4293322490,'lavenderblush':4294963445,'lawngreen':4286381056,'lemonchiffon':4294965965,'lightblue':4289583334,'lightcoral':4293951616,'lightcyan':4292935679,'lightgoldenrodyellow':4294638290,'lightgray':4292072403,'lightgreen':4287688336,'lightgrey':4292072403,'lightpink':4294948545,'lightsalmon':4294942842,'lightseagreen':4280332970,'lightskyblue':4287090426,'lightslategray':4286023833,'lightslategrey':4286023833,'lightsteelblue':4289774814,'lightyellow':4294967264,'lime':4278255360,'limegreen':4281519410,'linen':4294635750,'magenta':4294902015,'maroon':4286578688,'mediumaquamarine':4284927402,'mediumblue':4278190285,'mediumorchid':4290401747,'mediumpurple':4287852763,'mediumseagreen':4282168177,'mediumslateblue':4286277870,'mediumspringgreen':4278254234,'mediumturquoise':4282962380,'mediumvioletred':4291237253,'midnightblue':4279834992,'mintcream':4294311930,'mistyrose':4294960353,'moccasin':4294960309,'navajowhite':4294958765,'navy':4278190208,'oldlace':4294833638,'olive':4286611456,'olivedrab':4285238819,'orange':4294944000,'orangered':4294919424,'orchid':4292505814,'palegoldenrod':4293847210,'palegreen':4288215960,'paleturquoise':4289720046,'palevioletred':4292571283,'papayawhip':4294963157,'peachpuff':4294957753,'peru':4291659071,'pink':4294951115,'plum':4292714717,'powderblue':4289781990,'purple':4286578816,'rebeccapurple':4284887961,'red':4294901760,'rosybrown':4290547599,'royalblue':4282477025,'saddlebrown':4287317267,'salmon':4294606962,'sandybrown':4294222944,'seagreen':4281240407,'seashell':4294964718,'sienna':4288696877,'silver':4290822336,'skyblue':4287090411,'slateblue':4285160141,'slategray':4285563024,'slategrey':4285563024,'snow':4294966010,'springgreen':4278255487,'steelblue':4282811060,'tan':4291998860,'teal':4278222976,'thistle':4292394968,'transparent':0,'tomato':4294927175,'turquoise':4282441936,'violet':4293821166,'wheat':4294303411,'white':4294967295,'whitesmoke':4294309365,'yellow':4294967040,'yellowgreen':4288335154};
var colorMap = {
'aliceblue': Float32Array.of(0.941, 0.973, 1.000, 1.000),
'antiquewhite': Float32Array.of(0.980, 0.922, 0.843, 1.000),
'aqua': Float32Array.of(0.000, 1.000, 1.000, 1.000),
'aquamarine': Float32Array.of(0.498, 1.000, 0.831, 1.000),
'azure': Float32Array.of(0.941, 1.000, 1.000, 1.000),
'beige': Float32Array.of(0.961, 0.961, 0.863, 1.000),
'bisque': Float32Array.of(1.000, 0.894, 0.769, 1.000),
'black': Float32Array.of(0.000, 0.000, 0.000, 1.000),
'blanchedalmond': Float32Array.of(1.000, 0.922, 0.804, 1.000),
'blue': Float32Array.of(0.000, 0.000, 1.000, 1.000),
'blueviolet': Float32Array.of(0.541, 0.169, 0.886, 1.000),
'brown': Float32Array.of(0.647, 0.165, 0.165, 1.000),
'burlywood': Float32Array.of(0.871, 0.722, 0.529, 1.000),
'cadetblue': Float32Array.of(0.373, 0.620, 0.627, 1.000),
'chartreuse': Float32Array.of(0.498, 1.000, 0.000, 1.000),
'chocolate': Float32Array.of(0.824, 0.412, 0.118, 1.000),
'coral': Float32Array.of(1.000, 0.498, 0.314, 1.000),
'cornflowerblue': Float32Array.of(0.392, 0.584, 0.929, 1.000),
'cornsilk': Float32Array.of(1.000, 0.973, 0.863, 1.000),
'crimson': Float32Array.of(0.863, 0.078, 0.235, 1.000),
'cyan': Float32Array.of(0.000, 1.000, 1.000, 1.000),
'darkblue': Float32Array.of(0.000, 0.000, 0.545, 1.000),
'darkcyan': Float32Array.of(0.000, 0.545, 0.545, 1.000),
'darkgoldenrod': Float32Array.of(0.722, 0.525, 0.043, 1.000),
'darkgray': Float32Array.of(0.663, 0.663, 0.663, 1.000),
'darkgreen': Float32Array.of(0.000, 0.392, 0.000, 1.000),
'darkgrey': Float32Array.of(0.663, 0.663, 0.663, 1.000),
'darkkhaki': Float32Array.of(0.741, 0.718, 0.420, 1.000),
'darkmagenta': Float32Array.of(0.545, 0.000, 0.545, 1.000),
'darkolivegreen': Float32Array.of(0.333, 0.420, 0.184, 1.000),
'darkorange': Float32Array.of(1.000, 0.549, 0.000, 1.000),
'darkorchid': Float32Array.of(0.600, 0.196, 0.800, 1.000),
'darkred': Float32Array.of(0.545, 0.000, 0.000, 1.000),
'darksalmon': Float32Array.of(0.914, 0.588, 0.478, 1.000),
'darkseagreen': Float32Array.of(0.561, 0.737, 0.561, 1.000),
'darkslateblue': Float32Array.of(0.282, 0.239, 0.545, 1.000),
'darkslategray': Float32Array.of(0.184, 0.310, 0.310, 1.000),
'darkslategrey': Float32Array.of(0.184, 0.310, 0.310, 1.000),
'darkturquoise': Float32Array.of(0.000, 0.808, 0.820, 1.000),
'darkviolet': Float32Array.of(0.580, 0.000, 0.827, 1.000),
'deeppink': Float32Array.of(1.000, 0.078, 0.576, 1.000),
'deepskyblue': Float32Array.of(0.000, 0.749, 1.000, 1.000),
'dimgray': Float32Array.of(0.412, 0.412, 0.412, 1.000),
'dimgrey': Float32Array.of(0.412, 0.412, 0.412, 1.000),
'dodgerblue': Float32Array.of(0.118, 0.565, 1.000, 1.000),
'firebrick': Float32Array.of(0.698, 0.133, 0.133, 1.000),
'floralwhite': Float32Array.of(1.000, 0.980, 0.941, 1.000),
'forestgreen': Float32Array.of(0.133, 0.545, 0.133, 1.000),
'fuchsia': Float32Array.of(1.000, 0.000, 1.000, 1.000),
'gainsboro': Float32Array.of(0.863, 0.863, 0.863, 1.000),
'ghostwhite': Float32Array.of(0.973, 0.973, 1.000, 1.000),
'gold': Float32Array.of(1.000, 0.843, 0.000, 1.000),
'goldenrod': Float32Array.of(0.855, 0.647, 0.125, 1.000),
'gray': Float32Array.of(0.502, 0.502, 0.502, 1.000),
'green': Float32Array.of(0.000, 0.502, 0.000, 1.000),
'greenyellow': Float32Array.of(0.678, 1.000, 0.184, 1.000),
'grey': Float32Array.of(0.502, 0.502, 0.502, 1.000),
'honeydew': Float32Array.of(0.941, 1.000, 0.941, 1.000),
'hotpink': Float32Array.of(1.000, 0.412, 0.706, 1.000),
'indianred': Float32Array.of(0.804, 0.361, 0.361, 1.000),
'indigo': Float32Array.of(0.294, 0.000, 0.510, 1.000),
'ivory': Float32Array.of(1.000, 1.000, 0.941, 1.000),
'khaki': Float32Array.of(0.941, 0.902, 0.549, 1.000),
'lavender': Float32Array.of(0.902, 0.902, 0.980, 1.000),
'lavenderblush': Float32Array.of(1.000, 0.941, 0.961, 1.000),
'lawngreen': Float32Array.of(0.486, 0.988, 0.000, 1.000),
'lemonchiffon': Float32Array.of(1.000, 0.980, 0.804, 1.000),
'lightblue': Float32Array.of(0.678, 0.847, 0.902, 1.000),
'lightcoral': Float32Array.of(0.941, 0.502, 0.502, 1.000),
'lightcyan': Float32Array.of(0.878, 1.000, 1.000, 1.000),
'lightgoldenrodyellow': Float32Array.of(0.980, 0.980, 0.824, 1.000),
'lightgray': Float32Array.of(0.827, 0.827, 0.827, 1.000),
'lightgreen': Float32Array.of(0.565, 0.933, 0.565, 1.000),
'lightgrey': Float32Array.of(0.827, 0.827, 0.827, 1.000),
'lightpink': Float32Array.of(1.000, 0.714, 0.757, 1.000),
'lightsalmon': Float32Array.of(1.000, 0.627, 0.478, 1.000),
'lightseagreen': Float32Array.of(0.125, 0.698, 0.667, 1.000),
'lightskyblue': Float32Array.of(0.529, 0.808, 0.980, 1.000),
'lightslategray': Float32Array.of(0.467, 0.533, 0.600, 1.000),
'lightslategrey': Float32Array.of(0.467, 0.533, 0.600, 1.000),
'lightsteelblue': Float32Array.of(0.690, 0.769, 0.871, 1.000),
'lightyellow': Float32Array.of(1.000, 1.000, 0.878, 1.000),
'lime': Float32Array.of(0.000, 1.000, 0.000, 1.000),
'limegreen': Float32Array.of(0.196, 0.804, 0.196, 1.000),
'linen': Float32Array.of(0.980, 0.941, 0.902, 1.000),
'magenta': Float32Array.of(1.000, 0.000, 1.000, 1.000),
'maroon': Float32Array.of(0.502, 0.000, 0.000, 1.000),
'mediumaquamarine': Float32Array.of(0.400, 0.804, 0.667, 1.000),
'mediumblue': Float32Array.of(0.000, 0.000, 0.804, 1.000),
'mediumorchid': Float32Array.of(0.729, 0.333, 0.827, 1.000),
'mediumpurple': Float32Array.of(0.576, 0.439, 0.859, 1.000),
'mediumseagreen': Float32Array.of(0.235, 0.702, 0.443, 1.000),
'mediumslateblue': Float32Array.of(0.482, 0.408, 0.933, 1.000),
'mediumspringgreen': Float32Array.of(0.000, 0.980, 0.604, 1.000),
'mediumturquoise': Float32Array.of(0.282, 0.820, 0.800, 1.000),
'mediumvioletred': Float32Array.of(0.780, 0.082, 0.522, 1.000),
'midnightblue': Float32Array.of(0.098, 0.098, 0.439, 1.000),
'mintcream': Float32Array.of(0.961, 1.000, 0.980, 1.000),
'mistyrose': Float32Array.of(1.000, 0.894, 0.882, 1.000),
'moccasin': Float32Array.of(1.000, 0.894, 0.710, 1.000),
'navajowhite': Float32Array.of(1.000, 0.871, 0.678, 1.000),
'navy': Float32Array.of(0.000, 0.000, 0.502, 1.000),
'oldlace': Float32Array.of(0.992, 0.961, 0.902, 1.000),
'olive': Float32Array.of(0.502, 0.502, 0.000, 1.000),
'olivedrab': Float32Array.of(0.420, 0.557, 0.137, 1.000),
'orange': Float32Array.of(1.000, 0.647, 0.000, 1.000),
'orangered': Float32Array.of(1.000, 0.271, 0.000, 1.000),
'orchid': Float32Array.of(0.855, 0.439, 0.839, 1.000),
'palegoldenrod': Float32Array.of(0.933, 0.910, 0.667, 1.000),
'palegreen': Float32Array.of(0.596, 0.984, 0.596, 1.000),
'paleturquoise': Float32Array.of(0.686, 0.933, 0.933, 1.000),
'palevioletred': Float32Array.of(0.859, 0.439, 0.576, 1.000),
'papayawhip': Float32Array.of(1.000, 0.937, 0.835, 1.000),
'peachpuff': Float32Array.of(1.000, 0.855, 0.725, 1.000),
'peru': Float32Array.of(0.804, 0.522, 0.247, 1.000),
'pink': Float32Array.of(1.000, 0.753, 0.796, 1.000),
'plum': Float32Array.of(0.867, 0.627, 0.867, 1.000),
'powderblue': Float32Array.of(0.690, 0.878, 0.902, 1.000),
'purple': Float32Array.of(0.502, 0.000, 0.502, 1.000),
'rebeccapurple': Float32Array.of(0.400, 0.200, 0.600, 1.000),
'red': Float32Array.of(1.000, 0.000, 0.000, 1.000),
'rosybrown': Float32Array.of(0.737, 0.561, 0.561, 1.000),
'royalblue': Float32Array.of(0.255, 0.412, 0.882, 1.000),
'saddlebrown': Float32Array.of(0.545, 0.271, 0.075, 1.000),
'salmon': Float32Array.of(0.980, 0.502, 0.447, 1.000),
'sandybrown': Float32Array.of(0.957, 0.643, 0.376, 1.000),
'seagreen': Float32Array.of(0.180, 0.545, 0.341, 1.000),
'seashell': Float32Array.of(1.000, 0.961, 0.933, 1.000),
'sienna': Float32Array.of(0.627, 0.322, 0.176, 1.000),
'silver': Float32Array.of(0.753, 0.753, 0.753, 1.000),
'skyblue': Float32Array.of(0.529, 0.808, 0.922, 1.000),
'slateblue': Float32Array.of(0.416, 0.353, 0.804, 1.000),
'slategray': Float32Array.of(0.439, 0.502, 0.565, 1.000),
'slategrey': Float32Array.of(0.439, 0.502, 0.565, 1.000),
'snow': Float32Array.of(1.000, 0.980, 0.980, 1.000),
'springgreen': Float32Array.of(0.000, 1.000, 0.498, 1.000),
'steelblue': Float32Array.of(0.275, 0.510, 0.706, 1.000),
'tan': Float32Array.of(0.824, 0.706, 0.549, 1.000),
'teal': Float32Array.of(0.000, 0.502, 0.502, 1.000),
'thistle': Float32Array.of(0.847, 0.749, 0.847, 1.000),
'tomato': Float32Array.of(1.000, 0.388, 0.278, 1.000),
'transparent': Float32Array.of(0.000, 0.000, 0.000, 0.000),
'turquoise': Float32Array.of(0.251, 0.878, 0.816, 1.000),
'violet': Float32Array.of(0.933, 0.510, 0.933, 1.000),
'wheat': Float32Array.of(0.961, 0.871, 0.702, 1.000),
'white': Float32Array.of(1.000, 1.000, 1.000, 1.000),
'whitesmoke': Float32Array.of(0.961, 0.961, 0.961, 1.000),
'yellow': Float32Array.of(1.000, 1.000, 0.000, 1.000),
'yellowgreen': Float32Array.of(0.604, 0.804, 0.196, 1.000),
}
function colorToString(skcolor) {
// https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
var components = CanvasKit.getColorComponents(skcolor);

View File

@ -861,8 +861,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 SkColor
// (from CanvasKit.Color)
// colors, if provided, should be a CanvasKit.SkColorBuilder or array of Canvaskit.SimpleColor4f
CanvasKit.SkCanvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
/*optional*/ blendMode, colors) {
if (!atlas || !paint || !srcRects || !dstXforms) {
@ -871,6 +870,7 @@ CanvasKit.onRuntimeInitialized = function() {
}
if (srcRects.length !== dstXforms.length || (colors && colors.length !== dstXforms.length)) {
SkDebug('Doing nothing since input arrays length mismatches');
return;
}
if (!blendMode) {
blendMode = CanvasKit.BlendMode.SrcOver;
@ -895,6 +895,13 @@ CanvasKit.onRuntimeInitialized = function() {
if (colors.build) {
colorPtr = colors.build();
} else {
if (!isCanvasKitColor(colors[0])) {
SkDebug('DrawAtlas color argument expected to be CanvasKit.SkRectBuilder or array of ' +
'Canvaskit.SimpleColor4f, but got '+colors);
return;
}
// convert here
colors = colors.map(toUint32Color);
colorPtr = copy1dArray(colors, CanvasKit.HEAPU32);
}
}
@ -1077,7 +1084,7 @@ CanvasKit.onRuntimeInitialized = function() {
}
CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags) {
var colorPtr = copy1dArray(colors, CanvasKit.HEAPU32);
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
@ -1099,7 +1106,7 @@ CanvasKit.onRuntimeInitialized = function() {
}
CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags) {
var colorPtr = copy1dArray(colors, CanvasKit.HEAPU32);
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
@ -1149,7 +1156,7 @@ CanvasKit.onRuntimeInitialized = function() {
CanvasKit.SkShader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius,
colors, pos, mode, localMatrix, flags) {
var colorPtr = copy1dArray(colors, CanvasKit.HEAPU32);
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
@ -1271,6 +1278,7 @@ CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType) {
return CanvasKit._MakeImage(info, pptr, pixels.length, width * bytesPerPixel);
}
// colors is an array of SimpleColor4f
CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
indices, isVolatile) {
// Default isVolitile to true if not set
@ -1296,7 +1304,8 @@ CanvasKit.MakeSkVertices = function(mode, positions, textureCoordinates, colors,
copy2dArray(textureCoordinates, CanvasKit.HEAPF32, builder.texCoords());
}
if (builder.colors()) {
copy1dArray(colors, CanvasKit.HEAPU32, builder.colors());
// Convert from canvaskit 4f colors to 32 bit uint colors which builder supports.
copy1dArray(colors.map(toUint32Color), CanvasKit.HEAPU32, builder.colors());
}
if (builder.indices()) {
copy1dArray(indices, CanvasKit.HEAPU16, builder.indices());

View File

@ -65,9 +65,8 @@
CanvasKit.TextStyle = function(s) {
// Use [''] to tell closure not to minify the names
s['backgroundColor'] = s['backgroundColor'] || 0;
// Can't check for falsey as 0 is "white".
if (s['color'] === undefined) {
s['backgroundColor'] = s['backgroundColor'] || CanvasKit.WHITE;
if (!isCanvasKitColor(s['color'])) {
s['color'] = CanvasKit.BLACK;
}
s['decoration'] = s['decoration'] || 0;
@ -83,7 +82,7 @@
SkDebug("no font families provided, text may draw wrong or not at all")
}
s['fontStyle'] = fontStyle(s['fontStyle']);
s['foregroundColor'] = s['foregroundColor'] || 0;
s['foregroundColor'] = s['foregroundColor'] || CanvasKit.WHITE;
return s;
}

View File

@ -21,7 +21,7 @@
#include <emscripten.h>
#include <emscripten/bind.h>
#include "modules/canvaskit/WasmAliases.h"
#include "modules/canvaskit/WasmCommon.h"
using namespace emscripten;
@ -34,13 +34,13 @@ struct SimpleFontStyle {
};
struct SimpleTextStyle {
SkColor backgroundColor;
SkColor color;
SimpleColor4f backgroundColor;
SimpleColor4f color;
uint8_t decoration;
SkScalar decorationThickness;
SkScalar fontSize;
SimpleFontStyle fontStyle;
SkColor foregroundColor;
SimpleColor4f foregroundColor;
uintptr_t /* const char** */ fontFamilies;
int numFontFamilies;
@ -48,21 +48,20 @@ struct SimpleTextStyle {
para::TextStyle toTextStyle(const SimpleTextStyle& s) {
para::TextStyle ts;
if (s.color != 0) {
ts.setColor(s.color);
}
if (s.foregroundColor != 0) {
SkPaint p;
p.setColor(s.foregroundColor);
ts.setForegroundColor(p);
}
// textstype doesn't support a 4f color
//SkColor4f({s.color.r, s.color.g, s.color.b, s.color.a}
ts.setColor(s.color.toSkColor());
if (s.backgroundColor != 0) {
SkPaint p;
p.setColor(s.backgroundColor);
ts.setBackgroundColor(p);
}
// TODO(nifong): when color was a uint, these were left unset if the color was white, was that
// important?
SkPaint p1;
p1.setColor4f(s.foregroundColor.toSkColor4f());
ts.setForegroundColor(p1);
SkPaint p2;
p2.setColor4f(s.backgroundColor.toSkColor4f());
ts.setBackgroundColor(p2);
if (s.fontSize != 0) {
ts.setFontSize(s.fontSize);

View File

@ -15,7 +15,7 @@
#include <string>
#include "modules/canvaskit/WasmAliases.h"
#include "modules/canvaskit/WasmCommon.h"
#include <emscripten.h>
#include <emscripten/bind.h>

View File

@ -17,7 +17,7 @@
#include <emscripten.h>
#include <emscripten/bind.h>
#include "modules/canvaskit/WasmAliases.h"
#include "modules/canvaskit/WasmCommon.h"
#if SK_INCLUDE_MANAGED_SKOTTIE
#include "modules/skottie/include/SkottieProperty.h"
@ -220,7 +220,9 @@ 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" , &ManagedAnimation::setColor)
.function("setColor" , optional_override([](ManagedAnimation& self, const std::string& key, SimpleColor4f c) {
self.setColor(key, c.toSkColor());
}))
.function("setOpacity", &ManagedAnimation::setOpacity)
.function("getMarkers", &ManagedAnimation::getMarkers)
.function("getColorProps" , &ManagedAnimation::getColorProps)

View File

@ -14,6 +14,14 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
container.innerHTML = '';
});
function expectColorCloseTo(a, b) {
expect(a.length).toEqual(4);
expect(b.length).toEqual(4);
for (let i=0; i<4; i++){
expect(a[i]).toBeCloseTo(b[i], 3);
}
}
describe('color strings', function() {
function hex(s) {
return parseInt(s, 16);
@ -22,13 +30,13 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
it('parses hex color strings', function(done) {
LoadCanvasKit.then(catchException(done, () => {
const parseColor = CanvasKit.parseColorString;
expect(parseColor('#FED')).toEqual(
expectColorCloseTo(parseColor('#FED'),
CanvasKit.Color(hex('FF'), hex('EE'), hex('DD'), 1));
expect(parseColor('#FEDC')).toEqual(
expectColorCloseTo(parseColor('#FEDC'),
CanvasKit.Color(hex('FF'), hex('EE'), hex('DD'), hex('CC')/255));
expect(parseColor('#fed')).toEqual(
expectColorCloseTo(parseColor('#fed'),
CanvasKit.Color(hex('FF'), hex('EE'), hex('DD'), 1));
expect(parseColor('#fedc')).toEqual(
expectColorCloseTo(parseColor('#fedc'),
CanvasKit.Color(hex('FF'), hex('EE'), hex('DD'), hex('CC')/255));
done();
}));
@ -36,19 +44,19 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
it('parses rgba color strings', function(done) {
LoadCanvasKit.then(catchException(done, () => {
const parseColor = CanvasKit.parseColorString;
expect(parseColor('rgba(117, 33, 64, 0.75)')).toEqual(
expectColorCloseTo(parseColor('rgba(117, 33, 64, 0.75)'),
CanvasKit.Color(117, 33, 64, 0.75));
expect(parseColor('rgb(117, 33, 64, 0.75)')).toEqual(
expectColorCloseTo(parseColor('rgb(117, 33, 64, 0.75)'),
CanvasKit.Color(117, 33, 64, 0.75));
expect(parseColor('rgba(117,33,64)')).toEqual(
expectColorCloseTo(parseColor('rgba(117,33,64)'),
CanvasKit.Color(117, 33, 64, 1.0));
expect(parseColor('rgb(117,33, 64)')).toEqual(
expectColorCloseTo(parseColor('rgb(117,33, 64)'),
CanvasKit.Color(117, 33, 64, 1.0));
expect(parseColor('rgb(117,33, 64, 32%)')).toEqual(
expectColorCloseTo(parseColor('rgb(117,33, 64, 32%)'),
CanvasKit.Color(117, 33, 64, 0.32));
expect(parseColor('rgb(117,33, 64, 0.001)')).toEqual(
expectColorCloseTo(parseColor('rgb(117,33, 64, 0.001)'),
CanvasKit.Color(117, 33, 64, 0.001));
expect(parseColor('rgb(117,33,64,0)')).toEqual(
expectColorCloseTo(parseColor('rgb(117,33,64,0)'),
CanvasKit.Color(117, 33, 64, 0.0));
done();
}));
@ -58,11 +66,11 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
// Keep this one as the _testing version, because we don't include the large
// color map by default.
const parseColor = CanvasKit._testing.parseColor;
expect(parseColor('grey')).toEqual(
expectColorCloseTo(parseColor('grey'),
CanvasKit.Color(128, 128, 128, 1.0));
expect(parseColor('blanchedalmond')).toEqual(
expectColorCloseTo(parseColor('blanchedalmond'),
CanvasKit.Color(255, 235, 205, 1.0));
expect(parseColor('transparent')).toEqual(
expectColorCloseTo(parseColor('transparent'),
CanvasKit.Color(0, 0, 0, 0));
done();
}));
@ -75,7 +83,7 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
expect(colorToString(CanvasKit.Color(102, 51, 153, 1.0))).toEqual('#663399');
expect(colorToString(CanvasKit.Color(255, 235, 205, 0.5))).toEqual(
'rgba(255, 235, 205, 0.50196078)');
'rgba(255, 235, 205, 0.50000000)');
done();
}));
@ -111,7 +119,7 @@ describe('CanvasKit\'s Canvas 2d Behavior', function() {
for (let tc of testCases) {
// Print out the test case if the two don't match.
expect(multiplyByAlpha(tc.inColor, tc.inAlpha))
.toBe(tc.outColor, JSON.stringify(tc));
.toEqual(tc.outColor, JSON.stringify(tc));
}
done();

View File

@ -47,6 +47,15 @@ describe('Core canvas behavior', function() {
}));
});
function uIntColorToCanvasKitColor(c) {
return CanvasKit.Color(
(c >> 16) & 0xFF,
(c >> 8) & 0xFF,
(c >> 0) & 0xFF,
((c >> 24) & 0xFF) / 255
);
}
it('can compute tonal colors', function(done) {
LoadCanvasKit.then(catchException(done, () => {
const input = {
@ -54,14 +63,12 @@ describe('Core canvas behavior', function() {
spot: CanvasKit.RED,
};
const out = CanvasKit.computeTonalColors(input);
expect(out.ambient).toEqual(CanvasKit.Color(0,0,0,1));
const [r,g,b,a] = CanvasKit.getColorComponents(out.spot);
expect(r).toEqual(44);
expect(g).toEqual(0);
expect(b).toEqual(0);
expect(a).toBeCloseTo(0.969, 2);
expect(new Float32Array(out.ambient)).toEqual(CanvasKit.BLACK);
const expectedSpot = [0.173, 0, 0, 0.969];
expect(out.spot[0]).toBeCloseTo(expectedSpot[0], 3);
expect(out.spot[1]).toBeCloseTo(expectedSpot[1], 3);
expect(out.spot[2]).toBeCloseTo(expectedSpot[2], 3);
expect(out.spot[3]).toBeCloseTo(expectedSpot[3], 3);
done();
}));
});
@ -731,8 +738,8 @@ describe('Core canvas behavior', function() {
it('exports consts correctly', function(done) {
LoadCanvasKit.then(catchException(done, () => {
expect(CanvasKit.TRANSPARENT).toEqual(0);
expect(CanvasKit.RED).toEqual(4294901760);
expect(CanvasKit.TRANSPARENT).toEqual(Float32Array.of(0, 0, 0, 0));
expect(CanvasKit.RED).toEqual(Float32Array.of(1, 0, 0, 1));
expect(CanvasKit.QUAD_VERB).toEqual(2);
expect(CanvasKit.CONIC_VERB).toEqual(3);
@ -744,4 +751,15 @@ describe('Core canvas behavior', function() {
}));
});
it('can set and get a 4f color on a paint', function(done) {
LoadCanvasKit.then(catchException(done, () => {
const paint = new CanvasKit.SkPaint();
paint.setColor(CanvasKit.Color4f(3.3, 2.2, 1.1, 0.5));
expect(paint.getColor()).toEqual(Float32Array.of(3.3, 2.2, 1.1, 0.5));
done();
}));
});
});