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