OLD | NEW |
(Empty) | |
| 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 tra
nslated |
| 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 |
| 21 enum 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] |
| 34 static const float kMin = 100.5f; |
| 35 static const float kMid = 200.0f; |
| 36 static const float kMax = 299.5f; |
| 37 |
| 38 SkRect create_rect(const SkPoint& offset) { |
| 39 SkRect r = SkRect::MakeLTRB(kMin, kMin, kMax, kMax); |
| 40 r.offset(offset); |
| 41 return r; |
| 42 } |
| 43 |
| 44 SkRRect create_rrect(const SkPoint& offset) { |
| 45 SkRRect rrect; |
| 46 rrect.setRectXY(create_rect(offset), 10, 10); |
| 47 return rrect; |
| 48 } |
| 49 |
| 50 SkRRect create_circle(const SkPoint& offset) { |
| 51 SkRRect circle; |
| 52 circle.setOval(create_rect(offset)); |
| 53 return circle; |
| 54 } |
| 55 |
| 56 SkPath 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 |
| 66 SkPath 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 |
| 82 static 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, useA
A); |
| 98 break; |
| 99 case kConcavePath_Geometry: |
| 100 canvas->clipPath(create_concave_path(offset), SkRegion::kReplace_Op, use
AA); |
| 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 shad
er 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 shad
er 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 shad
er clips |
| 118 canvas->clipPath(create_convex_path(offset), SkRegion::kIntersect_Op, us
eAA); |
| 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 shad
er clips |
| 124 canvas->clipPath(create_concave_path(offset), SkRegion::kIntersect_Op, u
seAA); |
| 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 |
| 138 static 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 |
| 166 class ClipDrawMatchView : public SampleView { |
| 167 public: |
| 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 |
| 184 protected: |
| 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 tru
e; |
| 195 case '3': fGeom = kCircle_Geometry; this->inval(NULL); return tr
ue; |
| 196 case '4': fGeom = kConvexPath_Geometry; this->inval(NULL); retur
n true; |
| 197 case '5': fGeom = kConcavePath_Geometry; this->inval(NULL); retu
rn true; |
| 198 case '6': fGeom = kRectAndRect_Geometry; this->inval(NULL); retu
rn true; |
| 199 case '7': fGeom = kRectAndRRect_Geometry; this->inval(NULL); ret
urn true; |
| 200 case '8': fGeom = kRectAndConvex_Geometry; this->inval(NULL); re
turn true; |
| 201 case '9': fGeom = kRectAndConcave_Geometry; this->inval(NULL); r
eturn true; |
| 202 case 't': fClipFirst = !fClipFirst; this->inval(NULL); return tr
ue; |
| 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 |
| 238 private: |
| 239 SkInterpolator fTrans; |
| 240 Geometry fGeom; |
| 241 bool fClipFirst; |
| 242 |
| 243 typedef SampleView INHERITED; |
| 244 }; |
| 245 |
| 246 ////////////////////////////////////////////////////////////////////////////// |
| 247 |
| 248 static SkView* MyFactory() { return new ClipDrawMatchView; } |
| 249 static SkViewRegister reg(MyFactory); |
OLD | NEW |