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 SkFilterMode::kLinear)); 47 sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect)); 48 // This color matrix saturates the green component but only partly increases the opacity. 49 // For the opaque checkerboard, the opacity boost doesn't matter but it does impact the 50 // area outside the checkerboard. 51 float matrix[20] = { 1, 0, 0, 0, 0, 52 0, 1, 0, 0, 1, 53 0, 0, 1, 0, 0, 54 0, 0, 0, 1, 32.0f/255 }; 55 sk_sp<SkColorFilter> cfAlphaTrans(SkColorFilters::Matrix(matrix)); 56 57 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); 58 SkScalar MARGIN = SkIntToScalar(12); 59 60 SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10)); 61 SkScalar kd = SkIntToScalar(2); 62 SkScalar surfaceScale = SkIntToScalar(1); 63 SkIRect bounds; 64 r.roundOut(&bounds); 65 66 SkPaint paint; 67 canvas->translate(MARGIN, MARGIN); 68 for (int outset = -15; outset <= 20; outset += 5) { 69 canvas->save(); 70 SkIRect bigRect = cropRect; 71 bigRect.outset(outset, outset); 72 73 draw(canvas, checkerboard, bigRect, 74 SkImageFilters::ColorFilter(cfAlphaTrans, noopCropped, &bigRect)); 75 76 draw(canvas, checkerboard, bigRect, 77 SkImageFilters::Blur(0.3f, 0.3f, noopCropped, &bigRect)); 78 79 draw(canvas, checkerboard, bigRect, 80 SkImageFilters::Blur(8.0f, 8.0f, noopCropped, &bigRect)); 81 82 draw(canvas, checkerboard, bigRect, 83 SkImageFilters::Dilate(2, 2, noopCropped, &bigRect)); 84 85 draw(canvas, checkerboard, bigRect, 86 SkImageFilters::Erode(2, 2, noopCropped, &bigRect)); 87 88 draw(canvas, checkerboard, bigRect, 89 SkImageFilters::DropShadow(10, 10, 3, 3, SK_ColorBLUE, noopCropped, &bigRect)); 90 91 draw(canvas, checkerboard, bigRect, 92 SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR, 12, 93 gradientCircleSource, noopCropped, &bigRect)); 94 95 draw(canvas, checkerboard, bigRect, 96 SkImageFilters::Offset(SkIntToScalar(-8), SkIntToScalar(16), noopCropped, &bigRect)); 97 98 draw(canvas, checkerboard, bigRect, 99 SkImageFilters::PointLitDiffuse(pointLocation, SK_ColorWHITE, surfaceScale, kd, 100 noopCropped, &bigRect)); 101 102 canvas->restore(); 103 canvas->translate(0, SkIntToScalar(80)); 104 } 105 } 106 107 namespace { make_checkerboard()108 sk_sp<SkImage> make_checkerboard() { 109 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(64, 64)); 110 auto canvas = surf->getCanvas(); 111 canvas->clear(0xFFFF0000); 112 SkPaint darkPaint; 113 darkPaint.setColor(0xFF404040); 114 SkPaint lightPaint; 115 lightPaint.setColor(0xFFA0A0A0); 116 for (int y = 8; y < 48; y += 16) { 117 for (int x = 8; x < 48; x += 16) { 118 canvas->save(); 119 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 120 canvas->drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint); 121 canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint); 122 canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint); 123 canvas->drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint); 124 canvas->restore(); 125 } 126 } 127 return surf->makeImageSnapshot(); 128 } 129 make_gradient_circle(int width,int height)130 sk_sp<SkImage> make_gradient_circle(int width, int height) { 131 SkScalar x = SkIntToScalar(width / 2); 132 SkScalar y = SkIntToScalar(height / 2); 133 SkScalar radius = std::min(x, y) * 0.8f; 134 auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(width, height))); 135 SkCanvas* canvas = surface->getCanvas(); 136 canvas->clear(0x00000000); 137 SkColor colors[2]; 138 colors[0] = SK_ColorWHITE; 139 colors[1] = SK_ColorBLACK; 140 SkPaint paint; 141 paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr, 142 2, SkTileMode::kClamp)); 143 canvas->drawCircle(x, y, radius, paint); 144 145 return surface->makeImageSnapshot(); 146 } 147 draw(SkCanvas * canvas,sk_sp<SkImage> image,const SkIRect & layerRect,sk_sp<SkImageFilter> filter)148 void draw(SkCanvas* canvas, sk_sp<SkImage> image, const SkIRect& layerRect, 149 sk_sp<SkImageFilter> filter) { 150 SkPaint paint; 151 paint.setImageFilter(std::move(filter)); 152 153 // We don't pass 'layerRect' in as the saveLayer bounds hint because that is not the 154 // pre-filtering local bounds (which would be image->dimensions()). We could clip before 155 // the saveLayer but every 'filter' should have been constructed with a crop rect equal 156 // to 'layerRect', so do an unclipped saveLayer to ensure that the crop rect itself is 157 // what restricts the output of the filter. 158 canvas->saveLayer(nullptr, &paint); 159 canvas->drawImage(image, 0, 0); 160 canvas->restore(); 161 162 SkPaint strokePaint; 163 strokePaint.setColor(0xFFFF0000); 164 strokePaint.setStyle(SkPaint::kStroke_Style); 165 canvas->drawRect(SkRect::Make(layerRect), strokePaint); 166 167 canvas->translate(SkIntToScalar(80), 0); 168 } 169 } // namespace 170