1/* 2 * Copyright 2013 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/SkColorSpace.h" 13#include "include/core/SkImage.h" 14#include "include/core/SkImageFilter.h" 15#include "include/core/SkImageInfo.h" 16#include "include/core/SkMatrix.h" 17#include "include/core/SkPaint.h" 18#include "include/core/SkRect.h" 19#include "include/core/SkRefCnt.h" 20#include "include/core/SkRegion.h" 21#include "include/core/SkSize.h" 22#include "include/core/SkString.h" 23#include "include/core/SkSurface.h" 24#include "include/effects/SkImageFilters.h" 25#include "include/utils/SkRandom.h" 26#include "tools/ToolUtils.h" 27 28#include <utility> 29 30#define WIDTH 500 31#define HEIGHT 500 32 33static void draw_rects(SkCanvas* canvas) { 34 SkPaint rectPaint; 35 rectPaint.setColor(SK_ColorBLUE); 36 canvas->drawRect(SkRect::MakeXYWH(0, 0, WIDTH / 2, HEIGHT / 2), rectPaint); 37 rectPaint.setColor(0xBFFF0000); 38 canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 2), rectPaint); 39 rectPaint.setColor(0x3F00FF00); 40 canvas->drawRect(SkRect::MakeXYWH(0, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint); 41 rectPaint.setColor(SK_ColorTRANSPARENT); 42 canvas->drawRect(SkRect::MakeXYWH(WIDTH / 2, HEIGHT / 2, WIDTH / 2, HEIGHT / 2), rectPaint); 43} 44 45static SkPaint create_filter_paint(SkIRect* cropRect = nullptr) { 46 SkIRect rects[2]; 47 rects[0] = SkIRect::MakeXYWH(0, 150, WIDTH, HEIGHT - 300); 48 rects[1] = SkIRect::MakeXYWH(150, 0, WIDTH - 300, HEIGHT); 49 SkRegion region; 50 region.setRects(rects, 2); 51 52 SkPaint paint; 53 sk_sp<SkImageFilter> offset(SkImageFilters::Offset(25, 25, nullptr)); 54 paint.setImageFilter( 55 SkImageFilters::AlphaThreshold(region, 0.2f, 0.7f, std::move(offset), cropRect)); 56 return paint; 57} 58 59class ImageAlphaThresholdGM : public skiagm::GM { 60public: 61 ImageAlphaThresholdGM(bool useCropRect) : fUseCropRect(useCropRect) { 62 this->setBGColor(SK_ColorWHITE); 63 } 64 65protected: 66 67 SkString onShortName() override { 68 if (fUseCropRect) { 69 return SkString("imagealphathreshold_crop"); 70 } 71 72 return SkString("imagealphathreshold"); 73 } 74 75 SkISize onISize() override { 76 return SkISize::Make(WIDTH, HEIGHT); 77 } 78 79 void onDraw(SkCanvas* canvas) override { 80 SkMatrix matrix; 81 matrix.reset(); 82 matrix.setTranslate(WIDTH * .1f, HEIGHT * .1f); 83 matrix.postScale(.8f, .8f); 84 85 canvas->concat(matrix); 86 87 SkIRect cropRect = SkIRect::MakeLTRB(100, 100, WIDTH - 100, HEIGHT - 100); 88 89 SkPaint paint = create_filter_paint(fUseCropRect ? &cropRect : nullptr); 90 canvas->saveLayer(nullptr, &paint); 91 draw_rects(canvas); 92 93 canvas->restore(); 94 } 95 96private: 97 bool fUseCropRect; 98 99 using INHERITED = GM; 100}; 101 102// Create a 'width' x 'height' SkSurface that matches the colorType of 'canvas' as 103// best we can 104static sk_sp<SkSurface> make_color_matching_surface(SkCanvas* canvas, int width, int height, 105 SkAlphaType at) { 106 107 SkColorType ct = canvas->imageInfo().colorType(); 108 sk_sp<SkColorSpace> cs(canvas->imageInfo().refColorSpace()); 109 110 if (kUnknown_SkColorType == ct) { 111 // For backends that aren't yet color-space aware we just fallback to N32. 112 ct = kN32_SkColorType; 113 cs = nullptr; 114 } else if (SkColorTypeIsAlwaysOpaque(ct)) { 115 at = kOpaque_SkAlphaType; 116 } 117 118 SkImageInfo info = SkImageInfo::Make(width, height, ct, at, std::move(cs)); 119 120 return ToolUtils::makeSurface(canvas, info); 121} 122 123class ImageAlphaThresholdSurfaceGM : public skiagm::GM { 124public: 125 ImageAlphaThresholdSurfaceGM() { 126 this->setBGColor(0xFFFFFFFF); 127 } 128 129protected: 130 SkString onShortName() override { 131 return SkString("imagealphathreshold_surface"); 132 } 133 134 SkISize onISize() override { 135 return SkISize::Make(WIDTH, HEIGHT); 136 } 137 138 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override { 139 SkMatrix matrix; 140 matrix.reset(); 141 matrix.setTranslate(WIDTH * .1f, HEIGHT * .1f); 142 matrix.postScale(.8f, .8f); 143 144 canvas->concat(matrix); 145 146 sk_sp<SkSurface> surface(make_color_matching_surface(canvas, WIDTH, HEIGHT, 147 kPremul_SkAlphaType)); 148 if (!surface) { 149 *errorMsg = "make_color_matching_surface failed"; 150 return DrawResult::kFail; 151 } 152 153 surface->getCanvas()->clear(SK_ColorTRANSPARENT); 154 draw_rects(surface->getCanvas()); 155 156 SkPaint paint = create_filter_paint(); 157 canvas->clipRect(SkRect::MakeLTRB(100, 100, WIDTH - 100, HEIGHT - 100)); 158 canvas->drawImage(surface->makeImageSnapshot().get(), 0, 0, SkSamplingOptions(), &paint); 159 return DrawResult::kOk; 160 } 161 162private: 163 using INHERITED = skiagm::GM; 164}; 165 166////////////////////////////////////////////////////////////////////////////// 167 168DEF_GM(return new ImageAlphaThresholdGM(true);) 169DEF_GM(return new ImageAlphaThresholdGM(false);) 170DEF_GM(return new ImageAlphaThresholdSurfaceGM();) 171 172////////////////////////////////////////////////////////////////////////////// 173 174static sk_sp<SkImage> make_img() { 175 SkBitmap bitmap; 176 bitmap.allocPixels(SkImageInfo::MakeS32(WIDTH, HEIGHT, kPremul_SkAlphaType)); 177 SkCanvas canvas(bitmap); 178 179 SkPaint paint; 180 SkRect rect = SkRect::MakeWH(WIDTH, HEIGHT); 181 SkRandom rnd; 182 183 while (!rect.isEmpty()) { 184 paint.setColor(rnd.nextU() | (0xFF << 24)); 185 canvas.drawRect(rect, paint); 186 rect.inset(25, 25); 187 } 188 189 return bitmap.asImage(); 190} 191 192DEF_SIMPLE_GM_BG(imagealphathreshold_image, canvas, WIDTH * 2, HEIGHT, SK_ColorBLACK) { 193 sk_sp<SkImage> image(make_img()); 194 195 SkIRect rects[2]; 196 rects[0] = SkIRect::MakeXYWH(0, 150, WIDTH, HEIGHT - 300); 197 rects[1] = SkIRect::MakeXYWH(150, 0, WIDTH - 300, HEIGHT); 198 SkRegion region; 199 region.setRects(rects, 2); 200 201 SkPaint filterPaint; 202 sk_sp<SkImageFilter> imageSource(SkImageFilters::Image(image)); 203 filterPaint.setImageFilter(SkImageFilters::AlphaThreshold(region, 0.2f, 0.7f, 204 std::move(imageSource))); 205 206 canvas->saveLayer(nullptr, &filterPaint); 207 canvas->restore(); 208 canvas->translate(WIDTH, 0); 209 canvas->drawImage(image, 0, 0); 210} 211