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