1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SampleCode.h" 9 #include "SkView.h" 10 #include "SkCanvas.h" 11 #include "SkCornerPathEffect.h" 12 #include "SkCullPoints.h" 13 #include "SkGradientShader.h" 14 #include "SkPath.h" 15 #include "SkRegion.h" 16 #include "SkShader.h" 17 #include "SkUtils.h" 18 #include "SkRandom.h" 19 20 static void addbump(SkPath* path, const SkPoint pts[2], SkScalar bump) { 21 SkVector tang; 22 23 tang.setLength(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY, bump); 24 25 path->lineTo(SkScalarHalf(pts[0].fX + pts[1].fX) - tang.fY, 26 SkScalarHalf(pts[0].fY + pts[1].fY) + tang.fX); 27 path->lineTo(pts[1]); 28 } 29 30 static void subdivide(SkPath* path, SkScalar bump) { 31 SkPath::Iter iter(*path, false); 32 SkPoint pts[4]; 33 SkPath tmp; 34 35 for (;;) 36 switch (iter.next(pts)) { 37 case SkPath::kMove_Verb: 38 tmp.moveTo(pts[0]); 39 break; 40 case SkPath::kLine_Verb: 41 addbump(&tmp, pts, bump); 42 bump = -bump; 43 break; 44 case SkPath::kDone_Verb: 45 goto FINISH; 46 default: 47 break; 48 } 49 50 FINISH: 51 path->swap(tmp); 52 } 53 54 static SkIPoint* getpts(const SkPath& path, int* count) { 55 SkPoint pts[4]; 56 int n = 1; 57 SkIPoint* array; 58 59 { 60 SkPath::Iter iter(path, false); 61 for (;;) 62 switch (iter.next(pts)) { 63 case SkPath::kLine_Verb: 64 n += 1; 65 break; 66 case SkPath::kDone_Verb: 67 goto FINISHED; 68 default: 69 break; 70 } 71 } 72 73 FINISHED: 74 array = new SkIPoint[n]; 75 n = 0; 76 77 { 78 SkPath::Iter iter(path, false); 79 for (;;) 80 switch (iter.next(pts)) { 81 case SkPath::kMove_Verb: 82 array[n++].set(SkScalarRoundToInt(pts[0].fX), 83 SkScalarRoundToInt(pts[0].fY)); 84 break; 85 case SkPath::kLine_Verb: 86 array[n++].set(SkScalarRoundToInt(pts[1].fX), 87 SkScalarRoundToInt(pts[1].fY)); 88 break; 89 case SkPath::kDone_Verb: 90 goto FINISHED2; 91 default: 92 break; 93 } 94 } 95 96 FINISHED2: 97 *count = n; 98 return array; 99 } 100 101 static SkScalar nextScalarRange(SkRandom& rand, SkScalar min, SkScalar max) { 102 return min + SkScalarMul(rand.nextUScalar1(), max - min); 103 } 104 105 class CullView : public SampleView { 106 public: 107 CullView() { 108 fClip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160)); 109 110 SkRandom rand; 111 112 for (int i = 0; i < 50; i++) { 113 SkScalar x = nextScalarRange(rand, -fClip.width()*1, fClip.width()*2); 114 SkScalar y = nextScalarRange(rand, -fClip.height()*1, fClip.height()*2); 115 if (i == 0) 116 fPath.moveTo(x, y); 117 else 118 fPath.lineTo(x, y); 119 } 120 121 SkScalar bump = fClip.width()/8; 122 subdivide(&fPath, bump); 123 subdivide(&fPath, bump); 124 subdivide(&fPath, bump); 125 fPoints = getpts(fPath, &fPtCount); 126 127 this->setBGColor(0xFFDDDDDD); 128 } 129 130 virtual ~CullView() { 131 delete[] fPoints; 132 } 133 134 protected: 135 // overrides from SkEventSink 136 virtual bool onQuery(SkEvent* evt) { 137 if (SampleCode::TitleQ(*evt)) { 138 SampleCode::TitleR(evt, "Culling"); 139 return true; 140 } 141 return this->INHERITED::onQuery(evt); 142 } 143 144 virtual void onDrawContent(SkCanvas* canvas) { 145 SkAutoCanvasRestore ar(canvas, true); 146 147 canvas->translate( SkScalarHalf(this->width() - fClip.width()), 148 SkScalarHalf(this->height() - fClip.height())); 149 150 // canvas->scale(SK_Scalar1*3, SK_Scalar1*3, 0, 0); 151 152 SkPaint paint; 153 154 // paint.setAntiAliasOn(true); 155 paint.setStyle(SkPaint::kStroke_Style); 156 157 canvas->drawRect(fClip, paint); 158 159 #if 1 160 paint.setColor(0xFF555555); 161 paint.setStrokeWidth(SkIntToScalar(2)); 162 // paint.setPathEffect(new SkCornerPathEffect(SkIntToScalar(30)))->unref(); 163 canvas->drawPath(fPath, paint); 164 // paint.setPathEffect(NULL); 165 #endif 166 167 SkPath tmp; 168 SkIRect iclip; 169 fClip.round(&iclip); 170 171 SkCullPointsPath cpp(iclip, &tmp); 172 173 cpp.moveTo(fPoints[0].fX, fPoints[0].fY); 174 for (int i = 0; i < fPtCount; i++) 175 cpp.lineTo(fPoints[i].fX, fPoints[i].fY); 176 177 paint.setColor(SK_ColorRED); 178 paint.setStrokeWidth(SkIntToScalar(3)); 179 paint.setStrokeJoin(SkPaint::kRound_Join); 180 canvas->drawPath(tmp, paint); 181 182 this->inval(NULL); 183 } 184 185 private: 186 SkRect fClip; 187 SkIPoint* fPoints; 188 SkPath fPath; 189 int fPtCount; 190 191 typedef SampleView INHERITED; 192 }; 193 194 ////////////////////////////////////////////////////////////////////////////// 195 196 static SkView* MyFactory() { return new CullView; } 197 static SkViewRegister reg(MyFactory); 198