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(sk_tool_utils::color_to_565(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 130 SkString onShortName() override { 131 return SkString("rrect"); 132 } 133 134 SkISize onISize() override { 135 return SkISize::Make(820, 710); 136 } 137 138 void onDraw(SkCanvas* canvas) override { 139 static const InsetProc insetProcs[] = { 140 inset0, inset1, inset2, inset3 141 }; 142 143 SkRRect rrect[4]; 144 SkRect r = { 0, 0, 120, 100 }; 145 SkVector radii[4] = { 146 { 0, 0 }, { 30, 1 }, { 10, 40 }, { 40, 40 } 147 }; 148 149 rrect[0].setRect(r); 150 rrect[1].setOval(r); 151 rrect[2].setRectXY(r, 20, 20); 152 rrect[3].setRectRadii(r, radii); 153 154 canvas->translate(50.5f, 50.5f); 155 for (size_t j = 0; j < SK_ARRAY_COUNT(insetProcs); ++j) { 156 canvas->save(); 157 for (size_t i = 0; i < SK_ARRAY_COUNT(rrect); ++i) { 158 drawrr(canvas, rrect[i], insetProcs[j]); 159 canvas->translate(200, 0); 160 } 161 canvas->restore(); 162 canvas->translate(0, 170); 163 } 164 } 165 166 private: 167 typedef GM INHERITED; 168 }; 169 170 DEF_GM( return new RRectGM; ) 171