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