Extend drawAtlas with optional sampling parameter
Change-Id: Id26f0d9ca5381da807b072c8b59745f2afd8df60 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/386860 Reviewed-by: Kevin Lubick <kjlubick@google.com> Reviewed-by: Yegor Jbanov <yjbanov@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
c98b2afc7b
commit
5514431d0e
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
- Skottie accessors for dynamic text properties (text string, font size).
|
||||
- Optional sampling parameter to drawAtlas (paint filter-quality is ignored/deprecated)
|
||||
|
||||
## [0.25.0] - 2021-03-02
|
||||
|
||||
|
@ -838,19 +838,32 @@ EMSCRIPTEN_BINDINGS(Skia) {
|
||||
const SkRect* oval = reinterpret_cast<const SkRect*>(fPtr);
|
||||
self.drawArc(*oval, startAngle, sweepAngle, useCenter, paint);
|
||||
}))
|
||||
// _drawAtlas takes an array of SkColor. There is no SkColor4f override.
|
||||
// TODO: take sampling as an explicit parameter from the caller
|
||||
.function("_drawAtlas", optional_override([](SkCanvas& self,
|
||||
.function("_drawAtlasOptions", optional_override([](SkCanvas& self,
|
||||
const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
|
||||
uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
|
||||
SkBlendMode mode, const SkPaint* paint)->void {
|
||||
SkBlendMode mode, SkFilterMode filter, SkMipmapMode mipmap,
|
||||
const SkPaint* paint)->void {
|
||||
const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
|
||||
const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
|
||||
const SkColor* colors = nullptr;
|
||||
if (cptr) {
|
||||
colors = reinterpret_cast<const SkColor*>(cptr);
|
||||
}
|
||||
SkSamplingOptions sampling(SkFilterMode::kLinear);
|
||||
SkSamplingOptions sampling(filter, mipmap);
|
||||
self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
|
||||
nullptr, paint);
|
||||
}), allow_raw_pointers())
|
||||
.function("_drawAtlasCubic", optional_override([](SkCanvas& self,
|
||||
const sk_sp<SkImage>& atlas, uintptr_t /* SkRSXform* */ xptr,
|
||||
uintptr_t /* SkRect* */ rptr, uintptr_t /* SkColor* */ cptr, int count,
|
||||
SkBlendMode mode, float B, float C, const SkPaint* paint)->void {
|
||||
const SkRSXform* dstXforms = reinterpret_cast<const SkRSXform*>(xptr);
|
||||
const SkRect* srcRects = reinterpret_cast<const SkRect*>(rptr);
|
||||
const SkColor* colors = nullptr;
|
||||
if (cptr) {
|
||||
colors = reinterpret_cast<const SkColor*>(cptr);
|
||||
}
|
||||
SkSamplingOptions sampling({B, C});
|
||||
self.drawAtlas(atlas.get(), dstXforms, srcRects, colors, count, mode, sampling,
|
||||
nullptr, paint);
|
||||
}), allow_raw_pointers())
|
||||
|
@ -261,7 +261,8 @@ var CanvasKit = {
|
||||
_clipRect: function() {},
|
||||
_concat: function() {},
|
||||
_drawArc: function() {},
|
||||
_drawAtlas: function() {},
|
||||
_drawAtlasOptions: function() {},
|
||||
_drawAtlasCubic: function() {},
|
||||
_drawColor: function() {},
|
||||
_drawDRRect: function() {},
|
||||
_drawImageNine: function() {},
|
||||
|
@ -479,7 +479,8 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
// a Flat Float32Array of float colors or a 2d Array of Float32Array(4) (deprecated)
|
||||
// TODO(kjlubick) remove Builders - no longer needed now that Malloc is a thing.
|
||||
CanvasKit.Canvas.prototype.drawAtlas = function(atlas, srcRects, dstXforms, paint,
|
||||
/*optional*/ blendMode, colors) {
|
||||
/* optional */ blendMode, /* optional */ colors,
|
||||
/* optional */ sampling) {
|
||||
if (!atlas || !paint || !srcRects || !dstXforms) {
|
||||
Debug('Doing nothing since missing a required input');
|
||||
return;
|
||||
@ -523,7 +524,28 @@ CanvasKit.onRuntimeInitialized = function() {
|
||||
}
|
||||
}
|
||||
|
||||
this._drawAtlas(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode, paint);
|
||||
// We require one of these:
|
||||
// 1. sampling is null (we default to linear/none)
|
||||
// 2. sampling.B and sampling.C --> CubicResampler
|
||||
// 3. sampling.filter [and sampling.mipmap] --> FilterOptions
|
||||
//
|
||||
// Thus if all fields are available, we will choose cubic (since we search for B,C first)
|
||||
|
||||
if (sampling && ('B' in sampling) && ('C' in sampling)) {
|
||||
this._drawAtlasCubic(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
|
||||
sampling['B'], sampling['C'], paint);
|
||||
} else {
|
||||
let filter = CanvasKit.FilterMode.Linear;
|
||||
let mipmap = CanvasKit.MipmapMode.None;
|
||||
if (sampling) {
|
||||
filter = sampling['filter']; // 'filter' is a required field
|
||||
if ('mipmap' in sampling) { // 'mipmap' is optional
|
||||
mipmap = sampling['mipmap'];
|
||||
}
|
||||
}
|
||||
this._drawAtlasOptions(atlas, dstXformPtr, srcRectPtr, colorPtr, count, blendMode,
|
||||
filter, mipmap, paint);
|
||||
}
|
||||
|
||||
if (srcRectPtr && !srcRects.build) {
|
||||
freeArraysThatAreNotMallocedByUsers(srcRectPtr, srcRects);
|
||||
|
@ -1065,7 +1065,8 @@
|
||||
dsts.set(0, 0.5, 0, (2*i)%200, (5*Math.round(i/200)) % 200);
|
||||
dsts.set(1, scale*Math.sin(i/20), scale*Math.cos(i/20), 200, 100);
|
||||
|
||||
canvas.drawAtlas(img, srcs, dsts, paint, CanvasKit.BlendMode.Plus, colors);
|
||||
canvas.drawAtlas(img, srcs, dsts, paint, CanvasKit.BlendMode.Plus, colors,
|
||||
{filter: CanvasKit.FilterMode.Nearest});
|
||||
surface.requestAnimationFrame(drawFrame);
|
||||
}
|
||||
surface.requestAnimationFrame(drawFrame);
|
||||
|
@ -97,7 +97,11 @@ function canvasTests(CK: CanvasKit, canvas?: Canvas, paint?: Paint, path?: Path,
|
||||
canvas.drawAtlas(img, [1, 2, 3, 4, 5, 6, 7, 8], [8, 7, 6, 5, 4, 3, 2, 1], paint,
|
||||
CK.BlendMode.Darken,
|
||||
[CK.ColorAsInt(100, 110, 120), CK.ColorAsInt(130, 140, 150)]);
|
||||
canvas.drawCircle(20, 20, 20, paint);
|
||||
canvas.drawAtlas(img, [1, 2, 3, 4, 5, 6, 7, 8], [8, 7, 6, 5, 4, 3, 2, 1], paint,
|
||||
null, null, {B: 0, C: 0.5});
|
||||
canvas.drawAtlas(img, [1, 2, 3, 4, 5, 6, 7, 8], [8, 7, 6, 5, 4, 3, 2, 1], paint,
|
||||
null, null, {filter: CK.FilterMode.Linear, mipmap: CK.MipmapMode.Nearest});
|
||||
canvas.drawCircle(20, 20, 20, paint);
|
||||
canvas.drawColor(someColor);
|
||||
canvas.drawColor(someColor, CK.BlendMode.ColorDodge);
|
||||
canvas.drawColorComponents(0.2, 1.0, -0.02, 0.5);
|
||||
|
20
modules/canvaskit/npm_build/types/index.d.ts
vendored
20
modules/canvaskit/npm_build/types/index.d.ts
vendored
@ -1054,10 +1054,12 @@ export interface Canvas extends EmbindObject<Canvas> {
|
||||
* @param paint
|
||||
* @param blendMode - BlendMode combining colors and sprites
|
||||
* @param colors - If provided, will be blended with sprite using blendMode.
|
||||
* @param sampling - Specifies sampling options. If null, bilinear is used.
|
||||
*/
|
||||
drawAtlas(atlas: Image, srcRects: InputFlattenedRectangleArray,
|
||||
dstXforms: InputFlattenedRSXFormArray, paint: Paint,
|
||||
blendMode?: BlendMode, colors?: ColorIntArray): void;
|
||||
blendMode?: BlendMode, colors?: ColorIntArray,
|
||||
sampling?: CubicResampler | FilterOptions): void;
|
||||
|
||||
/**
|
||||
* Draws a circle at (cx, cy) with the given radius.
|
||||
@ -1765,6 +1767,22 @@ export interface PartialImageInfo {
|
||||
width: number;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specifies sampling with bicubic coefficients
|
||||
*/
|
||||
export interface CubicResampler {
|
||||
B: number; // 0..1
|
||||
C: number; // 0..1
|
||||
}
|
||||
/**
|
||||
|
||||
* Specifies sampling using filter and mipmap options
|
||||
*/
|
||||
export interface FilterOptions {
|
||||
filter: FilterMode;
|
||||
mipmap?: MipmapMode; // defaults to None if not specified
|
||||
}
|
||||
|
||||
/**
|
||||
* See SkMaskFilter.h for more on this class. The objects are opaque.
|
||||
*/
|
||||
|
BIN
modules/canvaskit/tests/assets/mandrill_16.png
Normal file
BIN
modules/canvaskit/tests/assets/mandrill_16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
@ -296,31 +296,51 @@ describe('Core canvas behavior', () => {
|
||||
paint.setColor(CanvasKit.Color(0, 0, 0, 0.8));
|
||||
|
||||
const srcs = [
|
||||
0, 0, 256, 256,
|
||||
256, 0, 512, 256,
|
||||
0, 256, 256, 512,
|
||||
256, 256, 512, 512,
|
||||
0, 0, 8, 8,
|
||||
8, 0, 16, 8,
|
||||
0, 8, 8, 16,
|
||||
8, 8, 16, 16,
|
||||
];
|
||||
|
||||
const dsts = [
|
||||
0.5, 0, 20, 20,
|
||||
0.5, 0, 300, 20,
|
||||
0.5, 0, 20, 300,
|
||||
0.5, 0, 300, 300,
|
||||
10, 0, 0, 0,
|
||||
10, 0, 100, 0,
|
||||
10, 0, 0, 100,
|
||||
10, 0, 100, 100,
|
||||
];
|
||||
|
||||
const colors = Uint32Array.of(
|
||||
CanvasKit.ColorAsInt( 85, 170, 10, 128), // light green
|
||||
CanvasKit.ColorAsInt( 51, 51, 191, 128), // light blue
|
||||
CanvasKit.ColorAsInt( 0, 0, 0, 128),
|
||||
CanvasKit.ColorAsInt(256, 256, 256, 128),
|
||||
CanvasKit.ColorAsInt(255, 255, 255, 128),
|
||||
);
|
||||
|
||||
canvas.drawAtlas(atlas, srcs, dsts, paint, CanvasKit.BlendMode.Modulate, colors);
|
||||
// sampling for each of the 4 instances
|
||||
const sampling = [
|
||||
null,
|
||||
{B: 0, C: 0.5},
|
||||
{filter: CanvasKit.FilterMode.Nearest, mipmap: CanvasKit.MipmapMode.None},
|
||||
{filter: CanvasKit.FilterMode.Linear, mipmap: CanvasKit.MipmapMode.Nearest},
|
||||
];
|
||||
|
||||
// positioning for each of the 4 instances
|
||||
const offset = [
|
||||
[0, 0], [256, 0], [0, 256], [256, 256]
|
||||
];
|
||||
|
||||
canvas.translate(20, 20);
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
canvas.save();
|
||||
canvas.translate(offset[i][0], offset[i][1]);
|
||||
canvas.drawAtlas(atlas, srcs, dsts, paint, CanvasKit.BlendMode.SrcOver, colors,
|
||||
sampling[i]);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
atlas.delete();
|
||||
paint.delete();
|
||||
}, '/assets/mandrill_512.png');
|
||||
}, '/assets/mandrill_16.png');
|
||||
|
||||
gm('image_decoding_methods', async (canvas) => {
|
||||
canvas.clear(CanvasKit.WHITE);
|
||||
|
Loading…
Reference in New Issue
Block a user