xref: /aosp_15_r20/external/skia/tools/viewer/PathOverstrokeSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathUtils.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/Slide.h"
11*c8dee2aaSAndroid Build Coastguard Worker 
12*c8dee2aaSAndroid Build Coastguard Worker #include <iostream>
13*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
14*c8dee2aaSAndroid Build Coastguard Worker 
15*c8dee2aaSAndroid Build Coastguard Worker #define PI SK_ScalarPI
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #define LIN_SEGMENTS 10
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker class OverstrokeSlide : public Slide {
20*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fStroke;
21*c8dee2aaSAndroid Build Coastguard Worker     int fPathType;  // super lazy enum
22*c8dee2aaSAndroid Build Coastguard Worker     bool fClosePath;
23*c8dee2aaSAndroid Build Coastguard Worker     bool fDrawFillPath;
24*c8dee2aaSAndroid Build Coastguard Worker     bool fDumpHex;
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker public:
OverstrokeSlide()27*c8dee2aaSAndroid Build Coastguard Worker     OverstrokeSlide() {
28*c8dee2aaSAndroid Build Coastguard Worker         fStroke = 5;
29*c8dee2aaSAndroid Build Coastguard Worker         fPathType = 0;
30*c8dee2aaSAndroid Build Coastguard Worker         fClosePath = false;
31*c8dee2aaSAndroid Build Coastguard Worker         fDrawFillPath = false;
32*c8dee2aaSAndroid Build Coastguard Worker         fDumpHex = false;
33*c8dee2aaSAndroid Build Coastguard Worker         fName = "PathOverstroke";
34*c8dee2aaSAndroid Build Coastguard Worker     }
35*c8dee2aaSAndroid Build Coastguard Worker 
onChar(SkUnichar uni)36*c8dee2aaSAndroid Build Coastguard Worker     bool onChar(SkUnichar uni) override {
37*c8dee2aaSAndroid Build Coastguard Worker             switch (uni) {
38*c8dee2aaSAndroid Build Coastguard Worker                 case ',':
39*c8dee2aaSAndroid Build Coastguard Worker                     fStroke += 1.0;
40*c8dee2aaSAndroid Build Coastguard Worker                     return true;
41*c8dee2aaSAndroid Build Coastguard Worker                 case '.':
42*c8dee2aaSAndroid Build Coastguard Worker                     fStroke -= 1.0;
43*c8dee2aaSAndroid Build Coastguard Worker                     return true;
44*c8dee2aaSAndroid Build Coastguard Worker                 case 'x':
45*c8dee2aaSAndroid Build Coastguard Worker                     fPathType = (fPathType + 1) % 4;
46*c8dee2aaSAndroid Build Coastguard Worker                     return true;
47*c8dee2aaSAndroid Build Coastguard Worker                 case 'c':
48*c8dee2aaSAndroid Build Coastguard Worker                     fClosePath = !fClosePath;
49*c8dee2aaSAndroid Build Coastguard Worker                     return true;
50*c8dee2aaSAndroid Build Coastguard Worker                 case 'f':
51*c8dee2aaSAndroid Build Coastguard Worker                     fDrawFillPath = !fDrawFillPath;
52*c8dee2aaSAndroid Build Coastguard Worker                     return true;
53*c8dee2aaSAndroid Build Coastguard Worker                 case 'D':
54*c8dee2aaSAndroid Build Coastguard Worker                     fDumpHex = !fDumpHex;
55*c8dee2aaSAndroid Build Coastguard Worker                     return true;
56*c8dee2aaSAndroid Build Coastguard Worker                 default:
57*c8dee2aaSAndroid Build Coastguard Worker                     break;
58*c8dee2aaSAndroid Build Coastguard Worker             }
59*c8dee2aaSAndroid Build Coastguard Worker             return false;
60*c8dee2aaSAndroid Build Coastguard Worker     }
61*c8dee2aaSAndroid Build Coastguard Worker 
quadPath(SkPoint p1,SkPoint p2)62*c8dee2aaSAndroid Build Coastguard Worker     SkPath quadPath(SkPoint p1, SkPoint p2) {
63*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(p1.y() == p2.y());
64*c8dee2aaSAndroid Build Coastguard Worker 
65*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
66*c8dee2aaSAndroid Build Coastguard Worker         path.moveTo(p1);
67*c8dee2aaSAndroid Build Coastguard Worker         path.lineTo(p2);
68*c8dee2aaSAndroid Build Coastguard Worker 
69*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 2.0f, p1.y() * 0.7f);
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker         path.quadTo(p3, p1);
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker         return path;
74*c8dee2aaSAndroid Build Coastguard Worker     }
75*c8dee2aaSAndroid Build Coastguard Worker 
cubicPath(SkPoint p1,SkPoint p2)76*c8dee2aaSAndroid Build Coastguard Worker     SkPath cubicPath(SkPoint p1, SkPoint p2) {
77*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(p1.y() == p2.y());
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
80*c8dee2aaSAndroid Build Coastguard Worker         path.moveTo(p1);
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p3 = SkPoint::Make((p1.x() + p2.x()) / 3.0f, p1.y() * 0.7f);
83*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p4 = SkPoint::Make(2.0f*(p1.x() + p2.x()) / 3.0f, p1.y() * 1.5f);
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker         path.cubicTo(p3, p4, p2);
86*c8dee2aaSAndroid Build Coastguard Worker 
87*c8dee2aaSAndroid Build Coastguard Worker         return path;
88*c8dee2aaSAndroid Build Coastguard Worker     }
89*c8dee2aaSAndroid Build Coastguard Worker 
linSemicirclePath(SkPoint p1,SkPoint p2)90*c8dee2aaSAndroid Build Coastguard Worker     SkPath linSemicirclePath(SkPoint p1, SkPoint p2) {
91*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(p1.y() == p2.y());
92*c8dee2aaSAndroid Build Coastguard Worker 
93*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
94*c8dee2aaSAndroid Build Coastguard Worker         path.moveTo(p1);
95*c8dee2aaSAndroid Build Coastguard Worker         path.lineTo(p2);
96*c8dee2aaSAndroid Build Coastguard Worker 
97*c8dee2aaSAndroid Build Coastguard Worker         SkPoint pt;
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < LIN_SEGMENTS; i++) {
100*c8dee2aaSAndroid Build Coastguard Worker             float theta = i * PI / (LIN_SEGMENTS);
101*c8dee2aaSAndroid Build Coastguard Worker             SkScalar x = 65 + 15 * cos(theta);
102*c8dee2aaSAndroid Build Coastguard Worker             SkScalar y = 50 - 15 * sin(theta);
103*c8dee2aaSAndroid Build Coastguard Worker             pt = SkPoint::Make(x, y);
104*c8dee2aaSAndroid Build Coastguard Worker             path.lineTo(pt);
105*c8dee2aaSAndroid Build Coastguard Worker         }
106*c8dee2aaSAndroid Build Coastguard Worker         path.lineTo(p1);
107*c8dee2aaSAndroid Build Coastguard Worker 
108*c8dee2aaSAndroid Build Coastguard Worker         return path;
109*c8dee2aaSAndroid Build Coastguard Worker     }
110*c8dee2aaSAndroid Build Coastguard Worker 
rectPath(SkPoint p1)111*c8dee2aaSAndroid Build Coastguard Worker     SkPath rectPath(SkPoint p1) {
112*c8dee2aaSAndroid Build Coastguard Worker         SkRect r = SkRect::MakeXYWH(p1.fX, p1.fY, 20, 20);
113*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
114*c8dee2aaSAndroid Build Coastguard Worker         path.addRect(r);
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker         return path;
117*c8dee2aaSAndroid Build Coastguard Worker     }
118*c8dee2aaSAndroid Build Coastguard Worker 
draw(SkCanvas * canvas)119*c8dee2aaSAndroid Build Coastguard Worker     void draw(SkCanvas* canvas) override {
120*c8dee2aaSAndroid Build Coastguard Worker         canvas->clear(0xFFFFFFFF);
121*c8dee2aaSAndroid Build Coastguard Worker         const float SCALE = 1;
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker         canvas->translate(30, 40);
124*c8dee2aaSAndroid Build Coastguard Worker         canvas->scale(SCALE, SCALE);
125*c8dee2aaSAndroid Build Coastguard Worker 
126*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p1 = SkPoint::Make(50, 50);
127*c8dee2aaSAndroid Build Coastguard Worker         SkPoint p2 = SkPoint::Make(80, 50);
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker         SkPath path;
130*c8dee2aaSAndroid Build Coastguard Worker         switch (fPathType) {
131*c8dee2aaSAndroid Build Coastguard Worker             case 0:
132*c8dee2aaSAndroid Build Coastguard Worker                 path = quadPath(p1, p2);
133*c8dee2aaSAndroid Build Coastguard Worker                 break;
134*c8dee2aaSAndroid Build Coastguard Worker             case 1:
135*c8dee2aaSAndroid Build Coastguard Worker                 path = cubicPath(p1, p2);
136*c8dee2aaSAndroid Build Coastguard Worker                 break;
137*c8dee2aaSAndroid Build Coastguard Worker             case 2:
138*c8dee2aaSAndroid Build Coastguard Worker                 path = rectPath(p1);
139*c8dee2aaSAndroid Build Coastguard Worker                 break;
140*c8dee2aaSAndroid Build Coastguard Worker             case 3:
141*c8dee2aaSAndroid Build Coastguard Worker                 path = linSemicirclePath(p1, p2);
142*c8dee2aaSAndroid Build Coastguard Worker                 break;
143*c8dee2aaSAndroid Build Coastguard Worker             default:
144*c8dee2aaSAndroid Build Coastguard Worker                 path = quadPath(p1, p2);
145*c8dee2aaSAndroid Build Coastguard Worker                 break;
146*c8dee2aaSAndroid Build Coastguard Worker         }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker         if (fClosePath) {
149*c8dee2aaSAndroid Build Coastguard Worker             path.close();
150*c8dee2aaSAndroid Build Coastguard Worker         }
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker         SkPaint p;
153*c8dee2aaSAndroid Build Coastguard Worker         p.setColor(SK_ColorRED);
154*c8dee2aaSAndroid Build Coastguard Worker         p.setAntiAlias(true);
155*c8dee2aaSAndroid Build Coastguard Worker         p.setStyle(SkPaint::kStroke_Style);
156*c8dee2aaSAndroid Build Coastguard Worker         p.setStrokeWidth(fStroke);
157*c8dee2aaSAndroid Build Coastguard Worker 
158*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawPath(path, p);
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker         if (fDumpHex) {
161*c8dee2aaSAndroid Build Coastguard Worker             std::cerr << "path dumpHex" << std::endl;
162*c8dee2aaSAndroid Build Coastguard Worker             path.dumpHex();
163*c8dee2aaSAndroid Build Coastguard Worker         }
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker         SkPaint hairp;
166*c8dee2aaSAndroid Build Coastguard Worker         hairp.setColor(SK_ColorBLACK);
167*c8dee2aaSAndroid Build Coastguard Worker         hairp.setAntiAlias(true);
168*c8dee2aaSAndroid Build Coastguard Worker         hairp.setStyle(SkPaint::kStroke_Style);
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker         if (fDrawFillPath) {
171*c8dee2aaSAndroid Build Coastguard Worker             SkPath fillpath;
172*c8dee2aaSAndroid Build Coastguard Worker             skpathutils::FillPathWithPaint(path, p, &fillpath);
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker             canvas->drawPath(fillpath, hairp);
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker             if (fDumpHex) {
177*c8dee2aaSAndroid Build Coastguard Worker                 std::cerr << "fillpath dumpHex" << std::endl;
178*c8dee2aaSAndroid Build Coastguard Worker                 fillpath.dumpHex();
179*c8dee2aaSAndroid Build Coastguard Worker             }
180*c8dee2aaSAndroid Build Coastguard Worker         }
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker         if (fDumpHex) {
183*c8dee2aaSAndroid Build Coastguard Worker             std::cerr << std::endl;
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker             fDumpHex = false;
186*c8dee2aaSAndroid Build Coastguard Worker         }
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker         // draw original path with green hairline
189*c8dee2aaSAndroid Build Coastguard Worker         hairp.setColor(SK_ColorGREEN);
190*c8dee2aaSAndroid Build Coastguard Worker         canvas->drawPath(path, hairp);
191*c8dee2aaSAndroid Build Coastguard Worker     }
192*c8dee2aaSAndroid Build Coastguard Worker };
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
195*c8dee2aaSAndroid Build Coastguard Worker 
196*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new OverstrokeSlide(); )
197