1 /* 2 * Copyright 2014 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/SkBitmap.h" 10 #include "include/core/SkCanvas.h" 11 #include "include/core/SkColor.h" 12 #include "include/core/SkColorFilter.h" 13 #include "include/core/SkImage.h" 14 #include "include/core/SkImageFilter.h" 15 #include "include/core/SkPaint.h" 16 #include "include/core/SkPoint.h" 17 #include "include/core/SkPoint3.h" 18 #include "include/core/SkRect.h" 19 #include "include/core/SkRefCnt.h" 20 #include "include/core/SkScalar.h" 21 #include "include/core/SkShader.h" 22 #include "include/core/SkSurface.h" 23 #include "include/core/SkTileMode.h" 24 #include "include/effects/SkGradientShader.h" 25 #include "include/effects/SkImageFilters.h" 26 27 #include <utility> 28 29 namespace { 30 31 sk_sp<SkImage> make_checkerboard(); 32 sk_sp<SkImage> make_gradient_circle(int width, int height); 33 void draw(SkCanvas*, sk_sp<SkImage>, const SkIRect&, sk_sp<SkImageFilter>); 34 35 } // namespace 36 37 /////////////////////////////////////////////////////////////////////////////// 38 39 DEF_SIMPLE_GM(imagefilterscropexpand, canvas, 730, 650) { 40 SkIRect cropRect = SkIRect::MakeXYWH(10, 10, 44, 44); 41 42 sk_sp<SkImage> gradientCircle(make_gradient_circle(64, 64)); 43 auto checkerboard = make_checkerboard(); 44 45 sk_sp<SkImageFilter> gradientCircleSource(SkImageFilters::Image(std::move(gradientCircle))); 46 sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect)); 47 // This color matrix saturates the green component but only partly increases the opacity. 48 // For the opaque checkerboard, the opacity boost doesn't matter but it does impact the 49 // area outside the checkerboard. 50 float matrix[20] = { 1, 0, 0, 0, 0, 51 0, 1, 0, 0, 1, 52 0, 0, 1, 0, 0, 53 0, 0, 0, 1, 32.0f/255 }; 54 sk_sp<SkColorFilter> cfAlphaTrans(SkColorFilters::Matrix(matrix)); 55 56 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); 57 SkScalar MARGIN = SkIntToScalar(12); 58 59 SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10)); 60 SkScalar kd = SkIntToScalar(2); 61 SkScalar surfaceScale = SkIntToScalar(1); 62 SkIRect bounds; 63 r.roundOut(&bounds); 64 65 SkPaint paint; 66 canvas->translate(MARGIN, MARGIN); 67 for (int outset = -15; outset <= 20; outset += 5) { 68 canvas->save(); 69 SkIRect bigRect = cropRect; 70 bigRect.outset(outset, outset); 71 72 draw(canvas, checkerboard, bigRect, 73 SkImageFilters::ColorFilter(cfAlphaTrans, noopCropped, &bigRect)); 74 75 draw(canvas, checkerboard, bigRect, 76 SkImageFilters::Blur(0.3f, 0.3f, noopCropped, &bigRect)); 77 78 draw(canvas, checkerboard, bigRect, 79 SkImageFilters::Blur(8.0f, 8.0f, noopCropped, &bigRect)); 80 81 draw(canvas, checkerboard, bigRect, 82 SkImageFilters::Dilate(2, 2, noopCropped, &bigRect)); 83 84 draw(canvas, checkerboard, bigRect, 85 SkImageFilters::Erode(2, 2, noopCropped, &bigRect)); 86 87 draw(canvas, checkerboard, bigRect, 88 SkImageFilters::DropShadow(10, 10, 3, 3, SK_ColorBLUE, noopCropped, &bigRect)); 89 90 draw(canvas, checkerboard, bigRect, 91 SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR, 12, 92 gradientCircleSource, noopCropped, &bigRect)); 93 94 draw(canvas, checkerboard, bigRect, 95 SkImageFilters::Offset(SkIntToScalar(-8), SkIntToScalar(16), noopCropped, &bigRect)); 96 97 draw(canvas, checkerboard, bigRect, 98 SkImageFilters::PointLitDiffuse(pointLocation, SK_ColorWHITE, surfaceScale, kd, 99 noopCropped, &bigRect)); 100 101 canvas->restore(); 102 canvas->translate(0, SkIntToScalar(80)); 103 } 104 } 105 106 namespace { make_checkerboard()107 sk_sp<SkImage> make_checkerboard() { 108 auto surf = SkSurface::MakeRasterN32Premul(64, 64); 109 auto canvas = surf->getCanvas(); 110 canvas->clear(0xFFFF0000); 111 SkPaint darkPaint; 112 darkPaint.setColor(0xFF404040); 113 SkPaint lightPaint; 114 lightPaint.setColor(0xFFA0A0A0); 115 for (int y = 8; y < 48; y += 16) { 116 for (int x = 8; x < 48; x += 16) { 117 canvas->save(); 118 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 119 canvas->drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint); 120 canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint); 121 canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint); 122 canvas->drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint); 123 canvas->restore(); 124 } 125 } 126 return surf->makeImageSnapshot(); 127 } 128 make_gradient_circle(int width,int height)129 sk_sp<SkImage> make_gradient_circle(int width, int height) { 130 SkScalar x = SkIntToScalar(width / 2); 131 SkScalar y = SkIntToScalar(height / 2); 132 SkScalar radius = std::min(x, y) * 0.8f; 133 auto surface(SkSurface::MakeRasterN32Premul(width, height)); 134 SkCanvas* canvas = surface->getCanvas(); 135 canvas->clear(0x00000000); 136 SkColor colors[2]; 137 colors[0] = SK_ColorWHITE; 138 colors[1] = SK_ColorBLACK; 139 SkPaint paint; 140 paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 141 2, SkTileMode::kClamp)); 142 canvas->drawCircle(x, y, radius, paint); 143 144 return surface->makeImageSnapshot(); 145 } 146 draw(SkCanvas * canvas,sk_sp<SkImage> image,const SkIRect & layerRect,sk_sp<SkImageFilter> filter)147 void draw(SkCanvas* canvas, sk_sp<SkImage> image, const SkIRect& layerRect, 148 sk_sp<SkImageFilter> filter) { 149 // Convert SkIRect to SkRect since that's what saveLayer and drawRect need 150 SkRect rect = SkRect::Make(layerRect); 151 152 SkPaint paint; 153 paint.setImageFilter(std::move(filter)); 154 canvas->saveLayer(&rect, &paint); 155 canvas->drawImage(image, 0, 0); 156 canvas->restore(); 157 158 SkPaint strokePaint; 159 strokePaint.setColor(0xFFFF0000); 160 strokePaint.setStyle(SkPaint::kStroke_Style); 161 canvas->drawRect(rect, strokePaint); 162 163 canvas->translate(SkIntToScalar(80), 0); 164 } 165 } // namespace 166