| #include "SampleCode.h" | 
 | #include "SkView.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkCornerPathEffect.h" | 
 | #include "SkCullPoints.h" | 
 | #include "SkGradientShader.h" | 
 | #include "SkPath.h" | 
 | #include "SkRegion.h" | 
 | #include "SkShader.h" | 
 | #include "SkUtils.h" | 
 | #include "SkRandom.h" | 
 |  | 
 | static void addbump(SkPath* path, const SkPoint pts[2], SkScalar bump) { | 
 |     SkVector    tang; | 
 |      | 
 |     tang.setLength(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY, bump); | 
 |  | 
 |     path->lineTo(SkScalarHalf(pts[0].fX + pts[1].fX) - tang.fY, | 
 |                  SkScalarHalf(pts[0].fY + pts[1].fY) + tang.fX); | 
 |     path->lineTo(pts[1]); | 
 | } | 
 |  | 
 | static void subdivide(SkPath* path, SkScalar bump) { | 
 |     SkPath::Iter    iter(*path, false); | 
 |     SkPoint         pts[4]; | 
 |     SkPath          tmp; | 
 |      | 
 |     for (;;) | 
 |         switch (iter.next(pts)) { | 
 |         case SkPath::kMove_Verb: | 
 |             tmp.moveTo(pts[0]); | 
 |             break; | 
 |         case SkPath::kLine_Verb: | 
 |             addbump(&tmp, pts, bump); | 
 |             bump = -bump; | 
 |             break; | 
 |         case SkPath::kDone_Verb: | 
 |             goto FINISH; | 
 |         default: | 
 |             break; | 
 |         } | 
 |  | 
 | FINISH: | 
 |     path->swap(tmp); | 
 | } | 
 |  | 
 | static SkIPoint* getpts(const SkPath& path, int* count) { | 
 |     SkPoint     pts[4]; | 
 |     int         n = 1; | 
 |     SkIPoint*   array; | 
 |  | 
 |     { | 
 |         SkPath::Iter    iter(path, false); | 
 |         for (;;) | 
 |             switch (iter.next(pts)) { | 
 |             case SkPath::kLine_Verb: | 
 |                 n += 1; | 
 |                 break; | 
 |             case SkPath::kDone_Verb: | 
 |                 goto FINISHED; | 
 |             default: | 
 |                 break; | 
 |             } | 
 |     } | 
 |  | 
 | FINISHED: | 
 |     array = new SkIPoint[n]; | 
 |     n = 0; | 
 |  | 
 |     { | 
 |         SkPath::Iter    iter(path, false); | 
 |         for (;;) | 
 |             switch (iter.next(pts)) { | 
 |             case SkPath::kMove_Verb: | 
 |                 array[n++].set(SkScalarRound(pts[0].fX), SkScalarRound(pts[0].fY)); | 
 |                 break; | 
 |             case SkPath::kLine_Verb: | 
 |                 array[n++].set(SkScalarRound(pts[1].fX), SkScalarRound(pts[1].fY)); | 
 |                 break; | 
 |             case SkPath::kDone_Verb: | 
 |                 goto FINISHED2; | 
 |             default: | 
 |                 break; | 
 |             } | 
 |     } | 
 |      | 
 | FINISHED2: | 
 |     *count = n; | 
 |     return array; | 
 | } | 
 |  | 
 | static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max) { | 
 |     return min + SkScalarMul(rand.nextUScalar1(), max - min); | 
 | } | 
 |  | 
 | class CullView : public SampleView { | 
 | public: | 
 | 	CullView() { | 
 |         fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160)); | 
 |          | 
 |         SkRandom    rand; | 
 |          | 
 |         for (int i = 0; i < 50; i++) { | 
 |             SkScalar x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2); | 
 |             SkScalar y = nextScalarRange(rand, -fClip.height()*1, fClip.height()*2); | 
 |             if (i == 0) | 
 |                 fPath.moveTo(x, y); | 
 |             else | 
 |                 fPath.lineTo(x, y); | 
 |         } | 
 |          | 
 |         SkScalar bump = fClip.width()/8; | 
 |         subdivide(&fPath, bump); | 
 |         subdivide(&fPath, bump); | 
 |         subdivide(&fPath, bump); | 
 |         fPoints = getpts(fPath, &fPtCount); | 
 |          | 
 |         this->setBGColor(0xFFDDDDDD); | 
 |     } | 
 |      | 
 |     virtual ~CullView() { | 
 |         delete[] fPoints; | 
 |     } | 
 |  | 
 | protected: | 
 |     // overrides from SkEventSink | 
 |     virtual bool onQuery(SkEvent* evt) { | 
 |         if (SampleCode::TitleQ(*evt)) { | 
 |             SampleCode::TitleR(evt, "Culling"); | 
 |             return true; | 
 |         } | 
 |         return this->INHERITED::onQuery(evt); | 
 |     } | 
 |      | 
 |     virtual void onDrawContent(SkCanvas* canvas) { | 
 |         SkAutoCanvasRestore ar(canvas, true); | 
 |  | 
 |         canvas->translate(  SkScalarHalf(this->width() - fClip.width()), | 
 |                             SkScalarHalf(this->height() - fClip.height())); | 
 |  | 
 |    //     canvas->scale(SK_Scalar1*3, SK_Scalar1*3, 0, 0); | 
 |  | 
 |         SkPaint paint; | 
 |          | 
 |     //    paint.setAntiAliasOn(true); | 
 |         paint.setStyle(SkPaint::kStroke_Style); | 
 |  | 
 |         canvas->drawRect(fClip, paint); | 
 |  | 
 | #if 1 | 
 |         paint.setColor(0xFF555555); | 
 |         paint.setStrokeWidth(SkIntToScalar(2)); | 
 | //        paint.setPathEffect(new SkCornerPathEffect(SkIntToScalar(30)))->unref(); | 
 |         canvas->drawPath(fPath, paint); | 
 | //        paint.setPathEffect(NULL); | 
 | #endif | 
 |  | 
 |         SkPath  tmp; | 
 |         SkIRect iclip; | 
 |         fClip.round(&iclip); | 
 |          | 
 |         SkCullPointsPath    cpp(iclip, &tmp); | 
 |          | 
 |         cpp.moveTo(fPoints[0].fX, fPoints[0].fY); | 
 |         for (int i = 0; i < fPtCount; i++) | 
 |             cpp.lineTo(fPoints[i].fX, fPoints[i].fY); | 
 |          | 
 |         paint.setColor(SK_ColorRED); | 
 |         paint.setStrokeWidth(SkIntToScalar(3)); | 
 |         paint.setStrokeJoin(SkPaint::kRound_Join); | 
 |         canvas->drawPath(tmp, paint); | 
 |          | 
 |         this->inval(NULL); | 
 |     } | 
 |      | 
 | private: | 
 |     SkRect      fClip; | 
 |     SkIPoint*   fPoints; | 
 |     SkPath      fPath; | 
 |     int         fPtCount; | 
 |  | 
 |     typedef SampleView INHERITED; | 
 | }; | 
 |  | 
 | ////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | static SkView* MyFactory() { return new CullView; } | 
 | static SkViewRegister reg(MyFactory); | 
 |  |