OLD | NEW |
| (Empty) |
1 | |
2 /* | |
3 * Copyright 2011 Google Inc. | |
4 * | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 */ | |
8 #include "SampleCode.h" | |
9 #include "SkView.h" | |
10 #include "SkCanvas.h" | |
11 #include "SkGradientShader.h" | |
12 #include "SkPath.h" | |
13 #include "SkRegion.h" | |
14 #include "SkShader.h" | |
15 #include "SkUtils.h" | |
16 #include "SkImageDecoder.h" | |
17 | |
18 #include "SkBlurMaskFilter.h" | |
19 #include "SkTableMaskFilter.h" | |
20 | |
21 #define kNearlyZero (SK_Scalar1 / 8092) | |
22 | |
23 static void test_bigblur(SkCanvas* canvas) { | |
24 canvas->drawColor(SK_ColorBLACK); | |
25 | |
26 SkBitmap orig, mask; | |
27 SkImageDecoder::DecodeFile("/skimages/app_icon.png", &orig); | |
28 | |
29 SkMaskFilter* mf = SkBlurMaskFilter::Create(8, SkBlurMaskFilter::kNormal_Blu
rStyle); | |
30 SkPaint paint; | |
31 paint.setMaskFilter(mf)->unref(); | |
32 SkIPoint offset; | |
33 orig.extractAlpha(&mask, &paint, &offset); | |
34 | |
35 paint.setColor(0xFFBB8800); | |
36 paint.setColor(SK_ColorWHITE); | |
37 | |
38 int i; | |
39 canvas->save(); | |
40 float gamma = 0.8; | |
41 for (i = 0; i < 5; i++) { | |
42 paint.setMaskFilter(SkTableMaskFilter::CreateGamma(gamma))->unref(); | |
43 canvas->drawBitmap(mask, 0, 0, &paint); | |
44 paint.setMaskFilter(NULL); | |
45 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
46 gamma -= 0.1; | |
47 canvas->translate(120, 0); | |
48 } | |
49 canvas->restore(); | |
50 canvas->translate(0, 160); | |
51 | |
52 for (i = 0; i < 5; i++) { | |
53 paint.setMaskFilter(SkTableMaskFilter::CreateClip(i*30, 255 - 20))->unre
f(); | |
54 canvas->drawBitmap(mask, 0, 0, &paint); | |
55 paint.setMaskFilter(NULL); | |
56 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
57 canvas->translate(120, 0); | |
58 } | |
59 | |
60 #if 0 | |
61 paint.setColor(0xFFFFFFFF); | |
62 canvas->drawBitmap(mask, 0, 0, &paint); | |
63 paint.setMaskFilter(NULL); | |
64 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
65 | |
66 canvas->translate(120, 0); | |
67 | |
68 canvas->drawBitmap(mask, 0, 0, &paint); | |
69 canvas->drawBitmap(mask, 0, 0, &paint); | |
70 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
71 | |
72 canvas->translate(120, 0); | |
73 | |
74 canvas->drawBitmap(mask, 0, 0, &paint); | |
75 canvas->drawBitmap(mask, 0, 0, &paint); | |
76 canvas->drawBitmap(mask, 0, 0, &paint); | |
77 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
78 | |
79 canvas->translate(120, 0); | |
80 | |
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 | |
87 canvas->translate(120, 0); | |
88 | |
89 canvas->drawBitmap(mask, 0, 0, &paint); | |
90 canvas->drawBitmap(mask, 0, 0, &paint); | |
91 canvas->drawBitmap(mask, 0, 0, &paint); | |
92 canvas->drawBitmap(mask, 0, 0, &paint); | |
93 canvas->drawBitmap(mask, 0, 0, &paint); | |
94 canvas->drawBitmap(orig, -offset.fX, -offset.fY, &paint); | |
95 #endif | |
96 } | |
97 | |
98 #include "SkMeshUtils.h" | |
99 | |
100 static SkPoint SkMakePoint(SkScalar x, SkScalar y) { | |
101 SkPoint pt; | |
102 pt.set(x, y); | |
103 return pt; | |
104 } | |
105 | |
106 static SkPoint SkPointInterp(const SkPoint& a, const SkPoint& b, SkScalar t) { | |
107 return SkMakePoint(SkScalarInterp(a.fX, b.fX, t), | |
108 SkScalarInterp(a.fY, b.fY, t)); | |
109 } | |
110 | |
111 #include "SkBoundaryPatch.h" | |
112 | |
113 static void set_cubic(SkPoint pts[4], SkScalar x0, SkScalar y0, | |
114 SkScalar x3, SkScalar y3, SkScalar scale = 1) { | |
115 SkPoint tmp, tmp2; | |
116 | |
117 pts[0].set(x0, y0); | |
118 pts[3].set(x3, y3); | |
119 | |
120 tmp = SkPointInterp(pts[0], pts[3], SK_Scalar1/3); | |
121 tmp2 = pts[0] - tmp; | |
122 tmp2.rotateCW(); | |
123 tmp2.scale(scale); | |
124 pts[1] = tmp + tmp2; | |
125 | |
126 tmp = SkPointInterp(pts[0], pts[3], 2*SK_Scalar1/3); | |
127 tmp2 = pts[3] - tmp; | |
128 tmp2.rotateCW(); | |
129 tmp2.scale(scale); | |
130 pts[2] = tmp + tmp2; | |
131 } | |
132 | |
133 static void test_patch(SkCanvas* canvas, const SkBitmap& bm, SkScalar scale) { | |
134 SkCubicBoundary cubic; | |
135 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, scale); | |
136 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, scale); | |
137 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, -scale); | |
138 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0); | |
139 | |
140 SkBoundaryPatch patch; | |
141 patch.setBoundary(&cubic); | |
142 | |
143 const int Rows = 16; | |
144 const int Cols = 16; | |
145 SkPoint pts[Rows * Cols]; | |
146 patch.evalPatch(pts, Rows, Cols); | |
147 | |
148 SkPaint paint; | |
149 paint.setAntiAlias(true); | |
150 paint.setFilterBitmap(true); | |
151 paint.setStrokeWidth(1); | |
152 paint.setStrokeCap(SkPaint::kRound_Cap); | |
153 | |
154 canvas->translate(50, 50); | |
155 canvas->scale(3, 3); | |
156 | |
157 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint); | |
158 } | |
159 | |
160 static void test_drag(SkCanvas* canvas, const SkBitmap& bm, | |
161 const SkPoint& p0, const SkPoint& p1) { | |
162 SkCubicBoundary cubic; | |
163 set_cubic(cubic.fPts + 0, 0, 0, 100, 0, 0); | |
164 set_cubic(cubic.fPts + 3, 100, 0, 100, 100, 0); | |
165 set_cubic(cubic.fPts + 6, 100, 100, 0, 100, 0); | |
166 set_cubic(cubic.fPts + 9, 0, 100, 0, 0, 0); | |
167 | |
168 #if 0 | |
169 cubic.fPts[1] += p1 - p0; | |
170 cubic.fPts[2] += p1 - p0; | |
171 #else | |
172 SkScalar dx = p1.fX - p0.fX; | |
173 if (dx > 0) dx = 0; | |
174 SkScalar dy = p1.fY - p0.fY; | |
175 if (dy > 0) dy = 0; | |
176 | |
177 cubic.fPts[1].fY += dy; | |
178 cubic.fPts[2].fY += dy; | |
179 cubic.fPts[10].fX += dx; | |
180 cubic.fPts[11].fX += dx; | |
181 #endif | |
182 | |
183 SkBoundaryPatch patch; | |
184 patch.setBoundary(&cubic); | |
185 | |
186 const int Rows = 16; | |
187 const int Cols = 16; | |
188 SkPoint pts[Rows * Cols]; | |
189 patch.evalPatch(pts, Rows, Cols); | |
190 | |
191 SkPaint paint; | |
192 paint.setAntiAlias(true); | |
193 paint.setFilterBitmap(true); | |
194 paint.setStrokeWidth(1); | |
195 paint.setStrokeCap(SkPaint::kRound_Cap); | |
196 | |
197 canvas->translate(50, 50); | |
198 canvas->scale(3, 3); | |
199 | |
200 SkAutoCanvasRestore acr(canvas, true); | |
201 | |
202 SkRect r = { 0, 0, 100, 100 }; | |
203 canvas->clipRect(r); | |
204 SkMeshUtils::Draw(canvas, bm, Rows, Cols, pts, NULL, paint); | |
205 } | |
206 | |
207 /////////////////////////////////////////////////////////////////////////////// | |
208 | |
209 class Mesh { | |
210 public: | |
211 Mesh(); | |
212 ~Mesh(); | |
213 | |
214 Mesh& operator=(const Mesh& src); | |
215 | |
216 void init(const SkRect& bounds, int rows, int cols, | |
217 const SkRect& texture); | |
218 | |
219 const SkRect& bounds() const { return fBounds; } | |
220 | |
221 int rows() const { return fRows; } | |
222 int cols() const { return fCols; } | |
223 SkPoint& pt(int row, int col) { | |
224 return fPts[row * (fRows + 1) + col]; | |
225 } | |
226 | |
227 void draw(SkCanvas*, const SkPaint&); | |
228 void drawWireframe(SkCanvas* canvas, const SkPaint& paint); | |
229 | |
230 private: | |
231 SkRect fBounds; | |
232 int fRows, fCols; | |
233 SkPoint* fPts; | |
234 SkPoint* fTex; // just points into fPts, not separately allocated | |
235 int fCount; | |
236 uint16_t* fIndices; | |
237 int fIndexCount; | |
238 }; | |
239 | |
240 Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {} | |
241 | |
242 Mesh::~Mesh() { | |
243 delete[] fPts; | |
244 delete[] fIndices; | |
245 } | |
246 | |
247 Mesh& Mesh::operator=(const Mesh& src) { | |
248 delete[] fPts; | |
249 delete[] fIndices; | |
250 | |
251 fBounds = src.fBounds; | |
252 fRows = src.fRows; | |
253 fCols = src.fCols; | |
254 | |
255 fCount = src.fCount; | |
256 fPts = new SkPoint[fCount * 2]; | |
257 fTex = fPts + fCount; | |
258 memcpy(fPts, src.fPts, fCount * 2 * sizeof(SkPoint)); | |
259 | |
260 delete[] fIndices; | |
261 fIndexCount = src.fIndexCount; | |
262 fIndices = new uint16_t[fIndexCount]; | |
263 memcpy(fIndices, src.fIndices, fIndexCount * sizeof(uint16_t)); | |
264 | |
265 return *this; | |
266 } | |
267 | |
268 void Mesh::init(const SkRect& bounds, int rows, int cols, | |
269 const SkRect& texture) { | |
270 SkASSERT(rows > 0 && cols > 0); | |
271 | |
272 fBounds = bounds; | |
273 fRows = rows; | |
274 fCols = cols; | |
275 | |
276 delete[] fPts; | |
277 fCount = (rows + 1) * (cols + 1); | |
278 fPts = new SkPoint[fCount * 2]; | |
279 fTex = fPts + fCount; | |
280 | |
281 delete[] fIndices; | |
282 fIndexCount = rows * cols * 6; | |
283 fIndices = new uint16_t[fIndexCount]; | |
284 | |
285 SkPoint* pts = fPts; | |
286 const SkScalar dx = bounds.width() / rows; | |
287 const SkScalar dy = bounds.height() / cols; | |
288 SkPoint* tex = fTex; | |
289 const SkScalar dtx = texture.width() / rows; | |
290 const SkScalar dty = texture.height() / cols; | |
291 uint16_t* idx = fIndices; | |
292 int index = 0; | |
293 for (int y = 0; y <= cols; y++) { | |
294 for (int x = 0; x <= rows; x++) { | |
295 pts->set(bounds.fLeft + x*dx, bounds.fTop + y*dy); | |
296 pts += 1; | |
297 tex->set(texture.fLeft + x*dtx, texture.fTop + y*dty); | |
298 tex += 1; | |
299 | |
300 if (y < cols && x < rows) { | |
301 *idx++ = index; | |
302 *idx++ = index + rows + 1; | |
303 *idx++ = index + 1; | |
304 | |
305 *idx++ = index + 1; | |
306 *idx++ = index + rows + 1; | |
307 *idx++ = index + rows + 2; | |
308 | |
309 index += 1; | |
310 } | |
311 } | |
312 index += 1; | |
313 } | |
314 } | |
315 | |
316 void Mesh::draw(SkCanvas* canvas, const SkPaint& paint) { | |
317 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount, | |
318 fPts, fTex, NULL, NULL, fIndices, fIndexCount, | |
319 paint); | |
320 } | |
321 | |
322 void Mesh::drawWireframe(SkCanvas* canvas, const SkPaint& paint) { | |
323 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, fCount, | |
324 fPts, NULL, NULL, NULL, fIndices, fIndexCount, | |
325 paint); | |
326 } | |
327 | |
328 /////////////////////////////////////////////////////////////////////////////// | |
329 | |
330 class WarpView : public SkView { | |
331 Mesh fMesh, fOrig; | |
332 SkBitmap fBitmap; | |
333 SkMatrix fMatrix, fInverse; | |
334 public: | |
335 WarpView() { | |
336 SkBitmap bm; | |
337 // SkImageDecoder::DecodeFile("/skimages/marker.png", &bm); | |
338 SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm); | |
339 // SkImageDecoder::DecodeFile("/beach_shot.JPG", &bm); | |
340 fBitmap = bm; | |
341 | |
342 SkRect bounds, texture; | |
343 texture.set(0, 0, SkIntToScalar(fBitmap.width()), | |
344 SkIntToScalar(fBitmap.height())); | |
345 bounds = texture; | |
346 | |
347 // fMesh.init(bounds, fBitmap.width() / 40, fBitmap.height() / 40, textur
e); | |
348 fMesh.init(bounds, fBitmap.width()/16, fBitmap.height()/16, texture); | |
349 fOrig = fMesh; | |
350 | |
351 fP0.set(0, 0); | |
352 fP1 = fP0; | |
353 | |
354 fMatrix.setScale(2, 2); | |
355 fMatrix.invert(&fInverse); | |
356 } | |
357 | |
358 protected: | |
359 // overrides from SkEventSink | |
360 virtual bool onQuery(SkEvent* evt) { | |
361 if (SampleCode::TitleQ(*evt)) { | |
362 SampleCode::TitleR(evt, "Warp"); | |
363 return true; | |
364 } | |
365 return this->INHERITED::onQuery(evt); | |
366 } | |
367 | |
368 static SkPoint apply_warp(const SkVector& drag, SkScalar dragLength, | |
369 const SkPoint& dragStart, const SkPoint& dragCurr, | |
370 const SkPoint& orig) { | |
371 SkVector delta = orig - dragCurr; | |
372 SkScalar length = SkPoint::Normalize(&delta); | |
373 if (length <= kNearlyZero) { | |
374 return orig; | |
375 } | |
376 | |
377 const SkScalar period = 20; | |
378 const SkScalar mag = dragLength / 3; | |
379 | |
380 SkScalar d = length / (period); | |
381 d = mag * SkScalarSin(d) / d; | |
382 SkScalar dx = delta.fX * d; | |
383 SkScalar dy = delta.fY * d; | |
384 SkScalar px = orig.fX + dx; | |
385 SkScalar py = orig.fY + dy; | |
386 return SkPoint::Make(px, py); | |
387 } | |
388 | |
389 static SkPoint apply_warp2(const SkVector& drag, SkScalar dragLength, | |
390 const SkPoint& dragStart, const SkPoint& dragCurr, | |
391 const SkPoint& orig) { | |
392 SkVector delta = orig - dragCurr; | |
393 SkScalar length = SkPoint::Normalize(&delta); | |
394 if (length <= kNearlyZero) { | |
395 return orig; | |
396 } | |
397 | |
398 const SkScalar period = 10 + dragLength/4; | |
399 const SkScalar mag = dragLength / 3; | |
400 | |
401 SkScalar d = length / (period); | |
402 if (d > SK_ScalarPI) { | |
403 d = SK_ScalarPI; | |
404 } | |
405 | |
406 d = -mag * SkScalarSin(d); | |
407 | |
408 SkScalar dx = delta.fX * d; | |
409 SkScalar dy = delta.fY * d; | |
410 SkScalar px = orig.fX + dx; | |
411 SkScalar py = orig.fY + dy; | |
412 return SkPoint::Make(px, py); | |
413 } | |
414 | |
415 typedef SkPoint (*WarpProc)(const SkVector& drag, SkScalar dragLength, | |
416 const SkPoint& dragStart, const SkPoint& dragCurr, | |
417 const SkPoint& orig); | |
418 | |
419 void warp(const SkPoint& p0, const SkPoint& p1) { | |
420 WarpProc proc = apply_warp2; | |
421 SkPoint delta = p1 - p0; | |
422 SkScalar length = SkPoint::Normalize(&delta); | |
423 for (int y = 0; y < fMesh.rows(); y++) { | |
424 for (int x = 0; x < fMesh.cols(); x++) { | |
425 fMesh.pt(x, y) = proc(delta, length, p0, p1, fOrig.pt(x, y)); | |
426 } | |
427 } | |
428 fP0 = p0; | |
429 fP1 = p1; | |
430 } | |
431 | |
432 virtual void onDraw(SkCanvas* canvas) { | |
433 canvas->drawColor(SK_ColorLTGRAY); | |
434 // test_bigblur(canvas); return; | |
435 | |
436 canvas->concat(fMatrix); | |
437 | |
438 SkPaint paint; | |
439 paint.setFilterBitmap(true); | |
440 paint.setShader(SkShader::CreateBitmapShader(fBitmap, | |
441 SkShader::kClamp_TileMode, | |
442 SkShader::kClamp_TileMode))
->unref(); | |
443 fMesh.draw(canvas, paint); //return; | |
444 | |
445 paint.setShader(NULL); | |
446 paint.setColor(SK_ColorRED); | |
447 fMesh.draw(canvas, paint); | |
448 | |
449 // test_drag(canvas, fBitmap, fP0, fP1); | |
450 } | |
451 | |
452 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { | |
453 return new Click(this); | |
454 } | |
455 | |
456 virtual bool onClick(Click* click) { | |
457 SkPoint pts[2] = { click->fOrig, click->fCurr }; | |
458 fInverse.mapPoints(pts, 2); | |
459 this->warp(pts[0], pts[1]); | |
460 this->inval(NULL); | |
461 return true; | |
462 } | |
463 | |
464 private: | |
465 SkIRect fBase, fRect; | |
466 SkPoint fP0, fP1; | |
467 typedef SkView INHERITED; | |
468 }; | |
469 | |
470 ////////////////////////////////////////////////////////////////////////////// | |
471 | |
472 static SkView* MyFactory() { return new WarpView; } | |
473 static SkViewRegister reg(MyFactory); | |
474 | |
OLD | NEW |