blob: ea1bb779ecc9140b56fe5760d9e29ac5659a06c7 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkCornerPathEffect.h"
5#include "SkCullPoints.h"
6#include "SkGradientShader.h"
7#include "SkPath.h"
8#include "SkRegion.h"
9#include "SkShader.h"
10#include "SkUtils.h"
11#include "SkRandom.h"
12
13static void addbump(SkPath* path, const SkPoint pts[2], SkScalar bump)
14{
15 SkVector tang;
16
17 tang.setLength(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY, bump);
18
19 path->lineTo(SkScalarHalf(pts[0].fX + pts[1].fX) - tang.fY,
20 SkScalarHalf(pts[0].fY + pts[1].fY) + tang.fX);
21 path->lineTo(pts[1]);
22}
23
24static void subdivide(SkPath* path, SkScalar bump)
25{
26 SkPath::Iter iter(*path, false);
27 SkPoint pts[4];
28 SkPath tmp;
29
30 for (;;)
31 switch (iter.next(pts)) {
32 case SkPath::kMove_Verb:
33 tmp.moveTo(pts[0]);
34 break;
35 case SkPath::kLine_Verb:
36 addbump(&tmp, pts, bump);
37 bump = -bump;
38 break;
39 case SkPath::kDone_Verb:
40 goto FINISH;
41 default:
42 break;
43 }
44
45FINISH:
46 path->swap(tmp);
47}
48
49static SkIPoint* getpts(const SkPath& path, int* count)
50{
51 SkPoint pts[4];
52 int n = 1;
53 SkIPoint* array;
54
55 {
56 SkPath::Iter iter(path, false);
57 for (;;)
58 switch (iter.next(pts)) {
59 case SkPath::kLine_Verb:
60 n += 1;
61 break;
62 case SkPath::kDone_Verb:
63 goto FINISHED;
64 default:
65 break;
66 }
67 }
68
69FINISHED:
70 array = new SkIPoint[n];
71 n = 0;
72
73 {
74 SkPath::Iter iter(path, false);
75 for (;;)
76 switch (iter.next(pts)) {
77 case SkPath::kMove_Verb:
78 array[n++].set(SkScalarRound(pts[0].fX), SkScalarRound(pts[0].fY));
79 break;
80 case SkPath::kLine_Verb:
81 array[n++].set(SkScalarRound(pts[1].fX), SkScalarRound(pts[1].fY));
82 break;
83 case SkPath::kDone_Verb:
84 goto FINISHED2;
85 default:
86 break;
87 }
88 }
89
90FINISHED2:
91 *count = n;
92 return array;
93}
94
95static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max)
96{
97 return min + SkScalarMul(rand.nextUScalar1(), max - min);
98}
99
100class CullView : public SkView {
101public:
102 CullView()
103 {
104 fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
105
106 SkRandom rand;
107
108 for (int i = 0; i < 50; i++) {
109 int x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2);
110 int y = nextScalarRange(rand, -fClip.height()*1, fClip.height()*2);
111 if (i == 0)
112 fPath.moveTo(x, y);
113 else
114 fPath.lineTo(x, y);
115 }
116
117 SkScalar bump = fClip.width()/8;
118 subdivide(&fPath, bump);
119 subdivide(&fPath, bump);
120 subdivide(&fPath, bump);
121 fPoints = getpts(fPath, &fPtCount);
122 }
123
124 virtual ~CullView()
125 {
126 delete[] fPoints;
127 }
128
129protected:
130 // overrides from SkEventSink
131 virtual bool onQuery(SkEvent* evt)
132 {
133 if (SampleCode::TitleQ(*evt))
134 {
135 SampleCode::TitleR(evt, "Culling");
136 return true;
137 }
138 return this->INHERITED::onQuery(evt);
139 }
140
141 void drawBG(SkCanvas* canvas)
142 {
143 canvas->drawColor(0xFFDDDDDD);
144
145 #if 0
146 SkPaint paint;
147
148 paint.setAntiAliasOn(true);
149 paint.setTextSize(SkIntToScalar(20));
150 paint.setTypeface(SkTypeface::Create("serif", SkTypeface::kBoldItalic))->unref();
151
152 uint16_t text[20];
153
154 text[0] = 'H';
155 text[1] = 'i';
156 text[2] = ' ';
157 for (int i = 3; i < 20; i++)
158 text[i] = 0x3040 + i;
159 canvas->drawText16(text, 20, SkIntToScalar(20), SkIntToScalar(20), paint);
160 #endif
161 }
162
163 virtual void onDraw(SkCanvas* canvas)
164 {
165 this->drawBG(canvas);
166
167 SkAutoCanvasRestore ar(canvas, true);
168
169 canvas->translate( SkScalarHalf(this->width() - fClip.width()),
170 SkScalarHalf(this->height() - fClip.height()));
171
172 // canvas->scale(SK_Scalar1*3, SK_Scalar1*3, 0, 0);
173
174 SkPaint paint;
175
176 // paint.setAntiAliasOn(true);
177 paint.setStyle(SkPaint::kStroke_Style);
178
179 canvas->drawRect(fClip, paint);
180
181#if 1
182 paint.setColor(0xFF555555);
183 paint.setStrokeWidth(SkIntToScalar(2));
184// paint.setPathEffect(new SkCornerPathEffect(SkIntToScalar(30)))->unref();
185 canvas->drawPath(fPath, paint);
186// paint.setPathEffect(NULL);
187#endif
188
189 SkPath tmp;
190 SkIRect iclip;
191 fClip.round(&iclip);
192
193 SkCullPointsPath cpp(iclip, &tmp);
194
195 cpp.moveTo(fPoints[0].fX, fPoints[0].fY);
196 for (int i = 0; i < fPtCount; i++)
197 cpp.lineTo(fPoints[i].fX, fPoints[i].fY);
198
199 paint.setColor(SK_ColorRED);
200 paint.setStrokeWidth(SkIntToScalar(3));
201 paint.setStrokeJoin(SkPaint::kRound_Join);
202 canvas->drawPath(tmp, paint);
203
204 this->inval(NULL);
205 }
206
207 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)
208 {
209 return this->INHERITED::onFindClickHandler(x, y);
210 }
211
212 virtual bool onClick(Click* click)
213 {
214 return this->INHERITED::onClick(click);
215 }
216
217private:
218 SkRect fClip;
219 SkIPoint* fPoints;
220 SkPath fPath;
221 int fPtCount;
222
223 typedef SkView INHERITED;
224};
225
226//////////////////////////////////////////////////////////////////////////////
227
228static SkView* MyFactory() { return new CullView; }
229static SkViewRegister reg(MyFactory);
230