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 16static 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 25class PictureShaderGM : public skiagm::GM { 26public: 27 PictureShaderGM(SkScalar tileSize, SkScalar sceneSize) 28 : fTileSize(tileSize) 29 , fSceneSize(sceneSize) { 30 } 31 32 protected: 33 void onOnceBeforeDraw() override { 34 // Build the picture. 35 SkPictureRecorder recorder; 36 SkCanvas* pictureCanvas = recorder.beginRecording(fTileSize, fTileSize, nullptr, 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 48 SkString onShortName() override { 49 return SkString("pictureshader"); 50 } 51 52 SkISize onISize() override { 53 return SkISize::Make(1400, 1450); 54 } 55 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 87private: 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 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 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_tool_utils::color_to_565(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( 154 SkShader::CreatePictureShader(fPicture, kTileConfigs[tileMode].tmx, 155 kTileConfigs[tileMode].tmy, &localMatrix, nullptr)); 156 paint.setShader(pictureShader.get()); 157 canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); 158 159 canvas->translate(fSceneSize * 1.1f, 0); 160 161 SkAutoTUnref<SkShader> bitmapShader(SkShader::CreateBitmapShader( 162 fBitmap, 163 kTileConfigs[tileMode].tmx, 164 kTileConfigs[tileMode].tmy, 165 &localMatrix)); 166 paint.setShader(bitmapShader.get()); 167 canvas->drawRect(SkRect::MakeWH(fSceneSize, fSceneSize), paint); 168 169 canvas->restore(); 170 } 171 172 SkScalar fTileSize; 173 SkScalar fSceneSize; 174 175 SkAutoTUnref<SkPicture> fPicture; 176 SkBitmap fBitmap; 177 178 typedef GM INHERITED; 179}; 180 181DEF_GM(return new PictureShaderGM(50, 100);) 182 183DEF_SIMPLE_GM(tiled_picture_shader, canvas, 400, 400) { 184 // https://code.google.com/p/skia/issues/detail?id=3398 185 SkRect tile = SkRect::MakeWH(100, 100); 186 187 SkPictureRecorder recorder; 188 SkCanvas* c = recorder.beginRecording(tile); 189 190 SkRect r = tile; 191 r.inset(4, 4); 192 SkPaint p; 193 p.setColor(sk_tool_utils::color_to_565(0xFF303F9F)); // dark blue 194 c->drawRect(r, p); 195 p.setColor(sk_tool_utils::color_to_565(0xFFC5CAE9)); // light blue 196 p.setStrokeWidth(10); 197 c->drawLine(20, 20, 80, 80, p); 198 199 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 200 SkAutoTUnref<SkShader> shader( 201 SkShader::CreatePictureShader(picture.get(), SkShader::kRepeat_TileMode, 202 SkShader::kRepeat_TileMode, nullptr, nullptr)); 203 204 p.setColor(sk_tool_utils::color_to_565(0xFF8BC34A)); // green 205 canvas->drawPaint(p); 206 207 canvas->clipRect(SkRect::MakeXYWH(0, 0, 400, 350)); 208 p.setColor(sk_tool_utils::color_to_565(0xFFB6B6B6)); // gray 209 canvas->drawPaint(p); 210 p.setShader(shader.get()); 211 212 canvas->drawPaint(p); 213} 214