/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gm.h" #include "Resources.h" #include "SampleCode.h" #include "SkCanvas.h" #include "SkInterpolator.h" #include "SkSurface.h" #include "SkRandom.h" #include "SkTime.h" #define N 128 static SkImage* make_image() { SkImageInfo info = SkImageInfo::MakeN32Premul(N, N); SkAutoTUnref surface(SkSurface::NewRaster(info)); SkCanvas* canvas = surface->getCanvas(); SkPath path; path.setFillType(SkPath::kEvenOdd_FillType); path.addRect(SkRect::MakeWH(N/2, N)); path.addRect(SkRect::MakeWH(N, N/2)); path.moveTo(0, 0); path.lineTo(N, 0); path.lineTo(0, N); path.close(); canvas->drawPath(path, SkPaint()); return surface->newImageSnapshot(); } struct AnimValue { SkScalar fValue; SkScalar fMin; SkScalar fMax; SkScalar fMod; operator SkScalar() const { return fValue; } void set(SkScalar value, SkScalar min, SkScalar max) { fValue = value; fMin = min; fMax = max; fMod = 0; } void setMod(SkScalar value, SkScalar mod) { fValue = value; fMin = 0; fMax = 0; fMod = mod; } SkScalar inc(SkScalar delta) { fValue += delta; return this->fixUp(); } SkScalar fixUp() { if (fMod) { fValue = SkScalarMod(fValue, fMod); } else { if (fValue > fMax) { fValue = fMax; } else if (fValue < fMin) { fValue = fMin; } } return fValue; } }; #define ANGLE_DELTA 3 #define SCALE_DELTA (SK_Scalar1 / 32) class FilterQualityView : public SampleView { SkAutoTUnref fImage; AnimValue fScale, fAngle; SkInterpolator fTrans; public: FilterQualityView() : fImage(make_image()), fTrans(2, 2) { fScale.set(1, SK_Scalar1 / 8, 1); fAngle.setMod(0, 360); SkScalar values[2]; fTrans.setMirror(true); fTrans.setReset(true); fTrans.setRepeatCount(999); values[0] = values[1] = 0; fTrans.setKeyFrame(0, SkTime::GetMSecs(), values); values[0] = values[1] = 1; fTrans.setKeyFrame(1, SkTime::GetMSecs() + 2000, values); } protected: // overrides from SkEventSink bool onQuery(SkEvent* evt) SK_OVERRIDE { if (SampleCode::TitleQ(*evt)) { SampleCode::TitleR(evt, "FilterQuality"); return true; } SkUnichar uni; if (SampleCode::CharQ(*evt, &uni)) { switch (uni) { case '1': fAngle.inc(-ANGLE_DELTA); this->inval(NULL); return true; 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; default: break; } } return this->INHERITED::onQuery(evt); } void drawHere(SkCanvas* canvas, SkScalar x, SkScalar y, SkPaint::FilterLevel filter) { SkAutoCanvasRestore acr(canvas, true); SkPaint paint; paint.setAntiAlias(true); paint.setFilterLevel(filter); canvas->translate(x, y); canvas->scale(fScale, fScale); canvas->rotate(fAngle); canvas->drawImage(fImage, -SkScalarHalf(fImage->width()), -SkScalarHalf(fImage->height()), &paint); } void onDrawContent(SkCanvas* canvas) SK_OVERRIDE { 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); } SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(40); SkString str; str.appendScalar(fScale); canvas->drawText(str.c_str(), str.size(), 450, 100, paint); str.reset(); str.appendScalar(fAngle); canvas->drawText(str.c_str(), str.size(), 450, 150, paint); str.reset(); str.appendScalar(trans[0]); canvas->drawText(str.c_str(), str.size(), 450, 200, paint); str.reset(); str.appendScalar(trans[1]); canvas->drawText(str.c_str(), str.size(), 450, 250, paint); } virtual bool handleKey(SkKey key) { this->inval(NULL); return true; } private: typedef SampleView INHERITED; }; ////////////////////////////////////////////////////////////////////////////// static SkView* MyFactory() { return new FilterQualityView; } static SkViewRegister reg(MyFactory);