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 #include "SampleCode.h" 8 #include "SkBlurMask.h" 9 #include "SkCanvas.h" 10 #include "SkView.h" 11 #include "Sk1DPathEffect.h" 12 #include "Sk2DPathEffect.h" 13 #include "SkBlurMaskFilter.h" 14 #include "SkColorMatrixFilter.h" 15 #include "SkColorPriv.h" 16 #include "SkCornerPathEffect.h" 17 #include "SkDashPathEffect.h" 18 #include "SkDiscretePathEffect.h" 19 #include "SkEmbossMaskFilter.h" 20 #include "SkReadBuffer.h" 21 #include "SkWriteBuffer.h" 22 #include "SkGradientShader.h" 23 #include "SkMath.h" 24 #include "SkPath.h" 25 #include "SkPictureRecorder.h" 26 #include "SkRegion.h" 27 #include "SkShader.h" 28 #include "SkCornerPathEffect.h" 29 #include "SkPathMeasure.h" 30 #include "SkPicture.h" 31 #include "SkRandom.h" 32 #include "SkTypeface.h" 33 #include "SkUtils.h" 34 35 #include <math.h> 36 #include "DecodeFile.h" 37 38 class Dot2DPathEffect : public Sk2DPathEffect { 39 public: 40 Dot2DPathEffect(SkScalar radius, const SkMatrix& matrix) 41 : Sk2DPathEffect(matrix), fRadius(radius) {} 42 43 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Dot2DPathEffect) 44 45 protected: 46 void next(const SkPoint& loc, int u, int v, SkPath* dst) const override { 47 dst->addCircle(loc.fX, loc.fY, fRadius); 48 } 49 50 void flatten(SkWriteBuffer& buffer) const override { 51 this->INHERITED::flatten(buffer); 52 buffer.writeScalar(fRadius); 53 } 54 55 private: 56 SkScalar fRadius; 57 58 typedef Sk2DPathEffect INHERITED; 59 }; 60 61 class DemoView : public SampleView { 62 public: 63 DemoView() {} 64 65 protected: 66 // overrides from SkEventSink 67 virtual bool onQuery(SkEvent* evt) { 68 if (SampleCode::TitleQ(*evt)) { 69 SampleCode::TitleR(evt, "Demo"); 70 return true; 71 } 72 return this->INHERITED::onQuery(evt); 73 } 74 75 virtual bool onClick(Click* click) { 76 return this->INHERITED::onClick(click); 77 } 78 79 void makePath(SkPath& path) { 80 path.addCircle(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(20), 81 SkPath::kCCW_Direction); 82 for (int index = 0; index < 10; index++) { 83 SkScalar x = (float) cos(index / 10.0f * 2 * 3.1415925358f); 84 SkScalar y = (float) sin(index / 10.0f * 2 * 3.1415925358f); 85 x *= index & 1 ? 7 : 14; 86 y *= index & 1 ? 7 : 14; 87 x += SkIntToScalar(20); 88 y += SkIntToScalar(20); 89 if (index == 0) 90 path.moveTo(x, y); 91 else 92 path.lineTo(x, y); 93 } 94 path.close(); 95 } 96 97 virtual void onDrawContent(SkCanvas* canvas) { 98 canvas->save(); 99 this->drawPicture(canvas, 0); 100 canvas->restore(); 101 102 { 103 SkPictureRecorder recorder; 104 { 105 SkCanvas* record = recorder.beginRecording(320, 480, nullptr, 0); 106 this->drawPicture(record, 120); 107 } 108 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); 109 110 canvas->translate(0, SkIntToScalar(120)); 111 112 SkRect clip; 113 clip.set(0, 0, SkIntToScalar(160), SkIntToScalar(160)); 114 do { 115 canvas->save(); 116 canvas->clipRect(clip); 117 picture->playback(canvas); 118 canvas->restore(); 119 if (clip.fRight < SkIntToScalar(320)) 120 clip.offset(SkIntToScalar(160), 0); 121 else if (clip.fBottom < SkIntToScalar(480)) 122 clip.offset(-SkIntToScalar(320), SkIntToScalar(160)); 123 else 124 break; 125 } while (true); 126 } 127 } 128 129 void drawPicture(SkCanvas* canvas, int spriteOffset) { 130 SkMatrix matrix; matrix.reset(); 131 SkPaint paint; 132 SkPath path; 133 SkPoint start = {0, 0}; 134 SkPoint stop = { SkIntToScalar(40), SkIntToScalar(40) }; 135 SkRect rect = {0, 0, SkIntToScalar(40), SkIntToScalar(40) }; 136 SkRect rect2 = {0, 0, SkIntToScalar(65), SkIntToScalar(20) }; 137 SkScalar left = 0, top = 0, x = 0, y = 0; 138 int index; 139 140 char ascii[] = "ascii..."; 141 int asciiLength = sizeof(ascii) - 1; 142 char utf8[] = "utf8" "\xe2\x80\xa6"; 143 short utf16[] = {'u', 't', 'f', '1', '6', 0x2026 }; 144 short utf16simple[] = {'u', 't', 'f', '1', '6', '!' }; 145 146 makePath(path); 147 SkTDArray<SkPoint> pos; 148 pos.setCount(asciiLength); 149 for (index = 0; index < asciiLength; index++) 150 pos[index].set(SkIntToScalar((unsigned int)index * 10), 151 SkIntToScalar((unsigned int)index * 2)); 152 SkTDArray<SkPoint> pos2; 153 pos2.setCount(asciiLength); 154 for (index = 0; index < asciiLength; index++) 155 pos2[index].set(SkIntToScalar((unsigned int)index * 10), 156 SkIntToScalar(20)); 157 158 // shaders 159 SkPoint linearPoints[] = { { 0, 0, }, { SkIntToScalar(40), SkIntToScalar(40) } }; 160 SkColor linearColors[] = { SK_ColorRED, SK_ColorBLUE }; 161 SkScalar* linearPos = nullptr; 162 int linearCount = 2; 163 SkShader::TileMode linearMode = SkShader::kMirror_TileMode; 164 auto linear = SkGradientShader::MakeLinear(linearPoints, 165 linearColors, linearPos, linearCount, linearMode); 166 167 SkPoint radialCenter = { SkIntToScalar(25), SkIntToScalar(25) }; 168 SkScalar radialRadius = SkIntToScalar(25); 169 SkColor radialColors[] = { SK_ColorGREEN, SK_ColorGRAY, SK_ColorRED }; 170 SkScalar radialPos[] = { 0, SkIntToScalar(3) / 5, SkIntToScalar(1)}; 171 int radialCount = 3; 172 SkShader::TileMode radialMode = SkShader::kRepeat_TileMode; 173 auto radial = SkGradientShader::MakeRadial(radialCenter, 174 radialRadius, radialColors, radialPos, radialCount, 175 radialMode); 176 177 SkEmbossMaskFilter::Light light; 178 light.fDirection[0] = SK_Scalar1/2; 179 light.fDirection[1] = SK_Scalar1/2; 180 light.fDirection[2] = SK_Scalar1/3; 181 light.fAmbient = 0x48; 182 light.fSpecular = 0x80; 183 184 auto lightingFilter = SkColorMatrixFilter::MakeLightingFilter( 185 0xff89bc45, 0xff112233); 186 187 canvas->save(); 188 canvas->translate(SkIntToScalar(0), SkIntToScalar(5)); 189 paint.setAntiAlias(true); 190 paint.setFilterQuality(kLow_SkFilterQuality); 191 // !!! draw through a clip 192 paint.setColor(SK_ColorLTGRAY); 193 paint.setStyle(SkPaint::kFill_Style); 194 SkRect clip = {0, 0, SkIntToScalar(320), SkIntToScalar(120)}; 195 canvas->clipRect(clip); 196 paint.setShader(SkShader::MakeBitmapShader(fTx, 197 SkShader::kMirror_TileMode, SkShader::kRepeat_TileMode)); 198 canvas->drawPaint(paint); 199 canvas->save(); 200 201 // line (exercises xfermode, colorShader, colorFilter, filterShader) 202 paint.setColor(SK_ColorGREEN); 203 paint.setStrokeWidth(SkIntToScalar(10)); 204 paint.setStyle(SkPaint::kStroke_Style); 205 paint.setBlendMode(SkBlendMode::kXor); 206 paint.setColorFilter(lightingFilter); 207 canvas->drawLine(start, stop, paint); // should not be green 208 paint.setBlendMode(SkBlendMode::kSrcOver); 209 paint.setColorFilter(nullptr); 210 211 // rectangle 212 paint.setStyle(SkPaint::kFill_Style); 213 canvas->translate(SkIntToScalar(50), 0); 214 paint.setColor(SK_ColorYELLOW); 215 paint.setShader(linear); 216 paint.setPathEffect(pathEffectTest()); 217 canvas->drawRect(rect, paint); 218 paint.setPathEffect(nullptr); 219 220 // circle w/ emboss & transparent (exercises 3dshader) 221 canvas->translate(SkIntToScalar(50), 0); 222 paint.setMaskFilter(SkEmbossMaskFilter::Make( 223 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(12)/5), light)); 224 canvas->drawOval(rect, paint); 225 canvas->translate(SkIntToScalar(10), SkIntToScalar(10)); 226 // paint.setShader(transparentShader)->unref(); 227 canvas->drawOval(rect, paint); 228 canvas->translate(0, SkIntToScalar(-10)); 229 230 // path 231 canvas->translate(SkIntToScalar(50), 0); 232 paint.setColor(SK_ColorRED); 233 paint.setStyle(SkPaint::kStroke_Style); 234 paint.setStrokeWidth(SkIntToScalar(5)); 235 paint.setShader(radial); 236 paint.setMaskFilter(nullptr); 237 canvas->drawPath(path, paint); 238 239 paint.setShader(nullptr); 240 // bitmap 241 canvas->translate(SkIntToScalar(50), 0); 242 paint.setStyle(SkPaint::kFill_Style); 243 canvas->drawBitmap(fBug, left, top, &paint); 244 245 canvas->translate(-SkIntToScalar(30), SkIntToScalar(30)); 246 paint.setShader(shaderTest()); // test compose shader 247 canvas->drawRect(rect2, paint); 248 paint.setShader(nullptr); 249 250 canvas->restore(); 251 // text 252 canvas->translate(0, SkIntToScalar(60)); 253 canvas->save(); 254 paint.setColor(SK_ColorGRAY); 255 canvas->drawPosText(ascii, asciiLength, pos.begin(), paint); 256 canvas->drawPosText(ascii, asciiLength, pos2.begin(), paint); 257 258 canvas->translate(SkIntToScalar(50), 0); 259 paint.setColor(SK_ColorCYAN); 260 canvas->drawText(utf8, sizeof(utf8) - 1, x, y, paint); 261 262 canvas->translate(SkIntToScalar(30), 0); 263 paint.setColor(SK_ColorMAGENTA); 264 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); 265 matrix.setTranslate(SkIntToScalar(10), SkIntToScalar(10)); 266 canvas->drawTextOnPath((void*) utf16, sizeof(utf16), path, &matrix, paint); 267 canvas->translate(0, SkIntToScalar(20)); 268 canvas->drawTextOnPath((void*) utf16simple, sizeof(utf16simple), path, &matrix, paint); 269 canvas->restore(); 270 271 canvas->translate(0, SkIntToScalar(60)); 272 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); 273 canvas->restore(); 274 } 275 276 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) { 277 fClickPt.set(x, y); 278 return this->INHERITED::onFindClickHandler(x, y, modi); 279 } 280 281 sk_sp<SkPathEffect> pathEffectTest() { 282 static const int gXY[] = { 1, 0, 0, -1, 2, -1, 3, 0, 2, 1, 0, 1 }; 283 SkScalar gPhase = 0; 284 SkPath path; 285 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 286 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) 287 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 288 path.close(); 289 path.offset(SkIntToScalar(-6), 0); 290 auto outer = SkPath1DPathEffect::Make(path, SkIntToScalar(12), 291 gPhase, SkPath1DPathEffect::kRotate_Style); 292 auto inner = SkDiscretePathEffect::Make(SkIntToScalar(2), 293 SkIntToScalar(1)/10); // SkCornerPathEffect(SkIntToScalar(2)); 294 return SkPathEffect::MakeCompose(outer, inner); 295 } 296 297 sk_sp<SkShader> shaderTest() { 298 SkPoint pts[] = { { 0, 0, }, { SkIntToScalar(100), 0 } }; 299 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; 300 auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr, 301 2, SkShader::kClamp_TileMode); 302 pts[1].set(0, SkIntToScalar(100)); 303 SkColor colors2[] = {SK_ColorBLACK, SkColorSetARGB(0x80, 0, 0, 0)}; 304 auto shaderB = SkGradientShader::MakeLinear(pts, colors2, nullptr, 305 2, SkShader::kClamp_TileMode); 306 return SkShader::MakeComposeShader(std::move(shaderA), std::move(shaderB), 307 SkBlendMode::kDstIn); 308 } 309 310 virtual void startTest() { 311 decode_file("/Users/caryclark/Desktop/bugcirc.gif", &fBug); 312 decode_file("/Users/caryclark/Desktop/tbcirc.gif", &fTb); 313 decode_file("/Users/caryclark/Desktop/05psp04.gif", &fTx); 314 } 315 316 private: 317 SkPoint fClickPt; 318 SkBitmap fBug, fTb, fTx; 319 typedef SampleView INHERITED; 320 }; 321 322 ////////////////////////////////////////////////////////////////////////////// 323 324 static SkView* MyFactory() { return new DemoView; } 325 static SkViewRegister reg(MyFactory); 326