Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 8 | #include "gm/gm.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 9 | #include "include/core/SkBlendMode.h" |
| 10 | #include "include/core/SkBlurTypes.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "include/core/SkCanvas.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 12 | #include "include/core/SkColor.h" |
| 13 | #include "include/core/SkCoverageMode.h" |
| 14 | #include "include/core/SkFont.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 15 | #include "include/core/SkImage.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 16 | #include "include/core/SkImageFilter.h" |
| 17 | #include "include/core/SkImageInfo.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 18 | #include "include/core/SkMaskFilter.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 19 | #include "include/core/SkMatrix.h" |
| 20 | #include "include/core/SkPaint.h" |
| 21 | #include "include/core/SkPath.h" |
| 22 | #include "include/core/SkPicture.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 23 | #include "include/core/SkPictureRecorder.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 24 | #include "include/core/SkPoint.h" |
| 25 | #include "include/core/SkRect.h" |
| 26 | #include "include/core/SkRefCnt.h" |
| 27 | #include "include/core/SkScalar.h" |
| 28 | #include "include/core/SkShader.h" |
| 29 | #include "include/core/SkString.h" |
| 30 | #include "include/core/SkSurface.h" |
| 31 | #include "include/core/SkTileMode.h" |
| 32 | #include "include/core/SkTypes.h" |
| 33 | #include "include/effects/SkBlurImageFilter.h" |
| 34 | #include "include/effects/SkGradientShader.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 35 | #include "include/effects/SkShaderMaskFilter.h" |
| 36 | #include "include/utils/SkTextUtils.h" |
| 37 | #include "src/core/SkBlendModePriv.h" |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 38 | #include "tools/Resources.h" |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 39 | #include "tools/ToolUtils.h" |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 40 | |
Ben Wagner | 7fde8e1 | 2019-05-01 17:28:53 -0400 | [diff] [blame] | 41 | #include <initializer_list> |
| 42 | |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 43 | static void draw_masked_image(SkCanvas* canvas, const SkImage* image, SkScalar x, SkScalar y, |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 44 | const SkImage* mask, sk_sp<SkMaskFilter> outer, SkBlendMode mode) { |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 45 | SkMatrix matrix = SkMatrix::MakeScale(SkIntToScalar(image->width()) / mask->width(), |
| 46 | SkIntToScalar(image->height() / mask->height())); |
Michael Ludwig | b7d64b9 | 2019-02-11 11:09:15 -0500 | [diff] [blame] | 47 | // The geometry of the drawImage is also translated by (x,y) so make the mask filter's |
| 48 | // coordinate system align with the rendered rectangle. |
| 49 | matrix.postTranslate(x, y); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 50 | SkPaint paint; |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 51 | auto mf = SkShaderMaskFilter::Make(mask->makeShader(&matrix)); |
| 52 | if (outer) { |
Michael Ludwig | b7d64b9 | 2019-02-11 11:09:15 -0500 | [diff] [blame] | 53 | mf = SkMaskFilter::MakeCompose(outer->makeWithMatrix(matrix), mf); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 54 | } |
| 55 | paint.setMaskFilter(mf); |
Mike Reed | 28eaed2 | 2018-02-01 11:24:53 -0500 | [diff] [blame] | 56 | paint.setAntiAlias(true); |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 57 | paint.setBlendMode(mode); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 58 | canvas->drawImage(image, x, y, &paint); |
| 59 | } |
| 60 | |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 61 | static sk_sp<SkShader> make_shader(const SkRect& r) { |
| 62 | const SkPoint pts[] = { |
| 63 | { r.fLeft, r.fTop }, { r.fRight, r.fBottom }, |
| 64 | }; |
| 65 | const SkColor colors[] = { 0, SK_ColorWHITE }; |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 66 | return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kRepeat); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | DEF_SIMPLE_GM(shadermaskfilter_gradient, canvas, 512, 512) { |
| 70 | SkRect r = { 0, 0, 100, 150 }; |
| 71 | auto shader = make_shader(r); |
| 72 | auto mf = SkShaderMaskFilter::Make(shader); |
| 73 | |
| 74 | canvas->translate(20, 20); |
| 75 | canvas->scale(2, 2); |
| 76 | |
| 77 | SkPaint paint; |
| 78 | paint.setMaskFilter(mf); |
| 79 | paint.setColor(SK_ColorRED); |
Mike Reed | 28eaed2 | 2018-02-01 11:24:53 -0500 | [diff] [blame] | 80 | paint.setAntiAlias(true); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 81 | canvas->drawOval(r, paint); |
| 82 | } |
| 83 | |
Chris Dalton | 50e24d7 | 2019-02-07 16:20:09 -0700 | [diff] [blame] | 84 | DEF_SIMPLE_GM_CAN_FAIL(shadermaskfilter_image, canvas, errorMsg, 560, 370) { |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 85 | canvas->scale(1.25f, 1.25f); |
| 86 | |
| 87 | auto image = GetResourceAsImage("images/mandrill_128.png"); |
| 88 | auto mask = GetResourceAsImage("images/color_wheel.png"); |
Hal Canary | baa2a28 | 2018-11-26 15:34:12 -0500 | [diff] [blame] | 89 | if (!image || !mask) { |
Chris Dalton | 50e24d7 | 2019-02-07 16:20:09 -0700 | [diff] [blame] | 90 | *errorMsg = "Could not load images. Did you forget to set the resourcePath?"; |
| 91 | return skiagm::DrawResult::kFail; |
Hal Canary | baa2a28 | 2018-11-26 15:34:12 -0500 | [diff] [blame] | 92 | } |
Mike Reed | 1be1f8d | 2018-03-14 13:01:17 -0400 | [diff] [blame] | 93 | auto blurmf = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5); |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 94 | auto gradmf = SkShaderMaskFilter::Make(make_shader(SkRect::MakeIWH(mask->width(), |
| 95 | mask->height()))); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 96 | |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 97 | const sk_sp<SkMaskFilter> array[] = { nullptr , blurmf, gradmf }; |
| 98 | for (SkBlendMode mode : {SkBlendMode::kSrcOver, SkBlendMode::kSrcIn}) { |
| 99 | canvas->save(); |
| 100 | for (sk_sp<SkMaskFilter> mf : array) { |
| 101 | draw_masked_image(canvas, image.get(), 10, 10, mask.get(), mf, mode); |
| 102 | canvas->translate(image->width() + 20.f, 0); |
| 103 | } |
| 104 | canvas->restore(); |
| 105 | canvas->translate(0, image->height() + 20.f); |
| 106 | } |
Chris Dalton | 50e24d7 | 2019-02-07 16:20:09 -0700 | [diff] [blame] | 107 | return skiagm::DrawResult::kOk; |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 108 | } |
| 109 | |
| 110 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 111 | |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 112 | static sk_sp<SkMaskFilter> make_path_mf(const SkPath& path, unsigned alpha) { |
| 113 | SkPaint paint; |
| 114 | paint.setAntiAlias(true); |
| 115 | paint.setAlpha(alpha); |
| 116 | |
| 117 | SkPictureRecorder recorder; |
| 118 | recorder.beginRecording(1000, 1000)->drawPath(path, paint); |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 119 | auto shader = recorder.finishRecordingAsPicture()->makeShader(SkTileMode::kClamp, |
| 120 | SkTileMode::kClamp); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 121 | return SkShaderMaskFilter::Make(shader); |
| 122 | } |
| 123 | |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 124 | typedef void (*MakePathsProc)(const SkRect&, SkPath*, SkPath*); |
| 125 | |
| 126 | const char* gCoverageName[] = { |
| 127 | "union", "sect", "diff", "rev-diff", "xor" |
| 128 | }; |
| 129 | |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 130 | DEF_SIMPLE_GM(combinemaskfilter, canvas, 560, 510) { |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 131 | const SkRect r = { 0, 0, 100, 100 }; |
| 132 | |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 133 | SkPaint paint; |
| 134 | paint.setColor(SK_ColorRED); |
| 135 | |
Mike Reed | dc5863c | 2018-12-23 23:19:14 -0500 | [diff] [blame] | 136 | SkFont font; |
| 137 | font.setSize(20); |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 138 | |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 139 | const SkRect r2 = r.makeOutset(1.5f, 1.5f); |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 140 | SkPaint strokePaint; |
| 141 | strokePaint.setStyle(SkPaint::kStroke_Style); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 142 | |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 143 | auto proc0 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) { |
| 144 | pathA->moveTo(r.fLeft, r.fBottom); |
| 145 | pathA->lineTo(r.fRight, r.fTop); |
| 146 | pathA->lineTo(r.fRight, r.fBottom); |
| 147 | pathB->moveTo(r.fLeft, r.fTop); |
| 148 | pathB->lineTo(r.fRight, r.fBottom); |
| 149 | pathB->lineTo(r.fLeft, r.fBottom); |
| 150 | }; |
| 151 | auto proc1 = [](const SkRect& r, SkPath* pathA, SkPath* pathB) { |
| 152 | pathA->addCircle(r.width()*0.25f, r.height()*0.25f, r.width()*0.5f); |
| 153 | pathB->addCircle(r.width()*0.75f, r.height()*0.75f, r.width()*0.5f); |
| 154 | }; |
| 155 | MakePathsProc procs[] = { proc0, proc1 }; |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 156 | |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 157 | sk_sp<SkMaskFilter> mfA[2], mfB[2]; |
| 158 | for (int i = 0; i < 2; ++i) { |
| 159 | SkPath a, b; |
| 160 | procs[i](r, &a, &b); |
| 161 | mfA[i] = make_path_mf(a, 1 * 0xFF / 3); |
| 162 | mfB[i] = make_path_mf(b, 2 * 0xFF / 3); |
| 163 | } |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 164 | |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 165 | canvas->translate(10, 10 + 20); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 166 | canvas->save(); |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 167 | for (int i = 0; i < 5; ++i) { |
Mike Reed | dc5863c | 2018-12-23 23:19:14 -0500 | [diff] [blame] | 168 | SkTextUtils::DrawString(canvas, gCoverageName[i], r.width()*0.5f, -10, font, SkPaint(), |
Mike Reed | 3a42ec0 | 2018-10-30 12:53:21 -0400 | [diff] [blame] | 169 | SkTextUtils::kCenter_Align); |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 170 | |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 171 | SkCoverageMode cmode = static_cast<SkCoverageMode>(i); |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 172 | canvas->save(); |
Mike Reed | 547c859 | 2018-02-05 15:59:23 -0500 | [diff] [blame] | 173 | // esp. on gpu side, its valuable to exercise modes that do and do-not convolve coverage |
| 174 | // with alpha. SrcOver and SrcIn have these properties, but also happen to "look" the same |
| 175 | // for this test. |
| 176 | const SkBlendMode bmodes[] = { SkBlendMode::kSrcOver, SkBlendMode::kSrcIn }; |
| 177 | SkASSERT( SkBlendMode_SupportsCoverageAsAlpha(bmodes[0])); // test as-alpha |
| 178 | SkASSERT(!SkBlendMode_SupportsCoverageAsAlpha(bmodes[1])); // test not-as-alpha |
| 179 | for (auto bmode : bmodes) { |
| 180 | paint.setBlendMode(bmode); |
| 181 | for (int j = 0; j < 2; ++j) { |
| 182 | paint.setMaskFilter(SkMaskFilter::MakeCombine(mfA[j], mfB[j], cmode)); |
| 183 | canvas->drawRect(r2, strokePaint); |
| 184 | canvas->drawRect(r, paint); |
| 185 | canvas->translate(0, r.height() + 10); |
| 186 | } |
| 187 | canvas->translate(0, 40); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 188 | } |
Mike Reed | 1bd556a | 2018-01-26 11:42:38 -0500 | [diff] [blame] | 189 | canvas->restore(); |
| 190 | canvas->translate(r.width() + 10, 0); |
Mike Reed | 20dc672 | 2018-01-24 16:34:02 -0500 | [diff] [blame] | 191 | } |
| 192 | canvas->restore(); |
Mike Reed | 6e87eee | 2018-01-18 16:06:54 -0500 | [diff] [blame] | 193 | } |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 194 | |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 195 | static sk_sp<SkImage> make_circle_image(SkCanvas* canvas, SkScalar radius, int margin) { |
| 196 | const int n = SkScalarCeilToInt(radius) * 2 + margin * 2; |
Mike Klein | ea3f014 | 2019-03-20 11:12:10 -0500 | [diff] [blame] | 197 | auto surf = ToolUtils::makeSurface(canvas, SkImageInfo::MakeN32Premul(n, n)); |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 198 | SkPaint paint; |
| 199 | paint.setAntiAlias(true); |
| 200 | surf->getCanvas()->drawCircle(n * 0.5f, n * 0.5f, radius, paint); |
| 201 | return surf->makeImageSnapshot(); |
| 202 | } |
| 203 | |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 204 | DEF_SIMPLE_GM(savelayer_maskfilter, canvas, 450, 675) { |
| 205 | auto layerImage = GetResourceAsImage("images/mandrill_128.png"); |
| 206 | auto maskImage = make_circle_image(canvas, 50, 1); |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 207 | SkRect r = SkRect::MakeWH(102, 102); |
| 208 | |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 209 | SkPaint overlayPaint; |
| 210 | overlayPaint.setStyle(SkPaint::kStroke_Style); |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 211 | |
| 212 | // test that the maskfilter sees these changes to the ctm |
| 213 | canvas->translate(10, 10); |
| 214 | canvas->scale(2, 2); |
| 215 | |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 216 | sk_sp<SkMaskFilter> mfs[] = { |
| 217 | SkShaderMaskFilter::Make(maskImage->makeShader()), |
Mike Reed | 1be1f8d | 2018-03-14 13:01:17 -0400 | [diff] [blame] | 218 | SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 3.5f), |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 219 | nullptr, |
| 220 | }; |
| 221 | mfs[2] = SkMaskFilter::MakeCompose(mfs[1], mfs[0]); |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 222 | |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 223 | // Important that we test with and without an imagefilter attached to the layer, |
| 224 | // as cpu and gpu backends treat these differently (w/ or w/o a SkSpecialImage) |
| 225 | const sk_sp<SkImageFilter> imfs[] = {nullptr, SkBlurImageFilter::Make(3.5f, 3.5f, nullptr)}; |
| 226 | |
Mike Reed | b9fc24e | 2018-02-08 14:00:56 -0500 | [diff] [blame] | 227 | for (auto& mf : mfs) { |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 228 | SkPaint layerPaint; |
| 229 | layerPaint.setMaskFilter(mf); |
| 230 | canvas->save(); |
Mike Reed | b9fc24e | 2018-02-08 14:00:56 -0500 | [diff] [blame] | 231 | for (auto& imf : imfs) { |
Mike Reed | 2179b78 | 2018-02-07 11:59:57 -0500 | [diff] [blame] | 232 | layerPaint.setImageFilter(imf); |
| 233 | |
| 234 | canvas->saveLayer(&r, &layerPaint); |
| 235 | canvas->drawImage(layerImage, 0, 0, nullptr); |
| 236 | canvas->restore(); |
| 237 | |
| 238 | // now draw the (approximage) expected bounds of the mask |
| 239 | canvas->drawRect(r.makeOutset(1, 1), overlayPaint); |
| 240 | |
| 241 | canvas->translate(r.width() + 10, 0); |
| 242 | } |
| 243 | canvas->restore(); |
| 244 | canvas->translate(0, r.height() + 10); |
| 245 | } |
Mike Reed | be33bab | 2018-02-06 16:07:51 -0500 | [diff] [blame] | 246 | } |
| 247 | |
Florin Malita | c6c5ead | 2018-04-11 15:33:40 -0400 | [diff] [blame] | 248 | static void draw_mask(SkCanvas* canvas) { |
| 249 | SkPaint p; |
| 250 | p.setAntiAlias(true); |
| 251 | canvas->drawOval(SkRect::Make(canvas->imageInfo().bounds()), p); |
| 252 | } |
| 253 | |
| 254 | DEF_SIMPLE_GM(shadermaskfilter_localmatrix, canvas, 1500, 1000) { |
| 255 | static constexpr SkScalar kSize = 100; |
| 256 | |
| 257 | using ShaderMakerT = sk_sp<SkShader>(*)(SkCanvas*, const SkMatrix& lm); |
| 258 | static const ShaderMakerT gShaderMakers[] = { |
Mike Klein | ea3f014 | 2019-03-20 11:12:10 -0500 | [diff] [blame] | 259 | [](SkCanvas* canvas, const SkMatrix& lm) -> sk_sp<SkShader> { |
| 260 | auto surface = |
| 261 | ToolUtils::makeSurface(canvas, SkImageInfo::MakeN32Premul(kSize, kSize)); |
| 262 | draw_mask(surface->getCanvas()); |
| 263 | return surface->makeImageSnapshot()->makeShader( |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 264 | SkTileMode::kClamp, SkTileMode::kClamp, &lm); |
Mike Klein | ea3f014 | 2019-03-20 11:12:10 -0500 | [diff] [blame] | 265 | }, |
| 266 | [](SkCanvas*, const SkMatrix& lm) -> sk_sp<SkShader> { |
| 267 | SkPictureRecorder recorder; |
| 268 | draw_mask(recorder.beginRecording(kSize, kSize)); |
Mike Reed | fae8fce | 2019-04-03 10:27:45 -0400 | [diff] [blame] | 269 | return recorder.finishRecordingAsPicture()->makeShader( |
| 270 | SkTileMode::kClamp, |
| 271 | SkTileMode::kClamp, |
Mike Klein | ea3f014 | 2019-03-20 11:12:10 -0500 | [diff] [blame] | 272 | &lm, |
| 273 | nullptr); |
| 274 | }, |
Florin Malita | c6c5ead | 2018-04-11 15:33:40 -0400 | [diff] [blame] | 275 | }; |
| 276 | |
| 277 | struct Config { |
| 278 | SkMatrix fCanvasMatrix, |
| 279 | fMaskMatrix, |
| 280 | fShaderMatrix; |
| 281 | } gConfigs[] = { |
| 282 | { SkMatrix::I(), SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10) }, |
| 283 | { SkMatrix::MakeScale(2, 2), SkMatrix::I(), SkMatrix::MakeTrans(10, 10) }, |
| 284 | { SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10), SkMatrix::I() }, |
| 285 | { SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)), |
| 286 | SkMatrix::I(), SkMatrix::I() }, |
| 287 | { SkMatrix::I(), |
| 288 | SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)), |
| 289 | SkMatrix::I() }, |
| 290 | { SkMatrix::I(), SkMatrix::I(), |
| 291 | SkMatrix::Concat(SkMatrix::MakeScale(2, 2), SkMatrix::MakeTrans(10, 10)) }, |
| 292 | }; |
| 293 | |
| 294 | using DrawerT = void(*)(SkCanvas*, const SkRect&, const SkPaint&); |
| 295 | static const DrawerT gDrawers[] = { |
| 296 | [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) { |
| 297 | canvas->drawRect(dest, mask); |
| 298 | }, |
| 299 | [](SkCanvas* canvas, const SkRect& dest, const SkPaint& mask) { |
| 300 | canvas->saveLayer(&dest, &mask); |
| 301 | SkPaint p = mask; |
| 302 | p.setMaskFilter(nullptr); |
| 303 | canvas->drawPaint(p); |
| 304 | canvas->restore(); |
| 305 | }, |
| 306 | }; |
| 307 | |
| 308 | SkPaint paint, rectPaint; |
| 309 | paint.setColor(0xff00ff00); |
| 310 | rectPaint.setStyle(SkPaint::kStroke_Style); |
| 311 | rectPaint.setColor(0xffff0000); |
| 312 | |
| 313 | for (const auto& sm : gShaderMakers) { |
| 314 | for (const auto& drawer : gDrawers) { |
| 315 | { |
| 316 | SkAutoCanvasRestore acr(canvas, true); |
| 317 | for (const auto& cfg : gConfigs) { |
| 318 | paint.setMaskFilter(SkShaderMaskFilter::Make(sm(canvas, cfg.fShaderMatrix)) |
| 319 | ->makeWithMatrix(cfg.fMaskMatrix)); |
| 320 | auto dest = SkRect::MakeWH(kSize, kSize); |
| 321 | SkMatrix::Concat(cfg.fMaskMatrix, cfg.fShaderMatrix).mapRect(&dest); |
| 322 | |
| 323 | { |
| 324 | SkAutoCanvasRestore acr(canvas, true); |
| 325 | canvas->concat(cfg.fCanvasMatrix); |
| 326 | drawer(canvas, dest, paint); |
| 327 | canvas->drawRect(dest, rectPaint); |
| 328 | } |
| 329 | |
| 330 | canvas->translate(kSize * 2.5f, 0); |
| 331 | } |
| 332 | } |
| 333 | canvas->translate(0, kSize * 2.5f); |
| 334 | } |
| 335 | |
| 336 | } |
| 337 | } |