| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #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(SkScalarRoundToInt(pts[0].fX), | |
| SkScalarRoundToInt(pts[0].fY)); | |
| break; | |
| case SkPath::kLine_Verb: | |
| array[n++].set(SkScalarRoundToInt(pts[1].fX), | |
| SkScalarRoundToInt(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); |