1 /* 2 * Copyright 2014 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 "sk_tool_utils.h" 10 11 #include "SkBitmap.h" 12 #include "SkPaint.h" 13 #include "SkPicture.h" 14 #include "SkPictureRecorder.h" 15 #include "SkShader.h" 16 17 static struct { 18 SkShader::TileMode tmx; 19 SkShader::TileMode tmy; 20 } kTileConfigs[] = { 21 { SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode }, 22 { SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode }, 23 { SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode }, 24 }; 25 26 class PictureShaderGM : public skiagm::GM { 27 public: PictureShaderGM(SkScalar tileSize,SkScalar sceneSize,bool useLocalMatrixWrapper=false)28 PictureShaderGM(SkScalar tileSize, SkScalar sceneSize, bool useLocalMatrixWrapper = false) 29 : fTileSize(tileSize) 30 , fSceneSize(sceneSize) 31 , fUseLocalMatrixWrapper(useLocalMatrixWrapper) {} 32 33 protected: onOnceBeforeDraw()34 void onOnceBeforeDraw() override { 35 // Build the picture. 36 SkPictureRecorder recorder; 37 SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, nullptr, 0); 38 this->drawTile(pictureCanvas); 39 fPicture = recorder.finishRecordingAsPicture(); 40 41 // Build a reference bitmap. 42 fBitmap.allocN32Pixels(SkScalarCeilToInt(fTileSize), SkScalarCeilToInt(fTileSize)); 43 fBitmap.eraseColor(SK_ColorTRANSPARENT); 44 SkCanvas bitmapCanvas(fBitmap); 45 this->drawTile(&bitmapCanvas); 46 } 47 48 onShortName()49 SkString onShortName() override { 50 return SkStringPrintf("pictureshader%s", fUseLocalMatrixWrapper ? "_localwrapper" : ""); 51 } 52 onISize()53 SkISize onISize() override { 54 return SkISize::Make(1400, 1450); 55 } 56 onDraw(SkCanvas * canvas)57 void onDraw(SkCanvas* canvas) override { 58 this->drawSceneColumn(canvas, SkPoint::Make(0, 0), 1, 1, 0); 59 this->drawSceneColumn(canvas, SkPoint::Make(0, fSceneSize * 6.4f), 1, 2, 0); 60 this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, 0), 1, 1, 1); 61 this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 2.4f, fSceneSize * 6.4f), 1, 1, 2); 62 this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 4.8f, 0), 2, 1, 0); 63 this->drawSceneColumn(canvas, SkPoint::Make(fSceneSize * 9.6f, 0), 2, 2, 0); 64 65 // One last custom row to exercise negative scaling 66 SkMatrix ctm, localMatrix; 67 ctm.setTranslate(fSceneSize * 2.1f, fSceneSize * 13.8f); 68 ctm.preScale(-1, -1); 69 localMatrix.setScale(2, 2); 70 this->drawScene(canvas, ctm, localMatrix, 0); 71 72 ctm.setTranslate(fSceneSize * 2.4f, fSceneSize * 12.8f); 73 localMatrix.setScale(-1, -1); 74 this->drawScene(canvas, ctm, localMatrix, 0); 75 76 ctm.setTranslate(fSceneSize * 4.8f, fSceneSize * 12.3f); 77 ctm.preScale(2, 2); 78 this->drawScene(canvas, ctm, localMatrix, 0); 79 80 ctm.setTranslate(fSceneSize * 13.8f, fSceneSize * 14.3f); 81 ctm.preScale(-2, -2); 82 localMatrix.setTranslate(fTileSize / 4, fTileSize / 4); 83 localMatrix.preRotate(45); 84 localMatrix.preScale(-2, -2); 85 this->drawScene(canvas, ctm, localMatrix, 0); 86 } 87 88 private: drawSceneColumn(SkCanvas * canvas,const SkPoint & pos,SkScalar scale,SkScalar localScale,unsigned tileMode)89 void drawSceneColumn(SkCanvas* canvas, const SkPoint& pos, SkScalar scale, SkScalar localScale, 90 unsigned tileMode) { 91 SkMatrix ctm, localMatrix; 92 93 ctm.setTranslate(pos.x(), pos.y()); 94 ctm.preScale(scale, scale); 95 localMatrix.setScale(localScale, localScale); 96 this->drawScene(canvas, ctm, localMatrix, tileMode); 97 98 ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 1.2f * scale); 99 ctm.preScale(scale, scale); 100 localMatrix.setTranslate(fTileSize / 4, fTileSize / 4); 101 localMatrix.preScale(localScale, localScale); 102 this->drawScene(canvas, ctm, localMatrix, tileMode); 103 104 ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 2.4f * scale); 105 ctm.preScale(scale, scale); 106 localMatrix.setRotate(45); 107 localMatrix.preScale(localScale, localScale); 108 this->drawScene(canvas, ctm, localMatrix, tileMode); 109 110 ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 3.6f * scale); 111 ctm.preScale(scale, scale); 112 localMatrix.setSkew(1, 0); 113 localMatrix.preScale(localScale, localScale); 114 this->drawScene(canvas, ctm, localMatrix, tileMode); 115 116 ctm.setTranslate(pos.x(), pos.y() + fSceneSize * 4.8f * scale); 117 ctm.preScale(scale, scale); 118 localMatrix.setTranslate(fTileSize / 4, fTileSize / 4); 119 localMatrix.preRotate(45); 120 localMatrix.preScale(localScale, localScale); 121 this->drawScene(canvas, ctm, localMatrix, tileMode); 122 } 123 drawTile(SkCanvas * canvas)124 void drawTile(SkCanvas* canvas) { 125 SkPaint paint; 126 paint.setColor(SK_ColorGREEN); 127 paint.setStyle(SkPaint::kFill_Style); 128 paint.setAntiAlias(true); 129 130 canvas->drawCircle(fTileSize / 4, fTileSize / 4, fTileSize / 4, paint); 131 canvas->drawRect(SkRect::MakeXYWH(fTileSize / 2, fTileSize / 2, 132 fTileSize / 2, fTileSize / 2), paint); 133 134 paint.setColor(SK_ColorRED); 135 canvas->drawLine(fTileSize / 2, fTileSize * 1 / 3, 136 fTileSize / 2, fTileSize * 2 / 3, paint); 137 canvas->drawLine(fTileSize * 1 / 3, fTileSize / 2, 138 fTileSize * 2 / 3, fTileSize / 2, paint); 139 } 140 drawScene(SkCanvas * canvas,const SkMatrix & matrix,const SkMatrix & localMatrix,unsigned tileMode)141 void drawScene(SkCanvas* canvas, const SkMatrix& matrix, const SkMatrix& localMatrix, 142 unsigned tileMode) { 143 SkASSERT(tileMode < SK_ARRAY_COUNT(kTileConfigs)); 144 145 SkPaint paint; 146 paint.setStyle(SkPaint::kFill_Style); 147 paint.setColor(SK_ColorLTGRAY); 148 149 canvas->save(); 150 canvas->concat(matrix); 151 canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); 152 canvas->drawRect(SkRect::MakeXYWH(fSceneSize * 1.1f, 0, fSceneSize, fSceneSize), paint); 153 154 auto pictureShader = SkShader::MakePictureShader(fPicture, kTileConfigs[tileMode].tmx, 155 kTileConfigs[tileMode].tmy, 156 fUseLocalMatrixWrapper 157 ? nullptr : &localMatrix, 158 nullptr); 159 paint.setShader(fUseLocalMatrixWrapper 160 ? pictureShader->makeWithLocalMatrix(localMatrix) 161 : pictureShader); 162 canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); 163 164 canvas->translate(fSceneSize * 1.1f, 0); 165 166 auto bitmapShader = SkShader::MakeBitmapShader(fBitmap, 167 kTileConfigs[tileMode].tmx, 168 kTileConfigs[tileMode].tmy, 169 fUseLocalMatrixWrapper 170 ? nullptr : &localMatrix); 171 paint.setShader(fUseLocalMatrixWrapper 172 ? bitmapShader->makeWithLocalMatrix(localMatrix) 173 : bitmapShader); 174 canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); 175 176 canvas->restore(); 177 } 178 179 sk_sp<SkPicture> fPicture; 180 SkBitmap fBitmap; 181 182 SkScalar fTileSize; 183 SkScalar fSceneSize; 184 bool fUseLocalMatrixWrapper; 185 186 typedef GM INHERITED; 187 }; 188 189 DEF_GM(return new PictureShaderGM(50, 100);) 190 DEF_GM(return new PictureShaderGM(50, 100, true);) 191 192 DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) { 193 // https://code.google.com/p/skia/issues/detail?id=3398 194 SkRect tile = SkRect::MakeWH(100, 100); 195 196 SkPictureRecorder recorder; 197 SkCanvas* c = recorder.beginRecording(tile); 198 199 SkRect r = tile; 200 r.inset(4, 4); 201 SkPaint p; 202 p.setColor(sk_tool_utils::color_to_565(0xFF303F9F)); // dark blue 203 c->drawRect(r, p); 204 p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9)); // light blue 205 p.setStrokeWidth(10); 206 c->drawLine(20, 20, 80, 80, p); 207 208 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); 209 210 p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A)); // green 211 canvas->drawPaint(p); 212 213 canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350)); 214 p.setColor(0xFFB6B6B6); // gray 215 canvas->drawPaint(p); 216 217 p.setShader(SkShader::MakePictureShader(std::move(picture), SkShader::kRepeat_TileMode, 218 SkShader::kRepeat_TileMode, 219 nullptr, nullptr)); 220 canvas->drawPaint(p); 221 } 222