1/*
2 * Copyright 2014 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"
12#include "SkBlurMaskFilter.h"
13#include "SkCanvas.h"
14#include "SkColorPriv.h"
15#include "SkImageDecoder.h"
16#include "SkRandom.h"
17#include "SkStream.h"
18
19// Intended to exercise pixel snapping observed with scaled images (and
20// with non-scaled images, but for a different reason):  Bug 1145
21
22class SubpixelTranslateView : public SampleView {
23public:
24    SubpixelTranslateView(const char imageFilename[],
25                          float horizontalVelocity,
26                          float verticalVelocity)
27      : fFilename(imageFilename),
28        fHorizontalVelocity(horizontalVelocity),
29        fVerticalVelocity(verticalVelocity) {
30      SkString resourcePath = GetResourcePath();
31      resourcePath.append("/");
32      resourcePath.append(fFilename);
33
34      SkImageDecoder* codec = NULL;
35      SkFILEStream stream(resourcePath.c_str());
36      if (stream.isValid()) {
37          codec = SkImageDecoder::Factory(&stream);
38      }
39      if (codec) {
40          stream.rewind();
41          codec->decode(&stream, &fBM, kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode);
42          SkDELETE(codec);
43      } else {
44          fBM.allocN32Pixels(1, 1);
45          *(fBM.getAddr32(0,0)) = 0xFF0000FF; // red == bad
46      }
47      fCurPos = SkPoint::Make(0,0);
48      fSize = 200;
49    }
50
51protected:
52    SkBitmap fBM;
53    SkString fFilename;
54    SkScalar fSize;
55    float fHorizontalVelocity, fVerticalVelocity;
56
57    SkPoint fCurPos;
58
59    // overrides from SkEventSink
60    virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
61        if (SampleCode::TitleQ(*evt)) {
62            SampleCode::TitleR(evt, "SubpixelTranslate");
63            return true;
64        }
65        return this->INHERITED::onQuery(evt);
66    }
67
68    virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
69
70        static const SkPaint::FilterLevel gLevels[] = {
71            SkPaint::kNone_FilterLevel,
72            SkPaint::kLow_FilterLevel,
73            SkPaint::kMedium_FilterLevel,
74            SkPaint::kHigh_FilterLevel
75        };
76
77        SkPaint paint;
78        paint.setTextSize(48);
79
80        paint.setAntiAlias(true);
81        for (size_t i = 0; i < SK_ARRAY_COUNT(gLevels); ++i) {
82            paint.setFilterLevel(gLevels[i]);
83            SkRect r = SkRect::MakeXYWH( fCurPos.fX + i * (fSize + 10), fCurPos.fY, fSize, fSize );
84            canvas->drawBitmapRect( fBM, r, &paint );
85        }
86
87        canvas->drawText( "AA Scaled", strlen("AA Scaled"), fCurPos.fX + SK_ARRAY_COUNT(gLevels) * (fSize + 10), fCurPos.fY + fSize/2, paint );
88
89        paint.setAntiAlias(false);
90        for (size_t i = 0; i < SK_ARRAY_COUNT(gLevels); ++i) {
91            paint.setFilterLevel(gLevels[i]);
92            SkRect r = SkRect::MakeXYWH( fCurPos.fX + i * (fSize + 10), fCurPos.fY + fSize + 10, fSize, fSize );
93            canvas->drawBitmapRect( fBM, r, &paint );
94        }
95        canvas->drawText( "Scaled", strlen("Scaled"), fCurPos.fX + SK_ARRAY_COUNT(gLevels) * (fSize + 10), fCurPos.fY + fSize + 10 + fSize/2, paint );
96
97        paint.setAntiAlias(true);
98        for (size_t i = 0; i < SK_ARRAY_COUNT(gLevels); ++i) {
99            paint.setFilterLevel(gLevels[i]);
100            canvas->drawBitmap( fBM, fCurPos.fX + i * (fBM.width() + 10), fCurPos.fY + 2*(fSize + 10), &paint );
101        }
102
103        canvas->drawText( "AA No Scale", strlen("AA No Scale"), fCurPos.fX + SK_ARRAY_COUNT(gLevels) * (fBM.width() + 10), fCurPos.fY + 2*(fSize + 10) + fSize/2, paint );
104
105        paint.setAntiAlias(false);
106        for (size_t i = 0; i < SK_ARRAY_COUNT(gLevels); ++i) {
107            paint.setFilterLevel(gLevels[i]);
108            canvas->drawBitmap( fBM, fCurPos.fX + i * (fBM.width() + 10), fCurPos.fY + 2*(fSize + 10) + fBM.height() + 10, &paint );
109        }
110
111        canvas->drawText( "No Scale", strlen("No Scale"), fCurPos.fX + SK_ARRAY_COUNT(gLevels) * (fBM.width() + 10), fCurPos.fY + 2*(fSize + 10) + fBM.height() + 10 + fSize/2, paint );
112
113
114        fCurPos.fX += fHorizontalVelocity;
115        fCurPos.fY += fVerticalVelocity;
116        this->inval(NULL);
117    }
118
119private:
120    typedef SampleView INHERITED;
121};
122
123//////////////////////////////////////////////////////////////////////////////
124
125static SkView* MyFactory() { return new SubpixelTranslateView("mandrill_256.png", .05f, .05f); }
126static SkViewRegister reg(MyFactory);
127