Home | History | Annotate | Download | only in samplecode
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SampleCode.h"
      9 #include "SkView.h"
     10 #include "SkCanvas.h"
     11 #include "SkRandom.h"
     12 #include "SkRRect.h"
     13 #include "SkColorPriv.h"
     14 
     15 static void rotateAbout(SkCanvas* canvas, SkScalar degrees,
     16                         SkScalar cx, SkScalar cy) {
     17     canvas->translate(cx, cy);
     18     canvas->rotate(degrees);
     19     canvas->translate(-cx, -cy);
     20 }
     21 
     22 class RotateCirclesView : public SampleView {
     23 public:
     24     RotateCirclesView() {
     25         this->setBGColor(SK_ColorLTGRAY);
     26 
     27         fAngle = 0;
     28     }
     29 
     30 protected:
     31     // overrides from SkEventSink
     32     virtual bool onQuery(SkEvent* evt) {
     33         if (SampleCode::TitleQ(*evt)) {
     34             SampleCode::TitleR(evt, "RotateCircles");
     35             return true;
     36         }
     37         return this->INHERITED::onQuery(evt);
     38     }
     39 
     40     virtual void onDrawContent(SkCanvas* canvas) {
     41         SkRandom rand;
     42         SkPaint paint;
     43         paint.setAntiAlias(true);
     44         paint.setStrokeWidth(20);
     45 
     46         SkScalar cx = 240;
     47         SkScalar cy = 240;
     48         SkScalar DX = 240 * 2;
     49         SkColor color = 0;
     50 
     51         float scale = 1;
     52         float sign = 0.3f;
     53         for (SkScalar rad = 200; rad >= 20; rad -= 15) {
     54             sign = -sign;
     55             scale += 0.2f;
     56 
     57             paint.setColor(rand.nextU());
     58             paint.setAlpha(0xFF);
     59             color = ~color;
     60 
     61             paint.setStyle(SkPaint::kFill_Style);
     62 
     63             canvas->save();
     64             rotateAbout(canvas, fAngle * scale * sign, cx, cy);
     65             canvas->drawCircle(cx, cy, rad, paint);
     66             canvas->restore();
     67 
     68             paint.setStyle(SkPaint::kStroke_Style);
     69             paint.setStrokeWidth(rad*2);
     70 
     71             canvas->save();
     72             rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy);
     73             canvas->drawCircle(cx + DX, cy, 10, paint);
     74             canvas->restore();
     75 
     76             canvas->save();
     77             rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy + DX);
     78             canvas->drawCircle(cx + DX, cy + DX, 10, paint);
     79             canvas->restore();
     80 
     81         }
     82 
     83         fAngle = (fAngle + 1) % 360;
     84         this->inval(NULL);
     85     }
     86 
     87 private:
     88     int fAngle;
     89     typedef SkView INHERITED;
     90 };
     91 
     92 class TestCirclesView : public SampleView {
     93 public:
     94     TestCirclesView() {
     95     }
     96 
     97 protected:
     98     virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
     99         if (SampleCode::TitleQ(*evt)) {
    100             SampleCode::TitleR(evt, "RotateCircles2");
    101             return true;
    102         }
    103         return this->INHERITED::onQuery(evt);
    104     }
    105 
    106     void draw_real_circle(SkCanvas* canvas, SkScalar radius) {
    107         int w = SkScalarCeilToInt(radius * 2);
    108         int h = w;
    109 
    110         SkBitmap bm;
    111         bm.allocN32Pixels(w, h);
    112         bm.eraseColor(0);
    113 
    114         SkAutoLockPixels alp(bm);
    115 
    116         SkScalar cx = radius;
    117         SkScalar cy = radius;
    118         for (int y = 0; y < h; y += 1) {
    119             for (int x = 0; x < w; x += 1) {
    120                 float d = sqrtf((x - cx)*(x - cx) + (y - cy)*(y - cy));
    121                 if (d <= radius) {
    122                     *bm.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0, 0);
    123                 }
    124             }
    125         }
    126 
    127         canvas->drawBitmap(bm, 0, 0, NULL);
    128     }
    129 
    130     virtual void onDrawContent(SkCanvas* canvas) {
    131         SkScalar radius = 256;
    132         canvas->translate(10, 10);
    133 
    134         draw_real_circle(canvas, radius);
    135 
    136         SkPaint paint;
    137         paint.setAntiAlias(true);
    138 
    139         paint.setColor(0x80FF0000);
    140         canvas->drawCircle(radius, radius, radius, paint);
    141 
    142         paint.setStyle(SkPaint::kStroke_Style);
    143         paint.setStrokeWidth(radius);
    144         paint.setColor(0x8000FF00);
    145         canvas->drawCircle(radius, radius, radius/2, paint);
    146     }
    147 
    148 private:
    149     typedef SkView INHERITED;
    150 };
    151 
    152 static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
    153     const SkScalar TOL = 7;
    154     return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL;
    155 }
    156 
    157 static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
    158     SkPath::RawIter iter(path);
    159     SkPoint pts[4];
    160     SkPath::Verb verb;
    161 
    162     int count = 0;
    163     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
    164         switch (verb) {
    165             case SkPath::kMove_Verb:
    166             case SkPath::kLine_Verb:
    167             case SkPath::kQuad_Verb:
    168             case SkPath::kCubic_Verb:
    169                 storage[count++] = pts[0];
    170                 break;
    171             default:
    172                 break;
    173         }
    174     }
    175     return count;
    176 }
    177 
    178 #include "SkPathMeasure.h"
    179 
    180 class TestStrokeView : public SampleView {
    181     enum {
    182         SKELETON_COLOR = 0xFF0000FF,
    183         WIREFRAME_COLOR = 0x80FF0000
    184     };
    185 
    186     enum {
    187         kCount = 9
    188     };
    189     SkPoint fPts[kCount];
    190     SkScalar fWidth, fDWidth;
    191 public:
    192     TestStrokeView() {
    193         this->setBGColor(SK_ColorLTGRAY);
    194 
    195         fPts[0].set(50, 200);
    196         fPts[1].set(50, 100);
    197         fPts[2].set(150, 50);
    198         fPts[3].set(300, 50);
    199 
    200         fPts[4].set(350, 200);
    201         fPts[5].set(350, 100);
    202         fPts[6].set(450, 50);
    203 
    204         fPts[7].set(200, 200);
    205         fPts[8].set(400, 400);
    206 
    207         fWidth = 50;
    208         fDWidth = 0.25f;
    209     }
    210 
    211 protected:
    212     virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
    213         if (SampleCode::TitleQ(*evt)) {
    214             SampleCode::TitleR(evt, "RotateCircles3");
    215             return true;
    216         }
    217         return this->INHERITED::onQuery(evt);
    218     }
    219 
    220     void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color,
    221                      bool show_lines) {
    222         SkPaint paint;
    223         paint.setColor(color);
    224         paint.setAlpha(0x80);
    225 
    226         int n = path.countPoints();
    227         SkAutoSTArray<32, SkPoint> pts(n);
    228         if (show_lines) {
    229             path.getPoints(pts.get(), n);
    230             canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint);
    231         } else {
    232             n = getOnCurvePoints(path, pts.get());
    233         }
    234         paint.setStrokeWidth(5);
    235         canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint);
    236     }
    237 
    238     void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width,
    239                    SkColor color) {
    240         const SkScalar radius = width / 2;
    241 
    242         SkPathMeasure meas(path, false);
    243         SkScalar total = meas.getLength();
    244 
    245         SkScalar delta = 8;
    246         SkPaint paint;
    247         paint.setColor(color);
    248 
    249         SkPoint pos, tan;
    250         for (SkScalar dist = 0; dist <= total; dist += delta) {
    251             if (meas.getPosTan(dist, &pos, &tan)) {
    252                 tan.scale(radius);
    253                 tan.rotateCCW();
    254                 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
    255                                  pos.x() - tan.x(), pos.y() - tan.y(), paint);
    256             }
    257         }
    258     }
    259 
    260     void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width) {
    261         SkPaint paint;
    262         paint.setAntiAlias(true);
    263         paint.setStyle(SkPaint::kStroke_Style);
    264 
    265         paint.setColor(SKELETON_COLOR);
    266         canvas->drawPath(path, paint);
    267         draw_points(canvas, path, SKELETON_COLOR, true);
    268 
    269         draw_ribs(canvas, path, width, 0xFF00FF00);
    270 
    271         SkPath fill;
    272 
    273         SkPaint p;
    274         p.setStyle(SkPaint::kStroke_Style);
    275         p.setStrokeWidth(width);
    276         p.getFillPath(path, &fill);
    277 
    278         paint.setColor(WIREFRAME_COLOR);
    279         canvas->drawPath(fill, paint);
    280         draw_points(canvas, fill, WIREFRAME_COLOR, false);
    281     }
    282 
    283     virtual void onDrawContent(SkCanvas* canvas) {
    284         SkPath path;
    285         SkScalar width = fWidth;
    286 
    287         path.moveTo(fPts[0]);
    288         path.cubicTo(fPts[1], fPts[2], fPts[3]);
    289         draw_stroke(canvas, path, width);
    290 
    291         path.reset();
    292         path.moveTo(fPts[4]);
    293         path.quadTo(fPts[5], fPts[6]);
    294         draw_stroke(canvas, path, width);
    295 
    296         SkScalar rad = 32;
    297         SkRect r;
    298         r.set(&fPts[7], 2);
    299         path.reset();
    300         SkRRect rr;
    301         rr.setRectXY(r, rad, rad);
    302         path.addRRect(rr);
    303         draw_stroke(canvas, path, width);
    304 
    305         path.reset();
    306         SkRRect rr2;
    307         rr.inset(width/2, width/2, &rr2);
    308         path.addRRect(rr2, SkPath::kCCW_Direction);
    309         rr.inset(-width/2, -width/2, &rr2);
    310         path.addRRect(rr2, SkPath::kCW_Direction);
    311         SkPaint paint;
    312         paint.setAntiAlias(true);
    313         paint.setColor(0x40FF8844);
    314         canvas->drawPath(path, paint);
    315 
    316         fWidth += fDWidth;
    317         if (fDWidth > 0 && fWidth > 100) {
    318             fDWidth = -fDWidth;
    319         } else if (fDWidth < 0 && fWidth < 10) {
    320             fDWidth = -fDWidth;
    321         }
    322         this->inval(NULL);
    323     }
    324 
    325     class MyClick : public Click {
    326     public:
    327         int fIndex;
    328         MyClick(SkView* target, int index) : Click(target), fIndex(index) {}
    329     };
    330 
    331     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
    332                                               unsigned modi) SK_OVERRIDE {
    333         for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) {
    334             if (hittest(fPts[i], x, y)) {
    335                 return new MyClick(this, (int)i);
    336             }
    337         }
    338         return this->INHERITED::onFindClickHandler(x, y, modi);
    339     }
    340 
    341     virtual bool onClick(Click* click) {
    342         int index = ((MyClick*)click)->fIndex;
    343         fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX),
    344                            SkIntToScalar(click->fICurr.fY - click->fIPrev.fY));
    345         this->inval(NULL);
    346         return true;
    347     }
    348 
    349 private:
    350     typedef SkView INHERITED;
    351 };
    352 
    353 ///////////////////////////////////////////////////////////////////////////////
    354 
    355 static SkView* F0() { return new RotateCirclesView; }
    356 static SkViewRegister gR0(F0);
    357 static SkView* F1() { return new TestCirclesView; }
    358 static SkViewRegister gR1(F1);
    359 static SkView* F2() { return new TestStrokeView; }
    360 static SkViewRegister gR2(F2);
    361