/* * 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(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);