blob: aec079cfe2c1349c5db30bc1208e790fcd2c57ea [file] [log] [blame]
mike@reedtribe.orge51755f2011-12-10 19:36:56 +00001/*
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"
Brian Salomon89cb8212017-01-09 10:48:23 -05009#include "SkArithmeticImageFilter.h"
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000010#include "SkCanvas.h"
11#include "SkColorPriv.h"
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000012#include "SkGradientShader.h"
fmalitaad7cb812016-09-29 12:25:26 -070013#include "SkImage.h"
14#include "SkImageSource.h"
15#include "SkShader.h"
16#include "SkSurface.h"
fmalitaad7cb812016-09-29 12:25:26 -070017
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000018#define WW 100
19#define HH 32
20
fmalitaad7cb812016-09-29 12:25:26 -070021static sk_sp<SkImage> make_src() {
22 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
23 SkCanvas* canvas = surface->getCanvas();
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000024
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000025 SkPaint paint;
bsalomon@google.comcadbcb82012-01-06 19:22:11 +000026 SkPoint pts[] = { {0, 0}, {SkIntToScalar(WW), SkIntToScalar(HH)} };
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000027 SkColor colors[] = {
senorblanco@chromium.org35c733c2013-05-28 19:43:05 +000028 SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
29 SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000030 };
reed8a21c9f2016-03-08 18:50:00 -080031 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
32 SkShader::kClamp_TileMode));
fmalitaad7cb812016-09-29 12:25:26 -070033 canvas->drawPaint(paint);
34 return surface->makeImageSnapshot();
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000035}
36
fmalitaad7cb812016-09-29 12:25:26 -070037static sk_sp<SkImage> make_dst() {
38 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(WW, HH));
39 SkCanvas* canvas = surface->getCanvas();
40
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000041 SkPaint paint;
bsalomon@google.comcadbcb82012-01-06 19:22:11 +000042 SkPoint pts[] = { {0, SkIntToScalar(HH)}, {SkIntToScalar(WW), 0} };
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000043 SkColor colors[] = {
caryclarkdfcb7ab2015-07-17 09:39:16 -070044 SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
45 sk_tool_utils::color_to_565(SK_ColorGRAY)
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000046 };
reed8a21c9f2016-03-08 18:50:00 -080047 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
48 SkShader::kClamp_TileMode));
fmalitaad7cb812016-09-29 12:25:26 -070049 canvas->drawPaint(paint);
50 return surface->makeImageSnapshot();
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000051}
52
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000053static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
54 SkPaint paint;
reed@google.comeb0fa292011-12-12 22:01:06 +000055 paint.setTextSize(SkIntToScalar(24));
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000056 paint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -070057 sk_tool_utils::set_portable_typeface(&paint);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000058 for (int i = 0; i < 4; ++i) {
59 SkString str;
60 str.appendScalar(k[i]);
61 SkScalar width = paint.measureText(str.c_str(), str.size());
reed@google.comeb0fa292011-12-12 22:01:06 +000062 canvas->drawText(str.c_str(), str.size(), x, y + paint.getTextSize(), paint);
63 x += width + SkIntToScalar(10);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000064 }
65}
66
67class ArithmodeGM : public skiagm::GM {
68public:
69 ArithmodeGM () {}
70
71protected:
72
73 virtual SkString onShortName() {
74 return SkString("arithmode");
75 }
76
ericrkaf96fce2015-10-19 14:41:11 -070077 virtual SkISize onISize() { return SkISize::Make(640, 572); }
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000078
79 virtual void onDraw(SkCanvas* canvas) {
fmalitaad7cb812016-09-29 12:25:26 -070080 sk_sp<SkImage> src = make_src();
81 sk_sp<SkImage> dst = make_dst();
82 sk_sp<SkImageFilter> srcFilter = SkImageSource::Make(src);
83 sk_sp<SkImageFilter> dstFilter = SkImageSource::Make(dst);
rmistry@google.comae933ce2012-08-23 18:19:56 +000084
mtkleindbfd7ab2016-09-01 11:24:54 -070085 constexpr SkScalar one = SK_Scalar1;
86 constexpr SkScalar K[] = {
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000087 0, 0, 0, 0,
reed@google.comeb0fa292011-12-12 22:01:06 +000088 0, 0, 0, one,
89 0, one, 0, 0,
90 0, 0, one, 0,
91 0, one, one, 0,
92 0, one, -one, 0,
93 0, one/2, one/2, 0,
94 0, one/2, one/2, one/4,
95 0, one/2, one/2, -one/4,
96 one/4, one/2, one/2, 0,
97 -one/4, one/2, one/2, 0,
mike@reedtribe.orge51755f2011-12-10 19:36:56 +000098 };
rmistry@google.comae933ce2012-08-23 18:19:56 +000099
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000100 const SkScalar* k = K;
101 const SkScalar* stop = k + SK_ARRAY_COUNT(K);
fmalitaad7cb812016-09-29 12:25:26 -0700102 const SkRect rect = SkRect::MakeWH(WW, HH);
103 SkScalar gap = SkIntToScalar(WW + 20);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000104 while (k < stop) {
fmalitaad7cb812016-09-29 12:25:26 -0700105 {
106 SkAutoCanvasRestore acr(canvas, true);
107 canvas->drawImage(src, 0, 0);
108 canvas->translate(gap, 0);
109 canvas->drawImage(dst, 0, 0);
110 canvas->translate(gap, 0);
111 SkPaint paint;
Brian Salomon89cb8212017-01-09 10:48:23 -0500112 paint.setImageFilter(SkArithmeticImageFilter::Make(k[0], k[1], k[2], k[3], true,
113 dstFilter, srcFilter, nullptr));
fmalitaad7cb812016-09-29 12:25:26 -0700114 canvas->saveLayer(&rect, &paint);
115 canvas->restore();
116
117 canvas->translate(gap, 0);
118 show_k_text(canvas, 0, 0, k);
119 }
120
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000121 k += 4;
fmalitaad7cb812016-09-29 12:25:26 -0700122 canvas->translate(0, HH + 12);
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000123 }
ericrkaf96fce2015-10-19 14:41:11 -0700124
125 // Draw two special cases to test enforcePMColor. In these cases, we
126 // draw the dst bitmap twice, the first time it is halved and inverted,
127 // leading to invalid premultiplied colors. If we enforcePMColor, these
128 // invalid values should be clamped, and will not contribute to the
129 // second draw.
130 for (int i = 0; i < 2; i++) {
131 const bool enforcePMColor = (i == 0);
ericrkaf96fce2015-10-19 14:41:11 -0700132
fmalitaad7cb812016-09-29 12:25:26 -0700133 {
134 SkAutoCanvasRestore acr(canvas, true);
135 canvas->translate(gap, 0);
136 canvas->drawImage(dst, 0, 0);
137 canvas->translate(gap, 0);
ericrkaf96fce2015-10-19 14:41:11 -0700138
fmalitaad7cb812016-09-29 12:25:26 -0700139 sk_sp<SkImageFilter> bg =
Brian Salomon89cb8212017-01-09 10:48:23 -0500140 SkArithmeticImageFilter::Make(0, 0, -one / 2, 1, enforcePMColor, dstFilter);
fmalitaad7cb812016-09-29 12:25:26 -0700141 SkPaint p;
Brian Salomon89cb8212017-01-09 10:48:23 -0500142 p.setImageFilter(SkArithmeticImageFilter::Make(0, one / 2, -one, 1, true,
143 std::move(bg), dstFilter, nullptr));
fmalitaad7cb812016-09-29 12:25:26 -0700144 canvas->saveLayer(&rect, &p);
145 canvas->restore();
146 canvas->translate(gap, 0);
147
148 // Label
149 SkPaint paint;
150 paint.setTextSize(SkIntToScalar(24));
151 paint.setAntiAlias(true);
152 sk_tool_utils::set_portable_typeface(&paint);
153 SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
154 canvas->drawText(str.c_str(), str.size(), 0, paint.getTextSize(), paint);
155 }
156 canvas->translate(0, HH + 12);
ericrkaf96fce2015-10-19 14:41:11 -0700157 }
mike@reedtribe.orge51755f2011-12-10 19:36:56 +0000158 }
159
160private:
161 typedef GM INHERITED;
162};
163
164///////////////////////////////////////////////////////////////////////////////
165
scroggo96f16e82015-12-10 13:31:59 -0800166DEF_GM( return new ArithmodeGM; )