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