2 * Copyright 2011 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "sk_tool_utils.h"
10 #include "SkArithmeticImageFilter.h"
12 #include "SkColorPriv.h"
13 #include "SkGradientShader.h"
15 #include "SkImageSource.h"
17 #include "SkSurface.h"
22 static sk_sp<SkImage> make_src() {
23 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
24 SkCanvas* canvas = surface->getCanvas();
27 SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
29 SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
30 SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
32 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
33 SkShader::kClamp_TileMode));
34 canvas->drawPaint(paint);
35 return surface->makeImageSnapshot();
38 static sk_sp<SkImage> make_dst() {
39 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
40 SkCanvas* canvas = surface->getCanvas();
43 SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
45 SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
46 sk_tool_utils::color_to_565(SK_ColorGRAY)
48 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
49 SkShader::kClamp_TileMode));
50 canvas->drawPaint(paint);
51 return surface->makeImageSnapshot();
54 static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
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) {
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);
68 class ArithmodeGM : public skiagm::GM {
74 virtual SkString onShortName() {
75 return SkString("arithmode");
78 virtual SkISize onISize() { return SkISize::Make(640, 572); }
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);
86 constexpr SkScalar one = SK_Scalar1;
87 constexpr SkScalar K[] = {
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,
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);
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);
113 paint.setImageFilter(SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], true,
114 dstFilter, srcFilter, nullptr));
115 canvas->saveLayer(&rect, &paint);
118 canvas->translate(gap, 0);
119 show_k_text(canvas, 0, 0, k);
123 canvas->translate(0, HH + 12);
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
131 for (int i = 0; i < 2; i++) {
132 const bool enforcePMColor = (i == 0);
135 SkAutoCanvasRestore acr(canvas, true);
136 canvas->translate(gap, 0);
137 canvas->drawImage(dst, 0, 0);
138 canvas->translate(gap, 0);
140 sk_sp<SkImageFilter> bg =
141 SkArithmeticImageFilter::Make(0, 0, -one / 2, 1, enforcePMColor, dstFilter);
143 p.setImageFilter(SkArithmeticImageFilter::Make(0, one / 2, -one, 1, true,
144 std::move(bg), dstFilter, nullptr));
145 canvas->saveLayer(&rect, &p);
147 canvas->translate(gap, 0);
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);
157 canvas->translate(0, HH + 12);
162 typedef GM INHERITED;
165 ///////////////////////////////////////////////////////////////////////////////
167 DEF_GM( return new ArithmodeGM; )