blob: b1b433397bddb864f6617664d36588c9acbc71c6 [file] [log] [blame]
reed@android.comd2abab62009-10-20 21:27:15 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkPath.h"
6#include "SkRegion.h"
7#include "SkShader.h"
8#include "SkUtils.h"
9#include "SkImageDecoder.h"
10
reed@android.com3f2025f2009-10-29 17:37:56 +000011#include "SkBlurMaskFilter.h"
12#include "SkTableMaskFilter.h"
13
14static void test_bigblur(SkCanvas* canvas) {
15 canvas->drawColor(SK_ColorBLACK);
16
17 SkBitmap orig, mask;
18 SkImageDecoder::DecodeFile("/skimages/app_icon.png", &orig);
19
20 SkMaskFilter* mf = SkBlurMaskFilter::Create(8, SkBlurMaskFilter::kNormal_BlurStyle);
21 SkPaint paint;
22 paint.setMaskFilter(mf)->unref();
23 SkIPoint offset;
24 orig.extractAlpha(&mask, &paint, &offset);
25
26 paint.setColor(0xFFBB8800);
27 paint.setColor(SK_ColorWHITE);
28
29 int i;
30 canvas->save();
31 float gamma = 0.8;
32 for (i = 0; i < 5; i++) {
33 paint.setMaskFilter(SkTableMaskFilter::CreateGamma(gamma))->unref();
34 canvas->drawBitmap(mask, 0, 0, &paint);
35 paint.setMaskFilter(NULL);
36 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
37 gamma -= 0.1;
38 canvas->translate(120, 0);
39 }
40 canvas->restore();
41 canvas->translate(0, 160);
42
43 for (i = 0; i < 5; i++) {
44 paint.setMaskFilter(SkTableMaskFilter::CreateClip(i*30, 255 - 20))->unref();
45 canvas->drawBitmap(mask, 0, 0, &paint);
46 paint.setMaskFilter(NULL);
47 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
48 canvas->translate(120, 0);
49 }
50
51#if 0
52 paint.setColor(0xFFFFFFFF);
53 canvas->drawBitmap(mask, 0, 0, &paint);
54 paint.setMaskFilter(NULL);
55 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
56
57 canvas->translate(120, 0);
58
59 canvas->drawBitmap(mask, 0, 0, &paint);
60 canvas->drawBitmap(mask, 0, 0, &paint);
61 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
62
63 canvas->translate(120, 0);
64
65 canvas->drawBitmap(mask, 0, 0, &paint);
66 canvas->drawBitmap(mask, 0, 0, &paint);
67 canvas->drawBitmap(mask, 0, 0, &paint);
68 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
69
70 canvas->translate(120, 0);
71
72 canvas->drawBitmap(mask, 0, 0, &paint);
73 canvas->drawBitmap(mask, 0, 0, &paint);
74 canvas->drawBitmap(mask, 0, 0, &paint);
75 canvas->drawBitmap(mask, 0, 0, &paint);
76 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
77
78 canvas->translate(120, 0);
79
80 canvas->drawBitmap(mask, 0, 0, &paint);
81 canvas->drawBitmap(mask, 0, 0, &paint);
82 canvas->drawBitmap(mask, 0, 0, &paint);
83 canvas->drawBitmap(mask, 0, 0, &paint);
84 canvas->drawBitmap(mask, 0, 0, &paint);
85 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint);
86#endif
87}
88
reed@android.com2ee7c642009-10-28 14:25:34 +000089#include "SkMeshUtils.h"
90
reed@android.com4408cca2009-10-27 02:24:03 +000091static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
92 SkPoint pt;
93 pt.set(x, y);
94 return pt;
95}
96
97static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) {
98 return SkMakePoint(SkScalarInterp(a.fX, b.fX, t),
99 SkScalarInterp(a.fY, b.fY, t));
100}
101
102#include "SkBoundaryPatch.h"
103
reed@android.com4408cca2009-10-27 02:24:03 +0000104static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0,
105 SkScalar x3, SkScalar y3, SkScalar scale = 1) {
106 SkPoint tmp, tmp2;
107
108 pts[0].set(x0, y0);
109 pts[3].set(x3, y3);
110
111 tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3);
112 tmp2 = pts[0] - tmp;
113 tmp2.rotateCW();
114 tmp2.scale(scale);
115 pts[1] = tmp + tmp2;
116
117 tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3);
118 tmp2 = pts[3] - tmp;
119 tmp2.rotateCW();
120 tmp2.scale(scale);
121 pts[2] = tmp + tmp2;
122}
123
reed@android.com4408cca2009-10-27 02:24:03 +0000124static void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) {
reed@android.com2ee7c642009-10-28 14:25:34 +0000125 SkCubicBoundary cubic;
126 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, scale);
127 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, scale);
128 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, -scale);
129 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
reed@android.com4408cca2009-10-27 02:24:03 +0000130
reed@android.com4408cca2009-10-27 02:24:03 +0000131 SkBoundaryPatch patch;
reed@android.com2ee7c642009-10-28 14:25:34 +0000132 patch.setBoundary(&cubic);
133
134 const int Rows = 16;
135 const int Cols = 16;
reed@android.com4408cca2009-10-27 02:24:03 +0000136 SkPoint pts[Rows * Cols];
reed@android.com2ee7c642009-10-28 14:25:34 +0000137 patch.evalPatch(pts, Rows, Cols);
reed@android.com4408cca2009-10-27 02:24:03 +0000138
139 SkPaint paint;
140 paint.setAntiAlias(true);
reed@android.com2ee7c642009-10-28 14:25:34 +0000141 paint.setFilterBitmap(true);
reed@android.com4408cca2009-10-27 02:24:03 +0000142 paint.setStrokeWidth(1);
143 paint.setStrokeCap(SkPaint::kRound_Cap);
reed@android.com2ee7c642009-10-28 14:25:34 +0000144
reed@android.com4408cca2009-10-27 02:24:03 +0000145 canvas->translate(50, 50);
146 canvas->scale(3, 3);
reed@android.com2ee7c642009-10-28 14:25:34 +0000147
148 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
149}
reed@android.com4408cca2009-10-27 02:24:03 +0000150
reed@android.com2ee7c642009-10-28 14:25:34 +0000151static void test_drag(SkCanvas* canvas, const SkBitmap& bm,
152 const SkPoint& p0, const SkPoint& p1) {
153 SkCubicBoundary cubic;
154 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, 0);
155 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, 0);
156 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, 0);
157 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0);
158
159#if 0
160 cubic.fPts[1] += p1 - p0;
161 cubic.fPts[2] += p1 - p0;
162#else
163 SkScalar dx = p1.fX - p0.fX;
164 if (dx > 0) dx = 0;
165 SkScalar dy = p1.fY - p0.fY;
166 if (dy > 0) dy = 0;
167
168 cubic.fPts[1].fY += dy;
169 cubic.fPts[2].fY += dy;
170 cubic.fPts[10].fX += dx;
171 cubic.fPts[11].fX += dx;
172#endif
173
174 SkBoundaryPatch patch;
175 patch.setBoundary(&cubic);
176
177 const int Rows = 16;
178 const int Cols = 16;
179 SkPoint pts[Rows * Cols];
180 patch.evalPatch(pts, Rows, Cols);
181
182 SkPaint paint;
183 paint.setAntiAlias(true);
184 paint.setFilterBitmap(true);
185 paint.setStrokeWidth(1);
186 paint.setStrokeCap(SkPaint::kRound_Cap);
187
188 canvas->translate(50, 50);
189 canvas->scale(3, 3);
190
191 SkAutoCanvasRestore acr(canvas, true);
192
193 SkRect r = { 0, 0, 100, 100 };
194 canvas->clipRect(r);
195 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint);
reed@android.com4408cca2009-10-27 02:24:03 +0000196}
reed@android.com80b4ebe2009-10-21 19:41:10 +0000197
198///////////////////////////////////////////////////////////////////////////////
199
reed@android.comd2abab62009-10-20 21:27:15 +0000200class Mesh {
201public:
202 Mesh();
203 ~Mesh();
204
205 Mesh& operator=(const Mesh& src);
206
207 void init(const SkRect& bounds, int rows, int cols,
208 const SkRect& texture);
209
reed@android.com80b4ebe2009-10-21 19:41:10 +0000210 const SkRect& bounds() const { return fBounds; }
211
reed@android.comd2abab62009-10-20 21:27:15 +0000212 int rows() const { return fRows; }
213 int cols() const { return fCols; }
214 SkPoint& pt(int row, int col) {
215 return fPts[row * (fRows + 1) + col];
216 }
217
218 void draw(SkCanvas*, const SkPaint&);
219 void drawWireframe(SkCanvas* canvas, const SkPaint& paint);
220
221private:
reed@android.com80b4ebe2009-10-21 19:41:10 +0000222 SkRect fBounds;
reed@android.comd2abab62009-10-20 21:27:15 +0000223 int fRows, fCols;
224 SkPoint* fPts;
225 SkPoint* fTex; // just points into fPts, not separately allocated
226 int fCount;
227 uint16_t* fIndices;
228 int fIndexCount;
229};
230
231Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
232
233Mesh::~Mesh() {
234 delete[] fPts;
235 delete[] fIndices;
236}
237
238Mesh& Mesh::operator=(const Mesh& src) {
239 delete[] fPts;
240 delete[] fIndices;
241
reed@android.com80b4ebe2009-10-21 19:41:10 +0000242 fBounds = src.fBounds;
reed@android.comd2abab62009-10-20 21:27:15 +0000243 fRows = src.fRows;
244 fCols = src.fCols;
245
246 fCount = src.fCount;
247 fPts = new SkPoint[fCount * 2];
248 fTex = fPts + fCount;
249 memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint));
250
251 delete[] fIndices;
252 fIndexCount = src.fIndexCount;
253 fIndices = new uint16_t[fIndexCount];
254 memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t));
255
256 return *this;
257}
258
259void Mesh::init(const SkRect& bounds, int rows, int cols,
260 const SkRect& texture) {
261 SkASSERT(rows > 0 && cols > 0);
262
reed@android.com80b4ebe2009-10-21 19:41:10 +0000263 fBounds = bounds;
reed@android.comd2abab62009-10-20 21:27:15 +0000264 fRows = rows;
265 fCols = cols;
266
267 delete[] fPts;
268 fCount = (rows + 1) * (cols + 1);
269 fPts = new SkPoint[fCount * 2];
270 fTex = fPts + fCount;
271
272 delete[] fIndices;
273 fIndexCount = rows * cols * 6;
274 fIndices = new uint16_t[fIndexCount];
275
276 SkPoint* pts = fPts;
277 const SkScalar dx = bounds.width() / rows;
278 const SkScalar dy = bounds.height() / cols;
279 SkPoint* tex = fTex;
280 const SkScalar dtx = texture.width() / rows;
281 const SkScalar dty = texture.height() / cols;
282 uint16_t* idx = fIndices;
283 int index = 0;
284 for (int y = 0; y <= cols; y++) {
285 for (int x = 0; x <= rows; x++) {
286 pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy);
287 pts += 1;
288 tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty);
289 tex += 1;
290
291 if (y < cols && x < rows) {
292 *idx++ = index;
293 *idx++ = index + rows + 1;
294 *idx++ = index + 1;
295
296 *idx++ = index + 1;
297 *idx++ = index + rows + 1;
298 *idx++ = index + rows + 2;
299
300 index += 1;
301 }
302 }
303 index += 1;
304 }
305}
306
307void Mesh::draw(SkCanvas* canvas, const SkPaint& paint) {
308 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
309 fPts, fTex, NULL, NULL, fIndices, fIndexCount,
310 paint);
311}
312
313void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) {
314 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount,
315 fPts, NULL, NULL, NULL, fIndices, fIndexCount,
316 paint);
317}
318
319///////////////////////////////////////////////////////////////////////////////
320
321class WarpView : public SkView {
322 Mesh fMesh, fOrig;
323 SkBitmap fBitmap;
324public:
325 WarpView() {
326 SkBitmap bm;
reed@android.com2ee7c642009-10-28 14:25:34 +0000327 SkImageDecoder::DecodeFile("/skimages/beach.jpg", &bm);
328 // SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm);
reed@android.com4408cca2009-10-27 02:24:03 +0000329 fBitmap = bm;
reed@android.comd2abab62009-10-20 21:27:15 +0000330
331 SkRect bounds, texture;
332 texture.set(0, 0, SkIntToScalar(fBitmap.width()),
333 SkIntToScalar(fBitmap.height()));
334 bounds = texture;
335
336// fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, texture);
reed@android.com80b4ebe2009-10-21 19:41:10 +0000337 fMesh.init(bounds, 30, 30, texture);
reed@android.comd2abab62009-10-20 21:27:15 +0000338 fOrig = fMesh;
reed@android.com2ee7c642009-10-28 14:25:34 +0000339
340 fP0.set(0, 0);
341 fP1 = fP0;
reed@android.comd2abab62009-10-20 21:27:15 +0000342 }
343
344protected:
345 // overrides from SkEventSink
346 virtual bool onQuery(SkEvent* evt) {
347 if (SampleCode::TitleQ(*evt)) {
348 SampleCode::TitleR(evt, "Warp");
349 return true;
350 }
351 return this->INHERITED::onQuery(evt);
352 }
353
354 void warp(const SkPoint& p0, const SkPoint& p1) {
reed@android.com2ee7c642009-10-28 14:25:34 +0000355 fP0 = p0;
356 fP1 = p1;
reed@android.comd2abab62009-10-20 21:27:15 +0000357 }
358
359 virtual void onDraw(SkCanvas* canvas) {
reed@android.com3f2025f2009-10-29 17:37:56 +0000360 canvas->drawColor(SK_ColorLTGRAY);
361 // test_bigblur(canvas); return;
reed@android.comd2abab62009-10-20 21:27:15 +0000362
363 SkPaint paint;
364 paint.setFilterBitmap(true);
365 paint.setShader(SkShader::CreateBitmapShader(fBitmap,
366 SkShader::kClamp_TileMode,
367 SkShader::kClamp_TileMode))->unref();
reed@android.com4408cca2009-10-27 02:24:03 +0000368 // fMesh.draw(canvas, paint);
reed@android.comd2abab62009-10-20 21:27:15 +0000369
370 paint.setShader(NULL);
371 paint.setColor(SK_ColorRED);
reed@android.com80b4ebe2009-10-21 19:41:10 +0000372 // fMesh.draw(canvas, paint);
reed@android.com2ee7c642009-10-28 14:25:34 +0000373
reed@android.com2ee7c642009-10-28 14:25:34 +0000374 test_drag(canvas, fBitmap, fP0, fP1);
reed@android.comd2abab62009-10-20 21:27:15 +0000375 }
376
377 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
378 return new Click(this);
379 }
380
381 virtual bool onClick(Click* click) {
382 this->warp(click->fOrig, click->fCurr);
383 this->inval(NULL);
384 return true;
385 }
386
387private:
388 SkIRect fBase, fRect;
reed@android.com2ee7c642009-10-28 14:25:34 +0000389 SkPoint fP0, fP1;
reed@android.comd2abab62009-10-20 21:27:15 +0000390 typedef SkView INHERITED;
391};
392
393//////////////////////////////////////////////////////////////////////////////
394
395static SkView* MyFactory() { return new WarpView; }
396static SkViewRegister reg(MyFactory);
397