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* Make2Conical(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::CreateTwoPointConical( 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, Make2Conical 83}; 84 85/////////////////////////////////////////////////////////////////////////////// 86 87class ShaderTextGM : public GM { 88public: 89 ShaderTextGM() { 90 this->setBGColor(0xFFDDDDDD); 91 } 92 93protected: 94 95 SkString onShortName() override { 96 return SkString("shadertext"); 97 } 98 99 SkISize onISize() override { return SkISize::Make(1450, 500); } 100 101 void onDraw(SkCanvas* canvas) override { 102 const char text[] = "Shaded Text"; 103 const int textLen = SK_ARRAY_COUNT(text) - 1; 104 const int pointSize = 36; 105 106 const int w = pointSize * textLen; 107 const int h = pointSize; 108 109 SkPoint pts[2] = { 110 { 0, 0 }, 111 { SkIntToScalar(w), SkIntToScalar(h) } 112 }; 113 SkScalar textBase = SkIntToScalar(h/2); 114 115 SkShader::TileMode tileModes[] = { 116 SkShader::kClamp_TileMode, 117 SkShader::kRepeat_TileMode, 118 SkShader::kMirror_TileMode 119 }; 120 121 static const int gradCount = SK_ARRAY_COUNT(gGradData) * 122 SK_ARRAY_COUNT(gGradMakers); 123 static const int bmpCount = SK_ARRAY_COUNT(tileModes) * 124 SK_ARRAY_COUNT(tileModes); 125 SkShader* shaders[gradCount + bmpCount]; 126 127 int shdIdx = 0; 128 for (size_t d = 0; d < SK_ARRAY_COUNT(gGradData); ++d) { 129 for (size_t m = 0; m < SK_ARRAY_COUNT(gGradMakers); ++m) { 130 shaders[shdIdx++] = gGradMakers[m](pts, 131 gGradData[d], 132 SkShader::kClamp_TileMode); 133 } 134 } 135 136 SkBitmap bm; 137 makebm(&bm, w/16, h/4); 138 for (size_t tx = 0; tx < SK_ARRAY_COUNT(tileModes); ++tx) { 139 for (size_t ty = 0; ty < SK_ARRAY_COUNT(tileModes); ++ty) { 140 shaders[shdIdx++] = SkShader::CreateBitmapShader(bm, tileModes[tx], tileModes[ty]); 141 } 142 } 143 144 SkPaint paint; 145 paint.setDither(true); 146 paint.setAntiAlias(true); 147 sk_tool_utils::set_portable_typeface(&paint); 148 paint.setTextSize(SkIntToScalar(pointSize)); 149 150 canvas->save(); 151 canvas->translate(SkIntToScalar(20), SkIntToScalar(10)); 152 153 SkPath path; 154 path.arcTo(SkRect::MakeXYWH(SkIntToScalar(-40), SkIntToScalar(15), 155 SkIntToScalar(300), SkIntToScalar(90)), 156 SkIntToScalar(225), SkIntToScalar(90), 157 false); 158 path.close(); 159 160 static const int testsPerCol = 8; 161 static const int rowHeight = 60; 162 static const int colWidth = 300; 163 canvas->save(); 164 for (int s = 0; s < static_cast<int>(SK_ARRAY_COUNT(shaders)); s++) { 165 canvas->save(); 166 int i = 2*s; 167 canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), 168 SkIntToScalar((i % testsPerCol) * rowHeight)); 169 paint.setShader(shaders[s])->unref(); 170 canvas->drawText(text, textLen, 0, textBase, paint); 171 canvas->restore(); 172 canvas->save(); 173 ++i; 174 canvas->translate(SkIntToScalar((i / testsPerCol) * colWidth), 175 SkIntToScalar((i % testsPerCol) * rowHeight)); 176 canvas->drawTextOnPath(text, textLen, path, NULL, paint); 177 canvas->restore(); 178 } 179 canvas->restore(); 180 181 } 182 183private: 184 typedef GM INHERITED; 185}; 186 187/////////////////////////////////////////////////////////////////////////////// 188 189static GM* MyFactory(void*) { return new ShaderTextGM; } 190static GMRegistry reg(MyFactory); 191} 192