beefcb9d38
For API simplicity, if the rectangle is to be omitted, the client
should only provide the paint. (emscripten already does parameter
count checking, so let's use that instead of doing it ourselves).
This also adds tests to help verify the new behavior.
Revert "Revert "Allow null rect for saveLayer""
This reverts commit 7957d53c80
.
Bug: skia:10043
Change-Id: I9ed8caabbfc77deab1ca3d9b1a415489e012528f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/277399
Reviewed-by: Nathaniel Nifong <nifong@google.com>
Reviewed-by: Dan Field <dnfield@google.com>
728 lines
28 KiB
JavaScript
728 lines
28 KiB
JavaScript
describe('CanvasKit\'s Canvas Behavior', function() {
|
|
let container = document.createElement('div');
|
|
document.body.appendChild(container);
|
|
const CANVAS_WIDTH = 600;
|
|
const CANVAS_HEIGHT = 600;
|
|
|
|
beforeEach(function() {
|
|
container.innerHTML = `
|
|
<canvas width=600 height=600 id=test></canvas>
|
|
<canvas width=600 height=600 id=report></canvas>`;
|
|
});
|
|
|
|
afterEach(function() {
|
|
container.innerHTML = '';
|
|
});
|
|
|
|
it('can draw directly to a canvas', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
// This is taken from example.html
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
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);
|
|
|
|
canvas.drawLine(3, 10, 30, 15, paint);
|
|
canvas.drawRoundRect(CanvasKit.LTRBRect(5, 35, 45, 80), 15, 10, paint);
|
|
|
|
canvas.drawOval(CanvasKit.LTRBRect(5, 35, 45, 80), paint);
|
|
|
|
canvas.drawArc(CanvasKit.LTRBRect(55, 35, 95, 80), 15, 270, true, paint);
|
|
|
|
const font = new CanvasKit.SkFont(null, 20);
|
|
canvas.drawText('this is ascii text', 5, 100, paint, font);
|
|
|
|
const blob = CanvasKit.SkTextBlob.MakeFromText('Unicode chars 💩 é É ص', font);
|
|
canvas.drawTextBlob(blob, 5, 130, paint);
|
|
|
|
surface.flush();
|
|
font.delete();
|
|
blob.delete();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'canvas_api_example', done);
|
|
}));
|
|
// See canvas2d for more API tests
|
|
});
|
|
|
|
it('can apply an effect and draw text', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
const textPaint = new CanvasKit.SkPaint();
|
|
textPaint.setColor(CanvasKit.Color(40, 0, 0, 1.0));
|
|
textPaint.setAntiAlias(true);
|
|
|
|
const textFont = new CanvasKit.SkFont(null, 30);
|
|
|
|
const dpe = CanvasKit.SkPathEffect.MakeDash([15, 5, 5, 10], 1);
|
|
|
|
paint.setPathEffect(dpe);
|
|
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
|
paint.setStrokeWidth(5.0);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(CanvasKit.Color(66, 129, 164, 1.0));
|
|
|
|
canvas.clear(CanvasKit.Color(255, 255, 255, 1.0));
|
|
|
|
canvas.drawPath(path, paint);
|
|
canvas.drawText('This is text', 10, 280, textPaint, textFont);
|
|
surface.flush();
|
|
|
|
dpe.delete();
|
|
path.delete();
|
|
paint.delete();
|
|
textFont.delete();
|
|
textPaint.delete();
|
|
|
|
reportSurface(surface, 'effect_and_text_example', done);
|
|
}));
|
|
});
|
|
|
|
it('returns the depth of the save state stack', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
expect(canvas.getSaveCount()).toEqual(1);
|
|
canvas.save();
|
|
canvas.save();
|
|
canvas.restore();
|
|
canvas.save();
|
|
canvas.save();
|
|
expect(canvas.getSaveCount()).toEqual(4);
|
|
// does nothing, by the SkCanvas API
|
|
canvas.restoreToCount(500);
|
|
expect(canvas.getSaveCount()).toEqual(4);
|
|
canvas.restore();
|
|
expect(canvas.getSaveCount()).toEqual(3);
|
|
canvas.save();
|
|
canvas.restoreToCount(2);
|
|
expect(canvas.getSaveCount()).toEqual(2);
|
|
|
|
surface.delete();
|
|
|
|
done();
|
|
}));
|
|
});
|
|
|
|
it('draws circles', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
|
paint.setStrokeWidth(5.0);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(CanvasKit.CYAN);
|
|
|
|
canvas.clear(CanvasKit.WHITE);
|
|
|
|
canvas.drawCircle(30, 50, 15, paint);
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Fill);
|
|
paint.setColor(CanvasKit.RED);
|
|
canvas.drawCircle(130, 80, 60, paint);
|
|
canvas.drawCircle(20, 150, 60, paint);
|
|
|
|
surface.flush();
|
|
path.delete();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'circle_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('draws simple rrects', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
|
paint.setStrokeWidth(3.0);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(CanvasKit.BLACK);
|
|
|
|
canvas.clear(CanvasKit.WHITE);
|
|
|
|
canvas.drawRRect(CanvasKit.RRectXY(
|
|
CanvasKit.LTRBRect(10, 10, 50, 50), 5, 10), paint);
|
|
|
|
canvas.drawRRect(CanvasKit.RRectXY(
|
|
CanvasKit.LTRBRect(60, 10, 110, 50), 10, 5), paint);
|
|
|
|
canvas.drawRRect(CanvasKit.RRectXY(
|
|
CanvasKit.LTRBRect(10, 60, 210, 260), 0, 30), paint);
|
|
|
|
canvas.drawRRect(CanvasKit.RRectXY(
|
|
CanvasKit.LTRBRect(50, 90, 160, 210), 30, 30), paint);
|
|
|
|
surface.flush();
|
|
path.delete();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'rrect_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('draws complex rrects', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
|
paint.setStrokeWidth(3.0);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(CanvasKit.BLACK);
|
|
|
|
canvas.clear(CanvasKit.WHITE);
|
|
|
|
canvas.drawRRect({
|
|
rect: CanvasKit.LTRBRect(10, 10, 210, 210),
|
|
rx1: 10, // top left corner, going clockwise
|
|
ry1: 30,
|
|
rx2: 30,
|
|
ry2: 10,
|
|
rx3: 50,
|
|
ry3: 75,
|
|
rx4: 120,
|
|
ry4: 120,
|
|
}, paint);
|
|
|
|
surface.flush();
|
|
path.delete();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'rrect_8corners_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('draws between two rrects', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Fill);
|
|
paint.setStrokeWidth(3.0);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(CanvasKit.BLACK);
|
|
|
|
canvas.clear(CanvasKit.WHITE);
|
|
|
|
const outer = CanvasKit.RRectXY(CanvasKit.LTRBRect(10, 60, 210, 260), 10, 5);
|
|
const inner = CanvasKit.RRectXY(CanvasKit.LTRBRect(50, 90, 160, 210), 30, 30);
|
|
|
|
canvas.drawDRRect(outer, inner, paint);
|
|
|
|
surface.flush();
|
|
path.delete();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'drawDRRect_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('draws with color filters', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
const blue = CanvasKit.SkColorFilter.MakeBlend(
|
|
CanvasKit.BLUE, CanvasKit.BlendMode.SrcIn);
|
|
const red = CanvasKit.SkColorFilter.MakeBlend(
|
|
CanvasKit.Color(255, 0, 0, 0.8), CanvasKit.BlendMode.SrcOver);
|
|
const lerp = CanvasKit.SkColorFilter.MakeLerp(0.6, red, blue);
|
|
|
|
paint.setStyle(CanvasKit.PaintStyle.Fill);
|
|
paint.setAntiAlias(true);
|
|
|
|
canvas.clear(CanvasKit.Color(230, 230, 230));
|
|
|
|
paint.setColorFilter(blue)
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 10, 60, 60), paint);
|
|
paint.setColorFilter(lerp)
|
|
canvas.drawRect(CanvasKit.LTRBRect(50, 10, 100, 60), paint);
|
|
paint.setColorFilter(red)
|
|
canvas.drawRect(CanvasKit.LTRBRect(90, 10, 140, 60), paint);
|
|
|
|
const r = CanvasKit.SkColorMatrix.rotated(0, .707, -.707);
|
|
const b = CanvasKit.SkColorMatrix.rotated(2, .5, .866);
|
|
const s = CanvasKit.SkColorMatrix.scaled(0.9, 1.5, 0.8, 0.8);
|
|
let cm = CanvasKit.SkColorMatrix.concat(r, s);
|
|
cm = CanvasKit.SkColorMatrix.concat(cm, b);
|
|
CanvasKit.SkColorMatrix.postTranslate(cm, 20, 0, -10, 0);
|
|
|
|
const mat = CanvasKit.SkColorFilter.MakeMatrix(cm);
|
|
const final = CanvasKit.SkColorFilter.MakeCompose(mat, lerp);
|
|
|
|
paint.setColorFilter(final)
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 70, 140, 120), paint);
|
|
|
|
surface.flush();
|
|
paint.delete();
|
|
blue.delete();
|
|
red.delete();
|
|
lerp.delete();
|
|
final.delete();
|
|
|
|
reportSurface(surface, 'colorfilters_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can use Malloc to save a copy', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
const src = [
|
|
0.8, 0.45, 2, 0, 20,
|
|
0.53, -0.918, 0.566, 0, 0,
|
|
0.53, -0.918, -0.566, 0, -10,
|
|
0, 0, 0, 0.8, 0,
|
|
]
|
|
const cm = new CanvasKit.Malloc(Float32Array, 20);
|
|
for (i in src) {
|
|
cm[i] = src[i];
|
|
}
|
|
const final = CanvasKit.SkColorFilter.MakeMatrix(cm);
|
|
|
|
paint.setColorFilter(final)
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 70, 140, 120), paint);
|
|
|
|
surface.flush()
|
|
paint.delete();
|
|
final.delete();
|
|
|
|
reportSurface(surface, 'colorfilters_malloc_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can clip using rrect and path', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const path = starPath(CanvasKit);
|
|
const paint = new CanvasKit.SkPaint();
|
|
paint.setColor(CanvasKit.BLUE);
|
|
const rrect = CanvasKit.RRectXY(CanvasKit.LTRBRect(300, 300, 500, 500), 40, 40);
|
|
|
|
canvas.save();
|
|
// draw magenta around the outside edge of an rrect.
|
|
canvas.clipRRect(rrect, CanvasKit.ClipOp.Difference, true);
|
|
canvas.drawColor(CanvasKit.Color(250, 30, 240, 0.9), CanvasKit.BlendMode.SrcOver);
|
|
canvas.restore();
|
|
|
|
// draw grey inside of a star pattern, then the blue star on top
|
|
canvas.clipPath(path, CanvasKit.ClipOp.Intersect, false);
|
|
canvas.drawColor(CanvasKit.Color(200, 200, 200, 1.0), CanvasKit.BlendMode.SrcOver);
|
|
canvas.drawPath(path, paint);
|
|
|
|
surface.flush();
|
|
path.delete();
|
|
|
|
reportSurface(surface, 'clips_canvas', done);
|
|
}));
|
|
});
|
|
|
|
// inspired by https://fiddle.skia.org/c/feb2a08bb09ede5309678d6a0ab3f981
|
|
it('can save layers with rect and paint', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
canvas.clear(CanvasKit.WHITE);
|
|
const redPaint = new CanvasKit.SkPaint();
|
|
redPaint.setColor(CanvasKit.RED);
|
|
const solidBluePaint = new CanvasKit.SkPaint();
|
|
solidBluePaint.setColor(CanvasKit.BLUE);
|
|
|
|
const thirtyBluePaint = new CanvasKit.SkPaint();
|
|
thirtyBluePaint.setColor(CanvasKit.BLUE);
|
|
thirtyBluePaint.setAlphaf(0.3);
|
|
|
|
const alpha = new CanvasKit.SkPaint();
|
|
alpha.setAlphaf(0.3);
|
|
|
|
// Draw 4 solid red rectangles on the 0th layer.
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 10, 60, 60), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 10, 200, 60), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 70, 60, 120), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 70, 200, 120), redPaint);
|
|
|
|
// Draw 2 blue rectangles that overlap. One is solid, the other
|
|
// is 30% transparent. We should see purple from the right one,
|
|
// the left one overlaps the red because it is opaque.
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 10, 80, 60), solidBluePaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 10, 220, 60), thirtyBluePaint);
|
|
|
|
// Save a new layer. When the 1st layer gets merged onto the
|
|
// 0th layer (i.e. when restore() is called), it will use the provided
|
|
// paint to do so. The provided paint is set to have 30% opacity, but
|
|
// it could also have things set like blend modes or image filters.
|
|
// The rectangle is just a hint, so I've set it to be the area that
|
|
// we actually draw in before restore is called. It could also be omitted.
|
|
canvas.saveLayer(CanvasKit.LTRBRect(10, 10, 220, 180), alpha);
|
|
|
|
// Draw the same blue overlapping rectangles as before. Notice in the
|
|
// final output, we have two different shades of purple instead of the
|
|
// solid blue overwriting the red. This proves the opacity was applied.
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 70, 80, 120), solidBluePaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 70, 220, 120), thirtyBluePaint);
|
|
|
|
// We draw two more sets of overlapping red and blue rectangles. Notice
|
|
// the solid blue overwrites the red. This proves that the opacity from
|
|
// the alpha paint isn't available when the drawing happens - it only
|
|
// matters when restore() is called.
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 130, 60, 180), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 130, 80, 180), solidBluePaint);
|
|
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 130, 200, 180), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 130, 220, 180), thirtyBluePaint);
|
|
|
|
canvas.restore();
|
|
|
|
surface.flush();
|
|
redPaint.delete();
|
|
solidBluePaint.delete();
|
|
thirtyBluePaint.delete();
|
|
alpha.delete();
|
|
|
|
reportSurface(surface, 'savelayer_rect_paint_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can save layers with just paint', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
canvas.clear(CanvasKit.WHITE);
|
|
const redPaint = new CanvasKit.SkPaint();
|
|
redPaint.setColor(CanvasKit.RED);
|
|
const solidBluePaint = new CanvasKit.SkPaint();
|
|
solidBluePaint.setColor(CanvasKit.BLUE);
|
|
|
|
const thirtyBluePaint = new CanvasKit.SkPaint();
|
|
thirtyBluePaint.setColor(CanvasKit.BLUE);
|
|
thirtyBluePaint.setAlphaf(0.3);
|
|
|
|
const alpha = new CanvasKit.SkPaint();
|
|
alpha.setAlphaf(0.3);
|
|
|
|
// Draw 4 solid red rectangles on the 0th layer.
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 10, 60, 60), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 10, 200, 60), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 70, 60, 120), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 70, 200, 120), redPaint);
|
|
|
|
// Draw 2 blue rectangles that overlap. One is solid, the other
|
|
// is 30% transparent. We should see purple from the right one,
|
|
// the left one overlaps the red because it is opaque.
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 10, 80, 60), solidBluePaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 10, 220, 60), thirtyBluePaint);
|
|
|
|
// Save a new layer. When the 1st layer gets merged onto the
|
|
// 0th layer (i.e. when restore() is called), it will use the provided
|
|
// paint to do so. The provided paint is set to have 30% opacity, but
|
|
// it could also have things set like blend modes or image filters.
|
|
canvas.saveLayer(alpha);
|
|
|
|
// Draw the same blue overlapping rectangles as before. Notice in the
|
|
// final output, we have two different shades of purple instead of the
|
|
// solid blue overwriting the red. This proves the opacity was applied.
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 70, 80, 120), solidBluePaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 70, 220, 120), thirtyBluePaint);
|
|
|
|
// We draw two more sets of overlapping red and blue rectangles. Notice
|
|
// the solid blue overwrites the red. This proves that the opacity from
|
|
// the alpha paint isn't available when the drawing happens - it only
|
|
// matters when restore() is called.
|
|
canvas.drawRect(CanvasKit.LTRBRect(10, 130, 60, 180), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(30, 130, 80, 180), solidBluePaint);
|
|
|
|
canvas.drawRect(CanvasKit.LTRBRect(150, 130, 200, 180), redPaint);
|
|
canvas.drawRect(CanvasKit.LTRBRect(170, 130, 220, 180), thirtyBluePaint);
|
|
|
|
canvas.restore();
|
|
|
|
surface.flush();
|
|
redPaint.delete();
|
|
solidBluePaint.delete();
|
|
thirtyBluePaint.delete();
|
|
alpha.delete();
|
|
|
|
reportSurface(surface, 'savelayer_paint_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can save layer with SaveLayerRec-like things', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
// Note: fiddle.skia.org quietly draws a white background before doing
|
|
// other things, which is noticed in cases like this where we use saveLayer
|
|
// with the rec struct.
|
|
canvas.clear(CanvasKit.WHITE);
|
|
canvas.scale(8, 8);
|
|
const redPaint = new CanvasKit.SkPaint();
|
|
redPaint.setColor(CanvasKit.RED);
|
|
redPaint.setAntiAlias(true);
|
|
canvas.drawCircle(21, 21, 8, redPaint);
|
|
|
|
const bluePaint = new CanvasKit.SkPaint();
|
|
bluePaint.setColor(CanvasKit.BLUE);
|
|
canvas.drawCircle(31, 21, 8, bluePaint);
|
|
|
|
const blurIF = CanvasKit.SkImageFilter.MakeBlur(8, 0.2, CanvasKit.TileMode.Decal, null);
|
|
|
|
const count = canvas.saveLayer(null, blurIF, 0);
|
|
expect(count).toEqual(1);
|
|
canvas.scale(1/4, 1/4);
|
|
canvas.drawCircle(125, 85, 8, redPaint);
|
|
canvas.restore();
|
|
|
|
surface.flush();
|
|
blurIF.delete();
|
|
redPaint.delete();
|
|
bluePaint.delete();
|
|
|
|
reportSurface(surface, 'savelayerrec_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can drawPoints', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const paint = new CanvasKit.SkPaint();
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(CanvasKit.PaintStyle.Stroke);
|
|
paint.setStrokeWidth(10);
|
|
paint.setColor(CanvasKit.Color(153, 204, 162, 0.82));
|
|
|
|
const points = [[32, 16], [48, 48], [16, 32]];
|
|
|
|
const caps = [CanvasKit.StrokeCap.Round, CanvasKit.StrokeCap.Square,
|
|
CanvasKit.StrokeCap.Butt];
|
|
const joins = [CanvasKit.StrokeJoin.Round, CanvasKit.StrokeJoin.Miter,
|
|
CanvasKit.StrokeJoin.Bevel];
|
|
const modes = [CanvasKit.PointMode.Points, CanvasKit.PointMode.Lines,
|
|
CanvasKit.PointMode.Polygon];
|
|
|
|
for (let i = 0; i < caps.length; i++) {
|
|
paint.setStrokeCap(caps[i]);
|
|
paint.setStrokeJoin(joins[i]);
|
|
|
|
for (const m of modes) {
|
|
canvas.drawPoints(m, points, paint);
|
|
canvas.translate(64, 0);
|
|
}
|
|
// Try with the malloc approach. Note that the drawPoints
|
|
// will free the pointer when done.
|
|
const mPoints = CanvasKit.Malloc(Float32Array, 3*2);
|
|
mPoints.set([32, 16, 48, 48, 16, 32]);
|
|
canvas.drawPoints(CanvasKit.PointMode.Polygon, mPoints, paint);
|
|
canvas.translate(-192, 64);
|
|
}
|
|
|
|
surface.flush();
|
|
paint.delete();
|
|
|
|
reportSurface(surface, 'drawpoints_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can stretch an image with drawImageNine', function(done) {
|
|
const imgPromise = fetch('/assets/mandrill_512.png')
|
|
.then((response) => response.arrayBuffer());
|
|
Promise.all([imgPromise, LoadCanvasKit]).then((values) => {
|
|
const pngData = values[0];
|
|
expect(pngData).toBeTruthy();
|
|
catchException(done, () => {
|
|
let img = CanvasKit.MakeImageFromEncoded(pngData);
|
|
expect(img).toBeTruthy();
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
canvas.clear(CanvasKit.WHITE);
|
|
const paint = new CanvasKit.SkPaint();
|
|
|
|
canvas.drawImageNine(img, {
|
|
fLeft: 40,
|
|
fTop: 40,
|
|
fRight: 400,
|
|
fBottom: 300,
|
|
}, CanvasKit.LTRBRect(5, 5, 300, 650), paint);
|
|
surface.flush();
|
|
paint.delete();
|
|
img.delete();
|
|
|
|
reportSurface(surface, 'drawImageNine_canvas', done);
|
|
})();
|
|
});
|
|
});
|
|
|
|
it('can draw a triangle mesh with SkVertices', function(done) {
|
|
LoadCanvasKit.then(catchException(done, () => {
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const paint = new CanvasKit.SkPaint();
|
|
paint.setAntiAlias(true);
|
|
|
|
const points = [[ 0, 0 ], [ 250, 0 ], [ 100, 100 ], [ 0, 250 ]];
|
|
const colors = [CanvasKit.RED, CanvasKit.BLUE,
|
|
CanvasKit.YELLOW, CanvasKit.CYAN];
|
|
const vertices = CanvasKit.MakeSkVertices(CanvasKit.VertexMode.TriangleFan,
|
|
points, null /*textureCoordinates*/, colors, false /*isVolatile*/);
|
|
|
|
const bounds = vertices.bounds();
|
|
expect(bounds.fLeft).toEqual(0);
|
|
expect(bounds.fTop).toEqual(0);
|
|
expect(bounds.fRight).toEqual(250);
|
|
expect(bounds.fBottom).toEqual(250);
|
|
|
|
canvas.drawVertices(vertices, CanvasKit.BlendMode.Src, paint);
|
|
vertices.delete();
|
|
|
|
surface.flush();
|
|
reportSurface(surface, 'drawvertices_canvas', done);
|
|
}));
|
|
});
|
|
|
|
it('can draw a textured triangle mesh with SkVertices', function(done) {
|
|
const imgPromise = fetch('/assets/brickwork-texture.jpg')
|
|
.then((response) => response.arrayBuffer());
|
|
Promise.all([imgPromise, LoadCanvasKit]).then((values) => {
|
|
const imgData = values[0];
|
|
expect(imgData).toBeTruthy();
|
|
const img = CanvasKit.MakeImageFromEncoded(imgData);
|
|
|
|
const surface = CanvasKit.MakeCanvasSurface('test');
|
|
expect(surface).toBeTruthy('Could not make surface')
|
|
if (!surface) {
|
|
done();
|
|
return;
|
|
}
|
|
const canvas = surface.getCanvas();
|
|
const paint = new CanvasKit.SkPaint();
|
|
paint.setAntiAlias(true);
|
|
|
|
const points = [
|
|
[ 70, 170 ], [ 40, 90 ], [ 130, 150 ], [ 100, 50 ],
|
|
[ 225, 150 ], [ 225, 60 ], [ 310, 180 ], [ 330, 100 ]
|
|
];
|
|
const textureCoordinates = [
|
|
[ 0, 240 ], [ 0, 0 ], [ 80, 240 ], [ 80, 0 ],
|
|
[ 160, 240 ], [ 160, 0 ], [ 240, 240 ], [ 240, 0 ]
|
|
];
|
|
const vertices = CanvasKit.MakeSkVertices(CanvasKit.VertexMode.TrianglesStrip,
|
|
points, textureCoordinates, null /* colors */, false /*isVolatile*/);
|
|
|
|
const shader = img.makeShader(CanvasKit.TileMode.Repeat, CanvasKit.TileMode.Mirror);
|
|
paint.setShader(shader);
|
|
canvas.drawVertices(vertices, CanvasKit.BlendMode.Src, paint);
|
|
|
|
vertices.delete();
|
|
surface.flush();
|
|
reportSurface(surface, 'drawvertices_texture_canvas', done);
|
|
});
|
|
});
|
|
});
|