1/*
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#include "sk_tool_utils.h"
10
11namespace skiagm {
12
13// This GM exercises HighQuality anisotropic filtering.
14class AnisotropicGM : public GM {
15public:
16    AnisotropicGM() : fFilterQuality(kHigh_SkFilterQuality) {
17        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
18    }
19
20protected:
21
22    SkString onShortName() override { return SkString("anisotropic_hq"); }
23
24    SkISize onISize() override {
25        return SkISize::Make(2*kImageSize + 3*kSpacer,
26                             kNumVertImages*kImageSize + (kNumVertImages+1)*kSpacer);
27    }
28
29    // Create an image consisting of lines radiating from its center
30    void onOnceBeforeDraw() override {
31        constexpr int kNumLines = 100;
32        constexpr SkScalar kAngleStep = 360.0f / kNumLines;
33        constexpr int kInnerOffset = 10;
34
35        fBM.allocN32Pixels(kImageSize, kImageSize, true);
36
37        SkCanvas canvas(fBM);
38
39        canvas.clear(SK_ColorWHITE);
40
41        SkPaint p;
42        p.setAntiAlias(true);
43
44        SkScalar angle = 0.0f, sin, cos;
45
46        canvas.translate(kImageSize/2.0f, kImageSize/2.0f);
47        for (int i = 0; i < kNumLines; ++i, angle += kAngleStep) {
48            sin = SkScalarSinCos(angle, &cos);
49            canvas.drawLine(cos * kInnerOffset, sin * kInnerOffset,
50                            cos * kImageSize/2, sin * kImageSize/2, p);
51        }
52    }
53
54    void draw(SkCanvas* canvas, int x, int y, int xSize, int ySize) {
55        SkRect r = SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
56                                    SkIntToScalar(xSize), SkIntToScalar(ySize));
57        SkPaint p;
58        p.setFilterQuality(fFilterQuality);
59        canvas->drawBitmapRect(fBM, r, &p);
60    }
61
62    void onDraw(SkCanvas* canvas) override {
63        SkScalar gScales[] = { 0.9f, 0.8f, 0.75f, 0.6f, 0.5f, 0.4f, 0.25f, 0.2f, 0.1f };
64
65        SkASSERT(kNumVertImages-1 == (int)SK_ARRAY_COUNT(gScales)/2);
66
67        // Minimize vertically
68        for (int i = 0; i < (int)SK_ARRAY_COUNT(gScales); ++i) {
69            int height = SkScalarFloorToInt(fBM.height() * gScales[i]);
70
71            int yOff;
72            if (i <= (int)SK_ARRAY_COUNT(gScales)/2) {
73                yOff = kSpacer + i * (fBM.height() + kSpacer);
74            } else {
75                // Position the more highly squashed images with their less squashed counterparts
76                yOff = (SK_ARRAY_COUNT(gScales) - i) * (fBM.height() + kSpacer) - height;
77            }
78
79            this->draw(canvas, kSpacer, yOff, fBM.width(), height);
80        }
81
82        // Minimize horizontally
83        for (int i = 0; i < (int)SK_ARRAY_COUNT(gScales); ++i) {
84            int width = SkScalarFloorToInt(fBM.width() * gScales[i]);
85
86            int xOff, yOff;
87            if (i <= (int)SK_ARRAY_COUNT(gScales)/2) {
88                xOff = fBM.width() + 2*kSpacer;
89                yOff = kSpacer + i * (fBM.height() + kSpacer);
90            } else {
91                // Position the more highly squashed images with their less squashed counterparts
92                xOff = fBM.width() + 2*kSpacer + fBM.width() - width;
93                yOff = kSpacer + (SK_ARRAY_COUNT(gScales) - i - 1) * (fBM.height() + kSpacer);
94            }
95
96            this->draw(canvas, xOff, yOff, width, fBM.height());
97        }
98    }
99
100private:
101    static constexpr int kImageSize     = 256;
102    static constexpr int kSpacer        = 10;
103    static constexpr int kNumVertImages = 5;
104
105    SkBitmap         fBM;
106    SkFilterQuality  fFilterQuality;
107
108    typedef GM INHERITED;
109};
110
111//////////////////////////////////////////////////////////////////////////////
112
113DEF_GM(return new AnisotropicGM;)
114}
115