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