1363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger/*
2363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Copyright 2012 Google Inc.
3363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger *
4363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
5363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger * found in the LICENSE file.
6363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger */
7363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
8363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "gm.h"
9363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkRRect.h"
10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergernamespace skiagm {
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
15363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerclass RRectGM : public GM {
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerpublic:
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    RRectGM(bool doAA, bool doClip) : fDoAA(doAA), fDoClip(doClip) {
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->setBGColor(0xFFDDDDDD);
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->setUpRRects();
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerprotected:
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkString onShortName() {
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkString name("rrect");
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (fDoClip) {
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            name.append("_clip");
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (fDoAA) {
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            name.append("_aa");
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        } else {
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            name.append("_bw");
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return name;
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual SkISize onISize() { return make_isize(kImageWidth, kImageHeight); }
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void onDraw(SkCanvas* canvas) {
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkPaint paint;
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // when clipping the AA is pushed into the clip operation
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        paint.setAntiAlias(fDoClip ? false : fDoAA);
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY));
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int curRRect = 0;
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        for (int y = 1; y < kImageHeight; y += kTileY) {
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            for (int x = 1; x < kImageWidth; x += kTileX) {
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (curRRect >= kNumRRects) {
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    break;
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                }
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds()));
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                canvas->save();
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    if (fDoClip) {
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, fDoAA);
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        canvas->drawRect(kMaxTileBound, paint);
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    } else {
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        canvas->drawRRect(fRRects[curRRect], paint);
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    }
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    ++curRRect;
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                canvas->restore();
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    void setUpRRects() {
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA.
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // simple cases
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2));
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2));
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10);
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The first complex case needs special handling since it is a square
79363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]);
80d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) {
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]);
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerprivate:
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool fDoAA;
87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool fDoClip;   // use clipRRect & drawRect instead of drawRRect
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kImageWidth = 640;
90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kImageHeight = 480;
91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kTileX = 80;
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kTileY = 40;
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kNumSimpleCases = 3;
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kNumComplexCases = 19;
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const SkVector gRadii[kNumComplexCases][4];
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    static const int kNumRRects = kNumSimpleCases + kNumComplexCases;
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRRect fRRects[kNumRRects];
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    typedef GM INHERITED;
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// Radii for the various test cases. Order is UL, UR, LR, LL
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkVector RRectGM::gRadii[kNumComplexCases][4] = {
107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // a circle
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } },
109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // odd ball cases
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } },
112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } },
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } },
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // UL
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } },
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // UR
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } },
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } },
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } },
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // LR
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } },
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } },
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } },
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // LL
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } },
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } },
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } },
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // over-sized radii
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } },
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } },
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } },
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerDEF_GM( return new RRectGM(false, false); )
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerDEF_GM( return new RRectGM(true, false); )
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerDEF_GM( return new RRectGM(false, true); )
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerDEF_GM( return new RRectGM(true, true); )
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
149