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 "SkCanvas.h"
10#include "SkTArray.h"
11
12namespace skiagm {
13
14class ConicPathsGM : public GM {
15protected:
16
17    virtual SkString onShortName() SK_OVERRIDE {
18        return SkString("conicpaths");
19    }
20
21    virtual SkISize onISize() SK_OVERRIDE {
22        return SkISize::Make(1000, 1000);
23    }
24
25    virtual void onOnceBeforeDraw() SK_OVERRIDE {
26        {
27            SkPath* conicCirlce = &fPaths.push_back();
28            conicCirlce->moveTo(0, -0);
29            conicCirlce->conicTo(SkIntToScalar(0), SkIntToScalar(50),
30                                        SkIntToScalar(50), SkIntToScalar(50),
31                                        SkScalarHalf(SkScalarSqrt(2)));
32            conicCirlce->rConicTo(SkIntToScalar(50), SkIntToScalar(0),
33                                         SkIntToScalar(50), SkIntToScalar(-50),
34                                         SkScalarHalf(SkScalarSqrt(2)));
35            conicCirlce->rConicTo(SkIntToScalar(0), SkIntToScalar(-50),
36                                         SkIntToScalar(-50), SkIntToScalar(-50),
37                                         SkScalarHalf(SkScalarSqrt(2)));
38            conicCirlce->rConicTo(SkIntToScalar(-50), SkIntToScalar(0),
39                                         SkIntToScalar(-50), SkIntToScalar(50),
40                                         SkScalarHalf(SkScalarSqrt(2)));
41
42        }
43        {
44            SkPath* hyperbola = &fPaths.push_back();
45            hyperbola->moveTo(0, -0);
46            hyperbola->conicTo(SkIntToScalar(0), SkIntToScalar(100),
47                                        SkIntToScalar(100), SkIntToScalar(100),
48                                        SkIntToScalar(2));
49        }
50        {
51            SkPath* thinHyperbola = &fPaths.push_back();
52            thinHyperbola->moveTo(0, -0);
53            thinHyperbola->conicTo(SkIntToScalar(100), SkIntToScalar(100),
54                                        SkIntToScalar(5), SkIntToScalar(0),
55                                        SkIntToScalar(2));
56        }
57        {
58            SkPath* veryThinHyperbola = &fPaths.push_back();
59            veryThinHyperbola->moveTo(0, -0);
60            veryThinHyperbola->conicTo(SkIntToScalar(100), SkIntToScalar(100),
61                                        SkIntToScalar(1), SkIntToScalar(0),
62                                        SkIntToScalar(2));
63        }
64        {
65            SkPath* closedHyperbola = &fPaths.push_back();
66            closedHyperbola->moveTo(0, -0);
67            closedHyperbola->conicTo(SkIntToScalar(100), SkIntToScalar(100),
68                                        SkIntToScalar(0), SkIntToScalar(0),
69                                        SkIntToScalar(2));
70        }
71        {
72            // using 1 as weight defaults to using quadTo
73            SkPath* nearParabola = &fPaths.push_back();
74            nearParabola->moveTo(0, -0);
75            nearParabola->conicTo(SkIntToScalar(0), SkIntToScalar(100),
76                                        SkIntToScalar(100), SkIntToScalar(100),
77                                        0.999f);
78        }
79        {
80            SkPath* thinEllipse = &fPaths.push_back();
81            thinEllipse->moveTo(0, -0);
82            thinEllipse->conicTo(SkIntToScalar(100), SkIntToScalar(100),
83                                        SkIntToScalar(5), SkIntToScalar(0),
84                                        SK_ScalarHalf);
85        }
86        {
87            SkPath* veryThinEllipse = &fPaths.push_back();
88            veryThinEllipse->moveTo(0, -0);
89            veryThinEllipse->conicTo(SkIntToScalar(100), SkIntToScalar(100),
90                                        SkIntToScalar(1), SkIntToScalar(0),
91                                        SK_ScalarHalf);
92        }
93        {
94            SkPath* closedEllipse = &fPaths.push_back();
95            closedEllipse->moveTo(0, -0);
96            closedEllipse->conicTo(SkIntToScalar(100), SkIntToScalar(100),
97                                        SkIntToScalar(0), SkIntToScalar(0),
98                                        SK_ScalarHalf);
99        }
100    }
101
102    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
103        static const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };
104
105        enum {
106            kMargin = 15,
107        };
108        int wrapX = canvas->getDeviceSize().fWidth - kMargin;
109
110        SkScalar maxH = 0;
111        canvas->translate(SkIntToScalar(kMargin), SkIntToScalar(kMargin));
112        canvas->save();
113
114        SkScalar x = SkIntToScalar(kMargin);
115        for (int p = 0; p < fPaths.count(); ++p) {
116            for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphaValue); ++a) {
117                for (int aa = 0; aa < 2; ++aa) {
118                    for (int fh = 0; fh < 2; ++fh) {
119
120                        const SkRect& bounds = fPaths[p].getBounds();
121
122                        if (x + bounds.width() > wrapX) {
123                            canvas->restore();
124                            canvas->translate(0, maxH + SkIntToScalar(kMargin));
125                            canvas->save();
126                            maxH = 0;
127                            x = SkIntToScalar(kMargin);
128                        }
129
130                        SkPaint paint;
131                        paint.setARGB(kAlphaValue[a], 0, 0, 0);
132                        paint.setAntiAlias(SkToBool(aa));
133                        if (fh == 1) {
134                            paint.setStyle(SkPaint::kStroke_Style);
135                            paint.setStrokeWidth(0);
136                        } else if (fh == 0) {
137                            paint.setStyle(SkPaint::kFill_Style);
138                        }
139                        canvas->save();
140                        canvas->translate(-bounds.fLeft, -bounds.fTop);
141                        canvas->drawPath(fPaths[p], paint);
142                        canvas->restore();
143
144                        maxH = SkMaxScalar(maxH, bounds.height());
145
146                        SkScalar dx = bounds.width() + SkIntToScalar(kMargin);
147                        x += dx;
148                        canvas->translate(dx, 0);
149                    }
150                }
151            }
152        }
153        canvas->restore();
154    }
155
156    virtual uint32_t onGetFlags() const SK_OVERRIDE {
157        return  kSkipPDF_Flag;
158    }
159
160private:
161    SkTArray<SkPath> fPaths;
162    typedef GM INHERITED;
163};
164
165//////////////////////////////////////////////////////////////////////////////
166
167DEF_GM( return SkNEW(ConicPathsGM); )
168}
169