• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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