| #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 SkView { | 
 | public: | 
 | 	CullView() | 
 |     { | 
 |         fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160)); | 
 |          | 
 |         SkRandom    rand; | 
 |          | 
 |         for (int i = 0; i < 50; i++) { | 
 |             int x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2); | 
 |             int 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); | 
 |     } | 
 |      | 
 |     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); | 
 |     } | 
 |      | 
 |     void drawBG(SkCanvas* canvas) | 
 |     { | 
 |         canvas->drawColor(0xFFDDDDDD); | 
 |          | 
 |     #if 0 | 
 |         SkPaint paint; | 
 |          | 
 |         paint.setAntiAliasOn(true); | 
 |         paint.setTextSize(SkIntToScalar(20)); | 
 |         paint.setTypeface(SkTypeface::Create("serif", SkTypeface::kBoldItalic))->unref(); | 
 |  | 
 |         uint16_t    text[20]; | 
 |          | 
 |         text[0] = 'H'; | 
 |         text[1] = 'i'; | 
 |         text[2] = ' '; | 
 |         for (int i = 3; i < 20; i++) | 
 |             text[i] = 0x3040 + i; | 
 |         canvas->drawText16(text, 20, SkIntToScalar(20), SkIntToScalar(20), paint); | 
 |     #endif | 
 |     } | 
 |      | 
 |     virtual void onDraw(SkCanvas* canvas) | 
 |     { | 
 |         this->drawBG(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); | 
 |     } | 
 |      | 
 |     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y)  | 
 |     { | 
 |         return this->INHERITED::onFindClickHandler(x, y); | 
 |     } | 
 |      | 
 |     virtual bool onClick(Click* click)  | 
 |     { | 
 |         return this->INHERITED::onClick(click); | 
 |     } | 
 |      | 
 | private: | 
 |     SkRect      fClip; | 
 |     SkIPoint*   fPoints; | 
 |     SkPath      fPath; | 
 |     int         fPtCount; | 
 |  | 
 |     typedef SkView INHERITED; | 
 | }; | 
 |  | 
 | ////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | static SkView* MyFactory() { return new CullView; } | 
 | static SkViewRegister reg(MyFactory); | 
 |  |