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