Index: samplecode/SampleFilterQuality.cpp |
diff --git a/samplecode/SampleFilterQuality.cpp b/samplecode/SampleFilterQuality.cpp |
index 4c778e35e4881b29faaafe87b1c748adafdc534d..12aae83245c40d7bcc801316979fabbd53e77fb2 100644 |
--- a/samplecode/SampleFilterQuality.cpp |
+++ b/samplecode/SampleFilterQuality.cpp |
@@ -15,12 +15,23 @@ |
#include "SkRandom.h" |
#include "SkTime.h" |
+static SkSurface* make_surface(SkCanvas* canvas, const SkImageInfo& info) { |
+ SkSurface* surface = canvas->newSurface(info); |
+ if (!surface) { |
+ surface = SkSurface::NewRaster(info); |
+ } |
+ return surface; |
+} |
+ |
#define N 128 |
+#define ANGLE_DELTA 3 |
+#define SCALE_DELTA (SK_Scalar1 / 32) |
static SkImage* make_image() { |
- SkImageInfo info = SkImageInfo::MakeN32Premul(N, N); |
+ SkImageInfo info = SkImageInfo::MakeN32(N, N, kOpaque_SkAlphaType); |
SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info)); |
SkCanvas* canvas = surface->getCanvas(); |
+ canvas->drawColor(SK_ColorWHITE); |
SkPath path; |
path.setFillType(SkPath::kEvenOdd_FillType); |
@@ -33,6 +44,36 @@ static SkImage* make_image() { |
return surface->newImageSnapshot(); |
} |
+static SkImage* zoom_up(SkImage* orig) { |
+ const SkScalar S = 8; // amount to scale up |
+ const int D = 2; // dimension scaling for the offscreen |
+ // since we only view the center, don't need to produce the entire thing |
+ |
+ SkImageInfo info = SkImageInfo::MakeN32(orig->width() * D, orig->height() * D, |
+ kOpaque_SkAlphaType); |
+ SkAutoTUnref<SkSurface> surface(orig->newSurface(info)); |
+ SkCanvas* canvas = surface->getCanvas(); |
+ canvas->drawColor(SK_ColorWHITE); |
+ canvas->scale(S, S); |
+ canvas->translate(-SkScalarHalf(orig->width()) * (S - D) / S, |
+ -SkScalarHalf(orig->height()) * (S - D) / S); |
+ canvas->drawImage(orig, 0, 0, NULL); |
+ |
+ if (S > 3) { |
+ SkPaint paint; |
+ paint.setColor(SK_ColorWHITE); |
+ for (int i = 1; i < orig->height(); ++i) { |
+ SkScalar y = SkIntToScalar(i); |
+ canvas->drawLine(0, y, SkIntToScalar(orig->width()), y, paint); |
+ } |
+ for (int i = 1; i < orig->width(); ++i) { |
+ SkScalar x = SkIntToScalar(i); |
+ canvas->drawLine(x, 0, x, SkIntToScalar(orig->height()), paint); |
+ } |
+ } |
+ return surface->newImageSnapshot(); |
+} |
+ |
struct AnimValue { |
SkScalar fValue; |
SkScalar fMin; |
@@ -74,17 +115,28 @@ struct AnimValue { |
} |
}; |
-#define ANGLE_DELTA 3 |
-#define SCALE_DELTA (SK_Scalar1 / 32) |
+static void draw_box_frame(SkCanvas* canvas, int width, int height) { |
+ SkPaint p; |
+ p.setStyle(SkPaint::kStroke_Style); |
+ p.setColor(SK_ColorRED); |
+ SkRect r = SkRect::MakeIWH(width, height); |
+ r.inset(0.5f, 0.5f); |
+ canvas->drawRect(r, p); |
+ canvas->drawLine(r.left(), r.top(), r.right(), r.bottom(), p); |
+ canvas->drawLine(r.left(), r.bottom(), r.right(), r.top(), p); |
+} |
class FilterQualityView : public SampleView { |
SkAutoTUnref<SkImage> fImage; |
AnimValue fScale, fAngle; |
- |
+ SkSize fCell; |
SkInterpolator fTrans; |
+ bool fShowFatBits; |
public: |
- FilterQualityView() : fImage(make_image()), fTrans(2, 2) { |
+ FilterQualityView() : fImage(make_image()), fTrans(2, 2), fShowFatBits(true) { |
+ fCell.set(256, 256); |
+ |
fScale.set(1, SK_Scalar1 / 8, 1); |
fAngle.setMod(0, 360); |
@@ -100,8 +152,6 @@ public: |
} |
protected: |
- |
- // overrides from SkEventSink |
bool onQuery(SkEvent* evt) SK_OVERRIDE { |
if (SampleCode::TitleQ(*evt)) { |
SampleCode::TitleR(evt, "FilterQuality"); |
@@ -114,60 +164,115 @@ protected: |
case '2': fAngle.inc( ANGLE_DELTA); this->inval(NULL); return true; |
case '3': fScale.inc(-SCALE_DELTA); this->inval(NULL); return true; |
case '4': fScale.inc( SCALE_DELTA); this->inval(NULL); return true; |
+ case '5': fShowFatBits = !fShowFatBits; this->inval(NULL); return true; |
default: break; |
} |
} |
return this->INHERITED::onQuery(evt); |
} |
- void drawHere(SkCanvas* canvas, SkScalar x, SkScalar y, SkPaint::FilterLevel filter) { |
- SkAutoCanvasRestore acr(canvas, true); |
+ void drawTheImage(SkCanvas* canvas, const SkISize& size, SkPaint::FilterLevel filter, |
+ SkScalar dx, SkScalar dy) { |
SkPaint paint; |
paint.setAntiAlias(true); |
paint.setFilterLevel(filter); |
- canvas->translate(x, y); |
+ SkAutoCanvasRestore acr(canvas, true); |
+ |
+ canvas->translate(dx, dy); |
+ |
+ canvas->translate(SkScalarHalf(size.width()), SkScalarHalf(size.height())); |
canvas->scale(fScale, fScale); |
canvas->rotate(fAngle); |
canvas->drawImage(fImage, -SkScalarHalf(fImage->width()), -SkScalarHalf(fImage->height()), |
&paint); |
+ |
+ if (false) { |
+ acr.restore(); |
+ draw_box_frame(canvas, size.width(), size.height()); |
+ } |
+ } |
+ |
+ void drawHere(SkCanvas* canvas, SkPaint::FilterLevel filter, SkScalar dx, SkScalar dy) { |
+ SkCanvas* origCanvas = canvas; |
+ SkAutoCanvasRestore acr(canvas, true); |
+ |
+ SkISize size = SkISize::Make(fImage->width(), fImage->height()); |
+ |
+ SkAutoTUnref<SkSurface> surface; |
+ if (fShowFatBits) { |
+ // scale up so we don't clip rotations |
+ SkImageInfo info = SkImageInfo::MakeN32(fImage->width() * 2, fImage->height() * 2, |
+ kOpaque_SkAlphaType); |
+ surface.reset(make_surface(canvas, info)); |
+ canvas = surface->getCanvas(); |
+ canvas->drawColor(SK_ColorWHITE); |
+ size.set(info.width(), info.height()); |
+ } else { |
+ canvas->translate(SkScalarHalf(fCell.width() - fImage->width()), |
+ SkScalarHalf(fCell.height() - fImage->height())); |
+ } |
+ this->drawTheImage(canvas, size, filter, dx, dy); |
+ |
+ if (surface) { |
+ SkAutoTUnref<SkImage> orig(surface->newImageSnapshot()); |
+ SkAutoTUnref<SkImage> zoomed(zoom_up(orig)); |
+ origCanvas->drawImage(zoomed, |
+ SkScalarHalf(fCell.width() - zoomed->width()), |
+ SkScalarHalf(fCell.height() - zoomed->height())); |
+ } |
+ } |
+ |
+ void drawBorders(SkCanvas* canvas) { |
+ SkPaint p; |
+ p.setStyle(SkPaint::kStroke_Style); |
+ p.setColor(SK_ColorBLUE); |
+ |
+ SkRect r = SkRect::MakeWH(fCell.width() * 2, fCell.height() * 2); |
+ r.inset(SK_ScalarHalf, SK_ScalarHalf); |
+ canvas->drawRect(r, p); |
+ canvas->drawLine(r.left(), r.centerY(), r.right(), r.centerY(), p); |
+ canvas->drawLine(r.centerX(), r.top(), r.centerX(), r.bottom(), p); |
} |
void onDrawContent(SkCanvas* canvas) SK_OVERRIDE { |
+ fCell.set(this->height() / 2, this->height() / 2); |
+ |
SkScalar trans[2]; |
fTrans.timeToValues(SkTime::GetMSecs(), trans); |
- canvas->translate(trans[0], trans[1]); |
- this->inval(NULL); |
- const struct { |
- SkScalar fX; |
- SkScalar fY; |
- SkPaint::FilterLevel fFilter; |
- } rec[] = { |
- { 100, 100, SkPaint::kNone_FilterLevel }, |
- { 300, 100, SkPaint::kLow_FilterLevel }, |
- { 100, 300, SkPaint::kMedium_FilterLevel }, |
- { 300, 300, SkPaint::kHigh_FilterLevel }, |
- }; |
- |
- for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) { |
- this->drawHere(canvas, rec[i].fX, rec[i].fY, rec[i].fFilter); |
+ for (int y = 0; y < 2; ++y) { |
+ for (int x = 0; x < 2; ++x) { |
+ int index = y * 2 + x; |
+ SkAutoCanvasRestore acr(canvas, true); |
+ canvas->translate(fCell.width() * x, fCell.height() * y); |
+ SkRect r = SkRect::MakeWH(fCell.width(), fCell.height()); |
+ r.inset(4, 4); |
+ canvas->clipRect(r); |
+ this->drawHere(canvas, SkPaint::FilterLevel(index), trans[0], trans[1]); |
+ } |
} |
+ this->drawBorders(canvas); |
+ |
+ const SkScalar textX = fCell.width() * 2 + 30; |
+ |
SkPaint paint; |
paint.setAntiAlias(true); |
- paint.setTextSize(40); |
+ paint.setTextSize(36); |
SkString str; |
str.appendScalar(fScale); |
- canvas->drawText(str.c_str(), str.size(), 450, 100, paint); |
+ canvas->drawText(str.c_str(), str.size(), textX, 100, paint); |
str.reset(); str.appendScalar(fAngle); |
- canvas->drawText(str.c_str(), str.size(), 450, 150, paint); |
+ canvas->drawText(str.c_str(), str.size(), textX, 150, paint); |
str.reset(); str.appendScalar(trans[0]); |
- canvas->drawText(str.c_str(), str.size(), 450, 200, paint); |
+ canvas->drawText(str.c_str(), str.size(), textX, 200, paint); |
str.reset(); str.appendScalar(trans[1]); |
- canvas->drawText(str.c_str(), str.size(), 450, 250, paint); |
-} |
+ canvas->drawText(str.c_str(), str.size(), textX, 250, paint); |
+ |
+ this->inval(NULL); |
+ } |
virtual bool handleKey(SkKey key) { |
this->inval(NULL); |