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