1/*
2 * Copyright 2012 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 "SkCanvas.h"
11#include "SkRRect.h"
12#include "SkPath.h"
13
14typedef void (*InsetProc)(const SkRRect&, SkScalar dx, SkScalar dy, SkRRect*);
15
16static void inset0(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) {
17    SkRect r = src.rect();
18
19    r.inset(dx, dy);
20    if (r.isEmpty()) {
21        dst->setEmpty();
22        return;
23    }
24
25    SkVector radii[4];
26    for (int i = 0; i < 4; ++i) {
27        radii[i] = src.radii((SkRRect::Corner)i);
28    }
29    for (int i = 0; i < 4; ++i) {
30        radii[i].fX -= dx;
31        radii[i].fY -= dy;
32    }
33    dst->setRectRadii(r, radii);
34}
35
36static void inset1(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) {
37    SkRect r = src.rect();
38
39    r.inset(dx, dy);
40    if (r.isEmpty()) {
41        dst->setEmpty();
42        return;
43    }
44
45    SkVector radii[4];
46    for (int i = 0; i < 4; ++i) {
47        radii[i] = src.radii((SkRRect::Corner)i);
48    }
49    dst->setRectRadii(r, radii);
50}
51
52static void inset2(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) {
53    SkRect r = src.rect();
54
55    r.inset(dx, dy);
56    if (r.isEmpty()) {
57        dst->setEmpty();
58        return;
59    }
60
61    SkVector radii[4];
62    for (int i = 0; i < 4; ++i) {
63        radii[i] = src.radii((SkRRect::Corner)i);
64    }
65    for (int i = 0; i < 4; ++i) {
66        if (radii[i].fX) {
67            radii[i].fX -= dx;
68        }
69        if (radii[i].fY) {
70            radii[i].fY -= dy;
71        }
72    }
73    dst->setRectRadii(r, radii);
74}
75
76static SkScalar prop(SkScalar radius, SkScalar newSize, SkScalar oldSize) {
77    return newSize * radius / oldSize;
78}
79
80static void inset3(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) {
81    SkRect r = src.rect();
82
83    r.inset(dx, dy);
84    if (r.isEmpty()) {
85        dst->setEmpty();
86        return;
87    }
88
89    SkVector radii[4];
90    for (int i = 0; i < 4; ++i) {
91        radii[i] = src.radii((SkRRect::Corner)i);
92    }
93    for (int i = 0; i < 4; ++i) {
94        radii[i].fX = prop(radii[i].fX, r.width(), src.rect().width());
95        radii[i].fY = prop(radii[i].fY, r.height(), src.rect().height());
96    }
97    dst->setRectRadii(r, radii);
98}
99
100static void draw_rrect_color(SkCanvas* canvas, const SkRRect& rrect) {
101    SkPaint paint;
102    paint.setAntiAlias(true);
103    paint.setStyle(SkPaint::kStroke_Style);
104
105    if (rrect.isRect()) {
106        paint.setColor(SK_ColorRED);
107    } else if (rrect.isOval()) {
108        paint.setColor(sk_tool_utils::color_to_565(0xFF008800));
109    } else if (rrect.isSimple()) {
110        paint.setColor(SK_ColorBLUE);
111    } else {
112        paint.setColor(SK_ColorBLACK);
113    }
114    canvas->drawRRect(rrect, paint);
115}
116
117static void drawrr(SkCanvas* canvas, const SkRRect& rrect, InsetProc proc) {
118    SkRRect rr;
119    for (SkScalar d = -30; d <= 30; d += 5) {
120        proc(rrect, d, d, &rr);
121        draw_rrect_color(canvas, rr);
122    }
123}
124
125class RRectGM : public skiagm::GM {
126public:
127    RRectGM() {}
128
129protected:
130
131    SkString onShortName() override {
132        return SkString("rrect");
133    }
134
135    SkISize onISize() override {
136        return SkISize::Make(820, 710);
137    }
138
139    void onDraw(SkCanvas* canvas) override {
140        constexpr InsetProc insetProcs[] = {
141            inset0, inset1, inset2, inset3
142        };
143
144        SkRRect rrect[4];
145        SkRect r = { 0, 0, 120, 100 };
146        SkVector radii[4] = {
147            { 0, 0 }, { 30, 1 }, { 10, 40 }, { 40, 40 }
148        };
149
150        rrect[0].setRect(r);
151        rrect[1].setOval(r);
152        rrect[2].setRectXY(r, 20, 20);
153        rrect[3].setRectRadii(r, radii);
154
155        canvas->translate(50.5f, 50.5f);
156        for (size_t j = 0; j < SK_ARRAY_COUNT(insetProcs); ++j) {
157            canvas->save();
158            for (size_t i = 0; i < SK_ARRAY_COUNT(rrect); ++i) {
159                drawrr(canvas, rrect[i], insetProcs[j]);
160                canvas->translate(200, 0);
161            }
162            canvas->restore();
163            canvas->translate(0, 170);
164        }
165    }
166
167private:
168    typedef GM INHERITED;
169};
170
171DEF_GM( return new RRectGM; )
172