Hide legacy drawImage methods

Migrate clients to use drawImage(... sampling)
rather than relying on paint's filter-quality.

This CL just gets started, introducing the build-flag.

Bug: skia:7650
Change-Id: I4afdd964c6f805058afee0a8f3a6887d501ad42b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/356076
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
Mike Reed 2021-01-19 17:58:25 -05:00 committed by Skia Commit-Bot
parent e0fe62adaa
commit 18aeb5731b
9 changed files with 115 additions and 59 deletions

View File

@ -6,7 +6,6 @@
*/
#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFilterQuality.h"
@ -16,14 +15,14 @@
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/core/SkSurface.h"
namespace skiagm {
// This GM exercises HighQuality anisotropic filtering.
class AnisotropicGM : public GM {
public:
AnisotropicGM() : fFilterQuality(kHigh_SkFilterQuality) {
AnisotropicGM() : fSampling({1.0f/3, 1.0f/3}) {
this->setBGColor(0xFFCCCCCC);
}
@ -42,32 +41,32 @@ protected:
constexpr SkScalar kAngleStep = 360.0f / kNumLines;
constexpr int kInnerOffset = 10;
fBM.allocN32Pixels(kImageSize, kImageSize, true);
auto info = SkImageInfo::MakeN32(kImageSize, kImageSize, kOpaque_SkAlphaType);
auto surf = SkSurface::MakeRaster(info);
auto canvas = surf->getCanvas();
SkCanvas canvas(fBM);
canvas.clear(SK_ColorWHITE);
canvas->clear(SK_ColorWHITE);
SkPaint p;
p.setAntiAlias(true);
SkScalar angle = 0.0f, sin, cos;
canvas.translate(kImageSize/2.0f, kImageSize/2.0f);
canvas->translate(kImageSize/2.0f, kImageSize/2.0f);
for (int i = 0; i < kNumLines; ++i, angle += kAngleStep) {
sin = SkScalarSin(angle);
cos = SkScalarCos(angle);
canvas.drawLine(cos * kInnerOffset, sin * kInnerOffset,
cos * kImageSize/2, sin * kImageSize/2, p);
canvas->drawLine(cos * kInnerOffset, sin * kInnerOffset,
cos * kImageSize/2, sin * kImageSize/2, p);
}
fImage = surf->makeImageSnapshot();
}
void draw(SkCanvas* canvas, int x, int y, int xSize, int ySize) {
SkRect r = SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
SkIntToScalar(xSize), SkIntToScalar(ySize));
SkPaint p;
p.setFilterQuality(fFilterQuality);
canvas->drawImageRect(fBM.asImage(), r, &p);
canvas->drawImageRect(fImage.get(), r, fSampling, nullptr,
SkCanvas::kStrict_SrcRectConstraint);
}
void onDraw(SkCanvas* canvas) override {
@ -77,34 +76,34 @@ protected:
// Minimize vertically
for (int i = 0; i < (int)SK_ARRAY_COUNT(gScales); ++i) {
int height = SkScalarFloorToInt(fBM.height() * gScales[i]);
int height = SkScalarFloorToInt(fImage->height() * gScales[i]);
int yOff;
if (i <= (int)SK_ARRAY_COUNT(gScales)/2) {
yOff = kSpacer + i * (fBM.height() + kSpacer);
yOff = kSpacer + i * (fImage->height() + kSpacer);
} else {
// Position the more highly squashed images with their less squashed counterparts
yOff = (SK_ARRAY_COUNT(gScales) - i) * (fBM.height() + kSpacer) - height;
yOff = (SK_ARRAY_COUNT(gScales) - i) * (fImage->height() + kSpacer) - height;
}
this->draw(canvas, kSpacer, yOff, fBM.width(), height);
this->draw(canvas, kSpacer, yOff, fImage->width(), height);
}
// Minimize horizontally
for (int i = 0; i < (int)SK_ARRAY_COUNT(gScales); ++i) {
int width = SkScalarFloorToInt(fBM.width() * gScales[i]);
int width = SkScalarFloorToInt(fImage->width() * gScales[i]);
int xOff, yOff;
if (i <= (int)SK_ARRAY_COUNT(gScales)/2) {
xOff = fBM.width() + 2*kSpacer;
yOff = kSpacer + i * (fBM.height() + kSpacer);
xOff = fImage->width() + 2*kSpacer;
yOff = kSpacer + i * (fImage->height() + kSpacer);
} else {
// Position the more highly squashed images with their less squashed counterparts
xOff = fBM.width() + 2*kSpacer + fBM.width() - width;
yOff = kSpacer + (SK_ARRAY_COUNT(gScales) - i - 1) * (fBM.height() + kSpacer);
xOff = fImage->width() + 2*kSpacer + fImage->width() - width;
yOff = kSpacer + (SK_ARRAY_COUNT(gScales) - i - 1) * (fImage->height() + kSpacer);
}
this->draw(canvas, xOff, yOff, width, fBM.height());
this->draw(canvas, xOff, yOff, width, fImage->height());
}
}
@ -113,8 +112,8 @@ private:
static constexpr int kSpacer = 10;
static constexpr int kNumVertImages = 5;
SkBitmap fBM;
SkFilterQuality fFilterQuality;
sk_sp<SkImage> fImage;
SkSamplingOptions fSampling;
using INHERITED = GM;
};

View File

@ -65,7 +65,7 @@ void sk_test_c_api(sk_canvas_t* canvas) {
sk_image_t* img0 = sk_surface_new_image_snapshot(surf);
sk_surface_unref(surf);
sk_canvas_draw_image(canvas, img0, W + 10, 10, NULL);
sk_canvas_draw_image(canvas, img0, W + 10, 10, NULL, NULL);
sk_data_t* data = sk_image_encode(img0);
sk_image_unref(img0);
@ -74,7 +74,7 @@ void sk_test_c_api(sk_canvas_t* canvas) {
sk_data_unref(data);
if (img1) {
sk_canvas_draw_image(canvas, img1, W/2, H/2, NULL);
sk_canvas_draw_image(canvas, img1, W/2, H/2, NULL, NULL);
sk_image_unref(img1);
}
}

View File

@ -123,8 +123,8 @@ SK_API void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t
@param sk_paint_t* (may be NULL) the paint used to draw the image.
*/
SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*,
float x, float y, const sk_paint_t*);
SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*, float x, float y,
const sk_sampling_options_t*, const sk_paint_t*);
/**
Draw the specified image, scaling and translating so that it fills
the specified dst rect. If the src rect is non-null, only that
@ -133,8 +133,8 @@ SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*,
@param sk_paint_t* (may be NULL) The paint used to draw the image.
*/
SK_API void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*,
const sk_rect_t* src,
const sk_rect_t* dst, const sk_paint_t*);
const sk_rect_t* src, const sk_rect_t* dst,
const sk_sampling_options_t*, const sk_paint_t*);
/**
Draw the picture into this canvas (replay the pciture's drawing commands).

View File

@ -217,6 +217,28 @@ typedef struct sk_shader_t sk_shader_t;
*/
typedef struct sk_surface_t sk_surface_t;
typedef enum {
NEAREST_SK_FILTER_MODE,
LINEAR_SK_FILTER_MODE,
} sk_filter_mode_t;
typedef enum {
NONE_SK_MIPMAP_MODE,
NEAREST_SK_MIPMAP_MODE,
LINEAR_SK_MIPMAP_MODE,
} sk_mipmap_mode_t;
typedef struct {
float B, C;
} sk_cubic_resampler_t;
typedef struct {
bool useCubic;
sk_cubic_resampler_t cubic;
sk_filter_mode_t filter;
sk_mipmap_mode_t mipmap;
} sk_sampling_options_t;
typedef enum {
CLEAR_SK_XFERMODE_MODE,
SRC_SK_XFERMODE_MODE,

View File

@ -38,6 +38,8 @@
//#define SK_SUPPORT_LEGACY_ONDRAWIMAGERECT
#define SK_SUPPORT_LEGACY_DRAWBITMAP
#define SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
class GrBackendRenderTarget;
class GrRecordingContext;
class GrSurfaceDrawContext;
@ -1426,6 +1428,14 @@ public:
*/
void drawPath(const SkPath& path, const SkPaint& paint);
void drawImage(const SkImage* image, SkScalar left, SkScalar top) {
this->drawImage(image, left, top, SkSamplingOptions(), nullptr);
}
void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top) {
this->drawImage(image.get(), left, top, SkSamplingOptions(), nullptr);
}
#ifdef SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
/** Draws SkImage image, with its top-left corner at (left, top),
using clip, SkMatrix, and optional SkPaint paint.
@ -1439,7 +1449,7 @@ public:
and so on; or nullptr
*/
void drawImage(const SkImage* image, SkScalar left, SkScalar top,
const SkPaint* paint = nullptr);
const SkPaint* paint);
/** Draws SkImage image, with its top-left corner at (left, top),
using clip, SkMatrix, and optional SkPaint paint.
@ -1454,9 +1464,10 @@ public:
and so on; or nullptr
*/
void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
const SkPaint* paint = nullptr) {
const SkPaint* paint) {
this->drawImage(image.get(), left, top, paint);
}
#endif
/** \enum SkCanvas::SrcRectConstraint
SrcRectConstraint controls the behavior at the edge of source SkRect,
@ -1473,6 +1484,7 @@ public:
kFast_SrcRectConstraint, //!< sample outside bounds; faster
};
#ifdef SK_SUPPORT_LEGACY_DRAWIMAGE_NOSAMPLING
/** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
@ -1643,6 +1655,7 @@ public:
void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint) {
this->drawImageRect(image.get(), dst, paint);
}
#endif
void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkSamplingOptions&,
const SkPaint* = nullptr);

View File

@ -321,23 +321,36 @@ void sk_canvas_draw_path(sk_canvas_t* ccanvas, const sk_path_t* cpath, const sk_
AsCanvas(ccanvas)->drawPath(AsPath(*cpath), AsPaint(*cpaint));
}
static SkSamplingOptions to_sampling(const sk_sampling_options_t* s) {
if (s) {
if (s->useCubic) {
return SkSamplingOptions({s->cubic.B, s->cubic.C});
} else {
return SkSamplingOptions(SkFilterMode(s->filter), SkMipmapMode(s->mipmap));
}
}
return SkSamplingOptions();
}
void sk_canvas_draw_image(sk_canvas_t* ccanvas, const sk_image_t* cimage, float x, float y,
const sk_paint_t* cpaint) {
AsCanvas(ccanvas)->drawImage(AsImage(cimage), x, y, AsPaint(cpaint));
const sk_sampling_options_t* csamp, const sk_paint_t* cpaint) {
AsCanvas(ccanvas)->drawImage(AsImage(cimage), x, y, to_sampling(csamp), AsPaint(cpaint));
}
void sk_canvas_draw_image_rect(sk_canvas_t* ccanvas, const sk_image_t* cimage,
const sk_rect_t* csrcR, const sk_rect_t* cdstR,
const sk_paint_t* cpaint) {
const sk_sampling_options_t* csamp, const sk_paint_t* cpaint) {
SkCanvas* canvas = AsCanvas(ccanvas);
const SkImage* image = AsImage(cimage);
const SkRect& dst = AsRect(*cdstR);
const SkSamplingOptions sampling = to_sampling(csamp);
const SkPaint* paint = AsPaint(cpaint);
if (csrcR) {
canvas->drawImageRect(image, AsRect(*csrcR), dst, paint);
canvas->drawImageRect(image, AsRect(*csrcR), dst, sampling, paint,
SkCanvas::kStrict_SrcRectConstraint);
} else {
canvas->drawImageRect(image, dst, paint);
canvas->drawImageRect(image, dst, sampling, paint, SkCanvas::kStrict_SrcRectConstraint);
}
}

View File

@ -407,7 +407,7 @@ void DebugCanvas::onDrawImage(const SkImage* image,
SkScalar left,
SkScalar top,
const SkPaint* paint) {
this->addDrawCommand(new DrawImageCommand(image, left, top, paint));
this->addDrawCommand(new DrawImageCommand(image, left, top, SkSamplingOptions(), paint));
}
void DebugCanvas::onDrawImageLattice(const SkImage* image,
@ -434,7 +434,11 @@ void DebugCanvas::onDrawImageRect(const SkImage* image,
this->addDrawCommand(new DrawImageRectLayerCommand(
fLayerManager, fnextDrawImageRectLayerId, fFrame, src, dst, paint, constraint));
} else {
this->addDrawCommand(new DrawImageRectCommand(image, src, dst, paint, constraint));
if (!src) {
src = &dst; // wrong, but just needed until we can switch to new virtuals
}
this->addDrawCommand(new DrawImageRectCommand(image, *src, dst, SkSamplingOptions(),
paint, constraint));
}
// Reset expectation so next drawImageRect is not special.
fnextDrawImageRectLayerId = -1;
@ -465,9 +469,9 @@ void DebugCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[],
void DebugCanvas::onDrawImage2(const SkImage* image,
SkScalar left,
SkScalar top,
const SkSamplingOptions& sampling, // todo
const SkSamplingOptions& sampling,
const SkPaint* paint) {
this->addDrawCommand(new DrawImageCommand(image, left, top, paint));
this->addDrawCommand(new DrawImageCommand(image, left, top, sampling, paint));
}
void DebugCanvas::onDrawImageLattice2(const SkImage* image,
@ -481,7 +485,7 @@ void DebugCanvas::onDrawImageLattice2(const SkImage* image,
void DebugCanvas::onDrawImageRect2(const SkImage* image,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions& sampling, // todo
const SkSamplingOptions& sampling,
const SkPaint* paint,
SrcRectConstraint constraint) {
if (fnextDrawImageRectLayerId != -1 && fLayerManager) {
@ -496,7 +500,7 @@ void DebugCanvas::onDrawImageRect2(const SkImage* image,
this->addDrawCommand(new DrawImageRectLayerCommand(
fLayerManager, fnextDrawImageRectLayerId, fFrame, &src, dst, paint, constraint));
} else {
this->addDrawCommand(new DrawImageRectCommand(image, &src, dst, paint, constraint));
this->addDrawCommand(new DrawImageRectCommand(image, src, dst, sampling, paint, constraint));
}
// Reset expectation so next drawImageRect is not special.
fnextDrawImageRectLayerId = -1;

View File

@ -1195,18 +1195,20 @@ void DrawAnnotationCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlData
////
DrawImageCommand::DrawImageCommand(const SkImage* image,
SkScalar left,
SkScalar top,
const SkPaint* paint)
DrawImageCommand::DrawImageCommand(const SkImage* image,
SkScalar left,
SkScalar top,
const SkSamplingOptions& sampling,
const SkPaint* paint)
: INHERITED(kDrawImage_OpType)
, fImage(SkRef(image))
, fLeft(left)
, fTop(top)
, fSampling(sampling)
, fPaint(paint) {}
void DrawImageCommand::execute(SkCanvas* canvas) const {
canvas->drawImage(fImage.get(), fLeft, fTop, fPaint.getMaybeNull());
canvas->drawImage(fImage.get(), fLeft, fTop, fSampling, fPaint.getMaybeNull());
}
bool DrawImageCommand::render(SkCanvas* canvas) const {
@ -1299,20 +1301,21 @@ void DrawImageLatticeCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDa
}
DrawImageRectCommand::DrawImageRectCommand(const SkImage* image,
const SkRect* src,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions& sampling,
const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint)
: INHERITED(kDrawImageRect_OpType)
, fImage(SkRef(image))
, fSrc(src)
, fDst(dst)
, fSampling(sampling)
, fPaint(paint)
, fConstraint(constraint) {}
void DrawImageRectCommand::execute(SkCanvas* canvas) const {
canvas->legacy_drawImageRect(
fImage.get(), fSrc.getMaybeNull(), fDst, fPaint.getMaybeNull(), fConstraint);
canvas->drawImageRect(fImage.get(), fSrc, fDst, fSampling, fPaint.getMaybeNull(), fConstraint);
}
bool DrawImageRectCommand::render(SkCanvas* canvas) const {
@ -1332,10 +1335,8 @@ uint64_t DrawImageRectCommand::imageId(UrlDataManager& udm) const {
void DrawImageRectCommand::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const {
INHERITED::toJSON(writer, urlDataManager);
flatten(*fImage, writer, urlDataManager);
if (fSrc.isValid()) {
writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
MakeJsonRect(writer, *fSrc);
}
writer.appendName(DEBUGCANVAS_ATTRIBUTE_SRC);
MakeJsonRect(writer, fSrc);
writer.appendName(DEBUGCANVAS_ATTRIBUTE_DST);
MakeJsonRect(writer, fDst);
if (fPaint.isValid()) {

View File

@ -252,7 +252,8 @@ private:
class DrawImageCommand : public DrawCommand {
public:
DrawImageCommand(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint);
DrawImageCommand(const SkImage* image, SkScalar left, SkScalar top,
const SkSamplingOptions&, const SkPaint* paint);
void execute(SkCanvas* canvas) const override;
bool render(SkCanvas* canvas) const override;
void toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager) const override;
@ -262,6 +263,7 @@ private:
sk_sp<const SkImage> fImage;
SkScalar fLeft;
SkScalar fTop;
SkSamplingOptions fSampling;
SkTLazy<SkPaint> fPaint;
using INHERITED = DrawCommand;
@ -290,8 +292,9 @@ private:
class DrawImageRectCommand : public DrawCommand {
public:
DrawImageRectCommand(const SkImage* image,
const SkRect* src,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions& sampling,
const SkPaint* paint,
SkCanvas::SrcRectConstraint constraint);
void execute(SkCanvas* canvas) const override;
@ -301,8 +304,9 @@ public:
private:
sk_sp<const SkImage> fImage;
SkTLazy<SkRect> fSrc;
SkRect fSrc;
SkRect fDst;
SkSamplingOptions fSampling;
SkTLazy<SkPaint> fPaint;
SkCanvas::SrcRectConstraint fConstraint;