|  | #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); | 
|  |  |