blob: 64b7f5532217bd429e3701e416dbe0c934133528 [file] [log] [blame]
reedafdbedb2015-01-14 13:16:26 -08001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9
10#include "Resources.h"
11#include "SampleCode.h"
reed339cdbf2015-02-05 22:02:37 -080012#include "SkAnimTimer.h"
reedafdbedb2015-01-14 13:16:26 -080013#include "SkCanvas.h"
14#include "SkInterpolator.h"
15#include "SkSurface.h"
16#include "SkRandom.h"
17#include "SkTime.h"
18
reed09519db2015-01-17 19:36:08 -080019static SkSurface* make_surface(SkCanvas* canvas, const SkImageInfo& info) {
20 SkSurface* surface = canvas->newSurface(info);
21 if (!surface) {
22 surface = SkSurface::NewRaster(info);
23 }
24 return surface;
25}
26
reedafdbedb2015-01-14 13:16:26 -080027#define N 128
reed09519db2015-01-17 19:36:08 -080028#define ANGLE_DELTA 3
29#define SCALE_DELTA (SK_Scalar1 / 32)
reedafdbedb2015-01-14 13:16:26 -080030
31static SkImage* make_image() {
reed09519db2015-01-17 19:36:08 -080032 SkImageInfo info = SkImageInfo::MakeN32(N, N, kOpaque_SkAlphaType);
reedafdbedb2015-01-14 13:16:26 -080033 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
34 SkCanvas* canvas = surface->getCanvas();
reed09519db2015-01-17 19:36:08 -080035 canvas->drawColor(SK_ColorWHITE);
reedafdbedb2015-01-14 13:16:26 -080036
37 SkPath path;
38 path.setFillType(SkPath::kEvenOdd_FillType);
39
40 path.addRect(SkRect::MakeWH(N/2, N));
41 path.addRect(SkRect::MakeWH(N, N/2));
42 path.moveTo(0, 0); path.lineTo(N, 0); path.lineTo(0, N); path.close();
43
44 canvas->drawPath(path, SkPaint());
45 return surface->newImageSnapshot();
46}
47
reed09519db2015-01-17 19:36:08 -080048static SkImage* zoom_up(SkImage* orig) {
49 const SkScalar S = 8; // amount to scale up
50 const int D = 2; // dimension scaling for the offscreen
51 // since we only view the center, don't need to produce the entire thing
52
53 SkImageInfo info = SkImageInfo::MakeN32(orig->width() * D, orig->height() * D,
54 kOpaque_SkAlphaType);
55 SkAutoTUnref<SkSurface> surface(orig->newSurface(info));
56 SkCanvas* canvas = surface->getCanvas();
57 canvas->drawColor(SK_ColorWHITE);
58 canvas->scale(S, S);
59 canvas->translate(-SkScalarHalf(orig->width()) * (S - D) / S,
60 -SkScalarHalf(orig->height()) * (S - D) / S);
61 canvas->drawImage(orig, 0, 0, NULL);
62
63 if (S > 3) {
64 SkPaint paint;
65 paint.setColor(SK_ColorWHITE);
66 for (int i = 1; i < orig->height(); ++i) {
67 SkScalar y = SkIntToScalar(i);
68 canvas->drawLine(0, y, SkIntToScalar(orig->width()), y, paint);
69 }
70 for (int i = 1; i < orig->width(); ++i) {
71 SkScalar x = SkIntToScalar(i);
72 canvas->drawLine(x, 0, x, SkIntToScalar(orig->height()), paint);
73 }
74 }
75 return surface->newImageSnapshot();
76}
77
reedafdbedb2015-01-14 13:16:26 -080078struct AnimValue {
79 SkScalar fValue;
80 SkScalar fMin;
81 SkScalar fMax;
82 SkScalar fMod;
83
84 operator SkScalar() const { return fValue; }
85
86 void set(SkScalar value, SkScalar min, SkScalar max) {
87 fValue = value;
88 fMin = min;
89 fMax = max;
90 fMod = 0;
91 }
92
93 void setMod(SkScalar value, SkScalar mod) {
94 fValue = value;
95 fMin = 0;
96 fMax = 0;
97 fMod = mod;
98 }
99
100 SkScalar inc(SkScalar delta) {
101 fValue += delta;
102 return this->fixUp();
103 }
104
105 SkScalar fixUp() {
106 if (fMod) {
107 fValue = SkScalarMod(fValue, fMod);
108 } else {
109 if (fValue > fMax) {
110 fValue = fMax;
111 } else if (fValue < fMin) {
112 fValue = fMin;
113 }
114 }
115 return fValue;
116 }
117};
118
reed09519db2015-01-17 19:36:08 -0800119static void draw_box_frame(SkCanvas* canvas, int width, int height) {
120 SkPaint p;
121 p.setStyle(SkPaint::kStroke_Style);
122 p.setColor(SK_ColorRED);
123 SkRect r = SkRect::MakeIWH(width, height);
124 r.inset(0.5f, 0.5f);
125 canvas->drawRect(r, p);
126 canvas->drawLine(r.left(), r.top(), r.right(), r.bottom(), p);
127 canvas->drawLine(r.left(), r.bottom(), r.right(), r.top(), p);
128}
reedafdbedb2015-01-14 13:16:26 -0800129
130class FilterQualityView : public SampleView {
131 SkAutoTUnref<SkImage> fImage;
132 AnimValue fScale, fAngle;
reed09519db2015-01-17 19:36:08 -0800133 SkSize fCell;
reedafdbedb2015-01-14 13:16:26 -0800134 SkInterpolator fTrans;
reed339cdbf2015-02-05 22:02:37 -0800135 SkMSec fCurrTime;
reed09519db2015-01-17 19:36:08 -0800136 bool fShowFatBits;
reedafdbedb2015-01-14 13:16:26 -0800137
138public:
reed09519db2015-01-17 19:36:08 -0800139 FilterQualityView() : fImage(make_image()), fTrans(2, 2), fShowFatBits(true) {
140 fCell.set(256, 256);
141
reedafdbedb2015-01-14 13:16:26 -0800142 fScale.set(1, SK_Scalar1 / 8, 1);
143 fAngle.setMod(0, 360);
144
145 SkScalar values[2];
146 fTrans.setMirror(true);
147 fTrans.setReset(true);
148
reed339cdbf2015-02-05 22:02:37 -0800149 fCurrTime = 0;
150
reedafdbedb2015-01-14 13:16:26 -0800151 fTrans.setRepeatCount(999);
152 values[0] = values[1] = 0;
reed339cdbf2015-02-05 22:02:37 -0800153 fTrans.setKeyFrame(0, fCurrTime, values);
reedafdbedb2015-01-14 13:16:26 -0800154 values[0] = values[1] = 1;
reed339cdbf2015-02-05 22:02:37 -0800155 fTrans.setKeyFrame(1, fCurrTime + 2000, values);
reedafdbedb2015-01-14 13:16:26 -0800156 }
157
158protected:
mtklein36352bf2015-03-25 18:17:31 -0700159 bool onQuery(SkEvent* evt) override {
reedafdbedb2015-01-14 13:16:26 -0800160 if (SampleCode::TitleQ(*evt)) {
161 SampleCode::TitleR(evt, "FilterQuality");
162 return true;
163 }
164 SkUnichar uni;
165 if (SampleCode::CharQ(*evt, &uni)) {
166 switch (uni) {
167 case '1': fAngle.inc(-ANGLE_DELTA); this->inval(NULL); return true;
168 case '2': fAngle.inc( ANGLE_DELTA); this->inval(NULL); return true;
169 case '3': fScale.inc(-SCALE_DELTA); this->inval(NULL); return true;
170 case '4': fScale.inc( SCALE_DELTA); this->inval(NULL); return true;
reed09519db2015-01-17 19:36:08 -0800171 case '5': fShowFatBits = !fShowFatBits; this->inval(NULL); return true;
reedafdbedb2015-01-14 13:16:26 -0800172 default: break;
173 }
174 }
175 return this->INHERITED::onQuery(evt);
176 }
177
reed93a12152015-03-16 10:08:34 -0700178 void drawTheImage(SkCanvas* canvas, const SkISize& size, SkFilterQuality filter,
reed09519db2015-01-17 19:36:08 -0800179 SkScalar dx, SkScalar dy) {
reedafdbedb2015-01-14 13:16:26 -0800180 SkPaint paint;
181 paint.setAntiAlias(true);
reed93a12152015-03-16 10:08:34 -0700182 paint.setFilterQuality(filter);
reedafdbedb2015-01-14 13:16:26 -0800183
reed09519db2015-01-17 19:36:08 -0800184 SkAutoCanvasRestore acr(canvas, true);
185
186 canvas->translate(dx, dy);
187
188 canvas->translate(SkScalarHalf(size.width()), SkScalarHalf(size.height()));
reedafdbedb2015-01-14 13:16:26 -0800189 canvas->scale(fScale, fScale);
190 canvas->rotate(fAngle);
191 canvas->drawImage(fImage, -SkScalarHalf(fImage->width()), -SkScalarHalf(fImage->height()),
192 &paint);
reed09519db2015-01-17 19:36:08 -0800193
194 if (false) {
195 acr.restore();
196 draw_box_frame(canvas, size.width(), size.height());
197 }
198 }
199
reed93a12152015-03-16 10:08:34 -0700200 void drawHere(SkCanvas* canvas, SkFilterQuality filter, SkScalar dx, SkScalar dy) {
reed09519db2015-01-17 19:36:08 -0800201 SkCanvas* origCanvas = canvas;
202 SkAutoCanvasRestore acr(canvas, true);
203
204 SkISize size = SkISize::Make(fImage->width(), fImage->height());
205
206 SkAutoTUnref<SkSurface> surface;
207 if (fShowFatBits) {
208 // scale up so we don't clip rotations
209 SkImageInfo info = SkImageInfo::MakeN32(fImage->width() * 2, fImage->height() * 2,
210 kOpaque_SkAlphaType);
211 surface.reset(make_surface(canvas, info));
212 canvas = surface->getCanvas();
213 canvas->drawColor(SK_ColorWHITE);
214 size.set(info.width(), info.height());
215 } else {
216 canvas->translate(SkScalarHalf(fCell.width() - fImage->width()),
217 SkScalarHalf(fCell.height() - fImage->height()));
218 }
219 this->drawTheImage(canvas, size, filter, dx, dy);
220
221 if (surface) {
222 SkAutoTUnref<SkImage> orig(surface->newImageSnapshot());
223 SkAutoTUnref<SkImage> zoomed(zoom_up(orig));
224 origCanvas->drawImage(zoomed,
225 SkScalarHalf(fCell.width() - zoomed->width()),
226 SkScalarHalf(fCell.height() - zoomed->height()));
227 }
228 }
229
230 void drawBorders(SkCanvas* canvas) {
231 SkPaint p;
232 p.setStyle(SkPaint::kStroke_Style);
233 p.setColor(SK_ColorBLUE);
234
235 SkRect r = SkRect::MakeWH(fCell.width() * 2, fCell.height() * 2);
236 r.inset(SK_ScalarHalf, SK_ScalarHalf);
237 canvas->drawRect(r, p);
238 canvas->drawLine(r.left(), r.centerY(), r.right(), r.centerY(), p);
239 canvas->drawLine(r.centerX(), r.top(), r.centerX(), r.bottom(), p);
reedafdbedb2015-01-14 13:16:26 -0800240 }
241
mtklein36352bf2015-03-25 18:17:31 -0700242 void onDrawContent(SkCanvas* canvas) override {
reed09519db2015-01-17 19:36:08 -0800243 fCell.set(this->height() / 2, this->height() / 2);
244
reedafdbedb2015-01-14 13:16:26 -0800245 SkScalar trans[2];
reed339cdbf2015-02-05 22:02:37 -0800246 fTrans.timeToValues(fCurrTime, trans);
reedafdbedb2015-01-14 13:16:26 -0800247
reed09519db2015-01-17 19:36:08 -0800248 for (int y = 0; y < 2; ++y) {
249 for (int x = 0; x < 2; ++x) {
250 int index = y * 2 + x;
251 SkAutoCanvasRestore acr(canvas, true);
252 canvas->translate(fCell.width() * x, fCell.height() * y);
253 SkRect r = SkRect::MakeWH(fCell.width(), fCell.height());
254 r.inset(4, 4);
255 canvas->clipRect(r);
reed93a12152015-03-16 10:08:34 -0700256 this->drawHere(canvas, SkFilterQuality(index), trans[0], trans[1]);
reed09519db2015-01-17 19:36:08 -0800257 }
reedafdbedb2015-01-14 13:16:26 -0800258 }
259
reed09519db2015-01-17 19:36:08 -0800260 this->drawBorders(canvas);
261
262 const SkScalar textX = fCell.width() * 2 + 30;
263
reedafdbedb2015-01-14 13:16:26 -0800264 SkPaint paint;
265 paint.setAntiAlias(true);
reed09519db2015-01-17 19:36:08 -0800266 paint.setTextSize(36);
reedafdbedb2015-01-14 13:16:26 -0800267 SkString str;
268 str.appendScalar(fScale);
reed09519db2015-01-17 19:36:08 -0800269 canvas->drawText(str.c_str(), str.size(), textX, 100, paint);
reedafdbedb2015-01-14 13:16:26 -0800270 str.reset(); str.appendScalar(fAngle);
reed09519db2015-01-17 19:36:08 -0800271 canvas->drawText(str.c_str(), str.size(), textX, 150, paint);
reedafdbedb2015-01-14 13:16:26 -0800272
273 str.reset(); str.appendScalar(trans[0]);
reed09519db2015-01-17 19:36:08 -0800274 canvas->drawText(str.c_str(), str.size(), textX, 200, paint);
reedafdbedb2015-01-14 13:16:26 -0800275 str.reset(); str.appendScalar(trans[1]);
reed09519db2015-01-17 19:36:08 -0800276 canvas->drawText(str.c_str(), str.size(), textX, 250, paint);
reed339cdbf2015-02-05 22:02:37 -0800277 }
reed09519db2015-01-17 19:36:08 -0800278
mtklein36352bf2015-03-25 18:17:31 -0700279 bool onAnimate(const SkAnimTimer& timer) override {
reed339cdbf2015-02-05 22:02:37 -0800280 fCurrTime = timer.msec();
281 return true;
reed09519db2015-01-17 19:36:08 -0800282 }
reedafdbedb2015-01-14 13:16:26 -0800283
284 virtual bool handleKey(SkKey key) {
285 this->inval(NULL);
286 return true;
287 }
288
289private:
290 typedef SampleView INHERITED;
291};
292
293//////////////////////////////////////////////////////////////////////////////
294
295static SkView* MyFactory() { return new FilterQualityView; }
296static SkViewRegister reg(MyFactory);