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