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