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 "SkCornerPathEffect.h"
     12 #include "SkCullPoints.h"
     13 #include "SkGradientShader.h"
     14 #include "SkPath.h"
     15 #include "SkRegion.h"
     16 #include "SkShader.h"
     17 #include "SkUtils.h"
     18 #include "SkRandom.h"
     19 
     20 static void addbump(SkPath* path, const SkPoint pts[2], SkScalar bump) {
     21     SkVector    tang;
     22 
     23     tang.setLength(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY, bump);
     24 
     25     path->lineTo(SkScalarHalf(pts[0].fX + pts[1].fX) - tang.fY,
     26                  SkScalarHalf(pts[0].fY + pts[1].fY) + tang.fX);
     27     path->lineTo(pts[1]);
     28 }
     29 
     30 static void subdivide(SkPath* path, SkScalar bump) {
     31     SkPath::Iter    iter(*path, false);
     32     SkPoint         pts[4];
     33     SkPath          tmp;
     34 
     35     for (;;)
     36         switch (iter.next(pts)) {
     37         case SkPath::kMove_Verb:
     38             tmp.moveTo(pts[0]);
     39             break;
     40         case SkPath::kLine_Verb:
     41             addbump(&tmp, pts, bump);
     42             bump = -bump;
     43             break;
     44         case SkPath::kDone_Verb:
     45             goto FINISH;
     46         default:
     47             break;
     48         }
     49 
     50 FINISH:
     51     path->swap(tmp);
     52 }
     53 
     54 static SkIPoint* getpts(const SkPath& path, int* count) {
     55     SkPoint     pts[4];
     56     int         n = 1;
     57     SkIPoint*   array;
     58 
     59     {
     60         SkPath::Iter    iter(path, false);
     61         for (;;)
     62             switch (iter.next(pts)) {
     63             case SkPath::kLine_Verb:
     64                 n += 1;
     65                 break;
     66             case SkPath::kDone_Verb:
     67                 goto FINISHED;
     68             default:
     69                 break;
     70             }
     71     }
     72 
     73 FINISHED:
     74     array = new SkIPoint[n];
     75     n = 0;
     76 
     77     {
     78         SkPath::Iter    iter(path, false);
     79         for (;;)
     80             switch (iter.next(pts)) {
     81             case SkPath::kMove_Verb:
     82                 array[n++].set(SkScalarRoundToInt(pts[0].fX),
     83                                SkScalarRoundToInt(pts[0].fY));
     84                 break;
     85             case SkPath::kLine_Verb:
     86                 array[n++].set(SkScalarRoundToInt(pts[1].fX),
     87                                SkScalarRoundToInt(pts[1].fY));
     88                 break;
     89             case SkPath::kDone_Verb:
     90                 goto FINISHED2;
     91             default:
     92                 break;
     93             }
     94     }
     95 
     96 FINISHED2:
     97     *count = n;
     98     return array;
     99 }
    100 
    101 static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max) {
    102     return min + SkScalarMul(rand.nextUScalar1(), max - min);
    103 }
    104 
    105 class CullView : public SampleView {
    106 public:
    107     CullView() {
    108         fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160));
    109 
    110         SkRandom    rand;
    111 
    112         for (int i = 0; i < 50; i++) {
    113             SkScalar x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2);
    114             SkScalar y = nextScalarRange(rand, -fClip.height()*1, fClip.height()*2);
    115             if (i == 0)
    116                 fPath.moveTo(x, y);
    117             else
    118                 fPath.lineTo(x, y);
    119         }
    120 
    121         SkScalar bump = fClip.width()/8;
    122         subdivide(&fPath, bump);
    123         subdivide(&fPath, bump);
    124         subdivide(&fPath, bump);
    125         fPoints = getpts(fPath, &fPtCount);
    126 
    127         this->setBGColor(0xFFDDDDDD);
    128     }
    129 
    130     virtual ~CullView() {
    131         delete[] fPoints;
    132     }
    133 
    134 protected:
    135     // overrides from SkEventSink
    136     virtual bool onQuery(SkEvent* evt) {
    137         if (SampleCode::TitleQ(*evt)) {
    138             SampleCode::TitleR(evt, "Culling");
    139             return true;
    140         }
    141         return this->INHERITED::onQuery(evt);
    142     }
    143 
    144     virtual void onDrawContent(SkCanvas* canvas) {
    145         SkAutoCanvasRestore ar(canvas, true);
    146 
    147         canvas->translate(  SkScalarHalf(this->width() - fClip.width()),
    148                             SkScalarHalf(this->height() - fClip.height()));
    149 
    150    //     canvas->scale(SK_Scalar1*3, SK_Scalar1*3, 0, 0);
    151 
    152         SkPaint paint;
    153 
    154     //    paint.setAntiAliasOn(true);
    155         paint.setStyle(SkPaint::kStroke_Style);
    156 
    157         canvas->drawRect(fClip, paint);
    158 
    159 #if 1
    160         paint.setColor(0xFF555555);
    161         paint.setStrokeWidth(SkIntToScalar(2));
    162 //        paint.setPathEffect(new SkCornerPathEffect(SkIntToScalar(30)))->unref();
    163         canvas->drawPath(fPath, paint);
    164 //        paint.setPathEffect(NULL);
    165 #endif
    166 
    167         SkPath  tmp;
    168         SkIRect iclip;
    169         fClip.round(&iclip);
    170 
    171         SkCullPointsPath    cpp(iclip, &tmp);
    172 
    173         cpp.moveTo(fPoints[0].fX, fPoints[0].fY);
    174         for (int i = 0; i < fPtCount; i++)
    175             cpp.lineTo(fPoints[i].fX, fPoints[i].fY);
    176 
    177         paint.setColor(SK_ColorRED);
    178         paint.setStrokeWidth(SkIntToScalar(3));
    179         paint.setStrokeJoin(SkPaint::kRound_Join);
    180         canvas->drawPath(tmp, paint);
    181 
    182         this->inval(NULL);
    183     }
    184 
    185 private:
    186     SkRect      fClip;
    187     SkIPoint*   fPoints;
    188     SkPath      fPath;
    189     int         fPtCount;
    190 
    191     typedef SampleView INHERITED;
    192 };
    193 
    194 //////////////////////////////////////////////////////////////////////////////
    195 
    196 static SkView* MyFactory() { return new CullView; }
    197 static SkViewRegister reg(MyFactory);
    198