Home | History | Annotate | Download | only in samplecode
      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 
     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 
     93 static SkPoint SkMakePoint(SkScalar x, SkScalar y) {
     94     SkPoint pt;
     95     pt.set(x, y);
     96     return pt;
     97 }
     98 
     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 
    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 
    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 
    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 
    212     const SkRect& bounds() const { return fBounds; }
    213 
    214     int rows() const { return fRows; }
    215     int cols() const { return fCols; }
    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 
    233 Mesh::Mesh() : fPts(NULL), fCount(0), fIndices(NULL), fIndexCount(0) {}
    234 
    235 Mesh::~Mesh() {
    236     delete[] fPts;
    237     delete[] fIndices;
    238 }
    239 
    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 
    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 
    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 
    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:
    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
    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 
    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 
    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 
    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 
    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 
    445     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
    446         return new Click(this);
    447     }
    448 
    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 
    465 static SkView* MyFactory() { return new WarpView; }
    466 static SkViewRegister reg(MyFactory);
    467 
    468