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