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