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