SampleClipDrawMatch.cpp revision 9cc2f2613a4fa27de2c6c79830433867c72d8cd5
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SampleCode.h" 9#include "SkCanvas.h" 10#include "SkInterpolator.h" 11#include "SkTime.h" 12 13// This slide tests out the match up between BW clipping and rendering. It can 14// draw a large rect through some clip geometry and draw the same geometry 15// normally. Which one is drawn first can be toggled. The pair of objects is translated 16// fractionally (via an animator) to expose snapping bugs. The key bindings are: 17// 1-9: the different geometries 18// t: toggle which is drawn first the clip or the normal geometry 19 20// The possible geometric combinations to test 21enum Geometry { 22 kRect_Geometry, 23 kRRect_Geometry, 24 kCircle_Geometry, 25 kConvexPath_Geometry, 26 kConcavePath_Geometry, 27 kRectAndRect_Geometry, 28 kRectAndRRect_Geometry, 29 kRectAndConvex_Geometry, 30 kRectAndConcave_Geometry 31}; 32 33// The basic rect used is [kMin,kMin]..[kMax,kMax] 34static const float kMin = 100.5f; 35static const float kMid = 200.0f; 36static const float kMax = 299.5f; 37 38SkRect create_rect(const SkPoint& offset) { 39 SkRect r = SkRect::MakeLTRB(kMin, kMin, kMax, kMax); 40 r.offset(offset); 41 return r; 42} 43 44SkRRect create_rrect(const SkPoint& offset) { 45 SkRRect rrect; 46 rrect.setRectXY(create_rect(offset), 10, 10); 47 return rrect; 48} 49 50SkRRect create_circle(const SkPoint& offset) { 51 SkRRect circle; 52 circle.setOval(create_rect(offset)); 53 return circle; 54} 55 56SkPath create_convex_path(const SkPoint& offset) { 57 SkPath convexPath; 58 convexPath.moveTo(kMin, kMin); 59 convexPath.lineTo(kMax, kMax); 60 convexPath.lineTo(kMin, kMax); 61 convexPath.close(); 62 convexPath.offset(offset.fX, offset.fY); 63 return convexPath; 64} 65 66SkPath create_concave_path(const SkPoint& offset) { 67 SkPath concavePath; 68 concavePath.moveTo(kMin, kMin); 69 concavePath.lineTo(kMid, 105.0f); 70 concavePath.lineTo(kMax, kMin); 71 concavePath.lineTo(295.0f, kMid); 72 concavePath.lineTo(kMax, kMax); 73 concavePath.lineTo(kMid, 295.0f); 74 concavePath.lineTo(kMin, kMax); 75 concavePath.lineTo(105.0f, kMid); 76 concavePath.close(); 77 78 concavePath.offset(offset.fX, offset.fY); 79 return concavePath; 80} 81 82static void draw_clipped_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) { 83 84 int count = canvas->save(); 85 86 switch (geom) { 87 case kRect_Geometry: 88 canvas->clipRect(create_rect(offset), SkRegion::kReplace_Op, useAA); 89 break; 90 case kRRect_Geometry: 91 canvas->clipRRect(create_rrect(offset), SkRegion::kReplace_Op, useAA); 92 break; 93 case kCircle_Geometry: 94 canvas->clipRRect(create_circle(offset), SkRegion::kReplace_Op, useAA); 95 break; 96 case kConvexPath_Geometry: 97 canvas->clipPath(create_convex_path(offset), SkRegion::kReplace_Op, useAA); 98 break; 99 case kConcavePath_Geometry: 100 canvas->clipPath(create_concave_path(offset), SkRegion::kReplace_Op, useAA); 101 break; 102 case kRectAndRect_Geometry: { 103 SkRect r = create_rect(offset); 104 r.offset(-100.0f, -100.0f); 105 canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips 106 canvas->clipRect(create_rect(offset), SkRegion::kIntersect_Op, useAA); 107 } break; 108 case kRectAndRRect_Geometry: { 109 SkRect r = create_rect(offset); 110 r.offset(-100.0f, -100.0f); 111 canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips 112 canvas->clipRRect(create_rrect(offset), SkRegion::kIntersect_Op, useAA); 113 } break; 114 case kRectAndConvex_Geometry: { 115 SkRect r = create_rect(offset); 116 r.offset(-100.0f, -100.0f); 117 canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips 118 canvas->clipPath(create_convex_path(offset), SkRegion::kIntersect_Op, useAA); 119 } break; 120 case kRectAndConcave_Geometry: { 121 SkRect r = create_rect(offset); 122 r.offset(-100.0f, -100.0f); 123 canvas->clipRect(r, SkRegion::kReplace_Op, true); // AA here forces shader clips 124 canvas->clipPath(create_concave_path(offset), SkRegion::kIntersect_Op, useAA); 125 } break; 126 } 127 128 SkISize size = canvas->getDeviceSize(); 129 SkRect bigR = SkRect::MakeWH(SkIntToScalar(size.width()), SkIntToScalar(size.height())); 130 131 SkPaint p; 132 p.setColor(SK_ColorRED); 133 134 canvas->drawRect(bigR, p); 135 canvas->restoreToCount(count); 136} 137 138static void draw_normal_geom(SkCanvas* canvas, const SkPoint& offset, int geom, bool useAA) { 139 SkPaint p; 140 p.setAntiAlias(useAA); 141 p.setColor(SK_ColorBLACK); 142 143 switch (geom) { 144 case kRect_Geometry: // fall thru 145 case kRectAndRect_Geometry: 146 canvas->drawRect(create_rect(offset), p); 147 break; 148 case kRRect_Geometry: // fall thru 149 case kRectAndRRect_Geometry: 150 canvas->drawRRect(create_rrect(offset), p); 151 break; 152 case kCircle_Geometry: 153 canvas->drawRRect(create_circle(offset), p); 154 break; 155 case kConvexPath_Geometry: // fall thru 156 case kRectAndConvex_Geometry: 157 canvas->drawPath(create_convex_path(offset), p); 158 break; 159 case kConcavePath_Geometry: // fall thru 160 case kRectAndConcave_Geometry: 161 canvas->drawPath(create_concave_path(offset), p); 162 break; 163 } 164} 165 166class ClipDrawMatchView : public SampleView { 167public: 168 ClipDrawMatchView() : fTrans(2, 5), fGeom(kRect_Geometry), fClipFirst(true) { 169 SkScalar values[2]; 170 171 fTrans.setRepeatCount(999); 172 values[0] = values[1] = 0; 173 fTrans.setKeyFrame(0, SkTime::GetMSecs() + 1000, values); 174 values[1] = 1; 175 fTrans.setKeyFrame(1, SkTime::GetMSecs() + 2000, values); 176 values[0] = values[1] = 1; 177 fTrans.setKeyFrame(2, SkTime::GetMSecs() + 3000, values); 178 values[1] = 0; 179 fTrans.setKeyFrame(3, SkTime::GetMSecs() + 4000, values); 180 values[0] = 0; 181 fTrans.setKeyFrame(4, SkTime::GetMSecs() + 5000, values); 182 } 183 184protected: 185 bool onQuery(SkEvent* evt) SK_OVERRIDE { 186 if (SampleCode::TitleQ(*evt)) { 187 SampleCode::TitleR(evt, "ClipDrawMatch"); 188 return true; 189 } 190 SkUnichar uni; 191 if (SampleCode::CharQ(*evt, &uni)) { 192 switch (uni) { 193 case '1': fGeom = kRect_Geometry; this->inval(NULL); return true; 194 case '2': fGeom = kRRect_Geometry; this->inval(NULL); return true; 195 case '3': fGeom = kCircle_Geometry; this->inval(NULL); return true; 196 case '4': fGeom = kConvexPath_Geometry; this->inval(NULL); return true; 197 case '5': fGeom = kConcavePath_Geometry; this->inval(NULL); return true; 198 case '6': fGeom = kRectAndRect_Geometry; this->inval(NULL); return true; 199 case '7': fGeom = kRectAndRRect_Geometry; this->inval(NULL); return true; 200 case '8': fGeom = kRectAndConvex_Geometry; this->inval(NULL); return true; 201 case '9': fGeom = kRectAndConcave_Geometry; this->inval(NULL); return true; 202 case 't': fClipFirst = !fClipFirst; this->inval(NULL); return true; 203 default: break; 204 } 205 } 206 return this->INHERITED::onQuery(evt); 207 } 208 209 // Draw a big red rect through some clip geometry and also draw that same 210 // geometry in black. The order in which they are drawn can be swapped. 211 // This tests whether the clip and normally drawn geometry match up. 212 void drawGeometry(SkCanvas* canvas, const SkPoint& offset, bool useAA) { 213 if (fClipFirst) { 214 draw_clipped_geom(canvas, offset, fGeom, useAA); 215 } 216 217 draw_normal_geom(canvas, offset, fGeom, useAA); 218 219 if (!fClipFirst) { 220 draw_clipped_geom(canvas, offset, fGeom, useAA); 221 } 222 } 223 224 void onDrawContent(SkCanvas* canvas) SK_OVERRIDE { 225 SkScalar trans[2]; 226 fTrans.timeToValues(SkTime::GetMSecs(), trans); 227 228 SkPoint offset; 229 offset.set(trans[0], trans[1]); 230 231 int saveCount = canvas->save(); 232 this->drawGeometry(canvas, offset, false); 233 canvas->restoreToCount(saveCount); 234 235 this->inval(NULL); 236 } 237 238private: 239 SkInterpolator fTrans; 240 Geometry fGeom; 241 bool fClipFirst; 242 243 typedef SampleView INHERITED; 244}; 245 246////////////////////////////////////////////////////////////////////////////// 247 248static SkView* MyFactory() { return new ClipDrawMatchView; } 249static SkViewRegister reg(MyFactory); 250