• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
test_bigblur(SkCanvas * canvas)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_BlurStyle);
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))->unref();
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 
SkMakePoint(SkScalar x,SkScalar y)100 static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
101     SkPoint pt;
102     pt.set(x, y);
103     return pt;
104 }
105 
SkPointInterp(const SkPoint & a,const SkPoint & b,SkScalar t)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 
set_cubic(SkPoint pts[4],SkScalar x0,SkScalar y0,SkScalar x3,SkScalar y3,SkScalar scale=1)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 
test_patch(SkCanvas * canvas,const SkBitmap & bm,SkScalar scale)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 
test_drag(SkCanvas * canvas,const SkBitmap & bm,const SkPoint & p0,const SkPoint & p1)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 
bounds() const219     const SkRect& bounds() const { return fBounds; }
220 
rows() const221     int rows() const { return fRows; }
cols() const222     int cols() const { return fCols; }
pt(int row,int col)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 
Mesh()240 Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
241 
~Mesh()242 Mesh::~Mesh() {
243     delete[] fPts;
244     delete[] fIndices;
245 }
246 
operator =(const Mesh & src)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 
init(const SkRect & bounds,int rows,int cols,const SkRect & texture)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 
draw(SkCanvas * canvas,const SkPaint & paint)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 
drawWireframe(SkCanvas * canvas,const SkPaint & paint)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:
WarpView()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, texture);
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
onQuery(SkEvent * evt)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 
apply_warp(const SkVector & drag,SkScalar dragLength,const SkPoint & dragStart,const SkPoint & dragCurr,const SkPoint & orig)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 
apply_warp2(const SkVector & drag,SkScalar dragLength,const SkPoint & dragStart,const SkPoint & dragCurr,const SkPoint & orig)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 
warp(const SkPoint & p0,const SkPoint & p1)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 
onDraw(SkCanvas * canvas)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 
onFindClickHandler(SkScalar x,SkScalar y)452     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
453         return new Click(this);
454     }
455 
onClick(Click * click)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 
MyFactory()472 static SkView* MyFactory() { return new WarpView; }
473 static SkViewRegister reg(MyFactory);
474 
475