1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 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
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkGraphics.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPath.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRegion.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTime.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkUTF.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "tools/viewer/ClickHandlerSlide.h"
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker class PathClipSlide : public ClickHandlerSlide {
25*c8dee2aaSAndroid Build Coastguard Worker public:
26*c8dee2aaSAndroid Build Coastguard Worker SkRect fOval;
27*c8dee2aaSAndroid Build Coastguard Worker SkPoint fCenter;
28*c8dee2aaSAndroid Build Coastguard Worker
PathClipSlide()29*c8dee2aaSAndroid Build Coastguard Worker PathClipSlide() : fOval(SkRect::MakeWH(200, 50)), fCenter(SkPoint::Make(250, 250)) {
30*c8dee2aaSAndroid Build Coastguard Worker fName = "PathClip";
31*c8dee2aaSAndroid Build Coastguard Worker }
32*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)33*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) override {
34*c8dee2aaSAndroid Build Coastguard Worker const SkRect oval = fOval.makeOffset(fCenter.fX - fOval.centerX(),
35*c8dee2aaSAndroid Build Coastguard Worker fCenter.fY - fOval.centerY());
36*c8dee2aaSAndroid Build Coastguard Worker
37*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
38*c8dee2aaSAndroid Build Coastguard Worker p.setAntiAlias(true);
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
41*c8dee2aaSAndroid Build Coastguard Worker canvas->drawOval(oval, p);
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker const SkRect r = SkRect::MakeLTRB(200, 200, 300, 300);
44*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(r);
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kFill_Style);
47*c8dee2aaSAndroid Build Coastguard Worker p.setColor(SK_ColorRED);
48*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, p);
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker p.setColor(0x800000FF);
51*c8dee2aaSAndroid Build Coastguard Worker canvas->drawOval(oval, p);
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker protected:
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey)55*c8dee2aaSAndroid Build Coastguard Worker Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override {
56*c8dee2aaSAndroid Build Coastguard Worker return new Click([&](Click* c) {
57*c8dee2aaSAndroid Build Coastguard Worker fCenter = c->fCurr;
58*c8dee2aaSAndroid Build Coastguard Worker return false;
59*c8dee2aaSAndroid Build Coastguard Worker });
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker
onClick(ClickHandlerSlide::Click *)62*c8dee2aaSAndroid Build Coastguard Worker bool onClick(ClickHandlerSlide::Click *) override { return false; }
63*c8dee2aaSAndroid Build Coastguard Worker };
DEF_SLIDE(return new PathClipSlide;)64*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new PathClipSlide; )
65*c8dee2aaSAndroid Build Coastguard Worker
66*c8dee2aaSAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////////////
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker static int clip_line(const SkRect& bounds, SkPoint p0, SkPoint p1, SkPoint edges[]) {
69*c8dee2aaSAndroid Build Coastguard Worker SkPoint* edgesStart = edges;
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker if (p0.fY == p1.fY) {
72*c8dee2aaSAndroid Build Coastguard Worker return 0;
73*c8dee2aaSAndroid Build Coastguard Worker }
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker if (p0.fY > p1.fY) {
76*c8dee2aaSAndroid Build Coastguard Worker using std::swap;
77*c8dee2aaSAndroid Build Coastguard Worker swap(p0, p1);
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker // now we're monotonic in Y: p0 <= p1
80*c8dee2aaSAndroid Build Coastguard Worker if (p1.fY <= bounds.top() || p0.fY >= bounds.bottom()) {
81*c8dee2aaSAndroid Build Coastguard Worker return 0;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker double dxdy = (double)(p1.fX - p0.fX) / (p1.fY - p0.fY);
85*c8dee2aaSAndroid Build Coastguard Worker if (p0.fY < bounds.top()) {
86*c8dee2aaSAndroid Build Coastguard Worker p0.fX = SkDoubleToScalar(p0.fX + dxdy * (bounds.top() - p0.fY));
87*c8dee2aaSAndroid Build Coastguard Worker p0.fY = bounds.top();
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker if (p1.fY > bounds.bottom()) {
90*c8dee2aaSAndroid Build Coastguard Worker p1.fX = SkDoubleToScalar(p1.fX + dxdy * (bounds.bottom() - p1.fY));
91*c8dee2aaSAndroid Build Coastguard Worker p1.fY = bounds.bottom();
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker // Now p0...p1 is strictly inside bounds vertically, so we just need to clip horizontally
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker if (p0.fX > p1.fX) {
97*c8dee2aaSAndroid Build Coastguard Worker using std::swap;
98*c8dee2aaSAndroid Build Coastguard Worker swap(p0, p1);
99*c8dee2aaSAndroid Build Coastguard Worker }
100*c8dee2aaSAndroid Build Coastguard Worker // now we're left-to-right: p0 .. p1
101*c8dee2aaSAndroid Build Coastguard Worker
102*c8dee2aaSAndroid Build Coastguard Worker if (p1.fX <= bounds.left()) { // entirely to the left
103*c8dee2aaSAndroid Build Coastguard Worker p0.fX = p1.fX = bounds.left();
104*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p0;
105*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p1;
106*c8dee2aaSAndroid Build Coastguard Worker return 2;
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker if (p0.fX >= bounds.right()) { // entirely to the right
109*c8dee2aaSAndroid Build Coastguard Worker p0.fX = p1.fX = bounds.right();
110*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p0;
111*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p1;
112*c8dee2aaSAndroid Build Coastguard Worker return 2;
113*c8dee2aaSAndroid Build Coastguard Worker }
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker if (p0.fX < bounds.left()) {
116*c8dee2aaSAndroid Build Coastguard Worker float y = SkDoubleToScalar(p0.fY + (bounds.left() - p0.fX) / dxdy);
117*c8dee2aaSAndroid Build Coastguard Worker *edges++ = SkPoint::Make(bounds.left(), p0.fY);
118*c8dee2aaSAndroid Build Coastguard Worker *edges++ = SkPoint::Make(bounds.left(), y);
119*c8dee2aaSAndroid Build Coastguard Worker p0.set(bounds.left(), y);
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker if (p1.fX > bounds.right()) {
122*c8dee2aaSAndroid Build Coastguard Worker float y = SkDoubleToScalar(p0.fY + (bounds.right() - p0.fX) / dxdy);
123*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p0;
124*c8dee2aaSAndroid Build Coastguard Worker *edges++ = SkPoint::Make(bounds.right(), y);
125*c8dee2aaSAndroid Build Coastguard Worker *edges++ = SkPoint::Make(bounds.right(), p1.fY);
126*c8dee2aaSAndroid Build Coastguard Worker } else {
127*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p0;
128*c8dee2aaSAndroid Build Coastguard Worker *edges++ = p1;
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker return SkToInt(edges - edgesStart);
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
draw_clipped_line(SkCanvas * canvas,const SkRect & bounds,SkPoint p0,SkPoint p1,const SkPaint & paint)133*c8dee2aaSAndroid Build Coastguard Worker static void draw_clipped_line(SkCanvas* canvas, const SkRect& bounds,
134*c8dee2aaSAndroid Build Coastguard Worker SkPoint p0, SkPoint p1, const SkPaint& paint) {
135*c8dee2aaSAndroid Build Coastguard Worker SkPoint verts[6];
136*c8dee2aaSAndroid Build Coastguard Worker int count = clip_line(bounds, p0, p1, verts);
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
139*c8dee2aaSAndroid Build Coastguard Worker path.addPoly(verts, count, false);
140*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker // Demonstrate edge-clipping that is used in the scan converter
144*c8dee2aaSAndroid Build Coastguard Worker //
145*c8dee2aaSAndroid Build Coastguard Worker class EdgeClipSlide : public ClickHandlerSlide {
146*c8dee2aaSAndroid Build Coastguard Worker enum {
147*c8dee2aaSAndroid Build Coastguard Worker N = 3
148*c8dee2aaSAndroid Build Coastguard Worker };
149*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPoly[N];
150*c8dee2aaSAndroid Build Coastguard Worker SkRect fClip;
151*c8dee2aaSAndroid Build Coastguard Worker SkColor fEdgeColor[N];
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker public:
EdgeClipSlide()154*c8dee2aaSAndroid Build Coastguard Worker EdgeClipSlide() : fClip(SkRect::MakeLTRB(150, 150, 550, 450)) {
155*c8dee2aaSAndroid Build Coastguard Worker fPoly[0].set(300, 40);
156*c8dee2aaSAndroid Build Coastguard Worker fPoly[1].set(550, 250);
157*c8dee2aaSAndroid Build Coastguard Worker fPoly[2].set(40, 450);
158*c8dee2aaSAndroid Build Coastguard Worker
159*c8dee2aaSAndroid Build Coastguard Worker fEdgeColor[0] = 0xFFFF0000;
160*c8dee2aaSAndroid Build Coastguard Worker fEdgeColor[1] = 0xFF00FF00;
161*c8dee2aaSAndroid Build Coastguard Worker fEdgeColor[2] = 0xFF0000FF;
162*c8dee2aaSAndroid Build Coastguard Worker fName = "EdgeClip";
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker
snap(SkScalar x)165*c8dee2aaSAndroid Build Coastguard Worker static SkScalar snap(SkScalar x) {
166*c8dee2aaSAndroid Build Coastguard Worker return SkScalarRoundToScalar(x * 0.5f) * 2;
167*c8dee2aaSAndroid Build Coastguard Worker }
snap(const SkPoint & pt)168*c8dee2aaSAndroid Build Coastguard Worker static SkPoint snap(const SkPoint& pt) {
169*c8dee2aaSAndroid Build Coastguard Worker return SkPoint::Make(snap(pt.x()), snap(pt.y()));
170*c8dee2aaSAndroid Build Coastguard Worker }
snap(SkPoint dst[],const SkPoint src[],int count)171*c8dee2aaSAndroid Build Coastguard Worker static void snap(SkPoint dst[], const SkPoint src[], int count) {
172*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
173*c8dee2aaSAndroid Build Coastguard Worker dst[i] = snap(src[i]);
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas)177*c8dee2aaSAndroid Build Coastguard Worker void draw(SkCanvas* canvas) override {
178*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
179*c8dee2aaSAndroid Build Coastguard Worker path.addPoly(fPoly, N, true);
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker // Draw the full triangle, stroked and filled
182*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
183*c8dee2aaSAndroid Build Coastguard Worker p.setAntiAlias(true);
184*c8dee2aaSAndroid Build Coastguard Worker p.setColor(0xFFE0E0E0);
185*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, p);
186*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
187*c8dee2aaSAndroid Build Coastguard Worker p.setStrokeWidth(2);
188*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < N; ++i) {
189*c8dee2aaSAndroid Build Coastguard Worker const int j = (i + 1) % N;
190*c8dee2aaSAndroid Build Coastguard Worker p.setColor(fEdgeColor[i]);
191*c8dee2aaSAndroid Build Coastguard Worker p.setAlpha(0x88);
192*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(fPoly[i], fPoly[j], p);
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kFill_Style);
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker // Draw the clip itself
197*c8dee2aaSAndroid Build Coastguard Worker p.setColor(0xFF8888CC);
198*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(fClip, p);
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker // Draw the filled triangle through the clip
201*c8dee2aaSAndroid Build Coastguard Worker p.setColor(0xFF88CC88);
202*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
203*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(fClip);
204*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, p);
205*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
208*c8dee2aaSAndroid Build Coastguard Worker p.setStrokeWidth(6);
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker // Draw each of the "Edges" that survived the clipping
211*c8dee2aaSAndroid Build Coastguard Worker // We use a layer, so we can PLUS the different edge-colors, showing where two edges
212*c8dee2aaSAndroid Build Coastguard Worker // canceled each other out.
213*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(nullptr, nullptr);
214*c8dee2aaSAndroid Build Coastguard Worker p.setBlendMode(SkBlendMode::kPlus);
215*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < N; ++i) {
216*c8dee2aaSAndroid Build Coastguard Worker const int j = (i + 1) % N;
217*c8dee2aaSAndroid Build Coastguard Worker p.setColor(fEdgeColor[i]);
218*c8dee2aaSAndroid Build Coastguard Worker draw_clipped_line(canvas, fClip, fPoly[i], fPoly[j], p);
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker class MyClick : public Click {
224*c8dee2aaSAndroid Build Coastguard Worker public:
MyClick()225*c8dee2aaSAndroid Build Coastguard Worker MyClick() {}
226*c8dee2aaSAndroid Build Coastguard Worker virtual void handleMove() = 0;
227*c8dee2aaSAndroid Build Coastguard Worker };
228*c8dee2aaSAndroid Build Coastguard Worker
229*c8dee2aaSAndroid Build Coastguard Worker class VertClick : public MyClick {
230*c8dee2aaSAndroid Build Coastguard Worker SkPoint* fPt;
231*c8dee2aaSAndroid Build Coastguard Worker public:
VertClick(SkPoint * pt)232*c8dee2aaSAndroid Build Coastguard Worker VertClick(SkPoint* pt) : fPt(pt) {}
handleMove()233*c8dee2aaSAndroid Build Coastguard Worker void handleMove() override { *fPt = snap(fCurr); }
234*c8dee2aaSAndroid Build Coastguard Worker };
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker class DragRectClick : public MyClick {
237*c8dee2aaSAndroid Build Coastguard Worker SkRect* fRect;
238*c8dee2aaSAndroid Build Coastguard Worker public:
DragRectClick(SkRect * rect)239*c8dee2aaSAndroid Build Coastguard Worker DragRectClick(SkRect* rect) : fRect(rect) {}
handleMove()240*c8dee2aaSAndroid Build Coastguard Worker void handleMove() override { fRect->offset(fCurr.x() - fPrev.x(), fCurr.y() - fPrev.y()); }
241*c8dee2aaSAndroid Build Coastguard Worker };
242*c8dee2aaSAndroid Build Coastguard Worker
243*c8dee2aaSAndroid Build Coastguard Worker class DragPolyClick : public MyClick {
244*c8dee2aaSAndroid Build Coastguard Worker SkPoint fSrc[100];
245*c8dee2aaSAndroid Build Coastguard Worker SkPoint* fPoly;
246*c8dee2aaSAndroid Build Coastguard Worker int fCount;
247*c8dee2aaSAndroid Build Coastguard Worker public:
DragPolyClick(SkPoint poly[],int count)248*c8dee2aaSAndroid Build Coastguard Worker DragPolyClick(SkPoint poly[], int count) : fPoly(poly), fCount(count)
249*c8dee2aaSAndroid Build Coastguard Worker {
250*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((size_t)count <= std::size(fSrc));
251*c8dee2aaSAndroid Build Coastguard Worker memcpy(fSrc, poly, count * sizeof(SkPoint));
252*c8dee2aaSAndroid Build Coastguard Worker }
handleMove()253*c8dee2aaSAndroid Build Coastguard Worker void handleMove() override {
254*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dx = fCurr.x() - fOrig.x();
255*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dy = fCurr.y() - fOrig.y();
256*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < fCount; ++i) {
257*c8dee2aaSAndroid Build Coastguard Worker fPoly[i].set(snap(fSrc[i].x() + dx), snap(fSrc[i].y() + dy));
258*c8dee2aaSAndroid Build Coastguard Worker }
259*c8dee2aaSAndroid Build Coastguard Worker }
260*c8dee2aaSAndroid Build Coastguard Worker };
261*c8dee2aaSAndroid Build Coastguard Worker
262*c8dee2aaSAndroid Build Coastguard Worker class DoNothingClick : public MyClick {
263*c8dee2aaSAndroid Build Coastguard Worker public:
DoNothingClick()264*c8dee2aaSAndroid Build Coastguard Worker DoNothingClick() {}
handleMove()265*c8dee2aaSAndroid Build Coastguard Worker void handleMove() override {}
266*c8dee2aaSAndroid Build Coastguard Worker };
267*c8dee2aaSAndroid Build Coastguard Worker
hit_test(const SkPoint & pt,SkScalar x,SkScalar y)268*c8dee2aaSAndroid Build Coastguard Worker static bool hit_test(const SkPoint& pt, SkScalar x, SkScalar y) {
269*c8dee2aaSAndroid Build Coastguard Worker const SkScalar rad = 8;
270*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dx = pt.x() - x;
271*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dy = pt.y() - y;
272*c8dee2aaSAndroid Build Coastguard Worker return dx*dx + dy*dy <= rad*rad;
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker
275*c8dee2aaSAndroid Build Coastguard Worker protected:
onFindClickHandler(SkScalar x,SkScalar y,skui::ModifierKey)276*c8dee2aaSAndroid Build Coastguard Worker Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override {
277*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < N; ++i) {
278*c8dee2aaSAndroid Build Coastguard Worker if (hit_test(fPoly[i], x, y)) {
279*c8dee2aaSAndroid Build Coastguard Worker return new VertClick(&fPoly[i]);
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker }
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker SkPath path;
284*c8dee2aaSAndroid Build Coastguard Worker path.addPoly(fPoly, N, true);
285*c8dee2aaSAndroid Build Coastguard Worker if (path.contains(x, y)) {
286*c8dee2aaSAndroid Build Coastguard Worker return new DragPolyClick(fPoly, N);
287*c8dee2aaSAndroid Build Coastguard Worker }
288*c8dee2aaSAndroid Build Coastguard Worker
289*c8dee2aaSAndroid Build Coastguard Worker if (fClip.intersects(SkRect::MakeLTRB(x - 1, y - 1, x + 1, y + 1))) {
290*c8dee2aaSAndroid Build Coastguard Worker return new DragRectClick(&fClip);
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker return new DoNothingClick();
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker
onClick(Click * click)295*c8dee2aaSAndroid Build Coastguard Worker bool onClick(Click* click) override {
296*c8dee2aaSAndroid Build Coastguard Worker ((MyClick*)click)->handleMove();
297*c8dee2aaSAndroid Build Coastguard Worker return true;
298*c8dee2aaSAndroid Build Coastguard Worker }
299*c8dee2aaSAndroid Build Coastguard Worker };
300*c8dee2aaSAndroid Build Coastguard Worker
301*c8dee2aaSAndroid Build Coastguard Worker DEF_SLIDE( return new EdgeClipSlide; )
302