1 /* 2 * Copyright 2011 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 "SkCanvas.h" 10 #include "SkGradientShader.h" 11 12 namespace skiagm { 13 14 static void makebm(SkBitmap* bm, int w, int h) { 15 bm->allocN32Pixels(w, h); 16 bm->eraseColor(SK_ColorTRANSPARENT); 17 18 SkCanvas canvas(*bm); 19 SkScalar s = SkIntToScalar(SkMin32(w, h)); 20 SkPoint pts[] = { { 0, 0 }, { s, s } }; 21 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; 22 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 }; 23 SkPaint paint; 24 25 paint.setDither(true); 26 paint.setShader(SkGradientShader::CreateLinear(pts, colors, pos, 27 SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode))->unref(); 28 canvas.drawPaint(paint); 29 } 30 31 static SkShader* MakeBitmapShader(SkShader::TileMode tx, SkShader::TileMode ty, 32 int w, int h) { 33 static SkBitmap bmp; 34 if (bmp.isNull()) { 35 makebm(&bmp, w/2, h/4); 36 } 37 return SkShader::CreateBitmapShader(bmp, tx, ty); 38 } 39 40 /////////////////////////////////////////////////////////////////////////////// 41 42 struct GradData { 43 int fCount; 44 const SkColor* fColors; 45 const SkScalar* fPos; 46 }; 47 48 static const SkColor gColors[] = { 49 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK 50 }; 51 52 static const GradData gGradData[] = { 53 { 2, gColors, NULL }, 54 { 5, gColors, NULL }, 55 }; 56 57 static SkShader* MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 58 return SkGradientShader::CreateLinear(pts, data.fColors, data.fPos, data.fCount, tm); 59 } 60 61 static SkShader* MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 62 SkPoint center; 63 center.set(SkScalarAve(pts[0].fX, pts[1].fX), 64 SkScalarAve(pts[0].fY, pts[1].fY)); 65 return SkGradientShader::CreateRadial(center, center.fX, data.fColors, 66 data.fPos, data.fCount, tm); 67 } 68 69 static SkShader* MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode) { 70 SkPoint center; 71 center.set(SkScalarAve(pts[0].fX, pts[1].fX), 72 SkScalarAve(pts[0].fY, pts[1].fY)); 73 return SkGradientShader::CreateSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount); 74 } 75 76 static SkShader* Make2Radial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 77 SkPoint center0, center1; 78 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 79 SkScalarAve(pts[0].fY, pts[1].fY)); 80 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 81 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 82 return SkGradientShader::CreateTwoPointRadial( 83 center1, (pts[1].fX - pts[0].fX) / 7, 84 center0, (pts[1].fX - pts[0].fX) / 2, 85 data.fColors, data.fPos, data.fCount, tm); 86 } 87 88 typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm); 89 90 static const GradMaker gGradMakers[] = { 91 MakeLinear, MakeRadial, MakeSweep, Make2Radial 92 }; 93 94 /////////////////////////////////////////////////////////////////////////////// 95 96 class ShaderTextGM : public GM { 97 public: 98 ShaderTextGM() { 99 this->setBGColor(0xFFDDDDDD); 100 } 101 102 protected: 103 virtual uint32_t onGetFlags() const SK_OVERRIDE { 104 return kSkipTiled_Flag; 105 } 106 107 SkString onShortName() { 108 return SkString("shadertext"); 109 } 110 111 SkISize onISize() { return SkISize::Make(1450, 500); } 112 113 virtual void onDraw(SkCanvas* canvas) { 114 const char text[] = "Shaded Text"; 115 const int textLen = SK_ARRAY_COUNT(text) - 1; 116 const int pointSize = 36; 117 118 int w = pointSize * textLen; 119 int h = pointSize; 120 121 SkPoint pts[2] = { 122 { 0, 0 }, 123 { SkIntToScalar(w), SkIntToScalar(h) } 124 }; 125 SkScalar textBase = SkIntToScalar(h/2); 126 127 SkShader::TileMode tileModes[] = { 128 SkShader::kClamp_TileMode, 129 SkShader::kRepeat_TileMode, 130 SkShader::kMirror_TileMode 131 }; 132 133 static const int gradCount = SK_ARRAY_COUNT(gGradData) * 134 SK_ARRAY_COUNT(gGradMakers); 135 static const int bmpCount = SK_ARRAY_COUNT(tileModes) * 136 SK_ARRAY_COUNT(tileModes); 137 SkShader* shaders[gradCount + bmpCount]; 138 139 int shdIdx = 0; 140 for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) { 141 for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) { 142 shaders[shdIdx++] = gGradMakers[m](pts, 143 gGradData[d], 144 SkShader::kClamp_TileMode); 145 } 146 } 147 for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) { 148 for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) { 149 shaders[shdIdx++] = MakeBitmapShader(tileModes[tx], 150 tileModes[ty], 151 w/8, h); 152 } 153 } 154 155 SkPaint paint; 156 paint.setDither(true); 157 paint.setAntiAlias(true); 158 paint.setTextSize(SkIntToScalar(pointSize)); 159 160 canvas->save(); 161 canvas->translate(SkIntToScalar(20), SkIntToScalar(10)); 162 163 SkPath path; 164 path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15), 165 SkIntToScalar(300), SkIntToScalar(90)), 166 SkIntToScalar(225), SkIntToScalar(90), 167 false); 168 path.close(); 169 170 static const int testsPerCol = 8; 171 static const int rowHeight = 60; 172 static const int colWidth = 300; 173 canvas->save(); 174 for (int s = 0; s < static_cast<int>(SK_ARRAY_COUNT(shaders)); s++) { 175 canvas->save(); 176 int i = 2*s; 177 canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), 178 SkIntToScalar((i % testsPerCol) * rowHeight)); 179 paint.setShader(shaders[s])->unref(); 180 canvas->drawText(text, textLen, 0, textBase, paint); 181 canvas->restore(); 182 canvas->save(); 183 ++i; 184 canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), 185 SkIntToScalar((i % testsPerCol) * rowHeight)); 186 canvas->drawTextOnPath(text, textLen, path, NULL, paint); 187 canvas->restore(); 188 } 189 canvas->restore(); 190 191 } 192 193 private: 194 typedef GM INHERITED; 195 }; 196 197 /////////////////////////////////////////////////////////////////////////////// 198 199 static GM* MyFactory(void*) { return new ShaderTextGM; } 200 static GMRegistry reg(MyFactory); 201 } 202