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 "SkCanvas.h" 10 #include "SkRRect.h" 11 #include "SkPath.h" 12 13 typedef void (*InsetProc)(const SkRRect&, SkScalar dx, SkScalar dy, SkRRect*); 14 15 static void inset0(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) { 16 SkRect r = src.rect(); 17 18 r.inset(dx, dy); 19 if (r.isEmpty()) { 20 dst->setEmpty(); 21 return; 22 } 23 24 SkVector radii[4]; 25 for (int i = 0; i < 4; ++i) { 26 radii[i] = src.radii((SkRRect::Corner)i); 27 } 28 for (int i = 0; i < 4; ++i) { 29 radii[i].fX -= dx; 30 radii[i].fY -= dy; 31 } 32 dst->setRectRadii(r, radii); 33 } 34 35 static void inset1(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) { 36 SkRect r = src.rect(); 37 38 r.inset(dx, dy); 39 if (r.isEmpty()) { 40 dst->setEmpty(); 41 return; 42 } 43 44 SkVector radii[4]; 45 for (int i = 0; i < 4; ++i) { 46 radii[i] = src.radii((SkRRect::Corner)i); 47 } 48 dst->setRectRadii(r, radii); 49 } 50 51 static void inset2(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) { 52 SkRect r = src.rect(); 53 54 r.inset(dx, dy); 55 if (r.isEmpty()) { 56 dst->setEmpty(); 57 return; 58 } 59 60 SkVector radii[4]; 61 for (int i = 0; i < 4; ++i) { 62 radii[i] = src.radii((SkRRect::Corner)i); 63 } 64 for (int i = 0; i < 4; ++i) { 65 if (radii[i].fX) { 66 radii[i].fX -= dx; 67 } 68 if (radii[i].fY) { 69 radii[i].fY -= dy; 70 } 71 } 72 dst->setRectRadii(r, radii); 73 } 74 75 static SkScalar prop(SkScalar radius, SkScalar newSize, SkScalar oldSize) { 76 return newSize * radius / oldSize; 77 } 78 79 static void inset3(const SkRRect& src, SkScalar dx, SkScalar dy, SkRRect* dst) { 80 SkRect r = src.rect(); 81 82 r.inset(dx, dy); 83 if (r.isEmpty()) { 84 dst->setEmpty(); 85 return; 86 } 87 88 SkVector radii[4]; 89 for (int i = 0; i < 4; ++i) { 90 radii[i] = src.radii((SkRRect::Corner)i); 91 } 92 for (int i = 0; i < 4; ++i) { 93 radii[i].fX = prop(radii[i].fX, r.width(), src.rect().width()); 94 radii[i].fY = prop(radii[i].fY, r.height(), src.rect().height()); 95 } 96 dst->setRectRadii(r, radii); 97 } 98 99 static void draw_rrect_color(SkCanvas* canvas, const SkRRect& rrect) { 100 SkPaint paint; 101 paint.setAntiAlias(true); 102 paint.setStyle(SkPaint::kStroke_Style); 103 104 if (rrect.isRect()) { 105 paint.setColor(SK_ColorRED); 106 } else if (rrect.isOval()) { 107 paint.setColor(0xFF008800); 108 } else if (rrect.isSimple()) { 109 paint.setColor(SK_ColorBLUE); 110 } else { 111 paint.setColor(SK_ColorBLACK); 112 } 113 canvas->drawRRect(rrect, paint); 114 } 115 116 static void drawrr(SkCanvas* canvas, const SkRRect& rrect, InsetProc proc) { 117 SkRRect rr; 118 for (SkScalar d = -30; d <= 30; d += 5) { 119 proc(rrect, d, d, &rr); 120 draw_rrect_color(canvas, rr); 121 } 122 } 123 124 class RRectGM : public skiagm::GM { 125 public: 126 RRectGM() {} 127 128 protected: 129 virtual uint32_t onGetFlags() const SK_OVERRIDE { 130 return kSkipTiled_Flag; 131 } 132 133 virtual SkString onShortName() { 134 return SkString("rrect"); 135 } 136 137 virtual SkISize onISize() { 138 return SkISize::Make(820, 710); 139 } 140 141 virtual void onDraw(SkCanvas* canvas) { 142 static const InsetProc insetProcs[] = { 143 inset0, inset1, inset2, inset3 144 }; 145 146 SkRRect rrect[4]; 147 SkRect r = { 0, 0, 120, 100 }; 148 SkVector radii[4] = { 149 { 0, 0 }, { 30, 1 }, { 10, 40 }, { 40, 40 } 150 }; 151 152 rrect[0].setRect(r); 153 rrect[1].setOval(r); 154 rrect[2].setRectXY(r, 20, 20); 155 rrect[3].setRectRadii(r, radii); 156 157 canvas->translate(50.5f, 50.5f); 158 for (size_t j = 0; j < SK_ARRAY_COUNT(insetProcs); ++j) { 159 canvas->save(); 160 for (size_t i = 0; i < SK_ARRAY_COUNT(rrect); ++i) { 161 drawrr(canvas, rrect[i], insetProcs[j]); 162 canvas->translate(200, 0); 163 } 164 canvas->restore(); 165 canvas->translate(0, 170); 166 } 167 } 168 169 private: 170 typedef GM INHERITED; 171 }; 172 173 DEF_GM( return new RRectGM; ) 174