1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gm.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "sk_tool_utils.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAnimTimer.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlurMaskFilter.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRRectsGaussianEdgeMaskFilter.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathOps.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRRect.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStroke.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kNumCols = 2;
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kNumRows = 5;
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kCellSize = 128;
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr SkScalar kPad = 8.0f;
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr SkScalar kInitialBlurRadius = 8.0f;
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr SkScalar kPeriod = 8.0f;
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconstexpr int kClipOffset = 32;
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass Object {
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual ~Object() {}
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // When it returns true, this call will have placed a device-space _circle, rect or
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // simple circular_ RRect in "rr"
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const = 0;
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual SkPath asPath(SkScalar inset) const = 0;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void draw(SkCanvas* canvas, const SkPaint& paint) const = 0;
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void clip(SkCanvas* canvas) const = 0;
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual bool contains(const SkRect& r) const = 0;
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual const SkRect& bounds() const = 0;
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottypedef Object* (*PFMakeMthd)(const SkRect& r);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass RRect : public Object {
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    RRect(const SkRect& r) {
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRRect = SkRRect::MakeRectXY(r, 4*kPad, 4*kPad);
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!ctm.isSimilarity()) { // the corners have to remain circular
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar scales[2];
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!ctm.getMinMaxScales(scales)) {
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(SkScalarNearlyEqual(scales[0], scales[1]));
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect devRect;
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ctm.mapRect(&devRect, fRRect.rect());
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar scaledRad = scales[0] * fRRect.getSimpleRadii().fX;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *rr = SkRRect::MakeRectXY(devRect, scaledRad, scaledRad);
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath asPath(SkScalar inset) const override {
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRRect tmp = fRRect;
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tmp.inset(inset, inset);
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath p;
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.addRRect(tmp);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return p;
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRRect(fRRect, paint);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clip(SkCanvas* canvas) const override {
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->clipRRect(fRRect);
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& r) const override {
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRRect.contains(r);
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds() const override {
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRRect.getBounds();
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Object* Make(const SkRect& r) {
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new RRect(r);
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRRect  fRRect;
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass StrokedRRect : public Object {
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    StrokedRRect(const SkRect& r) {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRRect = SkRRect::MakeRectXY(r, 2*kPad, 2*kPad);
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStrokedBounds = r.makeOutset(kPad, kPad);
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath asPath(SkScalar inset) const override {
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRRect tmp = fRRect;
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tmp.inset(inset, inset);
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // In this case we want the outline of the stroked rrect
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setAntiAlias(true);
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setStyle(SkPaint::kStroke_Style);
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setStrokeWidth(kPad);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath p, stroked;
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.addRRect(tmp);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkStroke stroke(paint);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        stroke.strokePath(p, &stroked);
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return stroked;
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint stroke(paint);
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        stroke.setStyle(SkPaint::kStroke_Style);
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        stroke.setStrokeWidth(kPad);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRRect(fRRect, stroke);
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clip(SkCanvas* canvas) const override {
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->clipPath(this->asPath(0.0f));
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& r) const override {
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds() const override {
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fStrokedBounds;
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Object* Make(const SkRect& r) {
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new StrokedRRect(r);
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRRect  fRRect;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect   fStrokedBounds;
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass Oval : public Object {
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Oval(const SkRect& r) {
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRRect = SkRRect::MakeOval(r);
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!ctm.isSimilarity()) { // circles have to remain circles
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect devRect;
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ctm.mapRect(&devRect, fRRect.rect());
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *rr = SkRRect::MakeOval(devRect);
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath asPath(SkScalar inset) const override {
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRRect tmp = fRRect;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tmp.inset(inset, inset);
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath p;
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.addRRect(tmp);
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return p;
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRRect(fRRect, paint);
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clip(SkCanvas* canvas) const override {
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->clipRRect(fRRect);
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& r) const override {
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRRect.contains(r);
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds() const override {
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRRect.getBounds();
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Object* Make(const SkRect& r) {
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new Oval(r);
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRRect  fRRect;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass Rect : public Object {
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Rect(const SkRect& r) : fRect(r) { }
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!ctm.rectStaysRect()) {
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect devRect;
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ctm.mapRect(&devRect, fRect);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *rr = SkRRect::MakeRect(devRect);
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath asPath(SkScalar inset) const override {
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect tmp = fRect;
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        tmp.inset(inset, inset);
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath p;
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        p.addRect(tmp);
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return p;
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRect(fRect, paint);
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clip(SkCanvas* canvas) const override {
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->clipRect(fRect);
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& r) const override {
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRect.contains(r);
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds() const override {
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRect;
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Object* Make(const SkRect& r) {
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new Rect(r);
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect  fRect;
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass Pentagon : public Object {
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Pentagon(const SkRect& r) {
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint points[5] = {
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            {  0.000000f, -1.000000f },
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { -0.951056f, -0.309017f },
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            { -0.587785f,  0.809017f },
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            {  0.587785f,  0.809017f },
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            {  0.951057f, -0.309017f },
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar height = r.height()/2.0f;
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar width = r.width()/2.0f;
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.moveTo(r.centerX() + points[0].fX * width, r.centerY() + points[0].fY * height);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.lineTo(r.centerX() + points[1].fX * width, r.centerY() + points[1].fY * height);
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.lineTo(r.centerX() + points[2].fX * width, r.centerY() + points[2].fY * height);
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.lineTo(r.centerX() + points[3].fX * width, r.centerY() + points[3].fY * height);
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.lineTo(r.centerX() + points[4].fX * width, r.centerY() + points[4].fY * height);
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.close();
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override {
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath asPath(SkScalar inset) const override { return fPath; }
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const SkPaint& paint) const override {
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(fPath, paint);
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void clip(SkCanvas* canvas) const override {
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->clipPath(this->asPath(0.0f));
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& r) const override {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkRect& bounds() const override {
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fPath.getBounds();
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Object* Make(const SkRect& r) {
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return new Pentagon(r);
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath fPath;
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace skiagm {
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This GM attempts to mimic Android's reveal animation
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass RevealGM : public GM {
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum Mode {
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kBlurMask_Mode,
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRRectsGaussianEdge_Mode,
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLast_Mode = kRRectsGaussianEdge_Mode
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kModeCount = kLast_Mode + 1;
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum CoverageGeom {
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRect_CoverageGeom,
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRRect_CoverageGeom,
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kDRRect_CoverageGeom,
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPath_CoverageGeom,
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLast_CoverageGeom = kPath_CoverageGeom
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kCoverageGeomCount = kLast_CoverageGeom + 1;
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    RevealGM()
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fFraction(0.5f)
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fMode(kRRectsGaussianEdge_Mode)
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fPause(false)
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fBlurRadius(kInitialBlurRadius)
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fCoverageGeom(kRect_CoverageGeom) {
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool runAsBench() const override { return true; }
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString onShortName() override {
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkString("reveal");
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkISize onISize() override {
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkISize::Make(kNumCols * kCellSize, kNumRows * kCellSize);
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDraw(SkCanvas* canvas) override {
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        PFMakeMthd clipMakes[kNumCols] = { Oval::Make, Rect::Make };
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        PFMakeMthd drawMakes[kNumRows] = {
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            RRect::Make, StrokedRRect::Make, Oval::Make, Rect::Make, Pentagon::Make
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint strokePaint;
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        strokePaint.setStyle(SkPaint::kStroke_Style);
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        strokePaint.setStrokeWidth(0.0f);
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int y = 0; y < kNumRows; ++y) {
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int x = 0; x < kNumCols; ++x) {
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkRect cell = SkRect::MakeXYWH(SkIntToScalar(x*kCellSize),
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               SkIntToScalar(y*kCellSize),
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               SkIntToScalar(kCellSize),
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                               SkIntToScalar(kCellSize));
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->save();
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->clipRect(cell);
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                cell.inset(kPad, kPad);
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPoint clipCenter = SkPoint::Make(cell.centerX() - kClipOffset,
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                   cell.centerY() + kClipOffset);
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar curSize = kCellSize * fFraction;
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const SkRect clipRect = SkRect::MakeLTRB(clipCenter.fX - curSize,
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                         clipCenter.fY - curSize,
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                         clipCenter.fX + curSize,
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                         clipCenter.fY + curSize);
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::unique_ptr<Object> clipObj((*clipMakes[x])(clipRect));
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                std::unique_ptr<Object> drawObj((*drawMakes[y])(cell));
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // The goal is to replace this clipped draw (which clips the
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // shadow) with a draw using the geometric clip
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (kBlurMask_Mode == fMode) {
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPath clippedPath;
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar sigma = fBlurRadius / 4.0f;
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (clipObj->contains(drawObj->bounds())) {
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        clippedPath = drawObj->asPath(2.0f*sigma);
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } else {
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkPath drawnPath = drawObj->asPath(2.0f*sigma);
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkPath clipPath  = clipObj->asPath(2.0f*sigma);
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkAssertResult(Op(clipPath, drawnPath, kIntersect_SkPathOp, &clippedPath));
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPaint blurPaint;
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    blurPaint.setAntiAlias(true);
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    blurPaint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma));
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->drawPath(clippedPath, blurPaint);
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(kRRectsGaussianEdge_Mode == fMode);
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkRect cover = drawObj->bounds();
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkAssertResult(cover.intersect(clipObj->bounds()));
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPaint paint;
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkRRect devSpaceClipRR, devSpaceDrawnRR;
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (clipObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceClipRR) &&
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        drawObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceDrawnRR)) {
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceClipRR,
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                                 devSpaceDrawnRR,
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                                 fBlurRadius));
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    strokePaint.setColor(SK_ColorBLUE);
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    switch (fCoverageGeom) {
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case kRect_CoverageGeom:
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawRect(cover, paint);
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawRect(cover, strokePaint);
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case kRRect_CoverageGeom: {
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            const SkRRect rrect = SkRRect::MakeRectXY(
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                    cover.makeOutset(10.0f, 10.0f),
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                    10.0f, 10.0f);
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawRRect(rrect, paint);
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawRRect(rrect, strokePaint);
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case kDRRect_CoverageGeom: {
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            const SkRRect inner = SkRRect::MakeRectXY(cover.makeInset(10.0f, 10.0f),
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                      10.0f, 10.0f);
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            const SkRRect outer = SkRRect::MakeRectXY(
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                    cover.makeOutset(10.0f, 10.0f),
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                    10.0f, 10.0f);
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawDRRect(outer, inner, paint);
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawDRRect(outer, inner, strokePaint);
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case kPath_CoverageGeom: {
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkPath path;
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.moveTo(cover.fLeft, cover.fTop);
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.lineTo(cover.centerX(), cover.centerY());
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.lineTo(cover.fRight, cover.fTop);
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.lineTo(cover.fRight, cover.fBottom);
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.lineTo(cover.centerX(), cover.centerY());
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.lineTo(cover.fLeft, cover.fBottom);
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            path.close();
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawPath(path, paint);
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            canvas->drawPath(path, strokePaint);
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                // Draw the clip and draw objects for reference
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                strokePaint.setColor(SK_ColorRED);
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawPath(drawObj->asPath(0.0f), strokePaint);
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                strokePaint.setColor(SK_ColorGREEN);
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawPath(clipObj->asPath(0.0f), strokePaint);
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->restore();
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onHandleKey(SkUnichar uni) override {
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (uni) {
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 'C':
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fMode = (Mode)((fMode + 1) % kModeCount);
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case '+':
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fBlurRadius += 1.0f;
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case '-':
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fBlurRadius = SkTMax(1.0f, fBlurRadius - 1.0f);
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 'p':
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fPause = !fPause;
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case 'G':
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fCoverageGeom = (CoverageGeom) ((fCoverageGeom+1) % kCoverageGeomCount);
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onAnimate(const SkAnimTimer& timer) override {
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fPause) {
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fFraction = timer.pingPong(kPeriod, 0.0f, 0.0f, 1.0f);
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar     fFraction;
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Mode         fMode;
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool         fPause;
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    float        fBlurRadius;
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    CoverageGeom fCoverageGeom;
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef GM INHERITED;
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_GM(return new RevealGM;)
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
517