1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2015 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SampleCode.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGeometry.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkIntersections.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOpEdgeBuilder.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// #include "SkPathOpsSimplifyAA.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// #include "SkPathStroker.h"
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPointPriv.h"
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h"
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkView.h"
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeSegment::dump() const {
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("{{{%1.9g,%1.9g}, {%1.9g,%1.9g}", fPts[0].fX, fPts[0].fY, fPts[1].fX, fPts[1].fY);
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SkPath::kQuad_Verb == fVerb) {
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf(", {%1.9g,%1.9g}", fPts[2].fX, fPts[2].fY);
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("}}");
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf(" id=%d", fDebugID);
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("\n");
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeSegment::dumpAll() const {
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkStrokeSegment* segment = this;
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (segment) {
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        segment->dump();
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        segment = segment->fNext;
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeTriple::dump() const {
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("{{{%1.9g,%1.9g}, {%1.9g,%1.9g}", fPts[0].fX, fPts[0].fY, fPts[1].fX, fPts[1].fY);
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SkPath::kQuad_Verb <= fVerb) {
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf(", {%1.9g,%1.9g}", fPts[2].fX, fPts[2].fY);
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SkPath::kCubic_Verb == fVerb) {
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf(", {%1.9g,%1.9g}", fPts[3].fX, fPts[3].fY);
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (SkPath::kConic_Verb == fVerb) {
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDebugf(", %1.9g", weight());
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("}}");
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf(" triple id=%d", fDebugID);
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("\ninner:\n");
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fInner->dumpAll();
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("outer:\n");
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fOuter->dumpAll();
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("join:\n");
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fJoin->dumpAll();
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeTriple::dumpAll() const {
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkStrokeTriple* triple = this;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (triple) {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        triple->dump();
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        triple = triple->fNext;
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeContour::dump() const {
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("id=%d ", fDebugID);
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("head:\n");
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fHead->dumpAll();
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("head cap:\n");
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fHeadCap->dumpAll();
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("tail cap:\n");
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fTailCap->dumpAll();
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkStrokeContour::dumpAll() const {
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const SkStrokeContour* contour = this;
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while (contour) {
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        contour->dump();
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        contour = contour->fNext;
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalar gCurveDistance = 10;
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0  // unused
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkPath::Verb get_path_verb(int index, const SkPath& path) {
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (index < 0) {
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkPath::kMove_Verb;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Iter iter(path, true);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++counter < index) {
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return verb;
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0);
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return SkPath::kMove_Verb;
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkScalar get_path_weight(int index, const SkPath& path) {
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Iter iter(path, true);
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++counter < index) {
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return verb == SkPath::kConic_Verb ? iter.conicWeight() : 1;
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0);
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return 0;
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void set_path_pt(int index, const SkPoint& pt, SkPath* path) {
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath result;
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::RawIter iter(*path);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int startIndex = 0;
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int endIndex = 0;
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                endIndex += 1;
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                endIndex += 1;
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                endIndex += 2;
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                endIndex += 3;
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kDone_Verb:
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (startIndex <= index && index < endIndex) {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            pts[index - startIndex] = pt;
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            index = -1;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.moveTo(pts[0]);
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.lineTo(pts[1]);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                startIndex += 1;
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.quadTo(pts[1], pts[2]);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                startIndex += 2;
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.conicTo(pts[1], pts[2], iter.conicWeight());
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                startIndex += 2;
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.cubicTo(pts[1], pts[2], pts[3]);
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                startIndex += 3;
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.close();
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                startIndex += 1;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kDone_Verb:
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("\n\noriginal\n");
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path->dump();
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkDebugf("\nedited\n");
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    result.dump();
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *path = result;
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_path_segment(int index, SkPath* path) {
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath result;
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint firstPt = { 0, 0 };  // init to avoid warning
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint lastPt = { 0, 0 };  // init to avoid warning
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::RawIter iter(*path);
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar weight  SK_INIT_TO_AVOID_WARNING;
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++counter == index) {
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result.lineTo((pts[0].fX + pts[1].fX) / 2, (pts[0].fY + pts[1].fY) / 2);
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb: {
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPoint chop[5];
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkChopQuadAtHalf(pts, chop);
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result.quadTo(chop[1], chop[2]);
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    pts[1] = chop[3];
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb: {
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkConic chop[2];
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkConic conic;
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    conic.set(pts, iter.conicWeight());
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!conic.chopAt(0.5f, chop)) {
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return;
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result.conicTo(chop[0].fPts[1], chop[0].fPts[2], chop[0].fW);
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    pts[1] = chop[1].fPts[1];
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    weight = chop[1].fW;
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb: {
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPoint chop[7];
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkChopCubicAtHalf(pts, chop);
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result.cubicTo(chop[1], chop[2], chop[3]);
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    pts[1] = chop[4];
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    pts[2] = chop[5];
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kClose_Verb: {
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    result.lineTo((lastPt.fX + firstPt.fX) / 2, (lastPt.fY + firstPt.fY) / 2);
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(0);
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else if (verb == SkPath::kConic_Verb) {
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            weight = iter.conicWeight();
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.moveTo(firstPt = pts[0]);
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.lineTo(lastPt = pts[1]);
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.quadTo(pts[1], lastPt = pts[2]);
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.conicTo(pts[1], lastPt = pts[2], weight);
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.cubicTo(pts[1], pts[2], lastPt = pts[3]);
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.close();
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kDone_Verb:
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *path = result;
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void delete_path_segment(int index, SkPath* path) {
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath result;
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::RawIter iter(*path);
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++counter == index) {
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            continue;
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.moveTo(pts[0]);
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.lineTo(pts[1]);
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.quadTo(pts[1], pts[2]);
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.conicTo(pts[1], pts[2], iter.conicWeight());
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.cubicTo(pts[1], pts[2], pts[3]);
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.close();
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kDone_Verb:
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *path = result;
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void set_path_weight(int index, SkScalar w, SkPath* path) {
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath result;
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Iter iter(*path, true);
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ++counter;
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.moveTo(pts[0]);
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.lineTo(pts[1]);
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.quadTo(pts[1], pts[2]);
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.conicTo(pts[1], pts[2], counter == index ? w : iter.conicWeight());
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.cubicTo(pts[1], pts[2], pts[3]);
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.close();
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kDone_Verb:
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *path = result;
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void set_path_verb(int index, SkPath::Verb v, SkPath* path, SkScalar w) {
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(SkPath::kLine_Verb <= v && v <= SkPath::kCubic_Verb);
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath result;
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPoint pts[4];
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb verb;
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Iter iter(*path, true);
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int counter = -1;
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar weight = verb == SkPath::kConic_Verb ? iter.conicWeight() : 1;
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++counter == index && v != verb) {
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb);
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    switch (v) {
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kConic_Verb:
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            weight = w;
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kQuad_Verb:
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[2] = pts[1];
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1].fX = (pts[0].fX + pts[2].fX) / 2;
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1].fY = (pts[0].fY + pts[2].fY) / 2;
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kCubic_Verb:
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[3] = pts[1];
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1].fX = (pts[0].fX * 2 + pts[3].fX) / 3;
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1].fY = (pts[0].fY * 2 + pts[3].fY) / 3;
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[2].fX = (pts[0].fX + pts[3].fX * 2) / 3;
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[2].fY = (pts[0].fY + pts[3].fY * 2) / 3;
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         default:
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkASSERT(0);
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb:
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb:
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    switch (v) {
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kLine_Verb:
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1] = pts[2];
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kConic_Verb:
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            weight = w;
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kQuad_Verb:
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kCubic_Verb: {
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDQuad dQuad;
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            dQuad.set(pts);
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDCubic dCubic = dQuad.debugToCubic();
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[3] = pts[2];
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1] = dCubic[1].asSkPoint();
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[2] = dCubic[2].asSkPoint();
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            } break;
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                         default:
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkASSERT(0);
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb:
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    switch (v) {
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kLine_Verb:
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1] = pts[3];
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kConic_Verb:
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            weight = w;
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        case SkPath::kQuad_Verb: {
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDCubic dCubic;
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            dCubic.set(pts);
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkDQuad dQuad = dCubic.toQuad();
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[1] = dQuad[1].asSkPoint();
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            pts[2] = pts[3];
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            } break;
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        default:
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            SkASSERT(0);
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            break;
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(0);
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            verb = v;
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (verb) {
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kMove_Verb:
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.moveTo(pts[0]);
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kLine_Verb:
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.lineTo(pts[1]);
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kQuad_Verb:
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.quadTo(pts[1], pts[2]);
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kConic_Verb:
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.conicTo(pts[1], pts[2], weight);
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kCubic_Verb:
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.cubicTo(pts[1], pts[2], pts[3]);
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case SkPath::kClose_Verb:
449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                result.close();
450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    *path = result;
457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void add_to_map(SkScalar coverage, int x, int y, uint8_t* distanceMap, int w, int h) {
460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int byteCoverage = (int) (coverage * 256);
461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (byteCoverage < 0) {
462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        byteCoverage = 0;
463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } else if (byteCoverage > 255) {
464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        byteCoverage = 255;
465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(x < w);
467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(y < h);
468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    distanceMap[y * w + x] = SkTMax(distanceMap[y * w + x], (uint8_t) byteCoverage);
469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void filter_coverage(const uint8_t* map, int len, uint8_t min, uint8_t max,
472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint8_t* filter) {
473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int index = 0; index < len; ++index) {
474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint8_t in = map[index];
475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        filter[index] = in < min ? 0 : max < in ? 0 : in;
476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void construct_path(SkPath& path) {
480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.reset();
481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.moveTo(442, 101.5f);
482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.quadTo(413.5f, 691, 772, 514);
483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.lineTo(346, 721.5f);
484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.lineTo(154, 209);
485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.lineTo(442, 101.5f);
486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    path.close();
487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct ButtonPaints {
490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kMaxStateCount = 3;
491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fDisabled;
492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fStates[kMaxStateCount];
493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fLabel;
494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ButtonPaints() {
496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[0].setAntiAlias(true);
497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[0].setStyle(SkPaint::kStroke_Style);
498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[0].setColor(0xFF3F0000);
499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[1] = fStates[0];
500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[1].setStrokeWidth(3);
501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[2] = fStates[1];
502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStates[2].setColor(0xFFcf0000);
503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setAntiAlias(true);
504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setTextSize(25.0f);
505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setTextAlign(SkPaint::kCenter_Align);
506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setStyle(SkPaint::kFill_Style);
507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Button {
511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect fBounds;
512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fStateCount;
513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fState;
514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char fLabel;
515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fVisible;
516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button(char label) {
518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStateCount = 2;
519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fState = 0;
520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel = label;
521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fVisible = false;
522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button(char label, int stateCount) {
525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(stateCount <= ButtonPaints::kMaxStateCount);
526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStateCount = stateCount;
527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fState = 0;
528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel = label;
529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fVisible = false;
530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& rect) {
533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fVisible && fBounds.contains(rect);
534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool enabled() {
537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkToBool(fState);
538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw(SkCanvas* canvas, const ButtonPaints& paints) {
541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fVisible) {
542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRect(fBounds, paints.fStates[fState]);
545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawText(&fLabel, 1, fBounds.centerX(), fBounds.fBottom - 5, paints.fLabel);
546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void toggle() {
549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (++fState == fStateCount) {
550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fState = 0;
551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void setEnabled(bool enabled) {
555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fState = (int) enabled;
556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct ControlPaints {
560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fOutline;
561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fIndicator;
562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fFill;
563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fLabel;
564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fValue;
565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ControlPaints() {
567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fOutline.setAntiAlias(true);
568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fOutline.setStyle(SkPaint::kStroke_Style);
569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fIndicator = fOutline;
570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fIndicator.setColor(SK_ColorRED);
571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFill.setAntiAlias(true);
572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFill.setColor(0x7fff0000);
573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setAntiAlias(true);
574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLabel.setTextSize(13.0f);
575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fValue.setAntiAlias(true);
576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fValue.setTextSize(11.0f);
577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct UniControl {
581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString fName;
582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRect fBounds;
583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fMin;
584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fMax;
585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fValLo;
586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fYLo;
587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fVisible;
588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniControl(const char* name, SkScalar min, SkScalar max) {
590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fName = name;
591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fValLo =  fMin = min;
592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fMax = max;
593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fVisible = false;
594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual ~UniControl() {}
598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool contains(const SkRect& rect) {
600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fVisible && fBounds.contains(rect);
601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void draw(SkCanvas* canvas, const ControlPaints& paints) {
604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fVisible) {
605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRect(fBounds, paints.fOutline);
608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fYLo = fBounds.fTop + (fValLo - fMin) * fBounds.height() / (fMax - fMin);
609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawLine(fBounds.fLeft - 5, fYLo, fBounds.fRight + 5, fYLo, paints.fIndicator);
610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString label;
611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        label.printf("%0.3g", fValLo);
612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawString(label, fBounds.fLeft + 5, fYLo - 5, paints.fValue);
613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawString(fName, fBounds.fLeft, fBounds.bottom() + 11,
614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                paints.fLabel);
615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct BiControl : public UniControl {
619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fValHi;
620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    BiControl(const char* name, SkScalar min, SkScalar max)
622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : UniControl(name, min, max)
623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        ,  fValHi(fMax) {
624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual ~BiControl() {}
627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void draw(SkCanvas* canvas, const ControlPaints& paints) {
629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        UniControl::draw(canvas, paints);
630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fVisible || fValHi == fValLo) {
631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar yPos = fBounds.fTop + (fValHi - fMin) * fBounds.height() / (fMax - fMin);
634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawLine(fBounds.fLeft - 5, yPos, fBounds.fRight + 5, yPos, paints.fIndicator);
635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkString label;
636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        label.printf("%0.3g", fValHi);
637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (yPos < fYLo + 10) {
638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            yPos = fYLo + 10;
639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawString(label, fBounds.fLeft + 5, yPos - 5, paints.fValue);
641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect fill = { fBounds.fLeft, fYLo, fBounds.fRight, yPos };
642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawRect(fill, paints.fFill);
643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass MyClick : public SampleView::Click {
648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum ClickType {
650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kInvalidType = -1,
651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPtType,
652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kVerbType,
653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kControlType,
654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPathType,
655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } fType;
656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum ControlType {
658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kInvalidControl = -1,
659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFirstControl,
660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFilterControl = kFirstControl,
661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kResControl,
662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kWeightControl,
663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kWidthControl,
664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLastControl = kWidthControl,
665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFirstButton,
666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCubicButton = kFirstButton,
667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kConicButton,
668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kQuadButton,
669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLineButton,
670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLastVerbButton = kLineButton,
671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kAddButton,
672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kDeleteButton,
673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kInOutButton,
674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFillButton,
675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kSkeletonButton,
676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFilterButton,
677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kBisectButton,
678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kJoinButton,
679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLastButton = kJoinButton,
680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPathMove,
681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } fControl;
682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath::Verb fVerb;
684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fWeight;
685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    MyClick(SkView* target, ClickType type, ControlType control)
687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : Click(target)
688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fType(type)
689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fControl(control)
690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fVerb((SkPath::Verb) -1)
691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fWeight(1) {
692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    MyClick(SkView* target, ClickType type, int index)
695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : Click(target)
696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fType(type)
697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fControl((ControlType) index)
698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fVerb((SkPath::Verb) -1)
699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fWeight(1) {
700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    MyClick(SkView* target, ClickType type, int index, SkPath::Verb verb, SkScalar weight)
703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : Click(target)
704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fType(type)
705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fControl((ControlType) index)
706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fVerb(verb)
707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fWeight(weight) {
708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool isButton() {
711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return kFirstButton <= fControl && fControl <= kLastButton;
712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int ptHit() const {
715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fType == kPtType);
716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return (int) fControl;
717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int verbHit() const {
720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(fType == kVerbType);
721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return (int) fControl;
722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum {
726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kControlCount = MyClick::kLastControl - MyClick::kFirstControl + 1,
727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic struct ControlPair {
730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniControl* fControl;
731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    MyClick::ControlType fControlType;
732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} kControlList[kControlCount];
733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotenum {
735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kButtonCount = MyClick::kLastButton - MyClick::kFirstButton + 1,
736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    kVerbCount = MyClick::kLastVerbButton - MyClick::kFirstButton + 1,
737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic struct ButtonPair {
740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button* fButton;
741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    MyClick::ControlType fButtonType;
742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} kButtonList[kButtonCount];
743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void enable_verb_button(MyClick::ControlType type) {
745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int index = 0; index < kButtonCount; ++index) {
746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        MyClick::ControlType testType = kButtonList[index].fButtonType;
747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (MyClick::kFirstButton <= testType && testType <= MyClick::kLastVerbButton) {
748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Button* button = kButtonList[index].fButton;
749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            button->setEnabled(testType == type);
750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Stroke;
755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Active {
757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Active* fNext;
758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Stroke* fParent;
759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fStart;
760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar fEnd;
761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset() {
763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fNext = nullptr;
764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStart = 0;
765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fEnd = 1;
766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct Stroke {
770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath fPath;
771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Active fActive;
772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fInner;
773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset() {
775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.reset();
776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActive.reset();
777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct PathUndo {
781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath fPath;
782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    PathUndo* fNext;
783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass AAGeometryView : public SampleView {
786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fActivePaint;
787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fComplexPaint;
788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fCoveragePaint;
789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fLegendLeftPaint;
790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fLegendRightPaint;
791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fPointPaint;
792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fSkeletonPaint;
793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPaint fLightSkeletonPaint;
794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkPath fPath;
795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ControlPaints fControlPaints;
796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniControl fResControl;
797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniControl fWeightControl;
798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniControl fWidthControl;
799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    BiControl fFilterControl;
800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ButtonPaints fButtonPaints;
801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fCubicButton;
802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fConicButton;
803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fQuadButton;
804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fLineButton;
805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fAddButton;
806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fDeleteButton;
807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fFillButton;
808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fSkeletonButton;
809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fFilterButton;
810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fBisectButton;
811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fJoinButton;
812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Button fInOutButton;
813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTArray<Stroke> fStrokes;
814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    PathUndo* fUndo;
815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fActivePt;
816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int fActiveVerb;
817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fHandlePathMove;
818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fShowLegend;
819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fHideAll;
820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const int kHitToleranace = 25;
821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    AAGeometryView()
825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        : fResControl("error", 0, 10)
826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fWeightControl("weight", 0, 5)
827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fWidthControl("width", FLT_EPSILON, 100)
828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fFilterControl("filter", 0, 255)
829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fCubicButton('C')
830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fConicButton('K')
831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fQuadButton('Q')
832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fLineButton('L')
833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fAddButton('+')
834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fDeleteButton('x')
835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fFillButton('p')
836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fSkeletonButton('s')
837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fFilterButton('f', 3)
838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fBisectButton('b')
839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fJoinButton('j')
840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fInOutButton('|')
841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fUndo(nullptr)
842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fActivePt(-1)
843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fActiveVerb(-1)
844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fHandlePathMove(true)
845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fShowLegend(false)
846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        , fHideAll(false)
847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    {
848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCoveragePaint.setAntiAlias(true);
849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fCoveragePaint.setColor(SK_ColorBLUE);
850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint strokePaint;
851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        strokePaint.setAntiAlias(true);
852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        strokePaint.setStyle(SkPaint::kStroke_Style);
853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPointPaint = strokePaint;
854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPointPaint.setColor(0x99ee3300);
855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fSkeletonPaint = strokePaint;
856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fSkeletonPaint.setColor(SK_ColorRED);
857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLightSkeletonPaint = fSkeletonPaint;
858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLightSkeletonPaint.setColor(0xFFFF7f7f);
859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActivePaint = strokePaint;
860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActivePaint.setColor(0x99ee3300);
861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActivePaint.setStrokeWidth(5);
862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fComplexPaint = fActivePaint;
863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fComplexPaint.setColor(SK_ColorBLUE);
864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLegendLeftPaint.setAntiAlias(true);
865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLegendLeftPaint.setTextSize(13);
866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLegendRightPaint = fLegendLeftPaint;
867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLegendRightPaint.setTextAlign(SkPaint::kRight_Align);
868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        construct_path(fPath);
869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFillButton.fVisible = fSkeletonButton.fVisible = fFilterButton.fVisible
870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                = fBisectButton.fVisible = fJoinButton.fVisible = fInOutButton.fVisible = true;
871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fSkeletonButton.setEnabled(true);
872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fInOutButton.setEnabled(true);
873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fJoinButton.setEnabled(true);
874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFilterControl.fValLo = 120;
875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFilterControl.fValHi = 141;
876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fFilterControl.fVisible = fFilterButton.fState == 2;
877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fResControl.fValLo = 5;
878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fResControl.fVisible = true;
879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fWidthControl.fValLo = 50;
880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fWidthControl.fVisible = true;
881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        init_controlList();
882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        init_buttonList();
883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool constructPath() {
886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        construct_path(fPath);
887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void savePath(Click::State state) {
891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (state != Click::kDown_State) {
892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fUndo && fUndo->fPath == fPath) {
895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        PathUndo* undo = new PathUndo;
898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        undo->fPath = fPath;
899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        undo->fNext = fUndo;
900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fUndo = undo;
901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool undo() {
904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fUndo) {
905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath = fUndo->fPath;
908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        validatePath();
909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        PathUndo* next = fUndo->fNext;
910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        delete fUndo;
911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fUndo = next;
912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void validatePath() {
916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        PathUndo* undo = fUndo;
917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int match = 0;
918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while (undo) {
919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            match += fPath == undo->fPath;
920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            undo = undo->fNext;
921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void set_controlList(int index, UniControl* control, MyClick::ControlType type) {
925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kControlList[index].fControl = control;
926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kControlList[index].fControlType = type;
927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define SET_CONTROL(Name) set_controlList(index++, &f##Name##Control, \
930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        MyClick::k##Name##Control)
931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool hideAll() {
933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fHideAll ^= true;
934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void init_controlList() {
938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int index = 0;
939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_CONTROL(Width);
940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_CONTROL(Res);
941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_CONTROL(Filter);
942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_CONTROL(Weight);
943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #undef SET_CONTROL
946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void set_buttonList(int index, Button* button, MyClick::ControlType type) {
948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kButtonList[index].fButton = button;
949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kButtonList[index].fButtonType = type;
950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #define SET_BUTTON(Name) set_buttonList(index++, &f##Name##Button, \
953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            MyClick::k##Name##Button)
954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void init_buttonList() {
956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int index = 0;
957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Fill);
958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Skeleton);
959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Filter);
960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Bisect);
961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Join);
962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(InOut);
963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Cubic);
964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Conic);
965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Quad);
966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Line);
967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Add);
968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SET_BUTTON(Delete);
969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #undef SET_BUTTON
972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // overrides from SkEventSink
974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onQuery(SkEvent* evt) override;
975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onSizeChange() override {
977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        setControlButtonsPos();
978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->INHERITED::onSizeChange();
979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool pathDump() {
982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.dump();
983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool scaleDown() {
987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix matrix;
988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds = fPath.getBounds();
989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix.setScale(1.f / 1.5f, 1.f / 1.5f, bounds.centerX(), bounds.centerY());
990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.transform(matrix);
991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        validatePath();
992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool scaleToFit() {
996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix matrix;
997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds = fPath.getBounds();
998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar scale = SkTMin(this->width() / bounds.width(), this->height() / bounds.height())
999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                * 0.8f;
1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix.setScale(scale, scale, bounds.centerX(), bounds.centerY());
1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.transform(matrix);
1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bounds = fPath.getBounds();
1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar offsetX = (this->width() - bounds.width()) / 2 - bounds.fLeft;
1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar offsetY = (this->height() - bounds.height()) / 2 - bounds.fTop;
1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.offset(offsetX, offsetY);
1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        validatePath();
1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool scaleUp() {
1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkMatrix matrix;
1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds = fPath.getBounds();
1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        matrix.setScale(1.5f, 1.5f, bounds.centerX(), bounds.centerY());
1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPath.transform(matrix);
1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        validatePath();
1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void setControlButtonsPos() {
1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar widthOffset = this->width() - 100;
1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kControlCount; ++index) {
1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (kControlList[index].fControl->fVisible) {
1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                kControlList[index].fControl->fBounds.setXYWH(widthOffset, 30, 30, 400);
1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                widthOffset -= 50;
1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar buttonOffset = 0;
1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kButtonCount; ++index) {
1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            kButtonList[index].fButton->fBounds.setXYWH(this->width() - 50,
1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    buttonOffset += 50, 30, 30);
1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool showLegend() {
1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fShowLegend ^= true;
1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_bisect(SkCanvas* canvas, const SkVector& lastVector, const SkVector& vector,
1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                const SkPoint& pt) {
1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkVector lastV = lastVector;
1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar lastLen = lastVector.length();
1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkVector nextV = vector;
1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar nextLen = vector.length();
1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (lastLen < nextLen) {
1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            lastV.setLength(nextLen);
1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            nextV.setLength(lastLen);
1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkVector bisect = { (lastV.fX + nextV.fX) / 2, (lastV.fY + nextV.fY) / 2 };
1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bisect.setLength(fWidthControl.fValLo * 2);
1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fBisectButton.enabled()) {
1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawLine(pt, pt + bisect, fSkeletonPaint);
1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        lastV.setLength(fWidthControl.fValLo);
1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fBisectButton.enabled()) {
1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawLine(pt, {pt.fX - lastV.fY, pt.fY + lastV.fX}, fSkeletonPaint);
1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        nextV.setLength(fWidthControl.fValLo);
1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fBisectButton.enabled()) {
1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawLine(pt, {pt.fX + nextV.fY, pt.fY - nextV.fX}, fSkeletonPaint);
1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fJoinButton.enabled()) {
1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar r = fWidthControl.fValLo;
1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkRect oval = { pt.fX - r, pt.fY - r, pt.fX + r, pt.fY + r};
1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar startAngle = SkScalarATan2(lastV.fX, -lastV.fY) * 180.f / SK_ScalarPI;
1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkScalar endAngle = SkScalarATan2(-nextV.fX, nextV.fY) * 180.f / SK_ScalarPI;
1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (endAngle > startAngle) {
1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawArc(oval, startAngle, endAngle - startAngle, false, fSkeletonPaint);
1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                canvas->drawArc(oval, startAngle, 360 - (startAngle - endAngle), false,
1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fSkeletonPaint);
1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_bisects(SkCanvas* canvas, bool activeOnly) {
1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkVector firstVector, lastVector, nextLast, vector;
1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pts[4];
1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint firstPt = { 0, 0 };  // init to avoid warning;
1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Iter iter(fPath, true);
1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool foundFirst = false;
1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int counter = -1;
1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++counter;
1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (activeOnly && counter != fActiveVerb && counter - 1 != fActiveVerb
1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && counter + 1 != fActiveVerb
1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    && (fActiveVerb != 1 || counter != fPath.countVerbs())) {
1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    nextLast = pts[0] - pts[1];
1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    vector = pts[1] - pts[0];
1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb: {
1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    nextLast = pts[1] - pts[2];
1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(nextLast.length())) {
1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        nextLast = pts[0] - pts[2];
1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    vector = pts[1] - pts[0];
1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(vector.length())) {
1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        vector = pts[2] - pts[0];
1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!fBisectButton.enabled()) {
1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar t = SkFindQuadMaxCurvature(pts);
1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (0 < t && t < 1) {
1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkPoint maxPt = SkEvalQuadAt(pts, t);
1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkVector tangent = SkEvalQuadTangentAt(pts, t);
1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        tangent.setLength(fWidthControl.fValLo * 2);
1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        canvas->drawLine(maxPt, {maxPt.fX + tangent.fY, maxPt.fY - tangent.fX},
1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         fSkeletonPaint);
1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb:
1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    nextLast = pts[1] - pts[2];
1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(nextLast.length())) {
1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        nextLast = pts[0] - pts[2];
1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    vector = pts[1] - pts[0];
1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(vector.length())) {
1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        vector = pts[2] - pts[0];
1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!fBisectButton.enabled()) {
1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    // FIXME : need max curvature or equivalent here
1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb: {
1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    nextLast = pts[2] - pts[3];
1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(nextLast.length())) {
1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        nextLast = pts[1] - pts[3];
1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (SkScalarNearlyZero(nextLast.length())) {
1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            nextLast = pts[0] - pts[3];
1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    vector = pts[0] - pts[1];
1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (SkScalarNearlyZero(vector.length())) {
1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        vector = pts[0] - pts[2];
1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (SkScalarNearlyZero(vector.length())) {
1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            vector = pts[0] - pts[3];
1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (!fBisectButton.enabled()) {
1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar tMax[2];
1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    int tMaxCount = SkFindCubicMaxCurvature(pts, tMax);
1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    for (int tIndex = 0; tIndex < tMaxCount; ++tIndex) {
1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (0 >= tMax[tIndex] || tMax[tIndex] >= 1) {
1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            continue;
1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkPoint maxPt;
1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkVector tangent;
1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkEvalCubicAt(pts, tMax[tIndex], &maxPt, &tangent, nullptr);
1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        tangent.setLength(fWidthControl.fValLo * 2);
1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        canvas->drawLine(maxPt, {maxPt.fX + tangent.fY, maxPt.fY - tangent.fX},
1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                         fSkeletonPaint);
1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kClose_Verb:
1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (foundFirst) {
1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        draw_bisect(canvas, lastVector, firstVector, firstPt);
1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        foundFirst = false;
1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkPath::kLine_Verb <= verb && verb <= SkPath::kCubic_Verb) {
1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (!foundFirst) {
1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    firstPt = pts[0];
1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    firstVector = vector;
1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    foundFirst = true;
1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } else {
1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_bisect(canvas, lastVector, vector, pts[0]);
1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                lastVector = nextLast;
1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_legend(SkCanvas* canvas);
1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_segment(SkCanvas* canvas) {
1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pts[4];
1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Iter iter(fPath, true);
1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int counter = -1;
1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (++counter < fActiveVerb) {
1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                continue;
1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, fActivePaint);
1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_points(canvas, pts, 2);
1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb: {
1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPath qPath;
1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    qPath.moveTo(pts[0]);
1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    qPath.quadTo(pts[1], pts[2]);
1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->drawPath(qPath, fActivePaint);
1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_points(canvas, pts, 3);
1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb: {
1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPath conicPath;
1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    conicPath.moveTo(pts[0]);
1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    conicPath.conicTo(pts[1], pts[2], iter.conicWeight());
1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->drawPath(conicPath, fActivePaint);
1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_points(canvas, pts, 3);
1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb: {
1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar loopT[3];
1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    int complex = SkDCubic::ComplexBreak(pts, loopT);
1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkPath cPath;
1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    cPath.moveTo(pts[0]);
1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    cPath.cubicTo(pts[1], pts[2], pts[3]);
1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    canvas->drawPath(cPath, complex ? fComplexPaint : fActivePaint);
1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_points(canvas, pts, 4);
1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_points(SkCanvas* canvas, SkPoint* points, int count) {
1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < count; ++index) {
1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawCircle(points[index].fX, points[index].fY, 10, fPointPaint);
1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int hittest_verb(SkPoint pt, SkPath::Verb* verbPtr, SkScalar* weight) {
1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkIntersections i;
1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine hHit = {{{pt.fX - kHitToleranace, pt.fY }, {pt.fX + kHitToleranace, pt.fY}}};
1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDLine vHit = {{{pt.fX, pt.fY - kHitToleranace }, {pt.fX, pt.fY + kHitToleranace}}};
1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pts[4];
1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Iter iter(fPath, true);
1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int counter = -1;
1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++counter;
1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb: {
1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDLine line;
1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    line.set(pts);
1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (i.intersect(line, hHit) || i.intersect(line, vHit)) {
1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *verbPtr = verb;
1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *weight = 1;
1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return counter;
1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb: {
1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDQuad quad;
1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    quad.set(pts);
1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (i.intersect(quad, hHit) || i.intersect(quad, vHit)) {
1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *verbPtr = verb;
1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *weight = 1;
1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return counter;
1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb: {
1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDConic conic;
1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar w = iter.conicWeight();
1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    conic.set(pts, w);
1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (i.intersect(conic, hHit) || i.intersect(conic, vHit)) {
1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *verbPtr = verb;
1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *weight = w;
1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return counter;
1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb: {
1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkDCubic cubic;
1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    cubic.set(pts);
1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (i.intersect(cubic, hHit) || i.intersect(cubic, vHit)) {
1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *verbPtr = verb;
1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        *weight = 1;
1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        return counter;
1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    } break;
1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return -1;
1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar pt_to_line(SkPoint s, SkPoint e, int x, int y) {
1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar radius = fWidthControl.fValLo;
1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkVector adjOpp = e - s;
1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar lenSq = SkPointPriv::LengthSqd(adjOpp);
1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint rotated = {
1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                (y - s.fY) * adjOpp.fY + (x - s.fX) * adjOpp.fX,
1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                (y - s.fY) * adjOpp.fX - (x - s.fX) * adjOpp.fY,
1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        };
1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (rotated.fX < 0 || rotated.fX > lenSq) {
1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return -radius;
1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        rotated.fY /= SkScalarSqrt(lenSq);
1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkTMax(-radius, SkTMin(radius, rotated.fY));
1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // given a line, compute the interior and exterior gradient coverage
1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool coverage(SkPoint s, SkPoint e, uint8_t* distanceMap, int w, int h) {
1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar radius = fWidthControl.fValLo;
1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int minX = SkTMax(0, (int) (SkTMin(s.fX, e.fX) - radius));
1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int minY = SkTMax(0, (int) (SkTMin(s.fY, e.fY) - radius));
1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int maxX = SkTMin(w, (int) (SkTMax(s.fX, e.fX) + radius) + 1);
1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int maxY = SkTMin(h, (int) (SkTMax(s.fY, e.fY) + radius) + 1);
1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int y = minY; y < maxY; ++y) {
1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int x = minX; x < maxX; ++x) {
1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar ptToLineDist = pt_to_line(s, e, x, y);
1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (ptToLineDist > -radius && ptToLineDist < radius) {
1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar coverage = ptToLineDist / radius;
1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkVector ptToS = { x - s.fX, y - s.fY };
1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkScalar dist = ptToS.length();
1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (dist < radius) {
1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar coverage = dist / radius;
1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkVector ptToE = { x - e.fX, y - e.fY };
1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                dist = ptToE.length();
1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (dist < radius) {
1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkScalar coverage = dist / radius;
1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    add_to_map(1 - SkScalarAbs(coverage), x, y, distanceMap, w, h);
1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void quad_coverage(SkPoint pts[3], uint8_t* distanceMap, int w, int h) {
1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar dist = pts[0].Distance(pts[0], pts[2]);
1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (dist < gCurveDistance) {
1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            (void) coverage(pts[0], pts[2], distanceMap, w, h);
1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint split[5];
1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkChopQuadAt(pts, split, 0.5f);
1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad_coverage(&split[0], distanceMap, w, h);
1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        quad_coverage(&split[2], distanceMap, w, h);
1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void conic_coverage(SkPoint pts[3], SkScalar weight, uint8_t* distanceMap, int w, int h) {
1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar dist = pts[0].Distance(pts[0], pts[2]);
1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (dist < gCurveDistance) {
1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            (void) coverage(pts[0], pts[2], distanceMap, w, h);
1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkConic split[2];
1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkConic conic;
1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        conic.set(pts, weight);
1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (conic.chopAt(0.5f, split)) {
1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            conic_coverage(split[0].fPts, split[0].fW, distanceMap, w, h);
1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            conic_coverage(split[1].fPts, split[1].fW, distanceMap, w, h);
1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void cubic_coverage(SkPoint pts[4], uint8_t* distanceMap, int w, int h) {
1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar dist = pts[0].Distance(pts[0], pts[3]);
1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (dist < gCurveDistance) {
1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            (void) coverage(pts[0], pts[3], distanceMap, w, h);
1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint split[7];
1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkChopCubicAt(pts, split, 0.5f);
1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic_coverage(&split[0], distanceMap, w, h);
1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        cubic_coverage(&split[3], distanceMap, w, h);
1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void path_coverage(const SkPath& path, uint8_t* distanceMap, int w, int h) {
1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        memset(distanceMap, 0, sizeof(distanceMap[0]) * w * h);
1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pts[4];
1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Iter iter(path, true);
1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (void) coverage(pts[0], pts[1], distanceMap, w, h);
1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb:
1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    quad_coverage(pts, distanceMap, w, h);
1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb:
1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    conic_coverage(pts, iter.conicWeight(), distanceMap, w, h);
1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb:
1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    cubic_coverage(pts, distanceMap, w, h);
1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static uint8_t* set_up_dist_map(const SkImageInfo& imageInfo, SkBitmap* distMap) {
1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        distMap->setInfo(imageInfo);
1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        distMap->setIsVolatile(true);
1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkAssertResult(distMap->tryAllocPixels());
1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT((int) distMap->rowBytes() == imageInfo.width());
1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return distMap->getAddr8(0, 0);
1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void path_stroke(int index, SkPath* inner, SkPath* outer) {
1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        #if 0
1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPathStroker stroker(fPath, fWidthControl.fValLo, 0,
1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPaint::kRound_Cap, SkPaint::kRound_Join, fResControl.fValLo);
1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pts[4], firstPt, lastPt;
1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Iter iter(fPath, true);
1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int counter = -1;
1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            ++counter;
1422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            switch (verb) {
1423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kMove_Verb:
1424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    firstPt = pts[0];
1425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kLine_Verb:
1427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (counter == index) {
1428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.moveTo(pts[0]);
1429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.lineTo(pts[1]);
1430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        goto done;
1431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    lastPt = pts[1];
1433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kQuad_Verb:
1435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (counter == index) {
1436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.moveTo(pts[0]);
1437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.quadTo(pts[1], pts[2]);
1438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        goto done;
1439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    lastPt = pts[2];
1441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kConic_Verb:
1443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (counter == index) {
1444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.moveTo(pts[0]);
1445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.conicTo(pts[1], pts[2], iter.conicWeight());
1446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        goto done;
1447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    lastPt = pts[2];
1449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kCubic_Verb:
1451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (counter == index) {
1452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.moveTo(pts[0]);
1453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.cubicTo(pts[1], pts[2], pts[3]);
1454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        goto done;
1455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    lastPt = pts[3];
1457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kClose_Verb:
1459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    if (counter == index) {
1460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.moveTo(lastPt);
1461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        stroker.lineTo(firstPt);
1462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        goto done;
1463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    }
1464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                case SkPath::kDone_Verb:
1466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    break;
1467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                default:
1468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    SkASSERT(0);
1469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    done:
1472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *inner = stroker.fInner;
1473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *outer = stroker.fOuter;
1474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
1475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void draw_stroke(SkCanvas* canvas, int active) {
1478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath inner, outer;
1479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path_stroke(active, &inner, &outer);
1480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(inner, fSkeletonPaint);
1481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(outer, fSkeletonPaint);
1482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void gather_strokes() {
1485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fStrokes.reset();
1486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < fPath.countVerbs(); ++index) {
1487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Stroke& inner = fStrokes.push_back();
1488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inner.reset();
1489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            inner.fInner = true;
1490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Stroke& outer = fStrokes.push_back();
1491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            outer.reset();
1492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            outer.fInner = false;
1493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            path_stroke(index, &inner.fPath, &outer.fPath);
1494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void trim_strokes() {
1498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // eliminate self-itersecting loops
1499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // trim outside edges
1500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        gather_strokes();
1501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < fStrokes.count(); ++index) {
1502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkPath& outPath = fStrokes[index].fPath;
1503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int inner = 0; inner < fStrokes.count(); ++inner) {
1504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (index == inner) {
1505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    continue;
1506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPath& inPath = fStrokes[inner].fPath;
1508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (!outPath.getBounds().intersects(inPath.getBounds())) {
1509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    continue;
1510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onDrawContent(SkCanvas* canvas) override {
1517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
1518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGCODE(SkDebugStrokeGlobals debugGlobals);
1519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkOpAA aaResult(fPath, fWidthControl.fValLo, fResControl.fValLo
1520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkDEBUGPARAMS(&debugGlobals));
1521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
1522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath strokePath;
1523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//        aaResult.simplify(&strokePath);
1524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(strokePath, fSkeletonPaint);
1525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRect bounds = fPath.getBounds();
1526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar radius = fWidthControl.fValLo;
1527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int w = (int) (bounds.fRight + radius + 1);
1528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int h = (int) (bounds.fBottom + radius + 1);
1529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkImageInfo imageInfo = SkImageInfo::MakeA8(w, h);
1530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkBitmap distMap;
1531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        uint8_t* distanceMap = set_up_dist_map(imageInfo, &distMap);
1532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path_coverage(fPath, distanceMap, w, h);
1533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fFillButton.enabled()) {
1534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawPath(fPath, fCoveragePaint);
1535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fFilterButton.fState == 2
1537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                && (0 < fFilterControl.fValLo || fFilterControl.fValHi < 255)) {
1538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkBitmap filteredMap;
1539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            uint8_t* filtered = set_up_dist_map(imageInfo, &filteredMap);
1540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            filter_coverage(distanceMap, sizeof(uint8_t) * w * h, (uint8_t) fFilterControl.fValLo,
1541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (uint8_t) fFilterControl.fValHi, filtered);
1542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawBitmap(filteredMap, 0, 0, &fCoveragePaint);
1543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else if (fFilterButton.enabled()) {
1544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawBitmap(distMap, 0, 0, &fCoveragePaint);
1545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fSkeletonButton.enabled()) {
1547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            canvas->drawPath(fPath, fActiveVerb >= 0 ? fLightSkeletonPaint : fSkeletonPaint);
1548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fActiveVerb >= 0) {
1550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            draw_segment(canvas);
1551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fBisectButton.enabled() || fJoinButton.enabled()) {
1553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            draw_bisects(canvas, fActiveVerb >= 0);
1554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fInOutButton.enabled()) {
1556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (fActiveVerb >= 0) {
1557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                draw_stroke(canvas, fActiveVerb);
1558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } else {
1559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                for (int index = 0; index < fPath.countVerbs(); ++index) {
1560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    draw_stroke(canvas, index);
1561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fHideAll) {
1565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return;
1566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kControlCount; ++index) {
1568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            kControlList[index].fControl->draw(canvas, fControlPaints);
1569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kButtonCount; ++index) {
1571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            kButtonList[index].fButton->draw(canvas, fButtonPaints);
1572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fShowLegend) {
1574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            draw_legend(canvas);
1575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0
1578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPaint paint;
1579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setARGB(255, 34, 31, 31);
1580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        paint.setAntiAlias(true);
1581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath path;
1583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.moveTo(18,439);
1584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(414,439);
1585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(414,702);
1586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(18,702);
1587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(18,439);
1588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.moveTo(19,701);
1590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(413,701);
1591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(413,440);
1592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(19,440);
1593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.lineTo(19,701);
1594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        path.close();
1595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(path, paint);
1596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->scale(1.0f, -1.0f);
1598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->translate(0.0f, -800.0f);
1599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawPath(path, paint);
1600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
1601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int hittest_pt(SkPoint pt) {
1605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < fPath.countPoints(); ++index) {
1606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (SkPoint::Distance(fPath.getPoint(index), pt) <= kHitToleranace * 2) {
1607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return index;
1608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return -1;
1611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
1614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPoint pt = {x, y};
1615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int ptHit = hittest_pt(pt);
1616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ptHit >= 0) {
1617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return new MyClick(this, MyClick::kPtType, ptHit);
1618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkPath::Verb verb;
1620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkScalar weight;
1621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int verbHit = hittest_verb(pt, &verb, &weight);
1622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (verbHit >= 0) {
1623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return new MyClick(this, MyClick::kVerbType, verbHit, verb, weight);
1624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!fHideAll) {
1626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const SkRect& rectPt = SkRect::MakeXYWH(x, y, 1, 1);
1627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int index = 0; index < kControlCount; ++index) {
1628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (kControlList[index].fControl->contains(rectPt)) {
1629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return new MyClick(this, MyClick::kControlType,
1630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            kControlList[index].fControlType);
1631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int index = 0; index < kButtonCount; ++index) {
1634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (kButtonList[index].fButton->contains(rectPt)) {
1635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return new MyClick(this, MyClick::kControlType, kButtonList[index].fButtonType);
1636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLineButton.fVisible = fQuadButton.fVisible = fConicButton.fVisible
1640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                = fCubicButton.fVisible = fWeightControl.fVisible = fAddButton.fVisible
1641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                = fDeleteButton.fVisible = false;
1642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActiveVerb = -1;
1643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fActivePt = -1;
1644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fHandlePathMove) {
1645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return new MyClick(this, MyClick::kPathType, MyClick::kPathMove);
1646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return this->INHERITED::onFindClickHandler(x, y, modi);
1648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static SkScalar MapScreenYtoValue(int y, const UniControl& control) {
1651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return SkTMin(1.f, SkTMax(0.f,
1652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkIntToScalar(y) - control.fBounds.fTop) / control.fBounds.height())
1653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                * (control.fMax - control.fMin) + control.fMin;
1654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onClick(Click* click) override {
1657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        MyClick* myClick = (MyClick*) click;
1658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        switch (myClick->fType) {
1659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MyClick::kPtType: {
1660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                savePath(click->fState);
1661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fActivePt = myClick->ptHit();
1662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkPoint pt = fPath.getPoint((int) myClick->fControl);
1663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                pt.offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX),
1664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkIntToScalar(click->fICurr.fY - click->fIPrev.fY));
1665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                set_path_pt(fActivePt, pt, &fPath);
1666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                validatePath();
1667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
1668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MyClick::kPathType:
1670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                savePath(click->fState);
1671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fPath.offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX),
1672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkIntToScalar(click->fICurr.fY - click->fIPrev.fY));
1673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                validatePath();
1674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
1675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MyClick::kVerbType: {
1676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fActiveVerb = myClick->verbHit();
1677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fLineButton.fVisible = fQuadButton.fVisible = fConicButton.fVisible
1678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        = fCubicButton.fVisible = fAddButton.fVisible = fDeleteButton.fVisible
1679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        = true;
1680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fLineButton.setEnabled(myClick->fVerb == SkPath::kLine_Verb);
1681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fQuadButton.setEnabled(myClick->fVerb == SkPath::kQuad_Verb);
1682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fConicButton.setEnabled(myClick->fVerb == SkPath::kConic_Verb);
1683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fCubicButton.setEnabled(myClick->fVerb == SkPath::kCubic_Verb);
1684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fWeightControl.fValLo = myClick->fWeight;
1685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fWeightControl.fVisible = myClick->fVerb == SkPath::kConic_Verb;
1686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                } break;
1687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            case MyClick::kControlType: {
1688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (click->fState != Click::kDown_State && myClick->isButton()) {
1689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return true;
1690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                switch (myClick->fControl) {
1692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kFilterControl: {
1693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkScalar val = MapScreenYtoValue(click->fICurr.fY, fFilterControl);
1694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (val - fFilterControl.fValLo < fFilterControl.fValHi - val) {
1695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fFilterControl.fValLo = SkTMax(0.f, val);
1696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } else {
1697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fFilterControl.fValHi = SkTMin(255.f, val);
1698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
1699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } break;
1700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kResControl:
1701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fResControl.fValLo = MapScreenYtoValue(click->fICurr.fY, fResControl);
1702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kWeightControl: {
1704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkScalar w = MapScreenYtoValue(click->fICurr.fY, fWeightControl);
1706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        set_path_weight(fActiveVerb, w, &fPath);
1707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fValLo = w;
1709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } break;
1710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kWidthControl:
1711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWidthControl.fValLo = MapScreenYtoValue(click->fICurr.fY, fWidthControl);
1712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kLineButton:
1714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        enable_verb_button(myClick->fControl);
1716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fVisible = false;
1717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        set_path_verb(fActiveVerb, SkPath::kLine_Verb, &fPath, 1);
1718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kQuadButton:
1721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        enable_verb_button(myClick->fControl);
1723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fVisible = false;
1724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        set_path_verb(fActiveVerb, SkPath::kQuad_Verb, &fPath, 1);
1725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kConicButton: {
1728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        enable_verb_button(myClick->fControl);
1730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fVisible = true;
1731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        const SkScalar defaultConicWeight = 1.f / SkScalarSqrt(2);
1732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        set_path_verb(fActiveVerb, SkPath::kConic_Verb, &fPath, defaultConicWeight);
1733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fValLo = get_path_weight(fActiveVerb, fPath);
1735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        } break;
1736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kCubicButton:
1737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        enable_verb_button(myClick->fControl);
1739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fWeightControl.fVisible = false;
1740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        set_path_verb(fActiveVerb, SkPath::kCubic_Verb, &fPath, 1);
1741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kAddButton:
1744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        add_path_segment(fActiveVerb, &fPath);
1746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        if (fWeightControl.fVisible) {
1748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                            fWeightControl.fValLo = get_path_weight(fActiveVerb, fPath);
1749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        }
1750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kDeleteButton:
1752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        savePath(click->fState);
1753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        delete_path_segment(fActiveVerb, &fPath);
1754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        validatePath();
1755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kFillButton:
1757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fFillButton.toggle();
1758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kSkeletonButton:
1760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fSkeletonButton.toggle();
1761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kFilterButton:
1763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fFilterButton.toggle();
1764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fFilterControl.fVisible = fFilterButton.fState == 2;
1765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kBisectButton:
1767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fBisectButton.toggle();
1768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kJoinButton:
1770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fJoinButton.toggle();
1771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    case MyClick::kInOutButton:
1773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        fInOutButton.toggle();
1774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    default:
1776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        SkASSERT(0);
1777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                        break;
1778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            } break;
1780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            default:
1781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkASSERT(0);
1782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                break;
1783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        setControlButtonsPos();
1785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
1789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef SampleView INHERITED;
1790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
1791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic struct KeyCommand {
1793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char fKey;
1794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char fAlternate;
1795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* fDescriptionL;
1796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const char* fDescriptionR;
1797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool (AAGeometryView::*fFunction)();
1798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} kKeyCommandList[] = {
1799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { ' ',  0,  "space",   "center path", &AAGeometryView::scaleToFit },
1800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { '-',  0,  "-",          "zoom out", &AAGeometryView::scaleDown },
1801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { '+', '=', "+/=",         "zoom in", &AAGeometryView::scaleUp },
1802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 'D',  0,  "D",   "dump to console", &AAGeometryView::pathDump },
1803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 'H',  0,  "H",     "hide controls", &AAGeometryView::hideAll },
1804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 'R',  0,  "R",        "reset path", &AAGeometryView::constructPath },
1805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { 'Z',  0,  "Z",              "undo", &AAGeometryView::undo },
1806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    { '?',  0,  "?",       "show legend", &AAGeometryView::showLegend },
1807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
1808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst int kKeyCommandCount = (int) SK_ARRAY_COUNT(kKeyCommandList);
1810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid AAGeometryView::draw_legend(SkCanvas* canvas) {
1812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkScalar bottomOffset = this->height() - 10;
1813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int index = kKeyCommandCount - 1; index >= 0; --index) {
1814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bottomOffset -= 15;
1815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawString(kKeyCommandList[index].fDescriptionL,
1816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->width() - 160, bottomOffset,
1817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fLegendLeftPaint);
1818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        canvas->drawString(kKeyCommandList[index].fDescriptionR,
1819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                this->width() - 20, bottomOffset,
1820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                fLegendRightPaint);
1821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// overrides from SkEventSink
1825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool AAGeometryView::onQuery(SkEvent* evt) {
1826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SampleCode::TitleQ(*evt)) {
1827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SampleCode::TitleR(evt, "AAGeometry");
1828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return true;
1829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkUnichar uni;
1831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (false) {
1832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return this->INHERITED::onQuery(evt);
1833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (SampleCode::CharQ(*evt, &uni)) {
1835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kButtonCount; ++index) {
1836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            Button* button = kButtonList[index].fButton;
1837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (button->fVisible && uni == button->fLabel) {
1838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                MyClick click(this, MyClick::kControlType, kButtonList[index].fButtonType);
1839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                click.fState = Click::kDown_State;
1840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                (void) this->onClick(&click);
1841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return true;
1842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int index = 0; index < kKeyCommandCount; ++index) {
1845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            KeyCommand& keyCommand = kKeyCommandList[index];
1846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            if (uni == keyCommand.fKey || uni == keyCommand.fAlternate) {
1847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                return (this->*keyCommand.fFunction)();
1848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (('A' <= uni && uni <= 'Z') || ('a' <= uni && uni <= 'z')) {
1851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            for (int index = 0; index < kButtonCount; ++index) {
1852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                Button* button = kButtonList[index].fButton;
1853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                if (button->fVisible && (uni & ~0x20) == (button->fLabel & ~0x20)) {
1854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    MyClick click(this, MyClick::kControlType, kButtonList[index].fButtonType);
1855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    click.fState = Click::kDown_State;
1856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    (void) this->onClick(&click);
1857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    return true;
1858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                }
1859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            }
1860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
1861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
1862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return this->INHERITED::onQuery(evt);
1863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
1864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
1865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDEF_SAMPLE( return new AAGeometryView; )
1866