1 /* 2 * Copyright 2011 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/SkBlurTypes.h" 10 #include "include/core/SkCanvas.h" 11 #include "include/core/SkColor.h" 12 #include "include/core/SkColorFilter.h" 13 #include "include/core/SkFont.h" 14 #include "include/core/SkMaskFilter.h" 15 #include "include/core/SkPaint.h" 16 #include "include/core/SkPathBuilder.h" 17 #include "include/core/SkRect.h" 18 #include "include/core/SkRefCnt.h" 19 #include "include/core/SkScalar.h" 20 #include "include/core/SkTypeface.h" 21 #include "include/core/SkTypes.h" 22 #include "include/effects/SkImageFilters.h" 23 #include "src/core/SkBlurMask.h" 24 #include "tools/DecodeUtils.h" 25 #include "tools/Resources.h" 26 #include "tools/ToolUtils.h" 27 #include "tools/fonts/FontToolUtils.h" 28 29 DEF_SIMPLE_GM_BG(blurs, canvas, 700, 500, 0xFFDDDDDD) { 30 SkBlurStyle NONE = SkBlurStyle(-999); 31 const struct { 32 SkBlurStyle fStyle; 33 int fCx, fCy; 34 } gRecs[] = { 35 { NONE, 0, 0 }, 36 { kInner_SkBlurStyle, -1, 0 }, 37 { kNormal_SkBlurStyle, 0, 1 }, 38 { kSolid_SkBlurStyle, 0, -1 }, 39 { kOuter_SkBlurStyle, 1, 0 }, 40 }; 41 42 SkPaint paint; 43 paint.setAntiAlias(true); 44 paint.setColor(SK_ColorBLUE); 45 46 canvas->translate(SkIntToScalar(-40), SkIntToScalar(0)); 47 48 for (size_t i = 0; i < std::size(gRecs); i++) { 49 if (gRecs[i].fStyle != NONE) { 50 paint.setMaskFilter(SkMaskFilter::MakeBlur(gRecs[i].fStyle, 51 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(20)))); 52 } else { 53 paint.setMaskFilter(nullptr); 54 } 55 canvas->drawCircle(SkIntToScalar(200 + gRecs[i].fCx*100), 56 SkIntToScalar(200 + gRecs[i].fCy*100), 57 SkIntToScalar(50), 58 paint); 59 } 60 // draw text 61 { 62 SkFont font(ToolUtils::DefaultPortableTypeface(), 25); 63 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 64 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(4)))); 65 SkScalar x = SkIntToScalar(70); 66 SkScalar y = SkIntToScalar(400); 67 paint.setColor(SK_ColorBLACK); 68 canvas->drawString("Hamburgefons Style", x, y, font, paint); 69 canvas->drawString("Hamburgefons Style", 70 x, y + SkIntToScalar(50), font, paint); 71 paint.setMaskFilter(nullptr); 72 paint.setColor(SK_ColorWHITE); 73 x -= SkIntToScalar(2); 74 y -= SkIntToScalar(2); 75 canvas->drawString("Hamburgefons Style", x, y, font, paint); 76 } 77 } 78 79 ////////////////////////////////////////////////////////////////////////////////////////////// 80 81 // exercise a special-case of blurs, which is two nested rects. These are drawn specially, 82 // and possibly cached. 83 // 84 // in particular, we want to notice that the 2nd rect draws slightly differently, since it 85 // is translated a fractional amount. 86 // 87 DEF_SIMPLE_GM(blur2rects, canvas, 700, 500) { 88 SkPaint paint; 89 90 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 2.3f)); 91 92 SkRect outer = SkRect::MakeXYWH(10.125f, 10.125f, 100.125f, 100); 93 SkRect inner = SkRect::MakeXYWH(20.25f, 20.125f, 80, 80); 94 SkPath path = SkPathBuilder().addRect(outer, SkPathDirection::kCW) 95 .addRect(inner, SkPathDirection::kCCW) 96 .detach(); 97 98 canvas->drawPath(path, paint); 99 // important to translate by a factional amount to exercise a different "phase" 100 // of the same path w.r.t. the pixel grid 101 SkScalar dx = SkScalarRoundToScalar(path.getBounds().width()) + 14 + 0.25f; 102 canvas->translate(dx, 0); 103 canvas->drawPath(path, paint); 104 } 105 106 DEF_SIMPLE_GM(blur2rectsnonninepatch, canvas, 700, 500) { 107 SkPaint paint; 108 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 4.3f)); 109 110 SkRect outer = SkRect::MakeXYWH(10, 110, 100, 100); 111 SkRect inner = SkRect::MakeXYWH(50, 150, 10, 10); 112 SkPath path = SkPathBuilder().addRect(outer, SkPathDirection::kCW) 113 .addRect(inner, SkPathDirection::kCW) 114 .detach(); 115 canvas->drawPath(path, paint); 116 117 SkScalar dx = SkScalarRoundToScalar(path.getBounds().width()) + 40 + 0.25f; 118 canvas->translate(dx, 0); 119 canvas->drawPath(path, paint); 120 121 // Translate to outside of clip bounds. 122 canvas->translate(-dx, 0); 123 canvas->translate(-30, -150); 124 canvas->drawPath(path, paint); 125 } 126 127 DEF_SIMPLE_GM(BlurDrawImage, canvas, 256, 256) { 128 SkPaint paint; 129 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10)); 130 canvas->clear(0xFF88FF88); 131 if (auto image = ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg")) { 132 canvas->scale(0.25, 0.25); 133 canvas->drawImage(image, 256, 256, SkSamplingOptions(), &paint); 134 } 135 } 136 137 DEF_SIMPLE_GM(BlurBigSigma, canvas, 1024, 1024) { 138 SkPaint layerPaint, p; 139 140 p.setImageFilter(SkImageFilters::Blur(500, 500, nullptr)); 141 142 canvas->drawRect(SkRect::MakeWH(700, 800), p); 143 } 144 145 DEF_SIMPLE_GM(BlurSmallSigma, canvas, 512, 256) { 146 { 147 // Normal sigma on x-axis, a small but non-zero sigma on y-axis that should 148 // be treated as identity. 149 SkPaint paint; 150 paint.setImageFilter(SkImageFilters::Blur(16.f, 1e-5f, nullptr)); 151 canvas->drawRect(SkRect::MakeLTRB(64, 64, 192, 192), paint); 152 } 153 154 { 155 // Small sigma on both axes, should be treated as identity and no red should show 156 SkPaint paint; 157 paint.setColor(SK_ColorRED); 158 SkRect rect = SkRect::MakeLTRB(320, 64, 448, 192); 159 canvas->drawRect(rect, paint); 160 paint.setColor(SK_ColorBLACK); 161 paint.setImageFilter(SkImageFilters::Blur(1e-5f, 1e-5f, nullptr)); 162 canvas->drawRect(rect, paint); 163 } 164 } 165 166 // Modeled after crbug.com/1500021, incorporates manual tiling to emulate Chrome's raster tiles 167 // or the tiled rendering mode in Viewer. 168 DEF_SIMPLE_GM(TiledBlurBigSigma, canvas, 1024, 768) { 169 static constexpr int kTileWidth = 342; 170 static constexpr int kTileHeight = 256; 171 172 SkM44 origCTM = canvas->getLocalToDevice(); 173 174 for (int y = 0; y < 3; ++y) { 175 for (int x = 0; x < 3; ++x) { 176 // Define tiled grid in the canvas pixel space 177 canvas->save(); 178 canvas->resetMatrix(); 179 180 canvas->clipIRect(SkIRect::MakeXYWH(x*kTileWidth, y*kTileHeight, 181 kTileWidth, kTileHeight)); 182 canvas->setMatrix(origCTM); 183 184 auto flood = SkImageFilters::ColorFilter(SkColorFilters::Blend( 185 SK_ColorBLACK, SkBlendMode::kSrc), nullptr); 186 auto blend = SkImageFilters::Blend(SkBlendMode::kSrcOver, 187 std::move(flood), nullptr); 188 auto blur = SkImageFilters::Blur(206.f, 206.f, std::move(blend)); 189 190 SkPaint p; 191 p.setImageFilter(std::move(blur)); 192 193 canvas->clipRect({0, 0, 1970, 1223}); 194 canvas->saveLayer(nullptr, &p); 195 SkPaint fill; 196 fill.setColor(SK_ColorBLUE); 197 canvas->drawCircle(600, 150, 350, fill); 198 canvas->restore(); 199 canvas->restore(); 200 } 201 } 202 } 203