1/* 2 * Copyright 2011 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.h" 9#include "sk_tool_utils.h" 10#include "SkCanvas.h" 11#include "SkColorFilter.h" 12#include "SkColorPriv.h" 13#include "SkImageFilterPriv.h" 14#include "SkShader.h" 15 16#include "SkBlurImageFilter.h" 17#include "SkColorFilterImageFilter.h" 18#include "SkDropShadowImageFilter.h" 19#include "SkSpecialImage.h" 20 21class FailImageFilter : public SkImageFilter { 22public: 23 class Registrar { 24 public: 25 Registrar() { 26 SkFlattenable::Register("FailImageFilter", 27 FailImageFilter::CreateProc, 28 FailImageFilter::GetFlattenableType()); 29 } 30 }; 31 static sk_sp<SkImageFilter> Make() { 32 return sk_sp<SkImageFilter>(new FailImageFilter); 33 } 34 35 SK_TO_STRING_OVERRIDE() 36 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(FailImageFilter) 37 38protected: 39 FailImageFilter() : INHERITED(nullptr, 0, nullptr) {} 40 41 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, 42 SkIPoint* offset) const override { 43 return nullptr; 44 } 45 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override { 46 return nullptr; 47 } 48 49private: 50 typedef SkImageFilter INHERITED; 51}; 52 53static FailImageFilter::Registrar gReg0; 54 55sk_sp<SkFlattenable> FailImageFilter::CreateProc(SkReadBuffer& buffer) { 56 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0); 57 return FailImageFilter::Make(); 58} 59 60#ifndef SK_IGNORE_TO_STRING 61void FailImageFilter::toString(SkString* str) const { 62 str->appendf("FailImageFilter: ("); 63 str->append(")"); 64} 65#endif 66 67class IdentityImageFilter : public SkImageFilter { 68public: 69 class Registrar { 70 public: 71 Registrar() { 72 SkFlattenable::Register("IdentityImageFilter", 73 IdentityImageFilter::CreateProc, 74 IdentityImageFilter::GetFlattenableType()); 75 } 76 }; 77 static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> input) { 78 return sk_sp<SkImageFilter>(new IdentityImageFilter(std::move(input))); 79 } 80 81 SK_TO_STRING_OVERRIDE() 82 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(IdentityImageFilter) 83 84protected: 85 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&, 86 SkIPoint* offset) const override { 87 offset->set(0, 0); 88 return sk_ref_sp<SkSpecialImage>(source); 89 } 90 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override { 91 return sk_ref_sp(const_cast<IdentityImageFilter*>(this)); 92 } 93 94private: 95 IdentityImageFilter(sk_sp<SkImageFilter> input) : INHERITED(&input, 1, nullptr) {} 96 97 typedef SkImageFilter INHERITED; 98}; 99 100static IdentityImageFilter::Registrar gReg1; 101 102sk_sp<SkFlattenable> IdentityImageFilter::CreateProc(SkReadBuffer& buffer) { 103 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 104 return IdentityImageFilter::Make(common.getInput(0)); 105} 106 107#ifndef SK_IGNORE_TO_STRING 108void IdentityImageFilter::toString(SkString* str) const { 109 str->appendf("IdentityImageFilter: ("); 110 str->append(")"); 111} 112#endif 113 114/////////////////////////////////////////////////////////////////////////////// 115 116static void draw_paint(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 117 SkPaint paint; 118 paint.setImageFilter(std::move(imf)); 119 paint.setColor(SK_ColorGREEN); 120 canvas->save(); 121 canvas->clipRect(r); 122 canvas->drawPaint(paint); 123 canvas->restore(); 124} 125 126static void draw_line(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 127 SkPaint paint; 128 paint.setColor(SK_ColorBLUE); 129 paint.setImageFilter(imf); 130 paint.setStrokeWidth(r.width()/10); 131 canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, paint); 132} 133 134static void draw_rect(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 135 SkPaint paint; 136 paint.setColor(SK_ColorYELLOW); 137 paint.setImageFilter(imf); 138 SkRect rr(r); 139 rr.inset(r.width()/10, r.height()/10); 140 canvas->drawRect(rr, paint); 141} 142 143static void draw_path(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 144 SkPaint paint; 145 paint.setColor(SK_ColorMAGENTA); 146 paint.setImageFilter(imf); 147 paint.setAntiAlias(true); 148 canvas->drawCircle(r.centerX(), r.centerY(), r.width()*2/5, paint); 149} 150 151static void draw_text(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 152 SkPaint paint; 153 paint.setImageFilter(imf); 154 paint.setColor(SK_ColorCYAN); 155 paint.setAntiAlias(true); 156 sk_tool_utils::set_portable_typeface(&paint); 157 paint.setTextSize(r.height()/2); 158 paint.setTextAlign(SkPaint::kCenter_Align); 159 canvas->drawString("Text", r.centerX(), r.centerY(), paint); 160} 161 162static void draw_bitmap(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) { 163 SkPaint paint; 164 paint.setImageFilter(std::move(imf)); 165 166 SkIRect bounds; 167 r.roundOut(&bounds); 168 169 SkBitmap bm; 170 bm.allocN32Pixels(bounds.width(), bounds.height()); 171 bm.eraseColor(SK_ColorTRANSPARENT); 172 SkCanvas c(bm); 173 draw_path(&c, r, nullptr); 174 175 canvas->drawBitmap(bm, 0, 0, &paint); 176} 177 178/////////////////////////////////////////////////////////////////////////////// 179 180class ImageFiltersBaseGM : public skiagm::GM { 181public: 182 ImageFiltersBaseGM () {} 183 184protected: 185 SkString onShortName() override { 186 return SkString("imagefiltersbase"); 187 } 188 189 SkISize onISize() override { return SkISize::Make(700, 500); } 190 191 void draw_frame(SkCanvas* canvas, const SkRect& r) { 192 SkPaint paint; 193 paint.setStyle(SkPaint::kStroke_Style); 194 paint.setColor(SK_ColorRED); 195 canvas->drawRect(r, paint); 196 } 197 198 void onDraw(SkCanvas* canvas) override { 199 void (*drawProc[])(SkCanvas*, const SkRect&, sk_sp<SkImageFilter>) = { 200 draw_paint, 201 draw_line, draw_rect, draw_path, draw_text, 202 draw_bitmap, 203 }; 204 205 auto cf = SkColorFilter::MakeModeFilter(SK_ColorRED, SkBlendMode::kSrcIn); 206 sk_sp<SkImageFilter> filters[] = { 207 nullptr, 208 IdentityImageFilter::Make(nullptr), 209 FailImageFilter::Make(), 210 SkColorFilterImageFilter::Make(std::move(cf), nullptr), 211 // The strage 0.29 value tickles an edge case where crop rect calculates 212 // a small border, but the blur really needs no border. This tickels 213 // an msan uninitialized value bug. 214 SkBlurImageFilter::Make(12.0f, 0.29f, nullptr), 215 SkDropShadowImageFilter::Make( 216 10.0f, 5.0f, 3.0f, 3.0f, SK_ColorBLUE, 217 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, 218 nullptr), 219 }; 220 221 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); 222 SkScalar MARGIN = SkIntToScalar(16); 223 SkScalar DX = r.width() + MARGIN; 224 SkScalar DY = r.height() + MARGIN; 225 226 canvas->translate(MARGIN, MARGIN); 227 for (size_t i = 0; i < SK_ARRAY_COUNT(drawProc); ++i) { 228 canvas->save(); 229 for (size_t j = 0; j < SK_ARRAY_COUNT(filters); ++j) { 230 drawProc[i](canvas, r, filters[j]); 231 232 draw_frame(canvas, r); 233 canvas->translate(0, DY); 234 } 235 canvas->restore(); 236 canvas->translate(DX, 0); 237 } 238 } 239 240private: 241 typedef GM INHERITED; 242}; 243DEF_GM( return new ImageFiltersBaseGM; ) 244 245/////////////////////////////////////////////////////////////////////////////// 246 247/* 248 * Want to test combos of filter and LCD text, to be sure we disable LCD in the presence of 249 * a filter. 250 */ 251class ImageFiltersTextBaseGM : public skiagm::GM { 252 SkString fSuffix; 253public: 254 ImageFiltersTextBaseGM(const char suffix[]) : fSuffix(suffix) {} 255 256protected: 257 SkString onShortName() override { 258 SkString name; 259 name.printf("%s_%s", "textfilter", fSuffix.c_str()); 260 return name; 261 } 262 263 SkISize onISize() override { return SkISize::Make(512, 342); } 264 265 void drawWaterfall(SkCanvas* canvas, const SkPaint& origPaint) { 266 const uint32_t flags[] = { 267 0, 268 SkPaint::kAntiAlias_Flag, 269 SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag, 270 }; 271 SkPaint paint(origPaint); 272 sk_tool_utils::set_portable_typeface(&paint); 273 paint.setTextSize(30); 274 275 SkAutoCanvasRestore acr(canvas, true); 276 for (size_t i = 0; i < SK_ARRAY_COUNT(flags); ++i) { 277 paint.setFlags(flags[i]); 278 canvas->drawString("Hamburgefon", 0, 0, paint); 279 canvas->translate(0, 40); 280 } 281 } 282 283 virtual void installFilter(SkPaint* paint) = 0; 284 285 void onDraw(SkCanvas* canvas) override { 286 SkPaint paint; 287 288 canvas->translate(20, 40); 289 290 for (int doSaveLayer = 0; doSaveLayer <= 1; ++doSaveLayer) { 291 SkAutoCanvasRestore acr(canvas, true); 292 for (int useFilter = 0; useFilter <= 1; ++useFilter) { 293 SkAutoCanvasRestore acr2(canvas, true); 294 295 SkPaint paint; 296 if (useFilter) { 297 this->installFilter(&paint); 298 } 299 if (doSaveLayer) { 300 canvas->saveLayer(nullptr, &paint); 301 paint.setImageFilter(nullptr); 302 } 303 this->drawWaterfall(canvas, paint); 304 305 acr2.restore(); 306 canvas->translate(250, 0); 307 } 308 acr.restore(); 309 canvas->translate(0, 200); 310 } 311 } 312 313private: 314 typedef GM INHERITED; 315}; 316 317class ImageFiltersText_IF : public ImageFiltersTextBaseGM { 318public: 319 ImageFiltersText_IF() : ImageFiltersTextBaseGM("image") {} 320 321 void installFilter(SkPaint* paint) override { 322 paint->setImageFilter(SkBlurImageFilter::Make(1.5f, 1.5f, nullptr)); 323 } 324}; 325DEF_GM( return new ImageFiltersText_IF; ) 326 327class ImageFiltersText_CF : public ImageFiltersTextBaseGM { 328public: 329 ImageFiltersText_CF() : ImageFiltersTextBaseGM("color") {} 330 331 void installFilter(SkPaint* paint) override { 332 paint->setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLUE, SkBlendMode::kSrcIn)); 333 } 334}; 335DEF_GM( return new ImageFiltersText_CF; ) 336