skia2/modules/canvaskit/tests/core.spec.js
Nathaniel Nifong b1ebbb19bc Wide color gamut support and working example.
Fixes release-cpu build issue, un-revert cl 289733

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.

Reviewed-on: https://skia-review.googlesource.com/c/skia/+/289733
Commit-Queue: Nathaniel Nifong <nifong@google.com>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Change-Id: I65ce1c643dac57e14b8476f598c96b12b7e040ce
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/291896
2020-05-26 20:13:33 +00:00

726 lines
28 KiB
JavaScript

describe('Core canvas behavior', () => {
let container;
beforeEach(async () => {
await LoadCanvasKit;
container = document.createElement('div');
container.innerHTML = `
<canvas width=600 height=600 id=test></canvas>
<canvas width=600 height=600 id=report></canvas>`;
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
});
gm('picture_test', (canvas) => {
const spr = new CanvasKit.SkPictureRecorder();
const rcanvas = spr.beginRecording(
CanvasKit.LTRBRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT));
const paint = new CanvasKit.SkPaint();
paint.setStrokeWidth(2.0);
paint.setAntiAlias(true);
paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Stroke);
rcanvas.drawRoundRect(CanvasKit.LTRBRect(5, 35, 45, 80), 15, 10, paint);
const font = new CanvasKit.SkFont(null, 20);
rcanvas.drawText('this picture has a round rect', 5, 100, paint, font);
const pic = spr.finishRecordingAsPicture();
spr.delete();
paint.delete();
canvas.drawPicture(pic);
pic.delete();
});
const uIntColorToCanvasKitColor = (c) => {
return CanvasKit.Color(
(c >> 16) & 0xFF,
(c >> 8) & 0xFF,
(c >> 0) & 0xFF,
((c >> 24) & 0xFF) / 255
);
}
it('can compute tonal colors', () => {
const input = {
ambient: CanvasKit.BLUE,
spot: CanvasKit.RED,
};
const out = CanvasKit.computeTonalColors(input);
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);
});
// This helper is used for all the MakeImageFromEncoded tests.
// TODO(kjlubick): rewrite this and callers to use gm
function decodeAndDrawSingleFrameImage(imgName, goldName, done) {
const imgPromise = fetch(imgName)
.then((response) => response.arrayBuffer());
Promise.all([imgPromise, LoadCanvasKit]).then((values) => {
const imgData = values[0];
expect(imgData).toBeTruthy();
catchException(done, () => {
let img = CanvasKit.MakeImageFromEncoded(imgData);
expect(img).toBeTruthy();
const surface = CanvasKit.MakeCanvasSurface('test');
expect(surface).toBeTruthy('Could not make surface');
if (!surface) {
done();
return;
}
const canvas = surface.getCanvas();
let paint = new CanvasKit.SkPaint();
canvas.drawImage(img, 0, 0, paint);
paint.delete();
img.delete();
reportSurface(surface, goldName, done);
})();
});
}
it('can decode and draw a png', (done) => {
decodeAndDrawSingleFrameImage('/assets/mandrill_512.png', 'drawImage_png', done);
});
it('can decode and draw a jpg', (done) => {
decodeAndDrawSingleFrameImage('/assets/mandrill_h1v1.jpg', 'drawImage_jpg', done);
});
it('can decode and draw a (still) gif', (done) => {
decodeAndDrawSingleFrameImage('/assets/flightAnim.gif', 'drawImage_gif', done);
});
it('can decode and draw a still webp', (done) => {
decodeAndDrawSingleFrameImage('/assets/color_wheel.webp', 'drawImage_webp', done);
});
it('can readPixels from an SkImage', (done) => {
const imgPromise = fetch('/assets/mandrill_512.png')
.then((response) => response.arrayBuffer());
Promise.all([imgPromise, LoadCanvasKit]).then((values) => {
const imgData = values[0];
expect(imgData).toBeTruthy();
catchException(done, () => {
let img = CanvasKit.MakeImageFromEncoded(imgData);
expect(img).toBeTruthy();
const imageInfo = {
alphaType: CanvasKit.AlphaType.Unpremul,
colorType: CanvasKit.ColorType.RGBA_8888,
colorSpace: CanvasKit.SkColorSpace.SRGB,
width: img.width(),
height: img.height(),
};
const pixels = img.readPixels(imageInfo, 0, 0);
// We know the image is 512 by 512 pixels in size, each pixel
// requires 4 bytes (R, G, B, A).
expect(pixels.length).toEqual(512 * 512 * 4);
img.delete();
done();
})();
});
});
gm('drawDrawable_animated_gif', (canvas, fetchedByteBuffers) => {
let aImg = CanvasKit.MakeAnimatedImageFromEncoded(fetchedByteBuffers[0]);
expect(aImg).toBeTruthy();
expect(aImg.getRepetitionCount()).toEqual(-1); // infinite loop
expect(aImg.width()).toEqual(320);
expect(aImg.height()).toEqual(240);
expect(aImg.getFrameCount()).toEqual(60);
// TODO(kjlubick): deprecate drawAnimatedImage and have it just snap off
// an SkImage at the desired frame.
canvas.drawAnimatedImage(aImg, 0, 0);
let c = aImg.decodeNextFrame();
expect(c).not.toEqual(-1);
canvas.drawAnimatedImage(aImg, 300, 0);
for(let i = 0; i < 10; i++) {
c = aImg.decodeNextFrame();
expect(c).not.toEqual(-1);
}
canvas.drawAnimatedImage(aImg, 0, 300);
for(let i = 0; i < 10; i++) {
c = aImg.decodeNextFrame();
expect(c).not.toEqual(-1);
}
canvas.drawAnimatedImage(aImg, 300, 300);
aImg.delete();
}, '/assets/flightAnim.gif');
gm('1x4_from_scratch', (canvas) => {
canvas.clear(CanvasKit.WHITE);
const paint = new CanvasKit.SkPaint();
// This creates and draws an SkImage that is 1 pixel wide, 4 pixels tall with
// the colors listed below.
const pixels = Uint8Array.from([
255, 0, 0, 255, // opaque red
0, 255, 0, 255, // opaque green
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);
canvas.drawImage(img, 1, 1, paint);
img.delete();
});
gm('sweep_gradient', (canvas) => {
const paint = new CanvasKit.SkPaint();
const shader = CanvasKit.SkShader.MakeSweepGradient(
100, 100, // X, Y coordinates
[CanvasKit.GREEN, CanvasKit.BLUE],
[0.0, 1.0],
CanvasKit.TileMode.Clamp,
);
expect(shader).toBeTruthy('Could not make shader');
paint.setShader(shader);
canvas.drawPaint(paint);
paint.delete();
shader.delete();
});
// TODO(kjlubick): There's a lot of shared code between the gradient gms
// It would be best to deduplicate that in a nice DAMP way.
// Inspired by https://fiddle.skia.org/c/b29ce50a341510784ac7d5281586d076
gm('linear_gradients', (canvas) => {
canvas.clear(CanvasKit.WHITE);
canvas.scale(2, 2);
const strokePaint = new CanvasKit.SkPaint();
strokePaint.setStyle(CanvasKit.PaintStyle.Stroke);
strokePaint.setColor(CanvasKit.BLACK);
const paint = new CanvasKit.SkPaint();
paint.setStyle(CanvasKit.PaintStyle.Fill);
const transparentGreen = CanvasKit.Color(0, 255, 255, 0);
const lgs = CanvasKit.SkShader.MakeLinearGradient(
[0, 0], [50, 100], // start and stop points
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror
);
paint.setShader(lgs);
let r = CanvasKit.LTRBRect(0, 0, 100, 100);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const lgsPremul = CanvasKit.SkShader.MakeLinearGradient(
[100, 0], [150, 100], // start and stop points
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
null, // no local matrix
1 // interpolate colors in premul
);
paint.setShader(lgsPremul);
r = CanvasKit.LTRBRect(100, 0, 200, 100);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const lgs45 = CanvasKit.SkShader.MakeLinearGradient(
[0, 100], [50, 200], // start and stop points
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 0, 100),
);
paint.setShader(lgs45);
r = CanvasKit.LTRBRect(0, 100, 100, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const lgs45Premul = CanvasKit.SkShader.MakeLinearGradient(
[100, 100], [150, 200], // start and stop points
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 100, 100),
1 // interpolate colors in premul
);
paint.setShader(lgs45Premul);
r = CanvasKit.LTRBRect(100, 100, 200, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
lgs.delete();
lgs45.delete();
lgsPremul.delete();
lgs45Premul.delete();
strokePaint.delete();
paint.delete();
});
gm('radial_gradients', (canvas) => {
canvas.clear(CanvasKit.WHITE);
canvas.scale(2, 2);
const strokePaint = new CanvasKit.SkPaint();
strokePaint.setStyle(CanvasKit.PaintStyle.Stroke);
strokePaint.setColor(CanvasKit.BLACK);
const paint = new CanvasKit.SkPaint();
paint.setStyle(CanvasKit.PaintStyle.Fill);
const transparentGreen = CanvasKit.Color(0, 255, 255, 0);
const rgs = CanvasKit.SkShader.MakeRadialGradient(
[50, 50], 50, // center, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror
);
paint.setShader(rgs);
let r = CanvasKit.LTRBRect(0, 0, 100, 100);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const rgsPremul = CanvasKit.SkShader.MakeRadialGradient(
[150, 50], 50, // center, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
null, // no local matrix
1 // interpolate colors in premul
);
paint.setShader(rgsPremul);
r = CanvasKit.LTRBRect(100, 0, 200, 100);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const rgsSkew = CanvasKit.SkShader.MakeRadialGradient(
[50, 150], 50, // center, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.skewed(0.5, 0, 100, 100),
null, // color space
);
paint.setShader(rgsSkew);
r = CanvasKit.LTRBRect(0, 100, 100, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const rgsSkewPremul = CanvasKit.SkShader.MakeRadialGradient(
[150, 150], 50, // center, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.skewed(0.5, 0, 100, 100),
1, // interpolate colors in premul
null, // color space
);
paint.setShader(rgsSkewPremul);
r = CanvasKit.LTRBRect(100, 100, 200, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
rgs.delete();
rgsPremul.delete();
rgsSkew.delete();
rgsSkewPremul.delete();
strokePaint.delete();
paint.delete();
});
gm('conical_gradients', (canvas) => {
canvas.clear(CanvasKit.WHITE);
canvas.scale(2, 2);
const strokePaint = new CanvasKit.SkPaint();
strokePaint.setStyle(CanvasKit.PaintStyle.Stroke);
strokePaint.setColor(CanvasKit.BLACK);
const paint = new CanvasKit.SkPaint();
paint.setStyle(CanvasKit.PaintStyle.Fill);
paint.setAntiAlias(true);
const transparentGreen = CanvasKit.Color(0, 255, 255, 0);
const cgs = CanvasKit.SkShader.MakeTwoPointConicalGradient(
[80, 10], 15, // start, radius
[10, 110], 60, // end, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
null, // color space
);
paint.setShader(cgs);
let r = CanvasKit.LTRBRect(0, 0, 100, 100);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const cgsPremul = CanvasKit.SkShader.MakeTwoPointConicalGradient(
[180, 10], 15, // start, radius
[110, 110], 60, // end, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
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);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const cgs45 = CanvasKit.SkShader.MakeTwoPointConicalGradient(
[80, 110], 15, // start, radius
[10, 210], 60, // end, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 0, 100),
null, // color space
);
paint.setShader(cgs45);
r = CanvasKit.LTRBRect(0, 100, 100, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
const cgs45Premul = CanvasKit.SkShader.MakeTwoPointConicalGradient(
[180, 110], 15, // start, radius
[110, 210], 60, // end, radius
[transparentGreen, CanvasKit.BLUE, CanvasKit.RED],
[0, 0.65, 1.0],
CanvasKit.TileMode.Mirror,
CanvasKit.SkMatrix.rotated(Math.PI/4, 100, 100),
1, // interpolate colors in premul
null, // color space
);
paint.setShader(cgs45Premul);
r = CanvasKit.LTRBRect(100, 100, 200, 200);
canvas.drawRect(r, paint);
canvas.drawRect(r, strokePaint);
cgs.delete();
cgsPremul.delete();
cgs45.delete();
strokePaint.delete();
paint.delete();
});
gm('blur_filters', (canvas) => {
const pathUL = starPath(CanvasKit, 100, 100, 80);
const pathBR = starPath(CanvasKit, 400, 300, 80);
const paint = new CanvasKit.SkPaint();
const textFont = new CanvasKit.SkFont(null, 24);
canvas.drawText('Above: MaskFilter', 20, 220, paint, textFont);
canvas.drawText('Right: ImageFilter', 20, 260, paint, textFont);
paint.setColor(CanvasKit.BLUE);
const blurMask = CanvasKit.SkMaskFilter.MakeBlur(CanvasKit.BlurStyle.Normal, 5, true);
paint.setMaskFilter(blurMask);
canvas.drawPath(pathUL, paint);
const blurIF = CanvasKit.SkImageFilter.MakeBlur(8, 1, CanvasKit.TileMode.Decal, null);
paint.setImageFilter(blurIF);
canvas.drawPath(pathBR, paint);
pathUL.delete();
pathBR.delete();
paint.delete();
blurMask.delete();
blurIF.delete();
textFont.delete();
});
gm('combined_filters', (canvas, fetchedByteBuffers) => {
const img = CanvasKit.MakeImageFromEncoded(fetchedByteBuffers[0]);
expect(img).toBeTruthy();
canvas.clear(CanvasKit.WHITE);
const paint = new CanvasKit.SkPaint();
paint.setAntiAlias(true);
paint.setColor(CanvasKit.Color(0, 255, 0, 1.0));
const redCF = CanvasKit.SkColorFilter.MakeBlend(
CanvasKit.Color(255, 0, 0, 0.1), CanvasKit.BlendMode.SrcOver);
const redIF = CanvasKit.SkImageFilter.MakeColorFilter(redCF, null);
const blurIF = CanvasKit.SkImageFilter.MakeBlur(8, 0.2, CanvasKit.TileMode.Decal, null);
const combined = CanvasKit.SkImageFilter.MakeCompose(redIF, blurIF);
// rotate 10 degrees centered on 200, 200
const m = CanvasKit.SkMatrix.rotated(Math.PI/18, 200, 200);
const rotated = CanvasKit.SkImageFilter.MakeMatrixTransform(m, CanvasKit.FilterQuality.Medium, combined);
paint.setImageFilter(rotated);
//canvas.rotate(10, 200, 200);
canvas.drawImage(img, 0, 0, paint);
canvas.drawRect(CanvasKit.LTRBRect(5, 35, 45, 80), paint);
paint.delete();
redIF.delete();
redCF.delete();
blurIF.delete();
combined.delete();
rotated.delete();
img.delete();
}, '/assets/mandrill_512.png');
gm('animated_filters', (canvas, fetchedByteBuffers) => {
const img = CanvasKit.MakeAnimatedImageFromEncoded(fetchedByteBuffers[0]);
expect(img).toBeTruthy();
img.decodeNextFrame();
img.decodeNextFrame();
canvas.clear(CanvasKit.WHITE);
const paint = new CanvasKit.SkPaint();
paint.setAntiAlias(true);
paint.setColor(CanvasKit.Color(0, 255, 0, 1.0));
const redCF = CanvasKit.SkColorFilter.MakeBlend(
CanvasKit.Color(255, 0, 0, 0.1), CanvasKit.BlendMode.SrcOver);
const redIF = CanvasKit.SkImageFilter.MakeColorFilter(redCF, null);
const blurIF = CanvasKit.SkImageFilter.MakeBlur(8, 0.2, CanvasKit.TileMode.Decal, null);
const combined = CanvasKit.SkImageFilter.MakeCompose(redIF, blurIF);
paint.setImageFilter(combined);
const frame = img.getCurrentFrame();
canvas.drawImage(frame, 100, 50, paint);
paint.delete();
redIF.delete();
redCF.delete();
blurIF.delete();
combined.delete();
frame.delete();
img.delete();
}, '/assets/flightAnim.gif');
gm('drawImage_skp', (canvas, fetchedByteBuffers) => {
const pic = CanvasKit.MakeSkPicture(fetchedByteBuffers[0]);
expect(pic).toBeTruthy();
canvas.clear(CanvasKit.TRANSPARENT);
canvas.drawPicture(pic);
}, '/assets/red_line.skp');
it('can draw once using drawOnce utility method', (done) => {
const surface = CanvasKit.MakeCanvasSurface('test');
expect(surface).toBeTruthy('Could not make surface');
if (!surface) {
done();
return;
}
const drawFrame = (canvas) => {
const paint = new CanvasKit.SkPaint();
paint.setStrokeWidth(1.0);
paint.setAntiAlias(true);
paint.setColor(CanvasKit.Color(0, 0, 0, 1.0));
paint.setStyle(CanvasKit.PaintStyle.Stroke);
const path = new CanvasKit.SkPath();
path.moveTo(20, 5);
path.lineTo(30, 20);
path.lineTo(40, 10);
canvas.drawPath(path, paint);
path.delete();
paint.delete();
// surface hasn't been flushed yet (nor should we call flush
// ourselves), so reportSurface would likely be blank if we
// were to call it.
done();
}
surface.drawOnce(drawFrame);
// Reminder: drawOnce is async. In this test, we are just making
// sure the drawOnce function is there and doesn't crash, so we can
// just call done() when the frame is rendered.
});
it('can use DecodeCache APIs', () => {
const initialLimit = CanvasKit.getDecodeCacheLimitBytes();
expect(initialLimit).toBeGreaterThan(1024 * 1024);
const newLimit = 42 * 1024 * 1024;
CanvasKit.setDecodeCacheLimitBytes(newLimit);
expect(CanvasKit.getDecodeCacheLimitBytes()).toEqual(newLimit);
// We cannot make any assumptions about this value,
// so we just make sure it doesn't crash.
CanvasKit.getDecodeCacheUsedBytes();
});
gm('combined_shaders', (canvas) => {
const rShader = CanvasKit.SkShader.Color(CanvasKit.Color(255, 0, 0, 1.0));
const gShader = CanvasKit.SkShader.Color(CanvasKit.Color(0, 255, 0, 0.6));
const bShader = CanvasKit.SkShader.Color(CanvasKit.Color(0, 0, 255, 1.0));
const rgShader = CanvasKit.SkShader.Blend(CanvasKit.BlendMode.SrcOver, rShader, gShader);
const p = new CanvasKit.SkPaint();
p.setShader(rgShader);
canvas.drawPaint(p);
const gbShader = CanvasKit.SkShader.Lerp(0.5, gShader, bShader);
p.setShader(gbShader);
canvas.drawRect(CanvasKit.LTRBRect(5, 100, 300, 400), p);
rShader.delete();
gShader.delete();
bShader.delete();
rgShader.delete();
gbShader.delete();
p.delete();
});
it('exports consts correctly', () => {
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);
expect(CanvasKit.SaveLayerInitWithPrevious).toEqual(4);
expect(CanvasKit.SaveLayerF16ColorType).toEqual(16);
});
it('can set and get a 4f color on a paint', () => {
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));
});
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();
const shader = CanvasKit.SkShader.MakeSweepGradient(
100, 100, // x y coordinates
[CanvasKit.GREEN, CanvasKit.BLUE],
[0.0, 1.0],
CanvasKit.TileMode.Clamp,
new DOMMatrix().translate(-10, 100),
);
expect(shader).toBeTruthy('Could not make shader');
if (!shader) {
return;
}
paint.setShader(shader);
canvas.drawPaint(paint);
paint.delete();
shader.delete();
});
const radiansToDegrees = (rad) => {
return (rad / Math.PI) * 180;
}
// this should draw the same as concat_with4x4_canvas
gm('concat_dommatrix', (canvas) => {
const path = starPath(CanvasKit, CANVAS_WIDTH/2, CANVAS_HEIGHT/2);
const paint = new CanvasKit.SkPaint();
paint.setAntiAlias(true);
canvas.clear(CanvasKit.WHITE);
canvas.concat(new DOMMatrix().translate(CANVAS_WIDTH/2, 0, 0));
canvas.concat(new DOMMatrix().rotateAxisAngle(1, 0, 0, radiansToDegrees(Math.PI/3)));
canvas.concat(new DOMMatrix().rotateAxisAngle(0, 1, 0, radiansToDegrees(Math.PI/4)));
canvas.concat(new DOMMatrix().rotateAxisAngle(0, 0, 1, radiansToDegrees(Math.PI/16)));
canvas.concat(new DOMMatrix().translate(-CANVAS_WIDTH/2, 0, 0));
// Draw some stripes to help the eye detect the turn
const stripeWidth = 10;
paint.setColor(CanvasKit.BLACK);
for (let i = 0; i < CANVAS_WIDTH; i += 2*stripeWidth) {
canvas.drawRect(CanvasKit.LTRBRect(i, 0, i + stripeWidth, CANVAS_HEIGHT), paint);
}
paint.setColor(CanvasKit.YELLOW);
canvas.drawPath(path, paint);
paint.delete();
path.delete();
});
}); // end describe('DOMMatrix support')
});