1/*
2 * Copyright 2013 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#include "SkPath.h"
11#include "SkRandom.h"
12#include "SkRRect.h"
13
14namespace skiagm {
15
16// Test out various combinations of nested rects, ovals and rrects.
17class NestedGM : public GM {
18public:
19    NestedGM(bool doAA, bool flipped) : fDoAA(doAA), fFlipped(flipped) {
20        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
21    }
22
23protected:
24
25    SkString onShortName() override {
26        SkString name("nested");
27        if (fFlipped) {
28            name.append("_flipY");
29        }
30        if (fDoAA) {
31            name.append("_aa");
32        } else {
33            name.append("_bw");
34        }
35        return name;
36    }
37
38    SkISize onISize() override {
39        return SkISize::Make(kImageWidth, kImageHeight);
40    }
41
42    enum Shapes {
43        kRect_Shape = 0,
44        kRRect_Shape,
45        kOval_Shape,
46        kShapeCount
47    };
48
49    static void AddShape(SkPath* path, const SkRect& rect, Shapes shape, SkPath::Direction dir) {
50        switch (shape) {
51            case kRect_Shape:
52                path->addRect(rect, dir);
53                break;
54            case kRRect_Shape: {
55                SkRRect rr;
56                rr.setRectXY(rect, 5, 5);
57                path->addRRect(rr, dir);
58                break;
59                }
60            case kOval_Shape:
61                path->addOval(rect, dir);
62                break;
63            default:
64                break;
65        }
66    }
67
68    void onDraw(SkCanvas* canvas) override {
69
70        SkPaint shapePaint;
71        shapePaint.setColor(SK_ColorBLACK);
72        shapePaint.setAntiAlias(fDoAA);
73
74        SkRect outerRect = SkRect::MakeWH(40, 40);
75
76        SkRect innerRects[] = {
77            { 10, 10, 30, 30 },     // small
78            { .5f, 18, 4.5f, 22 }   // smaller and offset to left
79        };
80
81        // draw a background pattern to make transparency errors more apparent
82        SkRandom rand;
83
84        for (int y = 0; y < kImageHeight; y += 10) {
85            for (int x = 0; x < kImageWidth; x += 10) {
86                SkRect r = SkRect::MakeXYWH(SkIntToScalar(x),
87                                            SkIntToScalar(y),
88                                            10, 10);
89                SkPaint p;
90                p.setColor(rand.nextU() | 0xFF000000);
91                canvas->drawRect(r, p);
92            }
93        }
94
95        SkScalar xOff = 2, yOff = 2;
96        for (int outerShape = 0; outerShape < kShapeCount; ++outerShape) {
97            for (int innerShape = 0; innerShape < kShapeCount; ++innerShape) {
98                for (size_t innerRect = 0; innerRect < SK_ARRAY_COUNT(innerRects); ++innerRect) {
99                    SkPath path;
100
101                    AddShape(&path, outerRect, (Shapes) outerShape, SkPath::kCW_Direction);
102                    AddShape(&path, innerRects[innerRect], (Shapes) innerShape,
103                             SkPath::kCCW_Direction);
104
105                    canvas->save();
106                    if (fFlipped) {
107                        canvas->scale(1.0f, -1.0f);
108                        canvas->translate(xOff, -yOff - 40.0f);
109                    } else {
110                        canvas->translate(xOff, yOff);
111                    }
112
113                    canvas->drawPath(path, shapePaint);
114                    canvas->restore();
115
116                    xOff += 45;
117                }
118            }
119
120            xOff = 2;
121            yOff += 45;
122        }
123
124    }
125
126private:
127    static constexpr int kImageWidth = 269;
128    static constexpr int kImageHeight = 134;
129
130    bool fDoAA;
131    bool fFlipped;
132
133    typedef GM INHERITED;
134};
135
136///////////////////////////////////////////////////////////////////////////////
137
138DEF_GM( return new NestedGM(/* doAA = */ true,  /* flipped = */ false); )
139DEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ false); )
140DEF_GM( return new NestedGM(/* doAA = */ true,  /* flipped = */ true); )
141DEF_GM( return new NestedGM(/* doAA = */ false, /* flipped = */ true); )
142
143}
144