Revert "Wide color gamut support and working example."

breaks CPU-backed canvaskit build

This reverts commit 3d52abc846.

Reason for revert: <INSERT REASONING HERE>

Original change's description:
> Wide color gamut support and working example.
> 
> Color space arguments accepted at surface creation, paint, gradient, and other call sites.
> Works correctly only when chrome happens to be rendering itself in the same color space
> the canvaskit user has chosen, there's not yet end to end color management of
> canvases supported in browsers.
> 
> readPixels not yet working due to possible chrome bug.
> 
> Change-Id: I3dea5b16c60a3871cd2a54f86716f4a438a90135
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/289733
> Commit-Queue: Nathaniel Nifong <nifong@google.com>
> Reviewed-by: Kevin Lubick <kjlubick@google.com>

TBR=kjlubick@google.com,brianosman@google.com,nifong@google.com

Change-Id: I2e03155c2512eec6730ecccda19df78174146008
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291339
Reviewed-by: Nathaniel Nifong <nifong@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Nathaniel Nifong <nifong@google.com>
This commit is contained in:
Nathaniel Nifong 2020-05-21 20:02:35 +00:00 committed by Skia Commit-Bot
parent 3d52abc846
commit 67e21a1925
10 changed files with 147 additions and 286 deletions

View File

@ -6,31 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Support for wide-gamut color spaces DisplayP3 and AdobeRGB. However, correct representation on a
WCG monitor requires that the browser is rendering everything to the DisplayP3 or AdobeRGB
profile, since there is not yet any way to indicate to the browser that a canvas element has a
non-sRGB color space. See color support example in extra.html. Only supported for WebGL2 backed
surfaces.
- Added `SkSurface.reportBackendType` which returns either 'CPU' or 'GPU'.
- Added `SkSurface.imageInfo` which returns an ImageInfo object describing the size and color
properties of the surface. colorSpace is added to ImageInfo everywhere it is used.
### Changed
- We now compile/ship with Emscripten v1.39.16.
- `CanvasKit.MakeCanvasSurface` accepts a new enum specifying one of the three color space and
pixel format combinations supported by CanvasKit.
- all `_Make*Shader` functions now accept a color space argument at the end. leaving it off or
passing null makes it behave as it did before, defaulting to sRGB
- `SkPaint.setColor` accepts a new color space argument, defaulting to sRGB.
- We now compile/ship with Emscripten v1.39.16.
### Breaking
- `CanvasKitInit(...)` now directly returns a Promise. As such, `CanvasKitInit(...).ready()`
has been removed.
- `CanvasKit.MakeCanvasSurface` no longer accepts width/height arguments to override those on
the canvas element. Use the canvas element's width/height attributes to dictate the size of
the drawing area, and use CSS width/height to set the size it will appear on the page
(it is rescaled after drawing when css sizing applies).
## [0.15.0] - 2020-05-14

View File

@ -1125,7 +1125,6 @@
height: 50,
alphaType: CanvasKit.AlphaType.Premul,
colorType: CanvasKit.ColorType.RGBA_8888,
colorSpace: CanvasKit.SkColorSpace.SRGB,
});
if (!subSurface) {

View File

@ -35,9 +35,8 @@
<h2> 3D perspective transformations </h2>
<canvas id=camera3d width=500 height=500></canvas>
<h2> Support for extended color spaces </h2>
<a href="chrome://flags/#force-color-profile">Force P3 profile</a>
<canvas id=colorsupport width=300 height=300></canvas>
<h2> Use of offscreen surfaces </h2>
<canvas id=surfaces width=500 height=500></canvas>
<script type="text/javascript" src="/node_modules/canvaskit/bin/canvaskit.js"></script>
@ -80,7 +79,7 @@
SkpExample(CanvasKit, skpData);
ColorSupport(CanvasKit);
SurfaceAPI1(CanvasKit);
});
fetch(cdn + 'lego_loader.json').then((resp) => {
@ -241,6 +240,76 @@ const curves = {
"Bindings": []
};
function SurfaceAPI1(CanvasKit) {
const surface = CanvasKit.MakeCanvasSurface('surfaces');
if (!surface) {
console.error('Could not make surface');
return;
}
console.log('SurfaceAPI1 top surface type = '+surface.reportBackendType() );
const context = CanvasKit.currentContext();
const canvas = surface.getCanvas();
//create a subsurface as a temporary workspace.
const subSurface = surface.makeSurface({
width: 50,
height: 50,
alphaType: CanvasKit.AlphaType.Premul,
colorType: CanvasKit.ColorType.RGBA_8888,
});
if (!subSurface) {
console.error('Could not make subsurface');
return;
}
console.log('SurfaceAPI1 subSurface type = '+subSurface.reportBackendType() );
// draw a small "scene"
const paint = new CanvasKit.SkPaint();
paint.setColor(CanvasKit.Color(139, 228, 135, 0.95)); // greenish
paint.setStyle(CanvasKit.PaintStyle.Fill);
paint.setAntiAlias(true);
const subCanvas = subSurface.getCanvas();
subCanvas.clear(CanvasKit.BLACK);
subCanvas.drawRect(CanvasKit.LTRBRect(5, 15, 45, 40), paint);
paint.setColor(CanvasKit.Color(214, 93, 244)); // purplish
for (let i = 0; i < 10; i++) {
const x = Math.random() * 50;
const y = Math.random() * 50;
subCanvas.drawOval(CanvasKit.XYWHRect(x, y, 6, 6), paint);
}
// Snap it off as an SkImage - this image will be in the form the
// parent surface prefers (e.g. Texture for GPU / Raster for CPU).
const img = subSurface.makeImageSnapshot();
// clean up the temporary surface
subSurface.delete();
paint.delete();
// Make it repeat a bunch with a shader
const pattern = img.makeShader(CanvasKit.TileMode.Repeat, CanvasKit.TileMode.Mirror);
const patternPaint = new CanvasKit.SkPaint();
patternPaint.setShader(pattern);
let i = 0;
function drawFrame() {
i++;
CanvasKit.setCurrentContext(context);
canvas.clear(CanvasKit.WHITE);
canvas.drawOval(CanvasKit.LTRBRect(i % 60, i % 60, 300 - (i% 60), 300 - (i % 60)), patternPaint);
surface.flush();
window.requestAnimationFrame(drawFrame);
}
window.requestAnimationFrame(drawFrame);
}
function ParagraphAPI1(CanvasKit, fontData) {
if (!CanvasKit || !fontData) {
return;
@ -821,30 +890,4 @@ const curves = {
surface.requestAnimationFrame(drawFrame);
}
function ColorSupport(CanvasKit) {
const surface = CanvasKit.MakeCanvasSurface('colorsupport', CanvasKit.SkColorSpace.ADOBE_RGB);
if (!surface) {
console.error('Could not make surface');
return;
}
const canvas = surface.getCanvas();
// If the surface is correctly initialized with a higher bit depth color type,
// And chrome is compositing it into a buffer with the P3 color space,
// then the inner round rect should be distinct and less saturated than the full red background.
// Even if the monitor it is viewed on cannot accurately represent that color space.
let red = CanvasKit.Color4f(1, 0, 0, 1);
let paint = new CanvasKit.SkPaint();
paint.setColor(red, CanvasKit.SkColorSpace.ADOBE_RGB);
canvas.drawPaint(paint);
paint.setColor(red, CanvasKit.SkColorSpace.DISPLAY_P3);
canvas.drawRoundRect(CanvasKit.LTRBRect(50, 50, 250, 250), 30, 30, paint);
paint.setColor(red, CanvasKit.SkColorSpace.SRGB);
canvas.drawRoundRect(CanvasKit.LTRBRect(100, 100, 200, 200), 30, 30, paint);
surface.flush();
surface.delete();
}
</script>

View File

@ -12,7 +12,6 @@
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkEncodedImageFormat.h"
@ -110,29 +109,13 @@ struct SimpleImageInfo {
int height;
SkColorType colorType;
SkAlphaType alphaType;
sk_sp<SkColorSpace> colorSpace;
// TODO color spaces?
};
SkImageInfo toSkImageInfo(const SimpleImageInfo& sii) {
return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType, sii.colorSpace);
return SkImageInfo::Make(sii.width, sii.height, sii.colorType, sii.alphaType);
}
// Set the pixel format based on the colortype.
// These degrees of freedom are removed from canvaskit only to keep the interface simpler.
struct ColorSettings {
ColorSettings(sk_sp<SkColorSpace> colorSpace) {
if (colorSpace == nullptr || colorSpace->isSRGB()) {
colorType = kRGBA_8888_SkColorType;
pixFormat = GL_RGBA8;
} else {
colorType = kRGBA_F16_SkColorType;
pixFormat = GL_RGBA16F;
}
};
SkColorType colorType;
GrGLenum pixFormat;
};
#ifdef SK_GL
sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
{
@ -148,27 +131,31 @@ sk_sp<GrContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
return grContext;
}
sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height,
sk_sp<SkColorSpace> colorSpace) {
sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrContext> grContext, int width, int height) {
glClearColor(0, 0, 0, 0);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Wrap the frame buffer object attached to the screen in a Skia render
// target so Skia can render to it
GrGLint buffer;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);
GrGLFramebufferInfo info;
info.fFBOID = (GrGLuint) buffer;
SkColorType colorType;
GrGLint stencil;
glGetIntegerv(GL_STENCIL_BITS, &stencil);
const auto colorSettings = ColorSettings(colorSpace);
info.fFormat = colorSettings.pixFormat;
info.fFormat = GL_RGBA8;
colorType = kRGBA_8888_SkColorType;
GrBackendRenderTarget target(width, height, 0, stencil, info);
sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,
kBottomLeft_GrSurfaceOrigin, colorSettings.colorType, colorSpace, nullptr));
kBottomLeft_GrSurfaceOrigin,
colorType, nullptr, nullptr));
return surface;
}
@ -771,17 +758,16 @@ EMSCRIPTEN_BINDINGS(Skia) {
return SkImage::MakeRasterData(info, pixelData, rowBytes);
}), allow_raw_pointers());
function("_MakeLinearGradientShader", optional_override([](SkPoint start, SkPoint end,
uintptr_t /* SkColor4f* */ cPtr,
uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
uintptr_t /* SkScalar* */ mPtr,
sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
SkPoint points[] = { start, end };
// See comment above for uintptr_t explanation
const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
return SkGradientShader::MakeLinear(points, colors, colorSpace, 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, &localMatrix);
}), allow_raw_pointers());
#ifdef SK_SERIALIZE_SKP
@ -795,48 +781,42 @@ EMSCRIPTEN_BINDINGS(Skia) {
}), allow_raw_pointers());
#endif
function("_MakeRadialGradientShader", optional_override([](SkPoint center, SkScalar radius,
uintptr_t /* SkColor4f* */ cPtr,
uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
uintptr_t /* SkScalar* */ mPtr,
sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
return SkGradientShader::MakeRadial(center, radius, colors, colorSpace, 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 /* SkColor4f* */ cPtr,
uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode,
SkScalar startAngle, SkScalar endAngle,
uint32_t flags,
uintptr_t /* SkScalar* */ mPtr,
sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor4f* colors = reinterpret_cast<const SkColor4f*>(cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
return SkGradientShader::MakeSweep(cx, cy, colors, colorSpace, positions, count,
return SkGradientShader::MakeSweep(cx, cy, colors, SkColorSpace::MakeSRGB(), positions, count,
mode, startAngle, endAngle, flags,
&localMatrix);
}), allow_raw_pointers());
function("_MakeTwoPointConicalGradientShader", optional_override([](
SkPoint start, SkScalar startRadius,
SkPoint end, SkScalar endRadius,
uintptr_t /* SkColor4f* */ cPtr,
uintptr_t /* SkScalar* */ pPtr,
uintptr_t /* SkColor4f* */ cPtr, uintptr_t /* SkScalar* */ pPtr,
int count, SkTileMode mode, uint32_t flags,
uintptr_t /* SkScalar* */ mPtr,
sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
// See comment above for uintptr_t explanation
const SkColor4f* colors = reinterpret_cast<const SkColor4f*> (cPtr);
const SkScalar* positions = reinterpret_cast<const SkScalar*>(pPtr);
OptionalMatrix localMatrix(mPtr);
return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius,
colors, colorSpace, positions, count, mode,
colors, SkColorSpace::MakeSRGB(), positions, count, mode,
flags, &localMatrix);
}), allow_raw_pointers());
@ -1277,9 +1257,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("setAntiAlias", &SkPaint::setAntiAlias)
.function("setAlphaf", &SkPaint::setAlphaf)
.function("setBlendMode", &SkPaint::setBlendMode)
.function("_setColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr,
sk_sp<SkColorSpace> colorSpace) {
self.setColor(ptrToSkColor4f(cPtr), colorSpace.get());
.function("_setColor", optional_override([](SkPaint& self, uintptr_t /* float* */ cPtr) {
self.setColor(ptrToSkColor4f(cPtr));
}))
.function("setColorFilter", &SkPaint::setColorFilter)
.function("setFilterQuality", &SkPaint::setFilterQuality)
@ -1293,21 +1272,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
.function("setStrokeWidth", &SkPaint::setStrokeWidth)
.function("setStyle", &SkPaint::setStyle);
class_<SkColorSpace>("SkColorSpace")
.smart_ptr<sk_sp<SkColorSpace>>("sk_sp<SkColorSpace>")
.class_function("Equals", optional_override([](sk_sp<SkColorSpace> a, sk_sp<SkColorSpace> b)->bool {
return SkColorSpace::Equals(a.get(), b.get());
}))
// These are private because they are to be called once in interface.js to
// avoid clients having to delete the returned objects.
.class_function("_MakeSRGB", &SkColorSpace::MakeSRGB)
.class_function("_MakeDisplayP3", optional_override([]()->sk_sp<SkColorSpace> {
return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDisplayP3);
}))
.class_function("_MakeAdobeRGB", optional_override([]()->sk_sp<SkColorSpace> {
return SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
}));
class_<SkPathEffect>("SkPathEffect")
.smart_ptr<sk_sp<SkPathEffect>>("sk_sp<SkPathEffect>")
.class_function("MakeCorner", &SkCornerPathEffect::Make)
@ -1441,8 +1405,8 @@ EMSCRIPTEN_BINDINGS(Skia) {
.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([](uintptr_t /* float* */ cPtr, sk_sp<SkColorSpace> colorSpace)->sk_sp<SkShader> {
return SkShaders::Color(ptrToSkColor4f(cPtr), colorSpace);
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));
@ -1493,10 +1457,6 @@ EMSCRIPTEN_BINDINGS(Skia) {
.smart_ptr<sk_sp<SkSurface>>("sk_sp<SkSurface>")
.function("_flush", select_overload<void()>(&SkSurface::flushAndSubmit))
.function("getCanvas", &SkSurface::getCanvas, allow_raw_pointers())
.function("imageInfo", optional_override([](SkSurface& self)->SimpleImageInfo {
const auto& ii = self.imageInfo();
return {ii.width(), ii.height(), ii.colorType(), ii.alphaType(), ii.refColorSpace()};
}))
.function("height", &SkSurface::height)
.function("makeImageSnapshot", select_overload<sk_sp<SkImage>()>(&SkSurface::makeImageSnapshot))
.function("makeImageSnapshot", select_overload<sk_sp<SkImage>(const SkIRect& bounds)>(&SkSurface::makeImageSnapshot))
@ -1694,6 +1654,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
.value("TrianglesStrip", SkVertices::VertexMode::kTriangleStrip_VertexMode)
.value("TriangleFan", SkVertices::VertexMode::kTriangleFan_VertexMode);
// A value object is much simpler than a class - it is returned as a JS
// object and does not require delete().
// https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#value-types
@ -1729,11 +1690,10 @@ EMSCRIPTEN_BINDINGS(Skia) {
.field("fBottom", &SkIRect::fBottom);
value_object<SimpleImageInfo>("SkImageInfo")
.field("width", &SimpleImageInfo::width)
.field("height", &SimpleImageInfo::height)
.field("colorType", &SimpleImageInfo::colorType)
.field("alphaType", &SimpleImageInfo::alphaType)
.field("colorSpace", &SimpleImageInfo::colorSpace);
.field("width", &SimpleImageInfo::width)
.field("height", &SimpleImageInfo::height)
.field("colorType", &SimpleImageInfo::colorType)
.field("alphaType", &SimpleImageInfo::alphaType);
// SkPoints can be represented by [x, y]
value_array<SkPoint>("SkPoint")

View File

@ -26,10 +26,6 @@
CanvasKit.MakeCanvasSurface = CanvasKit.MakeSWCanvasSurface;
}
// Note that color spaces are currently not supported in CPU surfaces. due to the limitation
// canvas.getContext('2d').putImageData imposes a limitatin of using an RGBA_8888 color type.
// TODO(nifong): support WGC color spaces while still using an RGBA_8888 color type when
// on a cpu backend.
CanvasKit.MakeSurface = function(width, height) {
/* @dict */
var imageInfo = {
@ -39,7 +35,6 @@
// Since we are sending these pixels directly into the HTML canvas,
// (and those pixels are un-premultiplied, i.e. straight r,g,b,a)
'alphaType': CanvasKit.AlphaType.Unpremul,
'colorSpace': CanvasKit.SkColorSpace.SRGB,
}
var pixelLen = width * height * 4; // it's 8888, so 4 bytes per pixel
// Allocate the buffer of pixels to be drawn into.

View File

@ -259,17 +259,6 @@ var CanvasKit = {
scaled: function() {},
},
SkColorSpace: {
Equals: function() {},
SRGB: {},
DISPLAY_P3: {},
ADOBE_RGB: {},
// private API (from C++ bindings)
_MakeSRGB: function() {},
_MakeDisplayP3: function() {},
_MakeAdobeRGB: function() {},
},
SkContourMeasureIter: {
next: function() {},
},
@ -531,7 +520,6 @@ var CanvasKit = {
// public API (from C++ bindings)
/** @return {CanvasKit.SkCanvas} */
getCanvas: function() {},
imageInfo: function() {},
/** @return {CanvasKit.SkImage} */
makeImageSnapshot: function() {},
makeSurface: function() {},

View File

@ -41,22 +41,19 @@
return CanvasKit.currentContext() || 0;
};
// idOrElement can be of types:
// arg can be of types:
// - String - in which case it is interpreted as an id of a
// canvas element.
// - HTMLCanvasElement - in which the provided canvas element will
// be used directly.
// colorSpace - sk_sp<SkColorSpace> - one of the supported color spaces:
// CanvasKit.SkColorSpace.SRGB
// CanvasKit.SkColorSpace.DISPLAY_P3
// CanvasKit.SkColorSpace.ADOBE_RGB
CanvasKit.MakeWebGLCanvasSurface = function(idOrElement, colorSpace) {
colorSpace = colorSpace || null;
var canvas = idOrElement;
// Width and height can be provided to override those on the canvas
// element, or specify a height for when a context is provided.
CanvasKit.MakeWebGLCanvasSurface = function(arg, width, height) {
var canvas = arg;
if (canvas.tagName !== 'CANVAS') {
canvas = document.getElementById(idOrElement);
canvas = document.getElementById(arg);
if (!canvas) {
throw 'Canvas with id ' + idOrElement + ' was not found';
throw 'Canvas with id ' + arg + ' was not found';
}
}
@ -67,6 +64,10 @@
throw 'failed to create webgl context: err ' + ctx;
}
if (!canvas && (!width || !height)) {
throw 'height and width must be provided with context';
}
var grcontext = this.MakeGrContext(ctx);
if (grcontext) {
@ -75,10 +76,12 @@
grcontext.setResourceCacheLimitBytes(RESOURCE_CACHE_BYTES);
}
// Note that canvas.width/height here is used because it gives the size of the buffer we're
// rendering into. This may not be the same size the element is displayed on the page, which
// constrolled by css, and available in canvas.clientWidth/height.
var surface = this.MakeOnScreenGLSurface(grcontext, canvas.width, canvas.height, colorSpace);
// Maybe better to use clientWidth/height. See:
// https://webglfundamentals.org/webgl/lessons/webgl-anti-patterns.html
var surface = this.MakeOnScreenGLSurface(grcontext,
width || canvas.width,
height || canvas.height);
if (!surface) {
SkDebug('falling back from GPU implementation to a SW based one');
// we need to throw away the old canvas (which was locked to

View File

@ -848,8 +848,7 @@ function CanvasRenderingContext2D(skcanvas) {
}
var img = CanvasKit.MakeImage(imageData.data, imageData.width, imageData.height,
CanvasKit.AlphaType.Unpremul,
CanvasKit.ColorType.RGBA_8888,
CanvasKit.SkColorSpace.SRGB);
CanvasKit.ColorType.RGBA_8888);
var src = CanvasKit.XYWHRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
var dst = CanvasKit.XYWHRect(x+dirtyX, y+dirtyY, dirtyWidth, dirtyHeight);
var inverted = CanvasKit.SkMatrix.invert(this._currentTransform);

View File

@ -8,12 +8,6 @@
CanvasKit.onRuntimeInitialized = function() {
// All calls to 'this' need to go in externs.js so closure doesn't minify them away.
// Create single copies of all three supported color spaces
// These are sk_sp<SkColorSpace>
CanvasKit.SkColorSpace.SRGB = CanvasKit.SkColorSpace._MakeSRGB();
CanvasKit.SkColorSpace.DISPLAY_P3 = CanvasKit.SkColorSpace._MakeDisplayP3();
CanvasKit.SkColorSpace.ADOBE_RGB = CanvasKit.SkColorSpace._MakeAdobeRGB();
// Add some helpers for matrices. This is ported from SkMatrix.cpp
// to save complexity and overhead of going back and forth between
// C++ and JS layers.
@ -1013,16 +1007,11 @@ CanvasKit.onRuntimeInitialized = function() {
// returns Uint8Array
CanvasKit.SkCanvas.prototype.readPixels = function(x, y, w, h, alphaType,
colorType, colorSpace, dstRowBytes) {
colorType, dstRowBytes) {
// supply defaults (which are compatible with HTMLCanvas's getImageData)
alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
colorType = colorType || CanvasKit.ColorType.RGBA_8888;
colorSpace = colorSpace || CanvasKit.SkColorSpace.SRGB;
var pixBytes = 4;
if (colorType === CanvasKit.ColorType.RGBA_F16) {
pixBytes = 8;
}
dstRowBytes = dstRowBytes || (pixBytes * w);
dstRowBytes = dstRowBytes || (4 * w);
var len = h * dstRowBytes
var pptr = CanvasKit._malloc(len);
@ -1031,7 +1020,6 @@ CanvasKit.onRuntimeInitialized = function() {
'height': h,
'colorType': colorType,
'alphaType': alphaType,
'colorSpace': colorSpace,
}, pptr, dstRowBytes, x, y);
if (!ok) {
CanvasKit._free(pptr);
@ -1048,7 +1036,7 @@ CanvasKit.onRuntimeInitialized = function() {
// pixels is a TypedArray. No matter the input size, it will be treated as
// a Uint8Array (essentially, a byte array).
CanvasKit.SkCanvas.prototype.writePixels = function(pixels, srcWidth, srcHeight,
destX, destY, alphaType, colorType, colorSpace) {
destX, destY, alphaType, colorType) {
if (pixels.byteLength % (srcWidth * srcHeight)) {
throw 'pixels length must be a multiple of the srcWidth * srcHeight';
}
@ -1056,7 +1044,6 @@ CanvasKit.onRuntimeInitialized = function() {
// supply defaults (which are compatible with HTMLCanvas's putImageData)
alphaType = alphaType || CanvasKit.AlphaType.Unpremul;
colorType = colorType || CanvasKit.ColorType.RGBA_8888;
colorSpace = colorSpace || CanvasKit.SkColorSpace.SRGB;
var srcRowBytes = bytesPerPixel * srcWidth;
var pptr = CanvasKit._malloc(pixels.byteLength);
@ -1067,7 +1054,6 @@ CanvasKit.onRuntimeInitialized = function() {
'height': srcHeight,
'colorType': colorType,
'alphaType': alphaType,
'colorSpace': colorSpace,
}, pptr, srcRowBytes, destX, destY);
CanvasKit._free(pptr);
@ -1107,11 +1093,9 @@ CanvasKit.onRuntimeInitialized = function() {
return copyColorFromWasm(cPtr);
}
CanvasKit.SkPaint.prototype.setColor = function(color4f, colorSpace) {
colorSpace = colorSpace || null; // null will be replaced with sRGB in the C++ method.
// emscripten wouldn't bind undefined to the sk_sp<SkColorSpace> expected here.
CanvasKit.SkPaint.prototype.setColor = function(color4f) {
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
this._setColor(cPtr, colorSpace);
this._setColor(cPtr);
CanvasKit._free(cPtr);
}
@ -1176,23 +1160,21 @@ CanvasKit.onRuntimeInitialized = function() {
return dpe;
}
CanvasKit.SkShader.Color = function(color4f, colorSpace) {
colorSpace = colorSpace || null
CanvasKit.SkShader.Color = function(color4f) {
var cPtr = copy1dArray(color4f, CanvasKit.HEAPF32);
var result = CanvasKit.SkShader._Color(cPtr, colorSpace);
var result = CanvasKit.SkShader._Color(cPtr);
CanvasKit._free(cPtr);
return result;
}
CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags, colorSpace) {
colorSpace = colorSpace || null
CanvasKit.SkShader.MakeLinearGradient = function(start, end, colors, pos, mode, localMatrix, flags) {
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
var lgs = CanvasKit._MakeLinearGradientShader(start, end, colorPtr, posPtr,
colors.length, mode, flags, localMatrixPtr, colorSpace);
colors.length, mode, flags, localMatrixPtr);
CanvasKit._free(localMatrixPtr);
CanvasKit._free(colorPtr);
@ -1200,15 +1182,14 @@ CanvasKit.onRuntimeInitialized = function() {
return lgs;
}
CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags, colorSpace) {
colorSpace = colorSpace || null
CanvasKit.SkShader.MakeRadialGradient = function(center, radius, colors, pos, mode, localMatrix, flags) {
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
var localMatrixPtr = copy3x3MatrixToWasm(localMatrix);
var rgs = CanvasKit._MakeRadialGradientShader(center, radius, colorPtr, posPtr,
colors.length, mode, flags, localMatrixPtr, colorSpace);
colors.length, mode, flags, localMatrixPtr);
CanvasKit._free(localMatrixPtr);
CanvasKit._free(colorPtr);
@ -1216,8 +1197,7 @@ CanvasKit.onRuntimeInitialized = function() {
return rgs;
}
CanvasKit.SkShader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle, colorSpace) {
colorSpace = colorSpace || null
CanvasKit.SkShader.MakeSweepGradient = function(cx, cy, colors, pos, mode, localMatrix, flags, startAngle, endAngle) {
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
@ -1228,7 +1208,7 @@ CanvasKit.onRuntimeInitialized = function() {
var sgs = CanvasKit._MakeSweepGradientShader(cx, cy, colorPtr, posPtr,
colors.length, mode,
startAngle, endAngle, flags,
localMatrixPtr, colorSpace);
localMatrixPtr);
CanvasKit._free(localMatrixPtr);
CanvasKit._free(colorPtr);
@ -1237,8 +1217,7 @@ CanvasKit.onRuntimeInitialized = function() {
}
CanvasKit.SkShader.MakeTwoPointConicalGradient = function(start, startRadius, end, endRadius,
colors, pos, mode, localMatrix, flags, colorSpace) {
colorSpace = colorSpace || null
colors, pos, mode, localMatrix, flags) {
var colorPtr = copy2dArray(colors, CanvasKit.HEAPF32);
var posPtr = copy1dArray(pos, CanvasKit.HEAPF32);
flags = flags || 0;
@ -1246,7 +1225,7 @@ CanvasKit.onRuntimeInitialized = function() {
var rgs = CanvasKit._MakeTwoPointConicalGradientShader(
start, startRadius, end, endRadius,
colorPtr, posPtr, colors.length, mode, flags, localMatrixPtr, colorSpace);
colorPtr, posPtr, colors.length, mode, flags, localMatrixPtr);
CanvasKit._free(localMatrixPtr);
CanvasKit._free(colorPtr);
@ -1356,14 +1335,13 @@ CanvasKit.MakeImageFromEncoded = function(data) {
// pixels must be a Uint8Array with bytes representing the pixel values
// (e.g. each set of 4 bytes could represent RGBA values for a single pixel).
CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType, colorSpace) {
CanvasKit.MakeImage = function(pixels, width, height, alphaType, colorType) {
var bytesPerPixel = pixels.length / (width * height);
var info = {
'width': width,
'height': height,
'alphaType': alphaType,
'colorType': colorType,
'colorSpace': colorSpace,
};
var pptr = copy1dArray(pixels, CanvasKit.HEAPU8);
// No need to _free pptr, Image takes it with SkData::MakeFromMalloc

View File

@ -116,7 +116,6 @@ describe('Core canvas behavior', () => {
const imageInfo = {
alphaType: CanvasKit.AlphaType.Unpremul,
colorType: CanvasKit.ColorType.RGBA_8888,
colorSpace: CanvasKit.SkColorSpace.SRGB,
width: img.width(),
height: img.height(),
};
@ -173,8 +172,7 @@ describe('Core canvas behavior', () => {
0, 0, 255, 255, // opaque blue
255, 0, 255, 100, // transparent purple
]);
const img = CanvasKit.MakeImage(pixels, 1, 4, CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_8888,
CanvasKit.SkColorSpace.SRGB);
const img = CanvasKit.MakeImage(pixels, 1, 4, CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_8888);
canvas.drawImage(img, 1, 1, paint);
img.delete();
});
@ -307,8 +305,7 @@ describe('Core canvas behavior', () => {
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.skewed(0.5, 0, 100, 100),
null, // color space
CanvasKit.SkMatrix.skewed(0.5, 0, 100, 100)
);
paint.setShader(rgsSkew);
r = CanvasKit.LTRBRect(0, 100, 100, 200);
@ -321,8 +318,7 @@ describe('Core canvas behavior', () => {
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.skewed(0.5, 0, 100, 100),
1, // interpolate colors in premul
null, // color space
1 // interpolate colors in premul
);
paint.setShader(rgsSkewPremul);
r = CanvasKit.LTRBRect(100, 100, 200, 200);
@ -354,8 +350,7 @@ describe('Core canvas behavior', () => {
[10, 110], 60, // end, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
null, // color space
CanvasKit.TileMode.Mirror
);
paint.setShader(cgs);
let r = CanvasKit.LTRBRect(0, 0, 100, 100);
@ -370,7 +365,6 @@ describe('Core canvas behavior', () => {
CanvasKit.TileMode.Mirror,
null, // no local matrix
1, // interpolate colors in premul
null, // color space
);
paint.setShader(cgsPremul);
r = CanvasKit.LTRBRect(100, 0, 200, 100);
@ -383,8 +377,7 @@ describe('Core canvas behavior', () => {
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 0, 100),
null, // color space
CanvasKit.SkMatrix.rotated(Math.PI/4, 0, 100)
);
paint.setShader(cgs45);
r = CanvasKit.LTRBRect(0, 100, 100, 200);
@ -398,8 +391,7 @@ describe('Core canvas behavior', () => {
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 100, 100),
1, // interpolate colors in premul
null, // color space
1 // interpolate colors in premul
);
paint.setShader(cgs45Premul);
r = CanvasKit.LTRBRect(100, 100, 200, 200);
@ -593,83 +585,6 @@ describe('Core canvas behavior', () => {
expect(paint.getColor()).toEqual(Float32Array.of(3.3, 2.2, 1.1, 0.5));
});
describe('ColorSpace Support', () => {
it('Can create an SRGB 8888 surface', () => {
const colorSpace = CanvasKit.SkColorSpace.SRGB;
const surface = CanvasKit.MakeCanvasSurface('test', CanvasKit.SkColorSpace.SRGB);
expect(surface).toBeTruthy('Could not make surface');
let info = surface.imageInfo()
expect(info.alphaType).toEqual(CanvasKit.AlphaType.Unpremul);
expect(info.colorType).toEqual(CanvasKit.ColorType.RGBA_8888);
expect(CanvasKit.SkColorSpace.Equals(info.colorSpace, colorSpace))
.toBeTruthy("Surface not created with correct color space.");
const pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_8888, colorSpace);
expect(pixels).toBeTruthy('Could not read pixels from surface');
});
it('Can create a Display P3 surface', () => {
const colorSpace = CanvasKit.SkColorSpace.DISPLAY_P3;
const surface = CanvasKit.MakeCanvasSurface('test', CanvasKit.SkColorSpace.DISPLAY_P3);
expect(surface).toBeTruthy('Could not make surface');
if (surface.reportBackendType() !== 'GPU') {
console.log('Not expecting color space support in cpu backed suface.');
return;
}
let info = surface.imageInfo()
expect(info.alphaType).toEqual(CanvasKit.AlphaType.Unpremul);
expect(info.colorType).toEqual(CanvasKit.ColorType.RGBA_F16);
expect(CanvasKit.SkColorSpace.Equals(info.colorSpace, colorSpace))
.toBeTruthy("Surface not created with correct color space.");
const pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_F16, colorSpace);
expect(pixels).toBeTruthy('Could not read pixels from surface');
});
it('Can create an Adobe RGB surface', () => {
const colorSpace = CanvasKit.SkColorSpace.ADOBE_RGB;
const surface = CanvasKit.MakeCanvasSurface('test', CanvasKit.SkColorSpace.ADOBE_RGB);
expect(surface).toBeTruthy('Could not make surface');
if (surface.reportBackendType() !== 'GPU') {
console.log('Not expecting color space support in cpu backed suface.');
return;
}
let info = surface.imageInfo()
expect(info.alphaType).toEqual(CanvasKit.AlphaType.Unpremul);
expect(info.colorType).toEqual(CanvasKit.ColorType.RGBA_F16);
expect(CanvasKit.SkColorSpace.Equals(info.colorSpace, colorSpace))
.toBeTruthy("Surface not created with correct color space.");
const pixels = surface.getCanvas().readPixels(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
CanvasKit.AlphaType.Unpremul, CanvasKit.ColorType.RGBA_F16, colorSpace);
expect(pixels).toBeTruthy('Could not read pixels from surface');
});
it('combine draws from several color spaces', () => {
const surface = CanvasKit.MakeCanvasSurface('test', CanvasKit.SkColorSpace.ADOBE_RGB);
expect(surface).toBeTruthy('Could not make surface');
if (surface.reportBackendType() !== 'GPU') {
console.log('Not expecting color space support in cpu backed suface.');
return;
}
const canvas = surface.getCanvas();
let paint = new CanvasKit.SkPaint();
paint.setColor(CanvasKit.RED, CanvasKit.SkColorSpace.ADOBE_RGB);
canvas.drawPaint(paint);
paint.setColor(CanvasKit.RED, CanvasKit.SkColorSpace.DISPLAY_P3); // 93.7 in adobeRGB
canvas.drawRect(CanvasKit.LTRBRect(200, 0, 400, 600), paint);
paint.setColor(CanvasKit.RED, CanvasKit.SkColorSpace.SRGB); // 85.9 in adobeRGB
canvas.drawRect(CanvasKit.LTRBRect(400, 0, 600, 600), paint);
// this test paints three bands of red, each the maximum red that a color space supports.
// They are each represented by skia by some color in the Adobe RGB space of the surface,
// as floats between 0 and 1.
// TODO(nifong) readpixels and verify correctness after f32 readpixels bug is fixed
});
}); // end describe('ColorSpace Support')
describe('DOMMatrix support', () => {
gm('sweep_gradient_dommatrix', (canvas) => {
const paint = new CanvasKit.SkPaint();