1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "gm/gm.h" 9cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 10cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 11cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 12cb93a386Sopenharmony_ci#include "include/core/SkFont.h" 13cb93a386Sopenharmony_ci#include "include/core/SkImageFilter.h" 14cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 15cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 16cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 17cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 18cb93a386Sopenharmony_ci#include "include/core/SkShader.h" 19cb93a386Sopenharmony_ci#include "include/core/SkSize.h" 20cb93a386Sopenharmony_ci#include "include/core/SkString.h" 21cb93a386Sopenharmony_ci#include "include/core/SkTileMode.h" 22cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 23cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 24cb93a386Sopenharmony_ci#include "include/effects/SkImageFilters.h" 25cb93a386Sopenharmony_ci#include "src/gpu/effects/GrMatrixConvolutionEffect.h" 26cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci#include <vector> 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cinamespace skiagm { 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cienum KernelFixture { 33cb93a386Sopenharmony_ci kBasic_KernelFixture, 34cb93a386Sopenharmony_ci kLarge_KernelFixture 35cb93a386Sopenharmony_ci}; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciclass MatrixConvolutionGM : public GM { 38cb93a386Sopenharmony_cipublic: 39cb93a386Sopenharmony_ci MatrixConvolutionGM(SkColor colorOne, SkColor colorTwo, KernelFixture kernelFixture, const char* nameSuffix) 40cb93a386Sopenharmony_ci : fNameSuffix(nameSuffix), 41cb93a386Sopenharmony_ci fKernelFixture(kernelFixture) { 42cb93a386Sopenharmony_ci this->setBGColor(0x00000000); 43cb93a386Sopenharmony_ci fColors[0] = colorOne; 44cb93a386Sopenharmony_ci fColors[1] = colorTwo; 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ciprotected: 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci SkString onShortName() override { 50cb93a386Sopenharmony_ci return SkStringPrintf("matrixconvolution%s", fNameSuffix); 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci void makeBitmap() { 54cb93a386Sopenharmony_ci // Draw our bitmap in N32, so legacy devices get "premul" values they understand 55cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterN32Premul(80, 80); 56cb93a386Sopenharmony_ci SkPaint paint; 57cb93a386Sopenharmony_ci paint.setColor(0xFFFFFFFF); 58cb93a386Sopenharmony_ci SkPoint pts[2] = { {0, 0}, 59cb93a386Sopenharmony_ci {0, 80.0f} }; 60cb93a386Sopenharmony_ci SkScalar pos[2] = { 0, 80.0f }; 61cb93a386Sopenharmony_ci paint.setShader(SkGradientShader::MakeLinear( 62cb93a386Sopenharmony_ci pts, fColors, pos, 2, SkTileMode::kClamp)); 63cb93a386Sopenharmony_ci SkFont font(ToolUtils::create_portable_typeface(), 180.0f); 64cb93a386Sopenharmony_ci surf->getCanvas()->drawString("e", -10.0f, 80.0f, font, paint); 65cb93a386Sopenharmony_ci fImage = surf->makeImageSnapshot(); 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci SkISize onISize() override { 69cb93a386Sopenharmony_ci return SkISize::Make(500, 300); 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci sk_sp<SkImageFilter> makeFilter(const SkIPoint &kernelOffset, SkTileMode tileMode, 73cb93a386Sopenharmony_ci bool convolveAlpha, const SkIRect *cropRect = nullptr) { 74cb93a386Sopenharmony_ci switch (fKernelFixture) { 75cb93a386Sopenharmony_ci case kBasic_KernelFixture: { 76cb93a386Sopenharmony_ci // All 1s except center value, which is -7 (sum of 1). 77cb93a386Sopenharmony_ci std::vector<SkScalar> kernel(9, SkIntToScalar(1)); 78cb93a386Sopenharmony_ci kernel[4] = SkIntToScalar(-7); 79cb93a386Sopenharmony_ci return SkImageFilters::MatrixConvolution({3,3}, kernel.data(), /* gain */ 0.3f, /* bias */ SkIntToScalar(100), kernelOffset, tileMode, convolveAlpha, nullptr, cropRect); 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci case kLarge_KernelFixture: { 82cb93a386Sopenharmony_ci static_assert(49 > GrMatrixConvolutionEffect::kMaxUniformSize); 83cb93a386Sopenharmony_ci // All 1s except center value, which is -47 (sum of 1). 84cb93a386Sopenharmony_ci std::vector<SkScalar> kernel(49, SkIntToScalar(1)); 85cb93a386Sopenharmony_ci kernel[24] = SkIntToScalar(-47); 86cb93a386Sopenharmony_ci return SkImageFilters::MatrixConvolution({7,7}, kernel.data(), /* gain */ 0.3f, /* bias */ SkIntToScalar(100), kernelOffset, tileMode, convolveAlpha, nullptr, cropRect); 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci default: 89cb93a386Sopenharmony_ci return nullptr; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci 93cb93a386Sopenharmony_ci void draw(SkCanvas* canvas, int x, int y, const SkIPoint& kernelOffset, 94cb93a386Sopenharmony_ci SkTileMode tileMode, bool convolveAlpha, 95cb93a386Sopenharmony_ci const SkIRect* cropRect = nullptr) { 96cb93a386Sopenharmony_ci SkPaint paint; 97cb93a386Sopenharmony_ci paint.setImageFilter(this->makeFilter(kernelOffset, tileMode, convolveAlpha, cropRect)); 98cb93a386Sopenharmony_ci canvas->save(); 99cb93a386Sopenharmony_ci canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 100cb93a386Sopenharmony_ci const SkRect layerBounds = SkRect::Make(fImage->bounds()); 101cb93a386Sopenharmony_ci canvas->clipRect(layerBounds); 102cb93a386Sopenharmony_ci // This GM is, in part, intended to display the wrapping behavior of the 103cb93a386Sopenharmony_ci // matrix image filter. The only (rational) way to achieve that for repeat mode 104cb93a386Sopenharmony_ci // is to create a tight layer. 105cb93a386Sopenharmony_ci canvas->saveLayer(layerBounds, &paint); 106cb93a386Sopenharmony_ci canvas->drawImage(fImage, 0, 0); 107cb93a386Sopenharmony_ci canvas->restore(); 108cb93a386Sopenharmony_ci canvas->restore(); 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci void onOnceBeforeDraw() override { 112cb93a386Sopenharmony_ci this->makeBitmap(); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ci void onDraw(SkCanvas* canvas) override { 116cb93a386Sopenharmony_ci canvas->clear(SK_ColorBLACK); 117cb93a386Sopenharmony_ci SkIPoint kernelOffset = SkIPoint::Make(1, 0); 118cb93a386Sopenharmony_ci SkIRect rect = fImage->bounds(); 119cb93a386Sopenharmony_ci for (int x = 10; x < 310; x += 100) { 120cb93a386Sopenharmony_ci this->draw(canvas, x, 10, kernelOffset, SkTileMode::kClamp, true, &rect); 121cb93a386Sopenharmony_ci this->draw(canvas, x, 110, kernelOffset, SkTileMode::kDecal, true, &rect); 122cb93a386Sopenharmony_ci this->draw(canvas, x, 210, kernelOffset, SkTileMode::kRepeat, true, &rect); 123cb93a386Sopenharmony_ci kernelOffset.fY++; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci kernelOffset.fY = 1; 126cb93a386Sopenharmony_ci SkIRect smallRect = SkIRect::MakeXYWH(10, 5, 60, 60); 127cb93a386Sopenharmony_ci this->draw(canvas, 310, 10, kernelOffset, SkTileMode::kClamp, true, &smallRect); 128cb93a386Sopenharmony_ci this->draw(canvas, 310, 110, kernelOffset, SkTileMode::kDecal, true, &smallRect); 129cb93a386Sopenharmony_ci this->draw(canvas, 310, 210, kernelOffset, SkTileMode::kRepeat, true, &smallRect); 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci this->draw(canvas, 410, 10, kernelOffset, SkTileMode::kClamp, false, &rect); 132cb93a386Sopenharmony_ci this->draw(canvas, 410, 110, kernelOffset, SkTileMode::kDecal, false, &rect); 133cb93a386Sopenharmony_ci this->draw(canvas, 410, 210, kernelOffset, SkTileMode::kRepeat, false, &rect); 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ciprivate: 137cb93a386Sopenharmony_ci sk_sp<SkImage> fImage; 138cb93a386Sopenharmony_ci SkColor fColors[2]; 139cb93a386Sopenharmony_ci const char* fNameSuffix; 140cb93a386Sopenharmony_ci KernelFixture fKernelFixture; 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci using INHERITED = GM; 143cb93a386Sopenharmony_ci}; 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ciDEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, KernelFixture::kBasic_KernelFixture, "");) 148cb93a386Sopenharmony_ciDEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, KernelFixture::kBasic_KernelFixture, "_color");) 149cb93a386Sopenharmony_ciDEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, KernelFixture::kLarge_KernelFixture, "_big");) 150cb93a386Sopenharmony_ciDEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, KernelFixture::kLarge_KernelFixture, "_big_color");) 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci} // namespace skiagm 153