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