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 void make_checkerboard(SkBitmap* bitmap); 32 sk_sp<SkImage> make_gradient_circle(int width, int height); 33 void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkIRect& rect, 34 sk_sp<SkImageFilter> filter); 35 36 }; 37 38 /////////////////////////////////////////////////////////////////////////////// 39 40 DEF_SIMPLE_GM(imagefilterscropexpand, canvas, 730, 650) { 41 SkIRect cropRect = SkIRect::MakeXYWH(10, 10, 44, 44); 42 43 sk_sp<SkImage> gradientCircle(make_gradient_circle(64, 64)); 44 SkBitmap checkerboard; 45 make_checkerboard(&checkerboard); 46 47 sk_sp<SkImageFilter> gradientCircleSource(SkImageFilters::Image(std::move(gradientCircle))); 48 sk_sp<SkImageFilter> noopCropped(SkImageFilters::Offset(0, 0, nullptr, &cropRect)); 49 // This color matrix saturates the green component but only partly increases the opacity. 50 // For the opaque checkerboard, the opacity boost doesn't matter but it does impact the 51 // area outside the checkerboard. 52 float matrix[20] = { 1, 0, 0, 0, 0, 53 0, 1, 0, 0, 1, 54 0, 0, 1, 0, 0, 55 0, 0, 0, 1, 32.0f/255 }; 56 sk_sp<SkColorFilter> cfAlphaTrans(SkColorFilters::Matrix(matrix)); 57 58 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); 59 SkScalar MARGIN = SkIntToScalar(12); 60 61 SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10)); 62 SkScalar kd = SkIntToScalar(2); 63 SkScalar surfaceScale = SkIntToScalar(1); 64 SkIRect bounds; 65 r.roundOut(&bounds); 66 67 SkPaint paint; 68 canvas->translate(MARGIN, MARGIN); 69 for (int outset = -15; outset <= 20; outset += 5) { 70 canvas->save(); 71 SkIRect bigRect = cropRect; 72 bigRect.outset(outset, outset); 73 74 draw(canvas, checkerboard, bigRect, 75 SkImageFilters::ColorFilter(cfAlphaTrans, noopCropped, &bigRect)); 76 77 draw(canvas, checkerboard, bigRect, 78 SkImageFilters::Blur(0.3f, 0.3f, noopCropped, &bigRect)); 79 80 draw(canvas, checkerboard, bigRect, 81 SkImageFilters::Blur(8.0f, 8.0f, noopCropped, &bigRect)); 82 83 draw(canvas, checkerboard, bigRect, 84 SkImageFilters::Dilate(2, 2, noopCropped, &bigRect)); 85 86 draw(canvas, checkerboard, bigRect, 87 SkImageFilters::Erode(2, 2, noopCropped, &bigRect)); 88 89 draw(canvas, checkerboard, bigRect, 90 SkImageFilters::DropShadow(10, 10, 3, 3, SK_ColorBLUE, noopCropped, &bigRect)); 91 92 draw(canvas, checkerboard, bigRect, 93 SkImageFilters::DisplacementMap(SkColorChannel::kR, SkColorChannel::kR, 12, 94 gradientCircleSource, noopCropped, &bigRect)); 95 96 draw(canvas, checkerboard, bigRect, 97 SkImageFilters::Offset(SkIntToScalar(-8), SkIntToScalar(16), noopCropped, &bigRect)); 98 99 draw(canvas, checkerboard, bigRect, 100 SkImageFilters::PointLitDiffuse(pointLocation, SK_ColorWHITE, surfaceScale, kd, 101 noopCropped, &bigRect)); 102 103 canvas->restore(); 104 canvas->translate(0, SkIntToScalar(80)); 105 } 106 } 107 108 namespace { make_checkerboard(SkBitmap * bitmap)109 void make_checkerboard(SkBitmap* bitmap) { 110 bitmap->allocN32Pixels(64, 64); 111 SkCanvas canvas(*bitmap); 112 canvas.clear(0xFFFF0000); 113 SkPaint darkPaint; 114 darkPaint.setColor(0xFF404040); 115 SkPaint lightPaint; 116 lightPaint.setColor(0xFFA0A0A0); 117 for (int y = 8; y < 48; y += 16) { 118 for (int x = 8; x < 48; x += 16) { 119 canvas.save(); 120 canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 121 canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint); 122 canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint); 123 canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint); 124 canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint); 125 canvas.restore(); 126 } 127 } 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 = SkMinScalar(x, y) * 0.8f; 134 auto surface(SkSurface::MakeRasterN32Premul(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,const SkBitmap & bitmap,const SkIRect & layerRect,sk_sp<SkImageFilter> filter)148 void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkIRect& layerRect, 149 sk_sp<SkImageFilter> filter) { 150 // Convert SkIRect to SkRect since that's what saveLayer and drawRect need 151 SkRect rect = SkRect::Make(layerRect); 152 153 SkPaint paint; 154 paint.setImageFilter(std::move(filter)); 155 canvas->saveLayer(&rect, &paint); 156 canvas->drawBitmap(bitmap, 0, 0); 157 canvas->restore(); 158 159 SkPaint strokePaint; 160 strokePaint.setColor(0xFFFF0000); 161 strokePaint.setStyle(SkPaint::kStroke_Style); 162 canvas->drawRect(rect, strokePaint); 163 164 canvas->translate(SkIntToScalar(80), 0); 165 } 166 }; 167