1 /* 2 * Copyright 2012 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 "gm.h" 9 #include "SkRRect.h" 10 11 namespace skiagm { 12 13 /////////////////////////////////////////////////////////////////////////////// 14 15 class RRectGM : public GM { 16 public: 17 RRectGM(bool doAA, bool doClip) : fDoAA(doAA), fDoClip(doClip) { 18 this->setBGColor(0xFFDDDDDD); 19 this->setUpRRects(); 20 } 21 22 protected: 23 SkString onShortName() { 24 SkString name("rrect"); 25 if (fDoClip) { 26 name.append("_clip"); 27 } 28 if (fDoAA) { 29 name.append("_aa"); 30 } else { 31 name.append("_bw"); 32 } 33 34 return name; 35 } 36 37 virtual SkISize onISize() { return make_isize(kImageWidth, kImageHeight); } 38 39 virtual void onDraw(SkCanvas* canvas) { 40 41 SkPaint paint; 42 // when clipping the AA is pushed into the clip operation 43 paint.setAntiAlias(fDoClip ? false : fDoAA); 44 45 static const SkRect kMaxTileBound = SkRect::MakeWH(SkIntToScalar(kTileX), SkIntToScalar(kTileY)); 46 47 int curRRect = 0; 48 for (int y = 1; y < kImageHeight; y += kTileY) { 49 for (int x = 1; x < kImageWidth; x += kTileX) { 50 if (curRRect >= kNumRRects) { 51 break; 52 } 53 SkASSERT(kMaxTileBound.contains(fRRects[curRRect].getBounds())); 54 55 canvas->save(); 56 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 57 if (fDoClip) { 58 canvas->clipRRect(fRRects[curRRect], SkRegion::kReplace_Op, fDoAA); 59 canvas->drawRect(kMaxTileBound, paint); 60 } else { 61 canvas->drawRRect(fRRects[curRRect], paint); 62 } 63 ++curRRect; 64 canvas->restore(); 65 } 66 } 67 } 68 69 void setUpRRects() { 70 // each RRect must fit in a 0x0 -> (kTileX-2)x(kTileY-2) block. These will be tiled across 71 // the screen in kTileX x kTileY tiles. The extra empty pixels on each side are for AA. 72 73 // simple cases 74 fRRects[0].setRect(SkRect::MakeWH(kTileX-2, kTileY-2)); 75 fRRects[1].setOval(SkRect::MakeWH(kTileX-2, kTileY-2)); 76 fRRects[2].setRectXY(SkRect::MakeWH(kTileX-2, kTileY-2), 10, 10); 77 78 // The first complex case needs special handling since it is a square 79 fRRects[kNumSimpleCases].setRectRadii(SkRect::MakeWH(kTileY-2, kTileY-2), gRadii[0]); 80 for (size_t i = 1; i < SK_ARRAY_COUNT(gRadii); ++i) { 81 fRRects[kNumSimpleCases+i].setRectRadii(SkRect::MakeWH(kTileX-2, kTileY-2), gRadii[i]); 82 } 83 } 84 85 private: 86 bool fDoAA; 87 bool fDoClip; // use clipRRect & drawRect instead of drawRRect 88 89 static const int kImageWidth = 640; 90 static const int kImageHeight = 480; 91 92 static const int kTileX = 80; 93 static const int kTileY = 40; 94 95 static const int kNumSimpleCases = 3; 96 static const int kNumComplexCases = 19; 97 static const SkVector gRadii[kNumComplexCases][4]; 98 99 static const int kNumRRects = kNumSimpleCases + kNumComplexCases; 100 SkRRect fRRects[kNumRRects]; 101 102 typedef GM INHERITED; 103 }; 104 105 // Radii for the various test cases. Order is UL, UR, LR, LL 106 const SkVector RRectGM::gRadii[kNumComplexCases][4] = { 107 // a circle 108 { { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY }, { kTileY, kTileY } }, 109 110 // odd ball cases 111 { { 8, 8 }, { 32, 32 }, { 8, 8 }, { 32, 32 } }, 112 { { 16, 8 }, { 8, 16 }, { 16, 8 }, { 8, 16 } }, 113 { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 32, 32 } }, 114 115 // UL 116 { { 30, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 117 { { 30, 15 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 118 { { 15, 30 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, 119 120 // UR 121 { { 0, 0 }, { 30, 30 }, { 0, 0 }, { 0, 0 } }, 122 { { 0, 0 }, { 30, 15 }, { 0, 0 }, { 0, 0 } }, 123 { { 0, 0 }, { 15, 30 }, { 0, 0 }, { 0, 0 } }, 124 125 // LR 126 { { 0, 0 }, { 0, 0 }, { 30, 30 }, { 0, 0 } }, 127 { { 0, 0 }, { 0, 0 }, { 30, 15 }, { 0, 0 } }, 128 { { 0, 0 }, { 0, 0 }, { 15, 30 }, { 0, 0 } }, 129 130 // LL 131 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 30 } }, 132 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 30, 15 } }, 133 { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 15, 30 } }, 134 135 // over-sized radii 136 { { 0, 0 }, { 100, 400 }, { 0, 0 }, { 0, 0 } }, 137 { { 0, 0 }, { 400, 400 }, { 0, 0 }, { 0, 0 } }, 138 { { 400, 400 }, { 400, 400 }, { 400, 400 }, { 400, 400 } }, 139 }; 140 141 /////////////////////////////////////////////////////////////////////////////// 142 143 DEF_GM( return new RRectGM(false, false); ) 144 DEF_GM( return new RRectGM(true, false); ) 145 DEF_GM( return new RRectGM(false, true); ) 146 DEF_GM( return new RRectGM(true, true); ) 147 148 } 149