1 /* 2 * Copyright 2012 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/SkBlendMode.h" 11 #include "include/core/SkCanvas.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkColorFilter.h" 14 #include "include/core/SkImage.h" 15 #include "include/core/SkImageFilter.h" 16 #include "include/core/SkPaint.h" 17 #include "include/core/SkPoint.h" 18 #include "include/core/SkRect.h" 19 #include "include/core/SkRefCnt.h" 20 #include "include/core/SkScalar.h" 21 #include "include/core/SkSize.h" 22 #include "include/core/SkString.h" 23 #include "include/effects/SkImageFilters.h" 24 #include "tools/ToolUtils.h" 25 26 #include <utility> 27 28 class ImageFiltersGraphGM : public skiagm::GM { 29 public: ImageFiltersGraphGM()30 ImageFiltersGraphGM() {} 31 32 protected: 33 onShortName()34 SkString onShortName() override { 35 return SkString("imagefiltersgraph"); 36 } 37 onISize()38 SkISize onISize() override { return SkISize::Make(600, 150); } 39 onOnceBeforeDraw()40 void onOnceBeforeDraw() override { 41 fImage = SkImage::MakeFromBitmap( 42 ToolUtils::create_string_bitmap(100, 100, SK_ColorWHITE, 20, 70, 96, "e")); 43 } 44 onDraw(SkCanvas * canvas)45 void onDraw(SkCanvas* canvas) override { 46 canvas->clear(SK_ColorBLACK); 47 { 48 sk_sp<SkImageFilter> bitmapSource(SkImageFilters::Image(fImage)); 49 sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorRED, 50 SkBlendMode::kSrcIn)); 51 sk_sp<SkImageFilter> blur(SkImageFilters::Blur(4.0f, 4.0f, std::move(bitmapSource))); 52 sk_sp<SkImageFilter> erode(SkImageFilters::Erode(4, 4, blur)); 53 sk_sp<SkImageFilter> color(SkImageFilters::ColorFilter(std::move(cf), 54 std::move(erode))); 55 sk_sp<SkImageFilter> merge(SkImageFilters::Merge(blur, color)); 56 57 SkPaint paint; 58 paint.setImageFilter(std::move(merge)); 59 canvas->drawPaint(paint); 60 canvas->translate(SkIntToScalar(100), 0); 61 } 62 { 63 sk_sp<SkImageFilter> morph(SkImageFilters::Dilate(5, 5, nullptr)); 64 65 float matrix[20] = { 1, 0, 0, 0, 0, 66 0, 1, 0, 0, 0, 67 0, 0, 1, 0, 0, 68 0, 0, 0, 0.5f, 0 }; 69 70 sk_sp<SkColorFilter> matrixFilter(SkColorFilters::Matrix(matrix)); 71 sk_sp<SkImageFilter> colorMorph(SkImageFilters::ColorFilter(std::move(matrixFilter), 72 std::move(morph))); 73 SkPaint paint; 74 paint.setImageFilter(SkImageFilters::Xfermode(SkBlendMode::kSrcOver, 75 std::move(colorMorph))); 76 77 DrawClippedImage(canvas, fImage.get(), paint); 78 canvas->translate(SkIntToScalar(100), 0); 79 } 80 { 81 float matrix[20] = { 1, 0, 0, 0, 0, 82 0, 1, 0, 0, 0, 83 0, 0, 1, 0, 0, 84 0, 0, 0, 0.5f, 0 }; 85 sk_sp<SkColorFilter> matrixCF(SkColorFilters::Matrix(matrix)); 86 sk_sp<SkImageFilter> matrixFilter(SkImageFilters::ColorFilter(std::move(matrixCF), 87 nullptr)); 88 sk_sp<SkImageFilter> offsetFilter(SkImageFilters::Offset(10.0f, 10.f, matrixFilter)); 89 90 SkPaint paint; 91 paint.setImageFilter(SkImageFilters::Arithmetic( 92 0, 1, 1, 0, true, std::move(matrixFilter), std::move(offsetFilter), nullptr)); 93 94 DrawClippedImage(canvas, fImage.get(), paint); 95 canvas->translate(SkIntToScalar(100), 0); 96 } 97 { 98 sk_sp<SkImageFilter> blur(SkImageFilters::Blur(10, 10, nullptr)); 99 100 SkIRect cropRect = SkIRect::MakeWH(95, 100); 101 SkPaint paint; 102 paint.setImageFilter( 103 SkImageFilters::Xfermode(SkBlendMode::kSrcIn, std::move(blur), nullptr, &cropRect)); 104 DrawClippedImage(canvas, fImage.get(), paint); 105 canvas->translate(SkIntToScalar(100), 0); 106 } 107 { 108 // Dilate -> matrix convolution. 109 // This tests that a filter using asFragmentProcessor (matrix 110 // convolution) correctly handles a non-zero source offset 111 // (supplied by the dilate). 112 sk_sp<SkImageFilter> dilate(SkImageFilters::Dilate(5, 5, nullptr)); 113 114 SkScalar kernel[9] = { -1, -1, -1, 115 -1, 7, -1, 116 -1, -1, -1 }; 117 SkISize kernelSize = SkISize::Make(3, 3); 118 SkScalar gain = 1.0f, bias = 0; 119 SkIPoint kernelOffset = SkIPoint::Make(1, 1); 120 bool convolveAlpha = false; 121 sk_sp<SkImageFilter> convolve(SkImageFilters::MatrixConvolution( 122 kernelSize, kernel, gain, bias, kernelOffset, SkTileMode::kClamp, convolveAlpha, 123 std::move(dilate))); 124 125 SkPaint paint; 126 paint.setImageFilter(std::move(convolve)); 127 DrawClippedImage(canvas, fImage.get(), paint); 128 canvas->translate(SkIntToScalar(100), 0); 129 } 130 { 131 // Test that crop offsets are absolute, not relative to the parent's crop rect. 132 sk_sp<SkColorFilter> cf1(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kSrcIn)); 133 sk_sp<SkColorFilter> cf2(SkColorFilters::Blend(SK_ColorGREEN, SkBlendMode::kSrcIn)); 134 SkIRect outerRect = SkIRect::MakeXYWH(10, 10, 80, 80); 135 SkIRect innerRect= SkIRect::MakeXYWH(20, 20, 60, 60); 136 sk_sp<SkImageFilter> color1(SkImageFilters::ColorFilter( 137 std::move(cf1), nullptr, &outerRect)); 138 sk_sp<SkImageFilter> color2(SkImageFilters::ColorFilter( 139 std::move(cf2), std::move(color1), &innerRect)); 140 141 SkPaint paint; 142 paint.setImageFilter(std::move(color2)); 143 paint.setColor(SK_ColorRED); 144 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint); 145 canvas->translate(SkIntToScalar(100), 0); 146 } 147 } 148 149 private: DrawClippedImage(SkCanvas * canvas,const SkImage * image,const SkPaint & paint)150 static void DrawClippedImage(SkCanvas* canvas, const SkImage* image, const SkPaint& paint) { 151 canvas->save(); 152 canvas->clipRect(SkRect::MakeIWH(image->width(), image->height())); 153 canvas->drawImage(image, 0, 0, &paint); 154 canvas->restore(); 155 } 156 157 sk_sp<SkImage> fImage; 158 159 typedef GM INHERITED; 160 }; 161 162 /////////////////////////////////////////////////////////////////////////////// 163 164 DEF_GM(return new ImageFiltersGraphGM;) 165