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