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 "SkGradientShader.h" 12#include "SkGraphics.h" 13#include "SkImageDecoder.h" 14#include "SkPath.h" 15#include "SkRegion.h" 16#include "SkShader.h" 17#include "SkUtils.h" 18#include "SkXfermode.h" 19#include "SkColorPriv.h" 20#include "SkColorFilter.h" 21#include "SkTime.h" 22#include "SkRandom.h" 23 24#include "SkLineClipper.h" 25#include "SkEdgeClipper.h" 26 27#define AUTO_ANIMATE true 28 29static int test0(SkPoint pts[], SkRect* clip) { 30 pts[0].set(200000, 140); 31 pts[1].set(-740000, 483); 32 pts[2].set(1.00000102e-06f, 9.10000017e-05f); 33 clip->set(0, 0, 640, 480); 34 return 2; 35} 36 37/////////////////////////////////////////////////////////////////////////////// 38 39static void drawQuad(SkCanvas* canvas, const SkPoint pts[3], const SkPaint& p) { 40 SkPath path; 41 path.moveTo(pts[0]); 42 path.quadTo(pts[1], pts[2]); 43 canvas->drawPath(path, p); 44} 45 46static void drawCubic(SkCanvas* canvas, const SkPoint pts[4], const SkPaint& p) { 47 SkPath path; 48 path.moveTo(pts[0]); 49 path.cubicTo(pts[1], pts[2], pts[3]); 50 canvas->drawPath(path, p); 51} 52 53typedef void (*clipper_proc)(const SkPoint src[], const SkRect& clip, 54 SkCanvas*, const SkPaint&, const SkPaint&); 55 56static void check_clipper(int count, const SkPoint pts[], const SkRect& clip) { 57 for (int i = 0; i < count; i++) { 58 SkASSERT(pts[i].fX >= clip.fLeft); 59 SkASSERT(pts[i].fX <= clip.fRight); 60 SkASSERT(pts[i].fY >= clip.fTop); 61 SkASSERT(pts[i].fY <= clip.fBottom); 62 } 63 64 if (count > 1) { 65 sk_assert_monotonic_y(pts, count); 66 } 67} 68 69static void line_intersector(const SkPoint src[], const SkRect& clip, 70 SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) { 71 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1); 72 73 SkPoint dst[2]; 74 if (SkLineClipper::IntersectLine(src, clip, dst)) { 75 check_clipper(2, dst, clip); 76 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, dst, p0); 77 } 78} 79 80static void line_clipper(const SkPoint src[], const SkRect& clip, 81 SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) { 82 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, src, p1); 83 84 SkPoint dst[SkLineClipper::kMaxPoints]; 85 int count = SkLineClipper::ClipLine(src, clip, dst); 86 for (int i = 0; i < count; i++) { 87 check_clipper(2, &dst[i], clip); 88 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, &dst[i], p0); 89 } 90} 91 92static void quad_clipper(const SkPoint src[], const SkRect& clip, 93 SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) { 94 drawQuad(canvas, src, p1); 95 96 SkEdgeClipper clipper; 97 if (clipper.clipQuad(src, clip)) { 98 SkPoint pts[4]; 99 SkPath::Verb verb; 100 while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) { 101 switch (verb) { 102 case SkPath::kLine_Verb: 103 check_clipper(2, pts, clip); 104 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0); 105 break; 106 case SkPath::kQuad_Verb: 107 check_clipper(3, pts, clip); 108 drawQuad(canvas, pts, p0); 109 break; 110 default: 111 SkASSERT(!"unexpected verb"); 112 } 113 } 114 } 115} 116 117static void cubic_clipper(const SkPoint src[], const SkRect& clip, 118 SkCanvas* canvas, const SkPaint& p0, const SkPaint& p1) { 119 drawCubic(canvas, src, p1); 120 121 SkEdgeClipper clipper; 122 if (clipper.clipCubic(src, clip)) { 123 SkPoint pts[4]; 124 SkPath::Verb verb; 125 while ((verb = clipper.next(pts)) != SkPath::kDone_Verb) { 126 switch (verb) { 127 case SkPath::kLine_Verb: 128 check_clipper(2, pts, clip); 129 canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p0); 130 break; 131 case SkPath::kCubic_Verb: 132 // check_clipper(4, pts, clip); 133 drawCubic(canvas, pts, p0); 134 break; 135 default: 136 SkASSERT(!"unexpected verb"); 137 } 138 } 139 } 140} 141 142static const clipper_proc gProcs[] = { 143 line_intersector, 144 line_clipper, 145 quad_clipper, 146 cubic_clipper 147}; 148 149/////////////////////////////////////////////////////////////////////////////// 150 151enum { 152 W = 640/3, 153 H = 480/3 154}; 155 156class LineClipperView : public SampleView { 157 SkMSec fNow; 158 int fCounter; 159 int fProcIndex; 160 SkRect fClip; 161 SkRandom fRand; 162 SkPoint fPts[4]; 163 164 void randPts() { 165 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); i++) { 166 fPts[i].set(fRand.nextUScalar1() * 640, 167 fRand.nextUScalar1() * 480); 168 } 169 fCounter += 1; 170 } 171 172public: 173 LineClipperView() { 174 fProcIndex = 0; 175 fCounter = 0; 176 fNow = 0; 177 178 int x = (640 - W)/2; 179 int y = (480 - H)/2; 180 fClip.set(SkIntToScalar(x), SkIntToScalar(y), 181 SkIntToScalar(x + W), SkIntToScalar(y + H)); 182 this->randPts(); 183 } 184 185protected: 186 // overrides from SkEventSink 187 virtual bool onQuery(SkEvent* evt) { 188 if (SampleCode::TitleQ(*evt)) { 189 SampleCode::TitleR(evt, "LineClipper"); 190 return true; 191 } 192 return this->INHERITED::onQuery(evt); 193 } 194 195 static void drawVLine(SkCanvas* canvas, SkScalar x, const SkPaint& paint) { 196 canvas->drawLine(x, -999, x, 999, paint); 197 } 198 199 static void drawHLine(SkCanvas* canvas, SkScalar y, const SkPaint& paint) { 200 canvas->drawLine(-999, y, 999, y, paint); 201 } 202 203 virtual void onDrawContent(SkCanvas* canvas) { 204 SkMSec now = SampleCode::GetAnimTime(); 205 if (fNow != now) { 206 fNow = now; 207 this->randPts(); 208 this->inval(NULL); 209 } 210 211 // fProcIndex = test0(fPts, &fClip); 212 213 SkPaint paint, paint1; 214 215 drawVLine(canvas, fClip.fLeft + SK_ScalarHalf, paint); 216 drawVLine(canvas, fClip.fRight - SK_ScalarHalf, paint); 217 drawHLine(canvas, fClip.fTop + SK_ScalarHalf, paint); 218 drawHLine(canvas, fClip.fBottom - SK_ScalarHalf, paint); 219 220 paint.setColor(SK_ColorLTGRAY); 221 canvas->drawRect(fClip, paint); 222 223 paint.setAntiAlias(true); 224 paint.setColor(SK_ColorBLUE); 225 paint.setStyle(SkPaint::kStroke_Style); 226 // paint.setStrokeWidth(SkIntToScalar(3)); 227 paint.setStrokeCap(SkPaint::kRound_Cap); 228 229 paint1.setAntiAlias(true); 230 paint1.setColor(SK_ColorRED); 231 paint1.setStyle(SkPaint::kStroke_Style); 232 gProcs[fProcIndex](fPts, fClip, canvas, paint, paint1); 233 this->inval(NULL); 234 } 235 236 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { 237 // fProcIndex = (fProcIndex + 1) % SK_ARRAY_COUNT(gProcs); 238 if (x < 50 && y < 50) { 239 this->randPts(); 240 } 241 this->inval(NULL); 242 return NULL; 243 } 244 245 virtual bool onClick(Click* click) { 246 return false; 247 } 248 249private: 250 typedef SampleView INHERITED; 251}; 252 253////////////////////////////////////////////////////////////////////////////// 254 255static SkView* MyFactory() { return new LineClipperView; } 256static SkViewRegister reg(MyFactory); 257 258