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 14 namespace skiagm { 15 16 static 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 35 struct GradData { 36 int fCount; 37 const SkColor* fColors; 38 const SkScalar* fPos; 39 }; 40 41 constexpr SkColor gColors[] = { 42 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK 43 }; 44 45 constexpr GradData gGradData[] = { 46 { 2, gColors, nullptr }, 47 { 5, gColors, nullptr }, 48 }; 49 50 static 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 54 static 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 62 static 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 69 static 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 81 typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm); 82 83 constexpr GradMaker gGradMakers[] = { 84 MakeLinear, MakeRadial, MakeSweep, Make2Conical 85 }; 86 87 /////////////////////////////////////////////////////////////////////////////// 88 89 class ShaderTextGM : public GM { 90 public: 91 ShaderTextGM() { 92 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); 93 } 94 95 protected: 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 185 private: 186 typedef GM INHERITED; 187 }; 188 189 /////////////////////////////////////////////////////////////////////////////// 190 191 static GM* MyFactory(void*) { return new ShaderTextGM; } 192 static GMRegistry reg(MyFactory); 193 } 194