xref: /aosp_15_r20/external/skia/gm/imagefiltersgraph.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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