• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPath.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkScalar.h"
16 #include "include/core/SkSize.h"
17 #include "include/core/SkString.h"
18 #include "include/core/SkTypes.h"
19 #include "include/private/SkFloatBits.h"
20 #include "include/private/SkTArray.h"
21 
22 class ConicPathsGM : public skiagm::GM {
23 protected:
24 
onShortName()25     SkString onShortName() override {
26         return SkString("conicpaths");
27     }
28 
onISize()29     SkISize onISize() override {
30         return SkISize::Make(920, 960);
31     }
32 
onOnceBeforeDraw()33     void onOnceBeforeDraw() override {
34         {
35             const SkScalar w = SkScalarSqrt(2)/2;
36             SkPath* conicCirlce = &fPaths.push_back();
37             conicCirlce->moveTo(0, 0);
38             conicCirlce->conicTo(0, 50, 50, 50, w);
39             conicCirlce->rConicTo(50, 0, 50, -50, w);
40             conicCirlce->rConicTo(0, -50, -50, -50, w);
41             conicCirlce->rConicTo(-50, 0, -50, 50, w);
42 
43         }
44         {
45             SkPath* hyperbola = &fPaths.push_back();
46             hyperbola->moveTo(0, 0);
47             hyperbola->conicTo(0, 100, 100, 100, 2);
48         }
49         {
50             SkPath* thinHyperbola = &fPaths.push_back();
51             thinHyperbola->moveTo(0, 0);
52             thinHyperbola->conicTo(100, 100, 5, 0, 2);
53         }
54         {
55             SkPath* veryThinHyperbola = &fPaths.push_back();
56             veryThinHyperbola->moveTo(0, 0);
57             veryThinHyperbola->conicTo(100, 100, 1, 0, 2);
58         }
59         {
60             SkPath* closedHyperbola = &fPaths.push_back();
61             closedHyperbola->moveTo(0, 0);
62             closedHyperbola->conicTo(100, 100, 0, 0, 2);
63         }
64         {
65             // using 1 as weight defaults to using quadTo
66             SkPath* nearParabola = &fPaths.push_back();
67             nearParabola->moveTo(0, 0);
68             nearParabola->conicTo(0, 100, 100, 100, 0.999f);
69         }
70         {
71             SkPath* thinEllipse = &fPaths.push_back();
72             thinEllipse->moveTo(0, 0);
73             thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf);
74         }
75         {
76             SkPath* veryThinEllipse = &fPaths.push_back();
77             veryThinEllipse->moveTo(0, 0);
78             veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf);
79         }
80         {
81             SkPath* closedEllipse = &fPaths.push_back();
82             closedEllipse->moveTo(0,  0);
83             closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf);
84         }
85         {
86             const SkScalar w = SkScalarSqrt(2)/2;
87             fGiantCircle.moveTo(2.1e+11f, -1.05e+11f);
88             fGiantCircle.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w);
89             fGiantCircle.conicTo(0, 0, 0, -1.05e+11f, w);
90             fGiantCircle.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w);
91             fGiantCircle.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w);
92 
93         }
94     }
95 
drawGiantCircle(SkCanvas * canvas)96     void drawGiantCircle(SkCanvas* canvas) {
97         SkPaint paint;
98         canvas->drawPath(fGiantCircle, paint);
99     }
100 
onDraw(SkCanvas * canvas)101     void onDraw(SkCanvas* canvas) override {
102         const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };
103 
104         const SkScalar margin = 15;
105         canvas->translate(margin, margin);
106 
107         SkPaint paint;
108         for (int p = 0; p < fPaths.count(); ++p) {
109             canvas->save();
110             for (size_t a = 0; a < SK_ARRAY_COUNT(kAlphaValue); ++a) {
111                 paint.setARGB(kAlphaValue[a], 0, 0, 0);
112                 for (int aa = 0; aa < 2; ++aa) {
113                     paint.setAntiAlias(SkToBool(aa));
114                     for (int fh = 0; fh < 2; ++fh) {
115                         paint.setStyle(fh ? SkPaint::kStroke_Style : SkPaint::kFill_Style);
116 
117                         const SkRect& bounds = fPaths[p].getBounds();
118                         canvas->save();
119                         canvas->translate(-bounds.fLeft, -bounds.fTop);
120                         canvas->drawPath(fPaths[p], paint);
121                         canvas->restore();
122 
123                         canvas->translate(110, 0);
124                     }
125                 }
126             }
127             canvas->restore();
128             canvas->translate(0, 110);
129         }
130         canvas->restore();
131 
132         this->drawGiantCircle(canvas);
133     }
134 
135 private:
136     SkTArray<SkPath> fPaths;
137     SkPath           fGiantCircle;
138     typedef skiagm::GM INHERITED;
139 };
140 DEF_GM(return new ConicPathsGM;)
141 
142 //////////////////////////////////////////////////////////////////////////////
143 
144 /* arc should be on top of circle */
145 DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
146     canvas->translate(50, 100);
147     SkPoint c = { 1052.5390625f, 506.8760978034711f };
148     SkScalar radius = 1096.702150363923f;
149     SkPaint paint;
150     paint.setAntiAlias(true);
151     paint.setStyle(SkPaint::kStroke_Style);
152     canvas->drawCircle(c, radius, paint);
153     SkPath path;
154     path.moveTo(288.88884710654133f, -280.26680862609f);
155     path.arcTo(0, 0, -39.00216443306411f, 400.6058925796476f, radius);
156     paint.setColor(0xff007f00);
157     canvas->drawPath(path, paint);
158 }
159 
160 /* circle should be antialiased */
161 DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
162     canvas->translate(50, 100);
163     SkPoint c = { 1052.5390625f, 506.8760978034711f };
164     SkScalar radius = 1096.702150363923f;
165     SkPaint paint;
166     paint.setAntiAlias(true);
167     paint.setStyle(SkPaint::kStroke_Style);
168     canvas->drawCircle(c, radius, paint);
169 }
170 
171 /* ovals should not be blurry */
172 DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
173     // Test EllipseOp
174     SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
175     SkPaint paint;
176     paint.setAntiAlias(true);
177     paint.setStyle(SkPaint::kStroke_Style);
178     paint.setStrokeWidth(100);
179     canvas->drawOval(r, paint);
180     r.offset(-15, -15);
181     paint.setColor(SK_ColorDKGRAY);
182     // we use stroke and fill to avoid falling into the SimpleFill path
183     paint.setStyle(SkPaint::kStrokeAndFill_Style);
184     paint.setStrokeWidth(1);
185     canvas->drawOval(r, paint);
186 
187     // Test DIEllipseOp
188     canvas->rotate(1.0f);
189     r.offset(55, 55);
190     paint.setColor(SK_ColorGRAY);
191     paint.setStyle(SkPaint::kStroke_Style);
192     paint.setStrokeWidth(100);
193     canvas->drawOval(r, paint);
194     r.offset(-15, -15);
195     paint.setColor(SK_ColorLTGRAY);
196     paint.setStyle(SkPaint::kStrokeAndFill_Style);
197     paint.setStrokeWidth(1);
198     canvas->drawOval(r, paint);
199 }
200 
201 DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) {
202     SkPath path;
203     path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
204     path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000));  // 103.923f, -60
205     path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006));  // 103.923f, -60
206     path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c),
207             SkBits2Float(0x42f00001), SkBits2Float(0x00000000),
208             SkBits2Float(0x3f7746ea));  // 120, -32.1539f, 120, 0, 0.965926f
209 
210     SkPaint paint;
211     paint.setAntiAlias(true);
212     canvas->translate(125, 125);
213     canvas->drawPath(path, paint);
214 }
215