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