|  |  | 
|  | /* | 
|  | * 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 "SkGradientShader.h" | 
|  | #include "SkPath.h" | 
|  | #include "SkRegion.h" | 
|  | #include "SkShader.h" | 
|  | #include "SkUtils.h" | 
|  | #include "Sk1DPathEffect.h" | 
|  | #include "SkCornerPathEffect.h" | 
|  | #include "SkPathMeasure.h" | 
|  | #include "SkRandom.h" | 
|  | #include "SkColorPriv.h" | 
|  | #include "SkPixelXorXfermode.h" | 
|  |  | 
|  | #define CORNER_RADIUS   12 | 
|  | static SkScalar gPhase; | 
|  |  | 
|  | static const int gXY[] = { | 
|  | 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 | 
|  | }; | 
|  |  | 
|  | static SkPathEffect* make_pe(int flags) { | 
|  | if (flags == 1) | 
|  | return SkCornerPathEffect::Create(SkIntToScalar(CORNER_RADIUS)); | 
|  |  | 
|  | SkPath  path; | 
|  | path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); | 
|  | for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) | 
|  | path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); | 
|  | path.close(); | 
|  | path.offset(SkIntToScalar(-6), 0); | 
|  |  | 
|  | SkPathEffect* outer = SkPath1DPathEffect::Create(path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kRotate_Style); | 
|  |  | 
|  | if (flags == 2) | 
|  | return outer; | 
|  |  | 
|  | SkPathEffect* inner = SkCornerPathEffect::Create(SkIntToScalar(CORNER_RADIUS)); | 
|  |  | 
|  | SkPathEffect* pe = SkComposePathEffect::Create(outer, inner); | 
|  | outer->unref(); | 
|  | inner->unref(); | 
|  | return pe; | 
|  | } | 
|  |  | 
|  | static SkPathEffect* make_warp_pe() { | 
|  | SkPath  path; | 
|  | path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); | 
|  | for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) | 
|  | path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); | 
|  | path.close(); | 
|  | path.offset(SkIntToScalar(-6), 0); | 
|  |  | 
|  | SkPathEffect* outer = SkPath1DPathEffect::Create( | 
|  | path, SkIntToScalar(12), gPhase, SkPath1DPathEffect::kMorph_Style); | 
|  | SkPathEffect* inner = SkCornerPathEffect::Create(SkIntToScalar(CORNER_RADIUS)); | 
|  |  | 
|  | SkPathEffect* pe = SkComposePathEffect::Create(outer, inner); | 
|  | outer->unref(); | 
|  | inner->unref(); | 
|  | return pe; | 
|  | } | 
|  |  | 
|  | /////////////////////////////////////////////////////////// | 
|  |  | 
|  | #include "SkColorFilter.h" | 
|  | #include "SkLayerRasterizer.h" | 
|  |  | 
|  | class TestRastBuilder : public SkLayerRasterizer::Builder { | 
|  | public: | 
|  | TestRastBuilder() { | 
|  | SkPaint paint; | 
|  | paint.setAntiAlias(true); | 
|  |  | 
|  | #if 0 | 
|  | paint.setStyle(SkPaint::kStroke_Style); | 
|  | paint.setStrokeWidth(SK_Scalar1*4); | 
|  | this->addLayer(paint); | 
|  |  | 
|  | paint.setStrokeWidth(SK_Scalar1*1); | 
|  | paint.setXfermode(SkXfermode::kClear_Mode); | 
|  | this->addLayer(paint); | 
|  | #else | 
|  | paint.setAlpha(0x66); | 
|  | this->addLayer(paint, SkIntToScalar(4), SkIntToScalar(4)); | 
|  |  | 
|  | paint.setAlpha(0xFF); | 
|  | this->addLayer(paint); | 
|  | #endif | 
|  | } | 
|  | }; | 
|  |  | 
|  | class PathEffectView : public SampleView { | 
|  | SkPath  fPath; | 
|  | SkPoint fClickPt; | 
|  | public: | 
|  | PathEffectView() { | 
|  | SkRandom    rand; | 
|  | int         steps = 20; | 
|  | SkScalar    dist = SkIntToScalar(400); | 
|  | SkScalar    x = SkIntToScalar(20); | 
|  | SkScalar    y = SkIntToScalar(50); | 
|  |  | 
|  | fPath.moveTo(x, y); | 
|  | for (int i = 0; i < steps; i++) { | 
|  | x += dist/steps; | 
|  | SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25); | 
|  | if (i == steps/2) { | 
|  | fPath.moveTo(x, tmpY); | 
|  | } else { | 
|  | fPath.lineTo(x, tmpY); | 
|  | } | 
|  | } | 
|  |  | 
|  | { | 
|  | SkRect  oval; | 
|  | oval.set(SkIntToScalar(20), SkIntToScalar(30), | 
|  | SkIntToScalar(100), SkIntToScalar(60)); | 
|  | oval.offset(x, 0); | 
|  | fPath.addRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8)); | 
|  | } | 
|  |  | 
|  | fClickPt.set(SkIntToScalar(200), SkIntToScalar(200)); | 
|  |  | 
|  | this->setBGColor(0xFFDDDDDD); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | // overrides from SkEventSink | 
|  | virtual bool onQuery(SkEvent* evt) { | 
|  | if (SampleCode::TitleQ(*evt)) { | 
|  | SampleCode::TitleR(evt, "PathEffects"); | 
|  | return true; | 
|  | } | 
|  | return this->INHERITED::onQuery(evt); | 
|  | } | 
|  |  | 
|  | virtual void onDrawContent(SkCanvas* canvas) { | 
|  | gPhase -= SampleCode::GetAnimSecondsDelta() * 40; | 
|  | this->inval(NULL); | 
|  |  | 
|  | SkPaint paint; | 
|  |  | 
|  | #if 0 | 
|  | paint.setAntiAlias(true); | 
|  | paint.setStyle(SkPaint::kStroke_Style); | 
|  | paint.setStrokeWidth(SkIntToScalar(5)); | 
|  | canvas->drawPath(fPath, paint); | 
|  | paint.setStrokeWidth(0); | 
|  |  | 
|  | paint.setColor(SK_ColorWHITE); | 
|  | paint.setPathEffect(make_pe(1))->unref(); | 
|  | canvas->drawPath(fPath, paint); | 
|  | #endif | 
|  |  | 
|  | canvas->translate(0, SkIntToScalar(50)); | 
|  |  | 
|  | paint.setColor(SK_ColorBLUE); | 
|  | paint.setPathEffect(make_pe(2))->unref(); | 
|  | canvas->drawPath(fPath, paint); | 
|  |  | 
|  | canvas->translate(0, SkIntToScalar(50)); | 
|  |  | 
|  | paint.setARGB(0xFF, 0, 0xBB, 0); | 
|  | paint.setPathEffect(make_pe(3))->unref(); | 
|  | canvas->drawPath(fPath, paint); | 
|  |  | 
|  | canvas->translate(0, SkIntToScalar(50)); | 
|  |  | 
|  | paint.setARGB(0xFF, 0, 0, 0); | 
|  | paint.setPathEffect(make_warp_pe())->unref(); | 
|  | TestRastBuilder testRastBuilder; | 
|  | paint.setRasterizer(testRastBuilder.detachRasterizer())->unref(); | 
|  | canvas->drawPath(fPath, paint); | 
|  | } | 
|  |  | 
|  | private: | 
|  | typedef SampleView INHERITED; | 
|  | }; | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | static SkView* MyFactory() { return new PathEffectView; } | 
|  | static SkViewRegister reg(MyFactory); |