Home | History | Annotate | Download | only in samplecode
      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_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 
    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, 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
    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