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