1 /* 2 * Copyright 2015 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" 9 #include "SkColorPriv.h" 10 #include "SkGradientShader.h" 11 #include "SkImage.h" 12 #include "SkMathPriv.h" 13 #include "SkRandom.h" 14 #include "SkShader.h" 15 #include "SkSurface.h" 16 17 static sk_sp<SkImage> makebm(int w, int h) { 18 SkImageInfo info = SkImageInfo::MakeN32Premul(w, h); 19 auto surface(SkSurface::MakeRaster(info)); 20 SkCanvas* canvas = surface->getCanvas(); 21 22 const SkScalar wScalar = SkIntToScalar(w); 23 const SkScalar hScalar = SkIntToScalar(h); 24 25 const SkPoint pt = { wScalar / 2, hScalar / 2 }; 26 27 const SkScalar radius = 4 * SkMaxScalar(wScalar, hScalar); 28 29 constexpr SkColor colors[] = { SK_ColorRED, SK_ColorYELLOW, 30 SK_ColorGREEN, SK_ColorMAGENTA, 31 SK_ColorBLUE, SK_ColorCYAN, 32 SK_ColorRED}; 33 34 constexpr SkScalar pos[] = {0, 35 SK_Scalar1 / 6, 36 2 * SK_Scalar1 / 6, 37 3 * SK_Scalar1 / 6, 38 4 * SK_Scalar1 / 6, 39 5 * SK_Scalar1 / 6, 40 SK_Scalar1}; 41 42 SkASSERT(SK_ARRAY_COUNT(colors) == SK_ARRAY_COUNT(pos)); 43 SkPaint paint; 44 SkRect rect = SkRect::MakeWH(wScalar, hScalar); 45 SkMatrix mat = SkMatrix::I(); 46 for (int i = 0; i < 4; ++i) { 47 paint.setShader(SkGradientShader::MakeRadial( 48 pt, radius, 49 colors, pos, 50 SK_ARRAY_COUNT(colors), 51 SkShader::kRepeat_TileMode, 52 0, &mat)); 53 canvas->drawRect(rect, paint); 54 rect.inset(wScalar / 8, hScalar / 8); 55 mat.postScale(SK_Scalar1 / 4, SK_Scalar1 / 4); 56 } 57 return surface->makeImageSnapshot(); 58 } 59 60 constexpr int gSize = 1024; 61 constexpr int gSurfaceSize = 2048; 62 63 // This GM calls drawImageRect several times using the same texture. This is intended to exercise 64 // combining GrDrawOps during these calls. 65 class DrawMiniBitmapRectGM : public skiagm::GM { 66 public: 67 DrawMiniBitmapRectGM(bool antiAlias) : fAA(antiAlias) { 68 fName.set("drawminibitmaprect"); 69 if (fAA) { 70 fName.appendf("_aa"); 71 } 72 } 73 74 protected: 75 SkString onShortName() override { return fName; } 76 77 SkISize onISize() override { return SkISize::Make(gSize, gSize); } 78 79 void onDraw(SkCanvas* canvas) override { 80 if (nullptr == fImage) { 81 fImage = makebm(gSurfaceSize, gSurfaceSize); 82 } 83 84 const SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; 85 const int kMaxSrcRectSize = 1 << (SkNextLog2(gSurfaceSize) + 2); 86 87 constexpr int kPadX = 30; 88 constexpr int kPadY = 40; 89 90 int rowCount = 0; 91 canvas->translate(SkIntToScalar(kPadX), SkIntToScalar(kPadY)); 92 canvas->save(); 93 SkRandom random; 94 95 SkPaint paint; 96 paint.setAntiAlias(fAA); 97 for (int w = 1; w <= kMaxSrcRectSize; w *= 3) { 98 for (int h = 1; h <= kMaxSrcRectSize; h *= 3) { 99 100 const SkIRect srcRect = 101 SkIRect::MakeXYWH((gSurfaceSize - w) / 2, (gSurfaceSize - h) / 2, w, h); 102 canvas->save(); 103 switch (random.nextU() % 3) { 104 case 0: 105 canvas->rotate(random.nextF() * 10.f); 106 break; 107 case 1: 108 canvas->rotate(-random.nextF() * 10.f); 109 break; 110 case 2: 111 // rect stays rect 112 break; 113 } 114 canvas->drawImageRect(fImage.get(), srcRect, dstRect, &paint, 115 SkCanvas::kFast_SrcRectConstraint); 116 canvas->restore(); 117 118 canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); 119 ++rowCount; 120 if ((dstRect.width() + 2 * kPadX) * rowCount > gSize) { 121 canvas->restore(); 122 canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); 123 canvas->save(); 124 rowCount = 0; 125 } 126 } 127 } 128 canvas->restore(); 129 } 130 131 private: 132 bool fAA; 133 sk_sp<SkImage> fImage; 134 SkString fName; 135 136 typedef skiagm::GM INHERITED; 137 }; 138 139 DEF_GM( return new DrawMiniBitmapRectGM(true); ) 140 DEF_GM( return new DrawMiniBitmapRectGM(false); ) 141