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