b0cee9bf9a
SkCanvas keeps its non-exotic drawBitmap calls for now but they immediately wrap the bitmap in SkImage::MakeFromBitmap. This will add a copy for mutable bitmaps, but this can be worked around by using images directly (preferred), or marking the bitmap as immutable. In practice, mutable bitmaps do not seem to be widely used so this is deemed acceptable for now. Several GMs are updated to mark the bitmaps as immutable in order to avoid pixel churn in how CPU vs. GPU mipmaps are generated. As we move towards explicit mipmap generation, this distinction will become less critical, so I'm just avoiding it for now. See skbug.com/9337 for mipmap proposal. The image diffs encountered in this CL directly related to generating mipmaps for bitmaps already cached on the GPU vs. not on the GPU yet. It was decided to copy if mutable vs. never copying the bitmap because it preserves the image guarantees the devices and canvas' rely on, and imposing the need to inspect an image for mutability is undesired. Bug: skia:10037, skia:9337 Change-Id: If152e6cae1e155ccf6bd2cd755895f3c7a0135a5 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/276004 Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
229 lines
7.5 KiB
C++
229 lines
7.5 KiB
C++
/*
|
|
* Copyright 2011 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/core/SkBitmap.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkColor.h"
|
|
#include "include/core/SkFilterQuality.h"
|
|
#include "include/core/SkFont.h"
|
|
#include "include/core/SkFontStyle.h"
|
|
#include "include/core/SkMatrix.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkRect.h"
|
|
#include "include/core/SkScalar.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkTypeface.h"
|
|
#include "include/core/SkTypes.h"
|
|
#include "tools/Resources.h"
|
|
#include "tools/ToolUtils.h"
|
|
|
|
static void setTypeface(SkFont* font, const char name[], SkFontStyle style) {
|
|
font->setTypeface(ToolUtils::create_portable_typeface(name, style));
|
|
}
|
|
|
|
static SkSize computeSize(const SkBitmap& bm, const SkMatrix& mat) {
|
|
SkRect bounds = SkRect::MakeWH(SkIntToScalar(bm.width()),
|
|
SkIntToScalar(bm.height()));
|
|
mat.mapRect(&bounds);
|
|
return SkSize::Make(bounds.width(), bounds.height());
|
|
}
|
|
|
|
static void draw_cell(SkCanvas* canvas, const SkBitmap& bm, const SkMatrix& mat, SkScalar dx,
|
|
SkFilterQuality lvl) {
|
|
SkPaint paint;
|
|
paint.setFilterQuality(lvl);
|
|
|
|
SkAutoCanvasRestore acr(canvas, true);
|
|
canvas->translate(dx, 0);
|
|
canvas->concat(mat);
|
|
canvas->drawBitmap(bm, 0, 0, &paint);
|
|
}
|
|
|
|
static void draw_row(SkCanvas* canvas, const SkBitmap& bm, const SkMatrix& mat, SkScalar dx) {
|
|
draw_cell(canvas, bm, mat, 0 * dx, kNone_SkFilterQuality);
|
|
draw_cell(canvas, bm, mat, 1 * dx, kLow_SkFilterQuality);
|
|
draw_cell(canvas, bm, mat, 2 * dx, kMedium_SkFilterQuality);
|
|
draw_cell(canvas, bm, mat, 3 * dx, kHigh_SkFilterQuality);
|
|
}
|
|
|
|
class FilterBitmapGM : public skiagm::GM {
|
|
void onOnceBeforeDraw() override {
|
|
this->setBGColor(0xFFDDDDDD);
|
|
|
|
this->makeBitmap();
|
|
fBM.setImmutable();
|
|
|
|
SkScalar cx = SkScalarHalf(fBM.width());
|
|
SkScalar cy = SkScalarHalf(fBM.height());
|
|
SkScalar scale = this->getScale();
|
|
|
|
// these two matrices use a scale factor configured by the subclass
|
|
fMatrix[0].setScale(scale, scale);
|
|
fMatrix[1].setRotate(30, cx, cy); fMatrix[1].postScale(scale, scale);
|
|
|
|
// up/down scaling mix
|
|
fMatrix[2].setScale(0.7f, 1.05f);
|
|
}
|
|
|
|
protected:
|
|
SkBitmap fBM;
|
|
SkMatrix fMatrix[3];
|
|
|
|
SkISize onISize() override { return SkISize::Make(1024, 768); }
|
|
|
|
virtual void makeBitmap() = 0;
|
|
virtual SkScalar getScale() = 0;
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
|
|
canvas->translate(10, 10);
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(fMatrix); ++i) {
|
|
SkSize size = computeSize(fBM, fMatrix[i]);
|
|
size.fWidth += 20;
|
|
size.fHeight += 20;
|
|
|
|
draw_row(canvas, fBM, fMatrix[i], size.fWidth);
|
|
canvas->translate(0, size.fHeight);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FilterBitmapTextGM: public FilterBitmapGM {
|
|
public:
|
|
FilterBitmapTextGM(float textSize) : fTextSize(textSize) {}
|
|
|
|
private:
|
|
SkString onShortName() override {
|
|
return SkStringPrintf("filterbitmap_text_%.2fpt", fTextSize);
|
|
}
|
|
const float fTextSize;
|
|
|
|
SkScalar getScale() override {
|
|
return 32.f/fTextSize;
|
|
}
|
|
|
|
void makeBitmap() override {
|
|
fBM.allocN32Pixels(int(fTextSize * 8), int(fTextSize * 6));
|
|
SkCanvas canvas(fBM);
|
|
canvas.drawColor(SK_ColorWHITE);
|
|
|
|
SkPaint paint;
|
|
SkFont font;
|
|
font.setSize(fTextSize);
|
|
font.setSubpixel(true);
|
|
|
|
setTypeface(&font, "serif", SkFontStyle::Normal());
|
|
canvas.drawString("Hamburgefons", fTextSize/2, 1.2f*fTextSize, font, paint);
|
|
setTypeface(&font, "serif", SkFontStyle::Bold());
|
|
canvas.drawString("Hamburgefons", fTextSize/2, 2.4f*fTextSize, font, paint);
|
|
setTypeface(&font, "serif", SkFontStyle::Italic());
|
|
canvas.drawString("Hamburgefons", fTextSize/2, 3.6f*fTextSize, font, paint);
|
|
setTypeface(&font, "serif", SkFontStyle::BoldItalic());
|
|
canvas.drawString("Hamburgefons", fTextSize/2, 4.8f*fTextSize, font, paint);
|
|
}
|
|
};
|
|
|
|
class FilterBitmapCheckerboardGM: public FilterBitmapGM {
|
|
SkString onShortName() override {
|
|
return SkStringPrintf("filterbitmap_checkerboard_%d_%d%s",
|
|
fSize, fNumChecks, fConvertToG8 ? "_g8" : "");
|
|
}
|
|
public:
|
|
FilterBitmapCheckerboardGM(int size, int num_checks, bool convertToG8 = false)
|
|
: fSize(size), fNumChecks(num_checks), fConvertToG8(convertToG8) {}
|
|
|
|
protected:
|
|
int fSize;
|
|
int fNumChecks;
|
|
|
|
SkScalar getScale() override {
|
|
return 192.f/fSize;
|
|
}
|
|
|
|
void makeBitmap() override {
|
|
fBM.allocN32Pixels(fSize, fSize);
|
|
for (int y = 0; y < fSize; y ++) {
|
|
for (int x = 0; x < fSize; x ++) {
|
|
SkPMColor* s = fBM.getAddr32(x, y);
|
|
int cx = (x * fNumChecks) / fSize;
|
|
int cy = (y * fNumChecks) / fSize;
|
|
if ((cx+cy)%2) {
|
|
*s = 0xFFFFFFFF;
|
|
} else {
|
|
*s = 0xFF000000;
|
|
}
|
|
}
|
|
}
|
|
if (fConvertToG8) {
|
|
SkBitmap tmp;
|
|
ToolUtils::copy_to_g8(&tmp, fBM);
|
|
fBM = tmp;
|
|
}
|
|
}
|
|
private:
|
|
const bool fConvertToG8;
|
|
typedef FilterBitmapGM INHERITED;
|
|
};
|
|
|
|
class FilterBitmapImageGM: public FilterBitmapGM {
|
|
const char* fFilename;
|
|
int fSize;
|
|
|
|
SkString onShortName() override {
|
|
return SkStringPrintf("filterbitmap_image_%s%s", fFilename, fConvertToG8 ? "_g8" : "");
|
|
}
|
|
|
|
public:
|
|
FilterBitmapImageGM(const char filename[], bool convertToG8 = false)
|
|
: fFilename(filename), fConvertToG8(convertToG8) {}
|
|
|
|
protected:
|
|
SkScalar getScale() override {
|
|
return 192.f/fSize;
|
|
}
|
|
|
|
void makeBitmap() override {
|
|
SkString resource = SkStringPrintf("images/%s", fFilename);
|
|
if (!GetResourceAsBitmap(resource.c_str(), &fBM)) {
|
|
fBM.allocN32Pixels(1, 1);
|
|
fBM.eraseARGB(255, 255, 0 , 0); // red == bad
|
|
}
|
|
fSize = fBM.height();
|
|
|
|
if (fConvertToG8) {
|
|
SkBitmap tmp;
|
|
ToolUtils::copy_to_g8(&tmp, fBM);
|
|
fBM = tmp;
|
|
}
|
|
}
|
|
private:
|
|
const bool fConvertToG8;
|
|
typedef FilterBitmapGM INHERITED;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DEF_GM( return new FilterBitmapTextGM(3); )
|
|
DEF_GM( return new FilterBitmapTextGM(7); )
|
|
DEF_GM( return new FilterBitmapTextGM(10); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(4,4); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(32,32); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(32,32, true); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(32,8); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(32,2); )
|
|
DEF_GM( return new FilterBitmapCheckerboardGM(192,192); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_16.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_32.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_64.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_64.png", true); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_128.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_256.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("mandrill_512.png"); )
|
|
DEF_GM( return new FilterBitmapImageGM("color_wheel.png"); )
|