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