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 "SkGraphics.h"
      6 #include "SkImageDecoder.h"
      7 #include "SkPath.h"
      8 #include "SkRandom.h"
      9 #include "SkRegion.h"
     10 #include "SkShader.h"
     11 #include "SkUtils.h"
     12 #include "SkXfermode.h"
     13 #include "SkColorPriv.h"
     14 #include "SkColorFilter.h"
     15 #include "SkTime.h"
     16 #include "SkTypeface.h"
     17 
     18 #include "SkOSFile.h"
     19 #include "SkStream.h"
     20 
     21 #include "SkGeometry.h" // private include :(
     22 
     23 static void drawtriangle(SkCanvas* canvas, const SkPaint& paint,
     24                          const SkPoint pts[3]) {
     25     SkPath path;
     26 
     27     path.moveTo(pts[0]);
     28     path.lineTo(pts[1]);
     29     path.lineTo(pts[2]);
     30 
     31     canvas->drawPath(path, paint);
     32 }
     33 
     34 static SkShader* make_shader0(SkIPoint* size) {
     35     SkBitmap    bm;
     36 
     37 //    SkImageDecoder::DecodeFile("/skimages/progressivejpg.jpg", &bm);
     38     SkImageDecoder::DecodeFile("/skimages/logo.png", &bm);
     39     size->set(bm.width(), bm.height());
     40     return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
     41                                         SkShader::kClamp_TileMode);
     42 }
     43 
     44 static SkShader* make_shader1(const SkIPoint& size) {
     45     SkPoint pts[] = { { 0, 0, },
     46                       { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } };
     47     SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED };
     48     return SkGradientShader::CreateLinear(pts, colors, NULL,
     49                     SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL);
     50 }
     51 
     52 ///////////////////////////////////////////////////////////////////////////////
     53 
     54 class Patch {
     55 public:
     56     Patch() { sk_bzero(fPts, sizeof(fPts)); }
     57     ~Patch() {}
     58 
     59     void setPatch(const SkPoint pts[12]) {
     60         memcpy(fPts, pts, 12 * sizeof(SkPoint));
     61         fPts[12] = pts[0];  // the last shall be first
     62     }
     63     void setBounds(int w, int h) { fW = w; fH = h; }
     64 
     65     void draw(SkCanvas*, const SkPaint&, int segsU, int segsV,
     66               bool doTextures, bool doColors);
     67 
     68 private:
     69     SkPoint fPts[13];
     70     int     fW, fH;
     71 };
     72 
     73 static void eval_patch_edge(const SkPoint cubic[], SkPoint samples[], int segs) {
     74     SkScalar t = 0;
     75     SkScalar dt = SK_Scalar1 / segs;
     76 
     77     samples[0] = cubic[0];
     78     for (int i = 1; i < segs; i++) {
     79         t += dt;
     80         SkEvalCubicAt(cubic, t, &samples[i], NULL, NULL);
     81     }
     82 }
     83 
     84 static void eval_sheet(const SkPoint edge[], int nu, int nv, int iu, int iv,
     85                        SkPoint* pt) {
     86     const int TL = 0;
     87     const int TR = nu;
     88     const int BR = TR + nv;
     89     const int BL = BR + nu;
     90 
     91     SkScalar u = SkIntToScalar(iu) / nu;
     92     SkScalar v = SkIntToScalar(iv) / nv;
     93 
     94     SkScalar uv = SkScalarMul(u, v);
     95     SkScalar Uv = SkScalarMul(SK_Scalar1 - u, v);
     96     SkScalar uV = SkScalarMul(u, SK_Scalar1 - v);
     97     SkScalar UV = SkScalarMul(SK_Scalar1 - u, SK_Scalar1 - v);
     98 
     99     SkScalar x0 = SkScalarMul(UV, edge[TL].fX) + SkScalarMul(uV, edge[TR].fX) +
    100                   SkScalarMul(Uv, edge[BL].fX) + SkScalarMul(uv, edge[BR].fX);
    101     SkScalar y0 = SkScalarMul(UV, edge[TL].fY) + SkScalarMul(uV, edge[TR].fY) +
    102                   SkScalarMul(Uv, edge[BL].fY) + SkScalarMul(uv, edge[BR].fY);
    103 
    104     SkScalar x =    SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fX) +
    105                     SkScalarMul(u, edge[TR+iv].fX) +
    106                     SkScalarMul(v, edge[BR+nu-iu].fX) +
    107                     SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fX) - x0;
    108     SkScalar y =    SkScalarMul(SK_Scalar1 - v, edge[TL+iu].fY) +
    109                     SkScalarMul(u, edge[TR+iv].fY) +
    110                     SkScalarMul(v, edge[BR+nu-iu].fY) +
    111                     SkScalarMul(SK_Scalar1 - u, edge[BL+nv-iv].fY) - y0;
    112     pt->set(x, y);
    113 }
    114 
    115 static int ScalarTo255(SkScalar v) {
    116     int scale = SkScalarToFixed(v) >> 8;
    117     if (scale < 0) {
    118         scale = 0;
    119     } else if (scale > 255) {
    120         scale = 255;
    121     }
    122     return scale;
    123 }
    124 
    125 static SkColor make_color(SkScalar s, SkScalar t) {
    126     int cs = ScalarTo255(s);
    127     int ct = ScalarTo255(t);
    128     return SkColorSetARGB(0xFF, cs, 0, 0) + SkColorSetARGB(0, 0, ct, 0);
    129 }
    130 
    131 void Patch::draw(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
    132                  bool doTextures, bool doColors) {
    133     if (nu < 1 || nv < 1) {
    134         return;
    135     }
    136 
    137     int i, npts = (nu + nv) * 2;
    138     SkAutoSTMalloc<16, SkPoint> storage(npts + 1);
    139     SkPoint* edge0 = storage.get();
    140     SkPoint* edge1 = edge0 + nu;
    141     SkPoint* edge2 = edge1 + nv;
    142     SkPoint* edge3 = edge2 + nu;
    143 
    144     // evaluate the edge points
    145     eval_patch_edge(fPts + 0, edge0, nu);
    146     eval_patch_edge(fPts + 3, edge1, nv);
    147     eval_patch_edge(fPts + 6, edge2, nu);
    148     eval_patch_edge(fPts + 9, edge3, nv);
    149     edge3[nv] = edge0[0];   // the last shall be first
    150 
    151     for (i = 0; i < npts; i++) {
    152 //        canvas->drawLine(edge0[i].fX, edge0[i].fY, edge0[i+1].fX, edge0[i+1].fY, paint);
    153     }
    154 
    155     int row, vertCount = (nu + 1) * (nv + 1);
    156     SkAutoTMalloc<SkPoint>  vertStorage(vertCount);
    157     SkPoint* verts = vertStorage.get();
    158 
    159     // first row
    160     memcpy(verts, edge0, (nu + 1) * sizeof(SkPoint));
    161     // rows
    162     SkPoint* r = verts;
    163     for (row = 1; row < nv; row++) {
    164         r += nu + 1;
    165         r[0] = edge3[nv - row];
    166         for (int col = 1; col < nu; col++) {
    167             eval_sheet(edge0, nu, nv, col, row, &r[col]);
    168         }
    169         r[nu] = edge1[row];
    170     }
    171     // last row
    172     SkPoint* last = verts + nv * (nu + 1);
    173     for (i = 0; i <= nu; i++) {
    174         last[i] = edge2[nu - i];
    175     }
    176 
    177 //    canvas->drawPoints(verts, vertCount, paint);
    178 
    179     int stripCount = (nu + 1) * 2;
    180     SkAutoTMalloc<SkPoint>  stripStorage(stripCount * 2);
    181     SkAutoTMalloc<SkColor>  colorStorage(stripCount);
    182     SkPoint* strip = stripStorage.get();
    183     SkPoint* tex = strip + stripCount;
    184     SkColor* colors = colorStorage.get();
    185     SkScalar t = 0;
    186     const SkScalar ds = SK_Scalar1 * fW / nu;
    187     const SkScalar dt = SK_Scalar1 * fH / nv;
    188     r = verts;
    189     for (row = 0; row < nv; row++) {
    190         SkPoint* upper = r;
    191         SkPoint* lower = r + nu + 1;
    192         r = lower;
    193         SkScalar s = 0;
    194         for (i = 0; i <= nu; i++)  {
    195             strip[i*2 + 0] = *upper++;
    196             strip[i*2 + 1] = *lower++;
    197             tex[i*2 + 0].set(s, t);
    198             tex[i*2 + 1].set(s, t + dt);
    199             colors[i*2 + 0] = make_color(s/fW, t/fH);
    200             colors[i*2 + 1] = make_color(s/fW, (t + dt)/fH);
    201             s += ds;
    202         }
    203         t += dt;
    204         canvas->drawVertices(SkCanvas::kTriangleStrip_VertexMode, stripCount,
    205                              strip, doTextures ? tex : NULL,
    206                              doColors ? colors : NULL, NULL,
    207                              NULL, 0, paint);
    208     }
    209 }
    210 
    211 static void drawpatches(SkCanvas* canvas, const SkPaint& paint, int nu, int nv,
    212                         Patch* patch) {
    213 
    214     SkAutoCanvasRestore ar(canvas, true);
    215 
    216     patch->draw(canvas, paint, 10, 10, false, false);
    217     canvas->translate(SkIntToScalar(180), 0);
    218     patch->draw(canvas, paint, 10, 10, true, false);
    219     canvas->translate(SkIntToScalar(180), 0);
    220     patch->draw(canvas, paint, 10, 10, false, true);
    221     canvas->translate(SkIntToScalar(180), 0);
    222     patch->draw(canvas, paint, 10, 10, true, true);
    223 }
    224 
    225 class PatchView : public SampleView {
    226     SkShader*   fShader0;
    227     SkShader*   fShader1;
    228     SkIPoint    fSize0, fSize1;
    229     SkPoint     fPts[12];
    230 
    231 public:
    232 	PatchView() {
    233         fShader0 = make_shader0(&fSize0);
    234         fSize1 = fSize0;
    235         if (fSize0.fX == 0 || fSize0.fY == 0) {
    236             fSize1.set(2, 2);
    237         }
    238         fShader1 = make_shader1(fSize1);
    239 
    240         const SkScalar S = SkIntToScalar(50);
    241         const SkScalar T = SkIntToScalar(40);
    242         fPts[0].set(S*0, T);
    243         fPts[1].set(S*1, T);
    244         fPts[2].set(S*2, T);
    245         fPts[3].set(S*3, T);
    246         fPts[4].set(S*3, T*2);
    247         fPts[5].set(S*3, T*3);
    248         fPts[6].set(S*3, T*4);
    249         fPts[7].set(S*2, T*4);
    250         fPts[8].set(S*1, T*4);
    251         fPts[9].set(S*0, T*4);
    252         fPts[10].set(S*0, T*3);
    253         fPts[11].set(S*0, T*2);
    254 
    255         this->setBGColor(SK_ColorGRAY);
    256     }
    257 
    258     virtual ~PatchView() {
    259         SkSafeUnref(fShader0);
    260         SkSafeUnref(fShader1);
    261     }
    262 
    263 protected:
    264     // overrides from SkEventSink
    265     virtual bool onQuery(SkEvent* evt)  {
    266         if (SampleCode::TitleQ(*evt))
    267         {
    268             SkString str("Patch");
    269             SampleCode::TitleR(evt, str.c_str());
    270             return true;
    271         }
    272         return this->INHERITED::onQuery(evt);
    273     }
    274 
    275     virtual void onDrawContent(SkCanvas* canvas) {
    276         SkPaint paint;
    277         paint.setDither(true);
    278         paint.setFilterBitmap(true);
    279 
    280         canvas->translate(SkIntToScalar(20), 0);
    281 
    282         Patch   patch;
    283 
    284         paint.setShader(fShader0);
    285         if (fSize0.fX == 0) {
    286             fSize0.fX = 1;
    287         }
    288         if (fSize0.fY == 0) {
    289             fSize0.fY = 1;
    290         }
    291         patch.setBounds(fSize0.fX, fSize0.fY);
    292 
    293         patch.setPatch(fPts);
    294         drawpatches(canvas, paint, 10, 10, &patch);
    295 
    296         paint.setShader(NULL);
    297         paint.setAntiAlias(true);
    298         paint.setStrokeWidth(SkIntToScalar(5));
    299         canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint);
    300 
    301         canvas->translate(0, SkIntToScalar(300));
    302 
    303         paint.setAntiAlias(false);
    304         paint.setShader(fShader1);
    305         patch.setBounds(fSize1.fX, fSize1.fY);
    306         drawpatches(canvas, paint, 10, 10, &patch);
    307     }
    308 
    309     class PtClick : public Click {
    310     public:
    311         int fIndex;
    312         PtClick(SkView* view, int index) : Click(view), fIndex(index) {}
    313     };
    314 
    315     static bool hittest(const SkPoint& pt, SkScalar x, SkScalar y) {
    316         return SkPoint::Length(pt.fX - x, pt.fY - y) < SkIntToScalar(5);
    317     }
    318 
    319     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
    320         for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) {
    321             if (hittest(fPts[i], x, y)) {
    322                 return new PtClick(this, i);
    323             }
    324         }
    325         return this->INHERITED::onFindClickHandler(x, y);
    326     }
    327 
    328     virtual bool onClick(Click* click) {
    329         fPts[((PtClick*)click)->fIndex].set(click->fCurr.fX, click->fCurr.fY);
    330         this->inval(NULL);
    331         return true;
    332     }
    333 
    334 private:
    335     typedef SampleView INHERITED;
    336 };
    337 
    338 //////////////////////////////////////////////////////////////////////////////
    339 
    340 static SkView* MyFactory() { return new PatchView; }
    341 static SkViewRegister reg(MyFactory);
    342 
    343