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