1/*
2 * Copyright 2011 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 "include/core/SkCanvas.h"
9#include "include/core/SkColorPriv.h"
10#include "include/core/SkPath.h"
11#include "include/core/SkPathMeasure.h"
12#include "include/core/SkRegion.h"
13#include "include/core/SkShader.h"
14#include "include/effects/Sk1DPathEffect.h"
15#include "include/effects/SkCornerPathEffect.h"
16#include "include/effects/SkGradientShader.h"
17#include "include/utils/SkRandom.h"
18#include "samplecode/Sample.h"
19#include "src/utils/SkUTF.h"
20#include "tools/timer/TimeUtils.h"
21
22#define CORNER_RADIUS   12
23
24static const int gXY[] = {
25    4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
26};
27
28static sk_sp<SkPathEffect> make_pe(int flags, SkScalar phase) {
29    if (flags == 1) {
30        return SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS));
31    }
32
33    SkPath  path;
34    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
35    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
36        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
37    path.close();
38    path.offset(SkIntToScalar(-6), 0);
39
40    auto outer = SkPath1DPathEffect::Make(path, 12, phase, SkPath1DPathEffect::kRotate_Style);
41
42    if (flags == 2)
43        return outer;
44
45    auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS));
46
47    return SkPathEffect::MakeCompose(outer, inner);
48}
49
50static sk_sp<SkPathEffect> make_warp_pe(SkScalar phase) {
51    SkPath  path;
52    path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
53    for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) {
54        path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
55    }
56    path.close();
57    path.offset(SkIntToScalar(-6), 0);
58
59    auto outer = SkPath1DPathEffect::Make(
60        path, 12, phase, SkPath1DPathEffect::kMorph_Style);
61    auto inner = SkCornerPathEffect::Make(SkIntToScalar(CORNER_RADIUS));
62
63    return SkPathEffect::MakeCompose(outer, inner);
64}
65
66///////////////////////////////////////////////////////////
67
68#include "include/core/SkColorFilter.h"
69
70class PathEffectView : public Sample {
71    SkPath  fPath;
72    SkPoint fClickPt;
73    SkScalar fPhase;
74
75public:
76    PathEffectView() : fPhase(0) {
77        }
78
79protected:
80    void onOnceBeforeDraw() override {
81        SkRandom    rand;
82        int         steps = 20;
83        SkScalar    dist = SkIntToScalar(400);
84        SkScalar    x = SkIntToScalar(20);
85        SkScalar    y = SkIntToScalar(50);
86
87        fPath.moveTo(x, y);
88        for (int i = 0; i < steps; i++) {
89            x += dist/steps;
90            SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25);
91            if (i == steps/2) {
92                fPath.moveTo(x, tmpY);
93            } else {
94                fPath.lineTo(x, tmpY);
95            }
96        }
97
98        {
99            SkRect  oval;
100            oval.setLTRB(20, 30, 100, 60);
101            oval.offset(x, 0);
102            fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8));
103        }
104
105        fClickPt.set(SkIntToScalar(200), SkIntToScalar(200));
106
107        this->setBGColor(0xFFDDDDDD);
108    }
109
110    SkString name() override { return SkString("PathEffects"); }
111
112    void onDrawContent(SkCanvas* canvas) override {
113        SkPaint paint;
114
115        canvas->translate(0, 50);
116
117        paint.setColor(SK_ColorBLUE);
118        paint.setPathEffect(make_pe(2, fPhase));
119        canvas->drawPath(fPath, paint);
120
121        canvas->translate(0, 50);
122
123        paint.setARGB(0xFF, 0, 0xBB, 0);
124        paint.setPathEffect(make_pe(3, fPhase));
125        canvas->drawPath(fPath, paint);
126
127        canvas->translate(0, 50);
128
129        paint.setARGB(0xFF, 0, 0, 0);
130        paint.setPathEffect(make_warp_pe(fPhase));
131        canvas->drawPath(fPath, paint);
132    }
133
134    bool onAnimate(double nanos) override {
135        fPhase = TimeUtils::Scaled(1e-9 * nanos, 40);
136        return true;
137    }
138
139private:
140    using INHERITED = Sample;
141};
142
143//////////////////////////////////////////////////////////////////////////////
144
145DEF_SAMPLE( return new PathEffectView(); )
146