add helper makeShader for the common Clamp case
[platform/upstream/libSkiaSharp.git] / gm / arithmode.cpp
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 "SkArithmeticImageFilter.h"
11 #include "SkCanvas.h"
12 #include "SkColorPriv.h"
13 #include "SkGradientShader.h"
14 #include "SkImage.h"
15 #include "SkImageSource.h"
16 #include "SkShader.h"
17 #include "SkSurface.h"
18
19 #define WW  100
20 #define HH  32
21
22 static sk_sp<SkImage> make_src() {
23     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
24     SkCanvas* canvas = surface->getCanvas();
25
26     SkPaint paint;
27     SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
28     SkColor colors[] = {
29         SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
30         SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
31     };
32     paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
33                                                  SkShader::kClamp_TileMode));
34     canvas->drawPaint(paint);
35     return surface->makeImageSnapshot();
36 }
37
38 static sk_sp<SkImage> make_dst() {
39     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
40     SkCanvas* canvas = surface->getCanvas();
41
42     SkPaint paint;
43     SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
44     SkColor colors[] = {
45         SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
46         sk_tool_utils::color_to_565(SK_ColorGRAY)
47     };
48     paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
49                                                  SkShader::kClamp_TileMode));
50     canvas->drawPaint(paint);
51     return surface->makeImageSnapshot();
52 }
53
54 static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
55     SkPaint paint;
56     paint.setTextSize(SkIntToScalar(24));
57     paint.setAntiAlias(true);
58     sk_tool_utils::set_portable_typeface(&paint);
59     for (int i = 0; i < 4; ++i) {
60         SkString str;
61         str.appendScalar(k[i]);
62         SkScalar width = paint.measureText(str.c_str(), str.size());
63         canvas->drawText(str.c_str(), str.size(), x, y + paint.getTextSize(), paint);
64         x += width + SkIntToScalar(10);
65     }
66 }
67
68 class ArithmodeGM : public skiagm::GM {
69 public:
70     ArithmodeGM () {}
71
72 protected:
73
74     virtual SkString onShortName() {
75         return SkString("arithmode");
76     }
77
78     virtual SkISize onISize() { return SkISize::Make(640, 572); }
79
80     virtual void onDraw(SkCanvas* canvas) {
81         sk_sp<SkImage> src = make_src();
82         sk_sp<SkImage> dst = make_dst();
83         sk_sp<SkImageFilter> srcFilter = SkImageSource::Make(src);
84         sk_sp<SkImageFilter> dstFilter = SkImageSource::Make(dst);
85
86         constexpr SkScalar one = SK_Scalar1;
87         constexpr SkScalar K[] = {
88             0, 0, 0, 0,
89             0, 0, 0, one,
90             0, one, 0, 0,
91             0, 0, one, 0,
92             0, one, one, 0,
93             0, one, -one, 0,
94             0, one/2, one/2, 0,
95             0, one/2, one/2, one/4,
96             0, one/2, one/2, -one/4,
97             one/4, one/2, one/2, 0,
98             -one/4, one/2, one/2, 0,
99         };
100
101         const SkScalar* k = K;
102         const SkScalar* stop = k + SK_ARRAY_COUNT(K);
103         const SkRect rect = SkRect::MakeWH(WW, HH);
104         SkScalar gap = SkIntToScalar(WW + 20);
105         while (k < stop) {
106             {
107                 SkAutoCanvasRestore acr(canvas, true);
108                 canvas->drawImage(src, 0, 0);
109                 canvas->translate(gap, 0);
110                 canvas->drawImage(dst, 0, 0);
111                 canvas->translate(gap, 0);
112                 SkPaint paint;
113                 paint.setImageFilter(SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], true,
114                                                                    dstFilter, srcFilter, nullptr));
115                 canvas->saveLayer(&rect, &paint);
116                 canvas->restore();
117
118                 canvas->translate(gap, 0);
119                 show_k_text(canvas, 0, 0, k);
120             }
121
122             k += 4;
123             canvas->translate(0, HH + 12);
124         }
125
126         // Draw two special cases to test enforcePMColor. In these cases, we
127         // draw the dst bitmap twice, the first time it is halved and inverted,
128         // leading to invalid premultiplied colors. If we enforcePMColor, these
129         // invalid values should be clamped, and will not contribute to the
130         // second draw.
131         for (int i = 0; i < 2; i++) {
132             const bool enforcePMColor = (i == 0);
133
134             {
135                 SkAutoCanvasRestore acr(canvas, true);
136                 canvas->translate(gap, 0);
137                 canvas->drawImage(dst, 0, 0);
138                 canvas->translate(gap, 0);
139
140                 sk_sp<SkImageFilter> bg =
141                         SkArithmeticImageFilter::Make(0, 0, -one / 2, 1, enforcePMColor, dstFilter);
142                 SkPaint p;
143                 p.setImageFilter(SkArithmeticImageFilter::Make(0, one / 2, -one, 1, true,
144                                                                std::move(bg), dstFilter, nullptr));
145                 canvas->saveLayer(&rect, &p);
146                 canvas->restore();
147                 canvas->translate(gap, 0);
148
149                 // Label
150                 SkPaint paint;
151                 paint.setTextSize(SkIntToScalar(24));
152                 paint.setAntiAlias(true);
153                 sk_tool_utils::set_portable_typeface(&paint);
154                 SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
155                 canvas->drawText(str.c_str(), str.size(), 0, paint.getTextSize(), paint);
156             }
157             canvas->translate(0, HH + 12);
158         }
159     }
160
161 private:
162     typedef GM INHERITED;
163 };
164
165 ///////////////////////////////////////////////////////////////////////////////
166
167 DEF_GM( return new ArithmodeGM; )