1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h" 9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h" 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h" 19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h" 20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h" 23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h" 24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h" 25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h" 26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h" 27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h" 28*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h" 29*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 30*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h" 31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h" 32*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h" 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker #include <string.h> 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm { 37*c8dee2aaSAndroid Build Coastguard Worker 38*c8dee2aaSAndroid Build Coastguard Worker /** 39*c8dee2aaSAndroid Build Coastguard Worker * This tests drawing device-covering rects with solid colors and bitmap shaders over a 40*c8dee2aaSAndroid Build Coastguard Worker * checkerboard background using different xfermodes. 41*c8dee2aaSAndroid Build Coastguard Worker */ 42*c8dee2aaSAndroid Build Coastguard Worker class Xfermodes3GM : public GM { 43*c8dee2aaSAndroid Build Coastguard Worker public: Xfermodes3GM()44*c8dee2aaSAndroid Build Coastguard Worker Xfermodes3GM() { this->setBGColor(ToolUtils::color_to_565(0xFF70D0E0)); } 45*c8dee2aaSAndroid Build Coastguard Worker 46*c8dee2aaSAndroid Build Coastguard Worker protected: getName() const47*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("xfermodes3"); } 48*c8dee2aaSAndroid Build Coastguard Worker getISize()49*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(630, 1215); } 50*c8dee2aaSAndroid Build Coastguard Worker onDraw(SkCanvas * canvas)51*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override { 52*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(SkIntToScalar(10), SkIntToScalar(20)); 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultPortableFont(); 55*c8dee2aaSAndroid Build Coastguard Worker SkPaint labelP; 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor kSolidColors[] = { 58*c8dee2aaSAndroid Build Coastguard Worker SK_ColorTRANSPARENT, 59*c8dee2aaSAndroid Build Coastguard Worker SK_ColorBLUE, 60*c8dee2aaSAndroid Build Coastguard Worker 0x80808000 61*c8dee2aaSAndroid Build Coastguard Worker }; 62*c8dee2aaSAndroid Build Coastguard Worker 63*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor kBmpAlphas[] = { 64*c8dee2aaSAndroid Build Coastguard Worker 0xff, 65*c8dee2aaSAndroid Build Coastguard Worker 0x80, 66*c8dee2aaSAndroid Build Coastguard Worker }; 67*c8dee2aaSAndroid Build Coastguard Worker 68*c8dee2aaSAndroid Build Coastguard Worker auto tempSurface(this->makeTempSurface(canvas, kSize, kSize)); 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker int test = 0; 71*c8dee2aaSAndroid Build Coastguard Worker int x = 0, y = 0; 72*c8dee2aaSAndroid Build Coastguard Worker constexpr struct { SkPaint::Style fStyle; SkScalar fWidth; } kStrokes[] = { 73*c8dee2aaSAndroid Build Coastguard Worker {SkPaint::kFill_Style, 0}, 74*c8dee2aaSAndroid Build Coastguard Worker {SkPaint::kStroke_Style, SkIntToScalar(kSize) / 2}, 75*c8dee2aaSAndroid Build Coastguard Worker }; 76*c8dee2aaSAndroid Build Coastguard Worker for (size_t s = 0; s < std::size(kStrokes); ++s) { 77*c8dee2aaSAndroid Build Coastguard Worker for (size_t m = 0; m < kSkBlendModeCount; ++m) { 78*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode = static_cast<SkBlendMode>(m); 79*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(SkBlendMode_Name(mode), 80*c8dee2aaSAndroid Build Coastguard Worker SkIntToScalar(x), 81*c8dee2aaSAndroid Build Coastguard Worker SkIntToScalar(y + kSize + 3) + font.getSize(), 82*c8dee2aaSAndroid Build Coastguard Worker font, labelP); 83*c8dee2aaSAndroid Build Coastguard Worker for (size_t c = 0; c < std::size(kSolidColors); ++c) { 84*c8dee2aaSAndroid Build Coastguard Worker SkPaint modePaint; 85*c8dee2aaSAndroid Build Coastguard Worker modePaint.setBlendMode(mode); 86*c8dee2aaSAndroid Build Coastguard Worker modePaint.setColor(kSolidColors[c]); 87*c8dee2aaSAndroid Build Coastguard Worker modePaint.setStyle(kStrokes[s].fStyle); 88*c8dee2aaSAndroid Build Coastguard Worker modePaint.setStrokeWidth(kStrokes[s].fWidth); 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempSurface.get()); 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker ++test; 93*c8dee2aaSAndroid Build Coastguard Worker x += kSize + 10; 94*c8dee2aaSAndroid Build Coastguard Worker if (!(test % kTestsPerRow)) { 95*c8dee2aaSAndroid Build Coastguard Worker x = 0; 96*c8dee2aaSAndroid Build Coastguard Worker y += kSize + 30; 97*c8dee2aaSAndroid Build Coastguard Worker } 98*c8dee2aaSAndroid Build Coastguard Worker } 99*c8dee2aaSAndroid Build Coastguard Worker for (size_t a = 0; a < std::size(kBmpAlphas); ++a) { 100*c8dee2aaSAndroid Build Coastguard Worker SkPaint modePaint; 101*c8dee2aaSAndroid Build Coastguard Worker modePaint.setBlendMode(mode); 102*c8dee2aaSAndroid Build Coastguard Worker modePaint.setAlpha(kBmpAlphas[a]); 103*c8dee2aaSAndroid Build Coastguard Worker modePaint.setShader(fBmpShader); 104*c8dee2aaSAndroid Build Coastguard Worker modePaint.setStyle(kStrokes[s].fStyle); 105*c8dee2aaSAndroid Build Coastguard Worker modePaint.setStrokeWidth(kStrokes[s].fWidth); 106*c8dee2aaSAndroid Build Coastguard Worker 107*c8dee2aaSAndroid Build Coastguard Worker this->drawMode(canvas, x, y, kSize, kSize, modePaint, tempSurface.get()); 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker ++test; 110*c8dee2aaSAndroid Build Coastguard Worker x += kSize + 10; 111*c8dee2aaSAndroid Build Coastguard Worker if (!(test % kTestsPerRow)) { 112*c8dee2aaSAndroid Build Coastguard Worker x = 0; 113*c8dee2aaSAndroid Build Coastguard Worker y += kSize + 30; 114*c8dee2aaSAndroid Build Coastguard Worker } 115*c8dee2aaSAndroid Build Coastguard Worker } 116*c8dee2aaSAndroid Build Coastguard Worker } 117*c8dee2aaSAndroid Build Coastguard Worker } 118*c8dee2aaSAndroid Build Coastguard Worker } 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker private: 121*c8dee2aaSAndroid Build Coastguard Worker /** 122*c8dee2aaSAndroid Build Coastguard Worker * GrContext has optimizations around full rendertarget draws that can be replaced with clears. 123*c8dee2aaSAndroid Build Coastguard Worker * We are trying to test those. We could use saveLayer() to create small SkGpuDevices but 124*c8dee2aaSAndroid Build Coastguard Worker * saveLayer() uses the texture cache. This means that the actual render target may be larger 125*c8dee2aaSAndroid Build Coastguard Worker * than the layer. Because the clip will contain the layer's bounds, no draws will be full-RT. 126*c8dee2aaSAndroid Build Coastguard Worker * So explicitly create a temporary canvas with dimensions exactly the layer size. 127*c8dee2aaSAndroid Build Coastguard Worker */ makeTempSurface(SkCanvas * baseCanvas,int w,int h)128*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> makeTempSurface(SkCanvas* baseCanvas, int w, int h) { 129*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo baseInfo = baseCanvas->imageInfo(); 130*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo info = SkImageInfo::Make(w, h, baseInfo.colorType(), baseInfo.alphaType(), 131*c8dee2aaSAndroid Build Coastguard Worker baseInfo.refColorSpace()); 132*c8dee2aaSAndroid Build Coastguard Worker return baseCanvas->makeSurface(info); 133*c8dee2aaSAndroid Build Coastguard Worker } 134*c8dee2aaSAndroid Build Coastguard Worker drawMode(SkCanvas * canvas,int x,int y,int w,int h,const SkPaint & modePaint,SkSurface * surface)135*c8dee2aaSAndroid Build Coastguard Worker void drawMode(SkCanvas* canvas, 136*c8dee2aaSAndroid Build Coastguard Worker int x, int y, int w, int h, 137*c8dee2aaSAndroid Build Coastguard Worker const SkPaint& modePaint, SkSurface* surface) { 138*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); 139*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); 140*c8dee2aaSAndroid Build Coastguard Worker 141*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeWH(SkIntToScalar(w), SkIntToScalar(h)); 142*c8dee2aaSAndroid Build Coastguard Worker 143*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* modeCanvas; 144*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == surface) { 145*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(&r, nullptr); 146*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(r); 147*c8dee2aaSAndroid Build Coastguard Worker modeCanvas = canvas; 148*c8dee2aaSAndroid Build Coastguard Worker } else { 149*c8dee2aaSAndroid Build Coastguard Worker modeCanvas = surface->getCanvas(); 150*c8dee2aaSAndroid Build Coastguard Worker } 151*c8dee2aaSAndroid Build Coastguard Worker 152*c8dee2aaSAndroid Build Coastguard Worker SkPaint bgPaint; 153*c8dee2aaSAndroid Build Coastguard Worker bgPaint.setAntiAlias(false); 154*c8dee2aaSAndroid Build Coastguard Worker bgPaint.setShader(fBGShader); 155*c8dee2aaSAndroid Build Coastguard Worker modeCanvas->drawRect(r, bgPaint); 156*c8dee2aaSAndroid Build Coastguard Worker modeCanvas->drawRect(r, modePaint); 157*c8dee2aaSAndroid Build Coastguard Worker modeCanvas = nullptr; 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == surface) { 160*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 161*c8dee2aaSAndroid Build Coastguard Worker } else { 162*c8dee2aaSAndroid Build Coastguard Worker surface->draw(canvas, 0, 0); 163*c8dee2aaSAndroid Build Coastguard Worker } 164*c8dee2aaSAndroid Build Coastguard Worker 165*c8dee2aaSAndroid Build Coastguard Worker r.inset(-SK_ScalarHalf, -SK_ScalarHalf); 166*c8dee2aaSAndroid Build Coastguard Worker SkPaint borderPaint; 167*c8dee2aaSAndroid Build Coastguard Worker borderPaint.setStyle(SkPaint::kStroke_Style); 168*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, borderPaint); 169*c8dee2aaSAndroid Build Coastguard Worker 170*c8dee2aaSAndroid Build Coastguard Worker canvas->restore(); 171*c8dee2aaSAndroid Build Coastguard Worker } 172*c8dee2aaSAndroid Build Coastguard Worker onOnceBeforeDraw()173*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override { 174*c8dee2aaSAndroid Build Coastguard Worker const uint32_t kCheckData[] = { 175*c8dee2aaSAndroid Build Coastguard Worker SkPackARGB32(0xFF, 0x42, 0x41, 0x42), 176*c8dee2aaSAndroid Build Coastguard Worker SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6), 177*c8dee2aaSAndroid Build Coastguard Worker SkPackARGB32(0xFF, 0xD6, 0xD3, 0xD6), 178*c8dee2aaSAndroid Build Coastguard Worker SkPackARGB32(0xFF, 0x42, 0x41, 0x42) 179*c8dee2aaSAndroid Build Coastguard Worker }; 180*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bg; 181*c8dee2aaSAndroid Build Coastguard Worker bg.allocN32Pixels(2, 2, true); 182*c8dee2aaSAndroid Build Coastguard Worker memcpy(bg.getPixels(), kCheckData, sizeof(kCheckData)); 183*c8dee2aaSAndroid Build Coastguard Worker 184*c8dee2aaSAndroid Build Coastguard Worker SkMatrix lm; 185*c8dee2aaSAndroid Build Coastguard Worker lm.setScale(SkIntToScalar(kCheckSize), SkIntToScalar(kCheckSize)); 186*c8dee2aaSAndroid Build Coastguard Worker fBGShader = bg.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, 187*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), lm); 188*c8dee2aaSAndroid Build Coastguard Worker 189*c8dee2aaSAndroid Build Coastguard Worker SkPaint bmpPaint; 190*c8dee2aaSAndroid Build Coastguard Worker const SkPoint kCenter = { SkIntToScalar(kSize) / 2, SkIntToScalar(kSize) / 2 }; 191*c8dee2aaSAndroid Build Coastguard Worker const SkColor kColors[] = { 192*c8dee2aaSAndroid Build Coastguard Worker SK_ColorTRANSPARENT, 0x80800000, 0xF020F060, SK_ColorWHITE 193*c8dee2aaSAndroid Build Coastguard Worker }; 194*c8dee2aaSAndroid Build Coastguard Worker bmpPaint.setShader(SkGradientShader::MakeRadial(kCenter, 3 * SkIntToScalar(kSize) / 4, 195*c8dee2aaSAndroid Build Coastguard Worker kColors, nullptr, std::size(kColors), 196*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat)); 197*c8dee2aaSAndroid Build Coastguard Worker 198*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bmp; 199*c8dee2aaSAndroid Build Coastguard Worker bmp.allocN32Pixels(kSize, kSize); 200*c8dee2aaSAndroid Build Coastguard Worker SkCanvas bmpCanvas(bmp); 201*c8dee2aaSAndroid Build Coastguard Worker 202*c8dee2aaSAndroid Build Coastguard Worker bmpCanvas.clear(SK_ColorTRANSPARENT); 203*c8dee2aaSAndroid Build Coastguard Worker SkRect rect = { SkIntToScalar(kSize) / 8, SkIntToScalar(kSize) / 8, 204*c8dee2aaSAndroid Build Coastguard Worker 7 * SkIntToScalar(kSize) / 8, 7 * SkIntToScalar(kSize) / 8}; 205*c8dee2aaSAndroid Build Coastguard Worker bmpCanvas.drawRect(rect, bmpPaint); 206*c8dee2aaSAndroid Build Coastguard Worker 207*c8dee2aaSAndroid Build Coastguard Worker fBmpShader = bmp.makeShader(SkSamplingOptions()); 208*c8dee2aaSAndroid Build Coastguard Worker } 209*c8dee2aaSAndroid Build Coastguard Worker 210*c8dee2aaSAndroid Build Coastguard Worker enum { 211*c8dee2aaSAndroid Build Coastguard Worker kCheckSize = 8, 212*c8dee2aaSAndroid Build Coastguard Worker kSize = 30, 213*c8dee2aaSAndroid Build Coastguard Worker kTestsPerRow = 15, 214*c8dee2aaSAndroid Build Coastguard Worker }; 215*c8dee2aaSAndroid Build Coastguard Worker 216*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fBGShader; 217*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fBmpShader; 218*c8dee2aaSAndroid Build Coastguard Worker 219*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM; 220*c8dee2aaSAndroid Build Coastguard Worker }; 221*c8dee2aaSAndroid Build Coastguard Worker 222*c8dee2aaSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////// 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker DEF_GM(return new Xfermodes3GM;) 225*c8dee2aaSAndroid Build Coastguard Worker 226*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm 227