[canvaskit] Expose sampling variants of drawImage and drawImageRect
Change-Id: I91f40374de1861385bddb977917f2e7a24fb6a27 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/345130 Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
7fb39366a0
commit
72f407636e
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- `Canvas.drawImageCubic`, `Canvas.drawImageOptions`, `Canvas.drawImageRectCubic`,
|
||||
`Canvas.drawImageRectOptions` to replace functionality that previously required FilterQuality.
|
||||
|
||||
## [0.21.0] - 2020-12-16
|
||||
|
||||
### Added
|
||||
|
@ -112,11 +112,17 @@ function canvasTests(CK: CanvasKit, canvas?: Canvas, paint?: Paint, path?: Path,
|
||||
canvas.drawImage(img, 0, -43, paint);
|
||||
canvas.drawImageAtCurrentFrame(aImg, 0, -43);
|
||||
canvas.drawImageAtCurrentFrame(aImg, 0, -43, paint);
|
||||
canvas.drawImageCubic(img, 0, -43, 1 / 3, 1 / 4, null);
|
||||
canvas.drawImageOptions(img, 0, -43, CK.FilterMode.Nearest, CK.MipmapMode.Nearest, paint);
|
||||
canvas.drawImageNine(img, someRect, someRect, paint);
|
||||
canvas.drawImageNine(img, CK.XYWHiRect(10, 20, 40, 40), someRect, paint);
|
||||
canvas.drawImageRect(img, someRect, someRect, paint);
|
||||
canvas.drawImageRect(img, CK.XYWHRect(90, 90, 40, 40), someRect, paint);
|
||||
canvas.drawImageRect(img, someRect, someRect, paint, true);
|
||||
canvas.drawImageRectCubic(img, someRect, someRect, 1 / 5, 1 / 6);
|
||||
canvas.drawImageRectCubic(img, someRect, someRect, 1 / 5, 1 / 6, paint);
|
||||
canvas.drawImageRectOptions(img, someRect, someRect, CK.FilterMode.Linear, CK.MipmapMode.None);
|
||||
canvas.drawImageRectOptions(img, someRect, someRect, CK.FilterMode.Linear, CK.MipmapMode.None, paint);
|
||||
canvas.drawLine(1, 2, 3, 4, paint);
|
||||
canvas.drawOval(someRect, paint);
|
||||
canvas.drawPaint(paint);
|
||||
|
60
modules/canvaskit/canvaskit/types/index.d.ts
vendored
60
modules/canvaskit/canvaskit/types/index.d.ts
vendored
@ -1039,6 +1039,33 @@ export interface Canvas extends EmbindObject<Canvas> {
|
||||
*/
|
||||
drawImage(img: Image, left: number, top: number, paint?: Paint): void;
|
||||
|
||||
/**
|
||||
* Draws the given image with its top-left corner at (left, top) using the current clip,
|
||||
* the current matrix. It will use the cubic sampling options B and C if necessary.
|
||||
* @param img
|
||||
* @param left
|
||||
* @param top
|
||||
* @param B - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param C - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param paint
|
||||
*/
|
||||
drawImageCubic(img: Image, left: number, top: number, B: number, C: number,
|
||||
paint: Paint | null): void;
|
||||
|
||||
/**
|
||||
* Draws the given image with its top-left corner at (left, top) using the current clip,
|
||||
* the current matrix. It will use the provided sampling options if necessary.
|
||||
* @param img
|
||||
* @param left
|
||||
* @param top
|
||||
* @param fm - The filter mode.
|
||||
* @param mm - The mipmap mode. Note: for settings other than None, the image must have mipmaps
|
||||
* calculated with makeCopyWithDefaultMipmaps;
|
||||
* @param paint
|
||||
*/
|
||||
drawImageOptions(img: Image, left: number, top: number, fm: FilterMode,
|
||||
mm: MipmapMode, paint: Paint | null): void;
|
||||
|
||||
/**
|
||||
* Draws the current frame of the given animated image with its top-left corner at
|
||||
* (left, top) using the current clip, the current matrix, and optionally-provided paint.
|
||||
@ -1072,6 +1099,33 @@ export interface Canvas extends EmbindObject<Canvas> {
|
||||
drawImageRect(img: Image, src: InputRect, dest: InputRect, paint: Paint,
|
||||
fastSample?: boolean): void;
|
||||
|
||||
/**
|
||||
* Draws sub-rectangle src from provided image, scaled and translated to fill dst rectangle.
|
||||
* It will use the cubic sampling options B and C if necessary.
|
||||
* @param img
|
||||
* @param src
|
||||
* @param dest
|
||||
* @param B - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param C - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param paint
|
||||
*/
|
||||
drawImageRectCubic(img: Image, src: InputRect, dest: InputRect,
|
||||
B: number, C: number, paint?: Paint): void;
|
||||
|
||||
/**
|
||||
* Draws sub-rectangle src from provided image, scaled and translated to fill dst rectangle.
|
||||
* It will use the provided sampling options if necessary.
|
||||
* @param img
|
||||
* @param src
|
||||
* @param dest
|
||||
* @param fm - The filter mode.
|
||||
* @param mm - The mipmap mode. Note: for settings other than None, the image must have mipmaps
|
||||
* calculated with makeCopyWithDefaultMipmaps;
|
||||
* @param paint
|
||||
*/
|
||||
drawImageRectOptions(img: Image, src: InputRect, dest: InputRect, fm: FilterMode,
|
||||
mm: MipmapMode, paint?: Paint): void;
|
||||
|
||||
/**
|
||||
* Draws line segment from (x0, y0) to (x1, y1) using the current clip, current matrix,
|
||||
* and the provided paint.
|
||||
@ -1597,11 +1651,11 @@ export interface Image extends EmbindObject<Image> {
|
||||
* Returns this image as a shader with the specified tiling. It will use cubic sampling.
|
||||
* @param tx - tile mode in the x direction.
|
||||
* @param ty - tile mode in the y direction.
|
||||
* @param b - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param c - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param B - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param C - See CubicResampler in SkSamplingOptions.h for more information
|
||||
* @param localMatrix
|
||||
*/
|
||||
makeShaderCubic(tx: TileMode, ty: TileMode, b: number, c: number,
|
||||
makeShaderCubic(tx: TileMode, ty: TileMode, B: number, C: number,
|
||||
localMatrix?: InputMatrix): Shader;
|
||||
|
||||
/**
|
||||
|
@ -894,11 +894,24 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
self.drawDRRect(ptrToSkRRect(outerPtr), ptrToSkRRect(innerPtr), paint);
|
||||
}))
|
||||
.function("drawImage", select_overload<void (const sk_sp<SkImage>&, SkScalar, SkScalar, const SkPaint*)>(&SkCanvas::drawImage), allow_raw_pointers())
|
||||
.function("drawImageCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
|
||||
SkScalar left, SkScalar top,
|
||||
float B, float C, // See SkSamplingOptions.h for docs.
|
||||
const SkPaint* paint)->void {
|
||||
self.drawImage(img.get(), left, top, SkSamplingOptions({B, C}), paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("drawImageOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& img,
|
||||
SkScalar left, SkScalar top,
|
||||
SkFilterMode filter, SkMipmapMode mipmap,
|
||||
const SkPaint* paint)->void {
|
||||
self.drawImage(img.get(), left, top, {filter, mipmap}, paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("drawImageAtCurrentFrame", optional_override([](SkCanvas& self, sk_sp<SkAnimatedImage> aImg,
|
||||
SkScalar left, SkScalar top, const SkPaint* paint)->void {
|
||||
SkScalar left, SkScalar top, const SkPaint* paint)->void {
|
||||
auto img = aImg->getCurrentFrame();
|
||||
self.drawImage(img, left, top, paint);
|
||||
}), allow_raw_pointers())
|
||||
|
||||
.function("_drawImageNine", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
|
||||
uintptr_t /* int* */ centerPtr, uintptr_t /* float* */ dstPtr,
|
||||
const SkPaint* paint)->void {
|
||||
@ -916,6 +929,22 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
fastSample ? SkCanvas::kFast_SrcRectConstraint:
|
||||
SkCanvas::kStrict_SrcRectConstraint);
|
||||
}), allow_raw_pointers())
|
||||
.function("_drawImageRectCubic", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
|
||||
uintptr_t /* float* */ srcPtr, uintptr_t /* float* */ dstPtr,
|
||||
float B, float C, // See SkSamplingOptions.h for docs.
|
||||
const SkPaint* paint)->void {
|
||||
const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
|
||||
const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
|
||||
self.drawImageRect(image.get(), *src, *dst, SkSamplingOptions({B, C}), paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("_drawImageRectOptions", optional_override([](SkCanvas& self, const sk_sp<SkImage>& image,
|
||||
uintptr_t /* float* */ srcPtr, uintptr_t /* float* */ dstPtr,
|
||||
SkFilterMode filter, SkMipmapMode mipmap,
|
||||
const SkPaint* paint)->void {
|
||||
const SkRect* src = reinterpret_cast<const SkRect*>(srcPtr);
|
||||
const SkRect* dst = reinterpret_cast<const SkRect*>(dstPtr);
|
||||
self.drawImageRect(image.get(), *src, *dst, {filter, mipmap}, paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("drawLine", select_overload<void (SkScalar, SkScalar, SkScalar, SkScalar, const SkPaint&)>(&SkCanvas::drawLine))
|
||||
.function("_drawOval", optional_override([](SkCanvas& self, uintptr_t /* float* */ fPtr,
|
||||
const SkPaint& paint)->void {
|
||||
@ -1235,7 +1264,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
}))
|
||||
.function("_makeShaderCubic", optional_override([](sk_sp<SkImage> self,
|
||||
SkTileMode tx, SkTileMode ty,
|
||||
float B, float C, // See SkImage::CubicResampler for docs.
|
||||
float B, float C, // See SkSamplingOptions.h for docs.
|
||||
uintptr_t /* SkScalar* */ mPtr)->sk_sp<SkShader> {
|
||||
return self->makeShader(tx, ty, SkSamplingOptions({B, C}), OptionalMatrix(mPtr));
|
||||
}), allow_raw_pointers())
|
||||
@ -1296,6 +1325,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
float* fourFloats = reinterpret_cast<float*>(cPtr);
|
||||
memcpy(fourFloats, c.vec(), 4 * sizeof(SkScalar));
|
||||
}))
|
||||
.function("getFilterQuality", &SkPaint::getFilterQuality)
|
||||
.function("getStrokeCap", &SkPaint::getStrokeCap)
|
||||
.function("getStrokeJoin", &SkPaint::getStrokeJoin)
|
||||
.function("getStrokeMiter", &SkPaint::getStrokeMiter)
|
||||
@ -1315,6 +1345,7 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
self.setColor(SkColor4f::FromColor(color), colorSpace.get());
|
||||
}))
|
||||
.function("setColorFilter", &SkPaint::setColorFilter)
|
||||
.function("setFilterQuality", &SkPaint::setFilterQuality)
|
||||
.function("setImageFilter", &SkPaint::setImageFilter)
|
||||
.function("setMaskFilter", &SkPaint::setMaskFilter)
|
||||
.function("setPathEffect", &SkPaint::setPathEffect)
|
||||
|
@ -199,6 +199,8 @@ var CanvasKit = {
|
||||
drawCircle: function() {},
|
||||
drawColorInt: function() {},
|
||||
drawImage: function() {},
|
||||
drawImageCubic: function() {},
|
||||
drawImageOptions: function() {},
|
||||
drawImageAtCurrentFrame: function() {},
|
||||
drawLine: function() {},
|
||||
drawPaint: function() {},
|
||||
@ -227,7 +229,6 @@ var CanvasKit = {
|
||||
clear: function() {},
|
||||
clipRRect: function() {},
|
||||
clipRect: function() {},
|
||||
concat44: function() {}, // deprecated
|
||||
concat: function() {},
|
||||
drawArc: function() {},
|
||||
drawAtlas: function() {},
|
||||
@ -236,6 +237,8 @@ var CanvasKit = {
|
||||
drawDRRect: function() {},
|
||||
drawImageNine: function() {},
|
||||
drawImageRect: function() {},
|
||||
drawImageRectCubic: function() {},
|
||||
drawImageRectOptions: function() {},
|
||||
drawOval: function() {},
|
||||
drawPoints: function() {},
|
||||
drawRect: function() {},
|
||||
@ -261,6 +264,8 @@ var CanvasKit = {
|
||||
_drawDRRect: function() {},
|
||||
_drawImageNine: function() {},
|
||||
_drawImageRect: function() {},
|
||||
_drawImageRectCubic: function() {},
|
||||
_drawImageRectOptions: function() {},
|
||||
_drawOval: function() {},
|
||||
_drawPoints: function() {},
|
||||
_drawRect: function() {},
|
||||
|
@ -1113,6 +1113,18 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
this._drawImageRect(img, sPtr, dPtr, paint, !!fastSample);
|
||||
};
|
||||
|
||||
CanvasKit.Canvas.prototype.drawImageRectCubic = function(img, src, dest, B, C, paint) {
|
||||
var sPtr = copyRectToWasm(src, _scratchRectPtr);
|
||||
var dPtr = copyRectToWasm(dest, _scratchRect2Ptr);
|
||||
this._drawImageRectCubic(img, sPtr, dPtr, B, C, paint || null);
|
||||
};
|
||||
|
||||
CanvasKit.Canvas.prototype.drawImageRectOptions = function(img, src, dest, filter, mipmap, paint) {
|
||||
var sPtr = copyRectToWasm(src, _scratchRectPtr);
|
||||
var dPtr = copyRectToWasm(dest, _scratchRect2Ptr);
|
||||
this._drawImageRectOptions(img, sPtr, dPtr, filter, mipmap, paint || null);
|
||||
};
|
||||
|
||||
CanvasKit.Canvas.prototype.drawOval = function(oval, paint) {
|
||||
var oPtr = copyRectToWasm(oval);
|
||||
this._drawOval(oPtr, paint);
|
||||
|
@ -200,7 +200,7 @@ describe('Core canvas behavior', () => {
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
const paint = new CanvasKit.Paint();
|
||||
const font = new CanvasKit.Font(null, 14);
|
||||
canvas.drawText('The following heart should be rotated 90 due to exif.',
|
||||
canvas.drawText('The following heart should be rotated 90 CCW due to exif.',
|
||||
5, 25, paint, font);
|
||||
|
||||
// TODO(kjlubick) it would be nice to also to test MakeAnimatedImageFromEncoded but
|
||||
@ -376,15 +376,15 @@ describe('Core canvas behavior', () => {
|
||||
const skImage4 = CanvasKit.MakeImageFromCanvasImageSource(image2);
|
||||
|
||||
// Draw decoded images
|
||||
const sourceRect = CanvasKit.XYWHRect(0,0, 150, 150);
|
||||
canvas.drawImageRect(skImage1, sourceRect, CanvasKit.XYWHRect(0,row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage2, sourceRect, CanvasKit.XYWHRect(100,row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage3, sourceRect, CanvasKit.XYWHRect(200,row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage4, sourceRect, CanvasKit.XYWHRect(300,row * 100, 90, 90), null, false);
|
||||
const sourceRect = CanvasKit.XYWHRect(0, 0, 150, 150);
|
||||
canvas.drawImageRect(skImage1, sourceRect, CanvasKit.XYWHRect(0, row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage2, sourceRect, CanvasKit.XYWHRect(100, row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage3, sourceRect, CanvasKit.XYWHRect(200, row * 100, 90, 90), null, false);
|
||||
canvas.drawImageRect(skImage4, sourceRect, CanvasKit.XYWHRect(300, row * 100, 90, 90), null, false);
|
||||
|
||||
row++;
|
||||
}
|
||||
//Label images with the method used to decode them
|
||||
// Label images with the method used to decode them
|
||||
const paint = new CanvasKit.Paint();
|
||||
const textFont = new CanvasKit.Font(null, 7);
|
||||
canvas.drawText('WASM Decoding', 0, 90, paint, textFont);
|
||||
@ -724,6 +724,61 @@ describe('Core canvas behavior', () => {
|
||||
img.delete();
|
||||
}, '/assets/flightAnim.gif');
|
||||
|
||||
gm('drawImageVariants', (canvas, fetchedByteBuffers) => {
|
||||
const img = CanvasKit.MakeImageFromEncoded(fetchedByteBuffers[0]);
|
||||
expect(img).toBeTruthy();
|
||||
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
canvas.scale(2, 2);
|
||||
const paint = new CanvasKit.Paint();
|
||||
const clipTo = (x, y) => {
|
||||
canvas.save();
|
||||
canvas.clipRect(CanvasKit.XYWHRect(x, y, 128, 128), CanvasKit.ClipOp.Intersect);
|
||||
};
|
||||
|
||||
clipTo(0, 0);
|
||||
canvas.drawImage(img, 0, 0, paint);
|
||||
canvas.restore();
|
||||
|
||||
clipTo(128, 0);
|
||||
canvas.drawImageCubic(img, 128, 0, 1/3, 1/3, null);
|
||||
canvas.restore();
|
||||
|
||||
clipTo(0, 128);
|
||||
canvas.drawImageOptions(img, 0, 128, CanvasKit.FilterMode.Linear, CanvasKit.MipmapMode.None, null);
|
||||
canvas.restore();
|
||||
|
||||
const mipImg = img.makeCopyWithDefaultMipmaps();
|
||||
clipTo(128, 128);
|
||||
canvas.drawImageOptions(mipImg, 128, 128,
|
||||
CanvasKit.FilterMode.Nearest, CanvasKit.MipmapMode.Nearest, null);
|
||||
canvas.restore();
|
||||
|
||||
paint.delete();
|
||||
mipImg.delete();
|
||||
img.delete();
|
||||
}, '/assets/mandrill_512.png');
|
||||
|
||||
gm('drawImageRectVariants', (canvas, fetchedByteBuffers) => {
|
||||
const img = CanvasKit.MakeImageFromEncoded(fetchedByteBuffers[0]);
|
||||
expect(img).toBeTruthy();
|
||||
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
const paint = new CanvasKit.Paint();
|
||||
const src = CanvasKit.XYWHRect(100, 100, 128, 128);
|
||||
canvas.drawImageRect(img, src, CanvasKit.XYWHRect(0, 0, 256, 256), paint);
|
||||
canvas.drawImageRectCubic(img, src, CanvasKit.XYWHRect(256, 0, 256, 256), 1/3, 1/3);
|
||||
canvas.drawImageRectOptions(img, src, CanvasKit.XYWHRect(0, 256, 256, 256),
|
||||
CanvasKit.FilterMode.Linear, CanvasKit.MipmapMode.None);
|
||||
const mipImg = img.makeCopyWithDefaultMipmaps();
|
||||
canvas.drawImageRectOptions(mipImg, src, CanvasKit.XYWHRect(256, 256, 256, 256),
|
||||
CanvasKit.FilterMode.Nearest, CanvasKit.MipmapMode.Nearest);
|
||||
|
||||
paint.delete();
|
||||
mipImg.delete();
|
||||
img.delete();
|
||||
}, '/assets/mandrill_512.png');
|
||||
|
||||
gm('drawImage_skp', (canvas, fetchedByteBuffers) => {
|
||||
const pic = CanvasKit.MakePicture(fetchedByteBuffers[0]);
|
||||
expect(pic).toBeTruthy();
|
||||
|
@ -201,6 +201,9 @@ function reportSurface(surface, testname, done) {
|
||||
|
||||
const reportingCanvas = document.getElementById('report');
|
||||
reportingCanvas.getContext('2d').putImageData(imageData, 0, 0);
|
||||
if (!done) {
|
||||
return;
|
||||
}
|
||||
reportCanvas(reportingCanvas, testname).then(() => {
|
||||
// TODO(kjlubick): should we call surface.delete() here?
|
||||
done();
|
||||
|
Loading…
Reference in New Issue
Block a user