2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkBlurMask.h"
10 #include "SkBlurMaskFilter.h"
14 #define STROKE_WIDTH SkIntToScalar(10)
16 typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
18 static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
19 canvas->drawRect(r, p);
22 static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
27 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
30 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
33 path.setFillType(SkPath::kEvenOdd_FillType);
35 canvas->drawPath(path, p);
38 static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
43 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
46 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
51 path.setFillType(SkPath::kEvenOdd_FillType);
53 canvas->drawPath(path, p);
56 #include "SkGradientShader.h"
59 * Spits out a dummy gradient to test blur with shader on paint
61 static sk_sp<SkShader> MakeRadial() {
64 { SkIntToScalar(100), SkIntToScalar(100) }
66 SkShader::TileMode tm = SkShader::kClamp_TileMode;
67 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
68 const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
70 scale.setScale(0.5f, 0.5f);
71 scale.postTranslate(25.f, 25.f);
72 SkPoint center0, center1;
73 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
74 SkScalarAve(pts[0].fY, pts[1].fY));
75 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
76 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
77 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
78 center0, (pts[1].fX - pts[0].fX) / 2,
79 colors, pos, SK_ARRAY_COUNT(colors), tm,
83 typedef void (*PaintProc)(SkPaint*, SkScalar width);
85 class BlurRectGM : public skiagm::GM {
86 sk_sp<SkMaskFilter> fMaskFilters[kLastEnum_SkBlurStyle + 1];
90 BlurRectGM(const char name[], U8CPU alpha)
92 , fAlpha(SkToU8(alpha)) {
96 void onOnceBeforeDraw() override {
97 for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
98 fMaskFilters[i] = SkBlurMaskFilter::Make((SkBlurStyle)i,
99 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(STROKE_WIDTH/2)),
100 SkBlurMaskFilter::kHighQuality_BlurFlag);
104 SkString onShortName() override {
108 SkISize onISize() override {
109 return SkISize::Make(860, 820);
112 void onDraw(SkCanvas* canvas) override {
113 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
115 SkRect r = { 0, 0, 100, 50 };
116 SkScalar scales[] = { SK_Scalar1, 0.6f };
118 for (size_t s = 0; s < SK_ARRAY_COUNT(scales); ++s) {
120 for (size_t f = 0; f < SK_ARRAY_COUNT(fMaskFilters); ++f) {
122 paint.setMaskFilter(fMaskFilters[f]);
123 paint.setAlpha(fAlpha);
125 SkPaint paintWithRadial = paint;
126 paintWithRadial.setShader(MakeRadial());
128 constexpr Proc procs[] = {
129 fill_rect, draw_donut, draw_donut_skewed
133 canvas->scale(scales[s], scales[s]);
134 this->drawProcs(canvas, r, paint, false, procs, SK_ARRAY_COUNT(procs));
135 canvas->translate(r.width() * 4/3, 0);
136 this->drawProcs(canvas, r, paintWithRadial, false, procs, SK_ARRAY_COUNT(procs));
137 canvas->translate(r.width() * 4/3, 0);
138 this->drawProcs(canvas, r, paint, true, procs, SK_ARRAY_COUNT(procs));
139 canvas->translate(r.width() * 4/3, 0);
140 this->drawProcs(canvas, r, paintWithRadial, true, procs, SK_ARRAY_COUNT(procs));
143 canvas->translate(0, SK_ARRAY_COUNT(procs) * r.height() * 4/3 * scales[s]);
146 canvas->translate(4 * r.width() * 4/3 * scales[s], 0);
151 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
152 bool doClip, const Proc procs[], size_t procsCount) {
153 SkAutoCanvasRestore acr(canvas, true);
154 for (size_t i = 0; i < procsCount; ++i) {
157 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
161 procs[i](canvas, r, paint);
165 canvas->translate(0, r.height() * 4/3);
169 typedef GM INHERITED;
172 DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024) {
173 const int fGMWidth = 1200;
174 const int fPadding = 10;
175 const int fMargin = 100;
177 const int widths[] = {25, 5, 5, 100, 150, 25};
178 const int heights[] = {100, 100, 5, 25, 150, 25};
179 const SkBlurStyle styles[] = {kNormal_SkBlurStyle, kInner_SkBlurStyle, kOuter_SkBlurStyle};
180 const float radii[] = {20, 5, 10};
182 canvas->translate(50,20);
189 for (size_t i = 0 ; i < SK_ARRAY_COUNT(widths) ; i++) {
190 int width = widths[i];
191 int height = heights[i];
193 r.setWH(SkIntToScalar(width), SkIntToScalar(height));
194 SkAutoCanvasRestore autoRestore(canvas, true);
196 for (size_t j = 0 ; j < SK_ARRAY_COUNT(radii) ; j++) {
197 float radius = radii[j];
198 for (size_t k = 0 ; k < SK_ARRAY_COUNT(styles) ; k++) {
199 SkBlurStyle style = styles[k];
202 if (!SkBlurMask::BlurRect(SkBlurMask::ConvertRadiusToSigma(radius),
207 SkAutoMaskFreeImage amfi(mask.fImage);
210 bm.installMaskPixels(mask);
212 if (cur_x + bm.width() >= fGMWidth - fMargin) {
214 cur_y += max_height + fPadding;
219 canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
220 canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
221 canvas->drawBitmap(bm, 0.f, 0.f, nullptr);
224 cur_x += bm.width() + fPadding;
225 if (bm.height() > max_height)
226 max_height = bm.height();
232 //////////////////////////////////////////////////////////////////////////////
234 DEF_GM(return new BlurRectGM("blurrects", 0xFF);)