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