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 "SkGraphics.h"
     12 #include "SkRandom.h"
     13 
     14 static void test_clearonlayers(SkCanvas* canvas) {
     15     SkCanvas& c = *canvas;
     16 
     17     SkPaint paint;
     18     paint.setColor(SK_ColorBLUE);
     19     paint.setStyle(SkPaint::kStrokeAndFill_Style);
     20     SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
     21     c.drawRect(rect, paint);
     22 
     23     c.clipRect(rect);
     24 
     25     c.saveLayer(NULL, NULL);
     26     rect = SkRect::MakeXYWH(50, 10, 40, 80);
     27     c.clipRect(rect, SkRegion::kUnion_Op);
     28 
     29     rect = SkRect::MakeXYWH(50, 0, 50, 100);
     30     // You might draw something here, but it's not necessary.
     31     // paint.setColor(SK_ColorRED);
     32     // c.drawRect(rect, paint);
     33     paint.setXfermodeMode(SkXfermode::kClear_Mode);
     34     c.drawRect(rect, paint);
     35     c.restore();
     36 }
     37 
     38 static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
     39     SkPaint p;
     40 
     41     p.setAntiAlias(true);
     42     p.setStyle(SkPaint::kStroke_Style);
     43     p.setStrokeWidth(4);
     44 
     45     canvas->drawRect(r, p);
     46 
     47     SkPath path;
     48     SkRect r2(r);
     49     r2.offset(18, 0);
     50     path.addRect(r2);
     51 
     52     canvas->drawPath(path, p);
     53 }
     54 
     55 static void test_strokerect(SkCanvas* canvas) {
     56     canvas->drawColor(SK_ColorWHITE);
     57 
     58     SkRect r;
     59 
     60     r.set(10, 10, 14, 14);
     61     r.offset(0.25f, 0.3333f);
     62     test_strokerect(canvas, r);
     63     canvas->translate(0, 20);
     64 
     65     r.set(10, 10, 14.5f, 14.5f);
     66     r.offset(0.25f, 0.3333f);
     67     test_strokerect(canvas, r);
     68     canvas->translate(0, 20);
     69 
     70     r.set(10, 10, 14.5f, 20);
     71     r.offset(0.25f, 0.3333f);
     72     test_strokerect(canvas, r);
     73     canvas->translate(0, 20);
     74 
     75     r.set(10, 10, 20, 14.5f);
     76     r.offset(0.25f, 0.3333f);
     77     test_strokerect(canvas, r);
     78     canvas->translate(0, 20);
     79 
     80     r.set(10, 10, 20, 20);
     81     r.offset(0.25f, 0.3333f);
     82     test_strokerect(canvas, r);
     83     canvas->translate(0, 20);
     84 
     85 }
     86 
     87 class Draw : public SkRefCnt {
     88 public:
     89     Draw() : fFlags(0) {}
     90 
     91     enum Flags {
     92         kSelected_Flag  = 1 << 0
     93     };
     94     int getFlags() const { return fFlags; }
     95     void setFlags(int flags);
     96 
     97     bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
     98     void setSelected(bool pred) {
     99         if (pred) {
    100             fFlags |= kSelected_Flag;
    101         } else {
    102             fFlags &= ~kSelected_Flag;
    103         }
    104     }
    105 
    106     void draw(SkCanvas* canvas) {
    107         int sc = canvas->save();
    108         this->onDraw(canvas);
    109         canvas->restoreToCount(sc);
    110 
    111         if (this->isSelected()) {
    112             this->drawSelection(canvas);
    113         }
    114     }
    115 
    116     void drawSelection(SkCanvas* canvas) {
    117         int sc = canvas->save();
    118         this->onDrawSelection(canvas);
    119         canvas->restoreToCount(sc);
    120     }
    121 
    122     void getBounds(SkRect* bounds) {
    123         this->onGetBounds(bounds);
    124     }
    125 
    126     bool hitTest(SkScalar x, SkScalar y) {
    127         return this->onHitTest(x, y);
    128     }
    129 
    130     void offset(SkScalar dx, SkScalar dy) {
    131         if (dx || dy) {
    132             this->onOffset(dx, dy);
    133         }
    134     }
    135 
    136 protected:
    137     virtual void onDraw(SkCanvas*) = 0;
    138     virtual void onGetBounds(SkRect*) = 0;
    139     virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
    140     virtual void onDrawSelection(SkCanvas* canvas) {
    141         SkRect r;
    142         this->getBounds(&r);
    143         SkPaint paint;
    144         SkPoint pts[4];
    145         r.toQuad(pts);
    146         paint.setStrokeWidth(SkIntToScalar(10));
    147         paint.setColor(0x80FF8844);
    148         paint.setStrokeCap(SkPaint::kRound_Cap);
    149         canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
    150     }
    151     virtual bool onHitTest(SkScalar x, SkScalar y) {
    152         SkRect bounds;
    153         this->getBounds(&bounds);
    154         return bounds.contains(x, y);
    155     }
    156 
    157 private:
    158     int fFlags;
    159 };
    160 
    161 class RDraw : public Draw {
    162 public:
    163     enum Style {
    164         kRect_Style,
    165         kOval_Style,
    166         kRRect_Style,
    167         kFrame_Style
    168     };
    169 
    170     RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
    171 
    172     void setRect(const SkRect& r) {
    173         fRect = r;
    174     }
    175 
    176     void setPaint(const SkPaint& p) {
    177         fPaint = p;
    178     }
    179 
    180 protected:
    181     virtual void onDraw(SkCanvas* canvas) {
    182         switch (fStyle) {
    183             case kRect_Style:
    184                 canvas->drawRect(fRect, fPaint);
    185                 break;
    186             case kOval_Style:
    187                 canvas->drawOval(fRect, fPaint);
    188                 break;
    189             case kRRect_Style: {
    190                 SkScalar rx = fRect.width() / 5;
    191                 SkScalar ry = fRect.height() / 5;
    192                 if (rx < ry) {
    193                     ry = rx;
    194                 } else {
    195                     rx = ry;
    196                 }
    197                 canvas->drawRoundRect(fRect, rx, ry, fPaint);
    198                 break;
    199             }
    200             case kFrame_Style: {
    201                 SkPath path;
    202                 path.addOval(fRect, SkPath::kCW_Direction);
    203                 SkRect r = fRect;
    204                 r.inset(fRect.width()/6, 0);
    205                 path.addOval(r, SkPath::kCCW_Direction);
    206                 canvas->drawPath(path, fPaint);
    207                 break;
    208             }
    209         }
    210     }
    211 
    212     virtual void onGetBounds(SkRect* bounds) {
    213         *bounds = fRect;
    214     }
    215 
    216     virtual void onOffset(SkScalar dx, SkScalar dy) {
    217         fRect.offset(dx, dy);
    218     }
    219 
    220 private:
    221     SkRect  fRect;
    222     SkPaint fPaint;
    223     Style   fStyle;
    224 };
    225 
    226 class DrawFactory {
    227 public:
    228     DrawFactory() {
    229         fPaint.setAntiAlias(true);
    230     }
    231 
    232     const SkPaint& getPaint() const { return fPaint; }
    233 
    234     void setPaint(const SkPaint& p) {
    235         fPaint = p;
    236     }
    237 
    238     virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
    239 
    240 private:
    241     SkPaint fPaint;
    242 };
    243 
    244 class RectFactory : public DrawFactory {
    245 public:
    246     virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
    247         SkRect r;
    248         r.set(p0.x(), p0.y(), p1.x(), p1.y());
    249         r.sort();
    250 
    251 //        RDraw* d = new RDraw(r, RDraw::kRRect_Style);
    252         RDraw* d = new RDraw(r, RDraw::kFrame_Style);
    253         d->setPaint(this->getPaint());
    254         return d;
    255     }
    256 };
    257 
    258 class DrawView : public SkView {
    259     Draw*           fDraw;
    260     DrawFactory*    fFactory;
    261     SkRandom        fRand;
    262     SkTDArray<Draw*> fList;
    263 
    264 public:
    265     DrawView() : fDraw(NULL) {
    266         fFactory = new RectFactory;
    267     }
    268 
    269     virtual ~DrawView() {
    270         fList.unrefAll();
    271         SkSafeUnref(fDraw);
    272         delete fFactory;
    273     }
    274 
    275     Draw* setDraw(Draw* d) {
    276         SkRefCnt_SafeAssign(fDraw, d);
    277         return d;
    278     }
    279 
    280     SkColor randColor() {
    281         return (SkColor)fRand.nextU() | 0xFF000000;
    282     }
    283 
    284     Draw* hitTestList(SkScalar x, SkScalar y) const {
    285         Draw** first = fList.begin();
    286         for (Draw** iter = fList.end(); iter > first;) {
    287             --iter;
    288             if ((*iter)->hitTest(x, y)) {
    289                 return *iter;
    290             }
    291         }
    292         return NULL;
    293     }
    294 
    295 protected:
    296     // overrides from SkEventSink
    297     virtual bool onQuery(SkEvent* evt) {
    298         if (SampleCode::TitleQ(*evt)) {
    299             SampleCode::TitleR(evt, "Draw");
    300             return true;
    301         }
    302         return this->INHERITED::onQuery(evt);
    303     }
    304 
    305     void drawBG(SkCanvas* canvas) {
    306         canvas->drawColor(0xFFDDDDDD);
    307 //        canvas->drawColor(SK_ColorWHITE);
    308     }
    309 
    310     virtual void onDraw(SkCanvas* canvas) {
    311         this->drawBG(canvas);
    312         test_clearonlayers(canvas); return;
    313      //   test_strokerect(canvas); return;
    314 
    315         for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
    316             (*iter)->draw(canvas);
    317         }
    318         if (fDraw) {
    319             fDraw->draw(canvas);
    320         }
    321     }
    322 
    323     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
    324         for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
    325             (*iter)->setSelected(false);
    326         }
    327 
    328         Click* c = new Click(this);
    329         Draw* d = this->hitTestList(x, y);
    330         if (d) {
    331             d->setSelected(true);
    332             c->setType("dragger");
    333         } else {
    334             c->setType("maker");
    335         }
    336         return c;
    337     }
    338 
    339     virtual bool onClick(Click* click) {
    340         if (Click::kUp_State == click->fState) {
    341             if (click->isType("maker")) {
    342                 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
    343                     *fList.append() = fDraw;
    344                 } else {
    345                     fDraw->unref();
    346                 }
    347                 fDraw = NULL;
    348             }
    349             return true;
    350         }
    351 
    352         if (Click::kDown_State == click->fState) {
    353             SkPaint p = fFactory->getPaint();
    354             p.setColor(this->randColor());
    355             fFactory->setPaint(p);
    356         }
    357 
    358         if (click->isType("maker")) {
    359             this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
    360         } else if (click->isType("dragger")) {
    361             for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
    362                 if ((*iter)->isSelected()) {
    363                     (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
    364                                     click->fCurr.y() - click->fPrev.y());
    365                 }
    366             }
    367         }
    368         this->inval(NULL);
    369         return true;
    370     }
    371 
    372 private:
    373     typedef SkView INHERITED;
    374 };
    375 
    376 //////////////////////////////////////////////////////////////////////////////
    377 
    378 static SkView* MyFactory() { return new DrawView; }
    379 static SkViewRegister reg(MyFactory);
    380 
    381