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 "Sample.h" 8 #include "SkBlurMask.h" 9 #include "SkBlurMaskFilter.h" 10 #include "SkCanvas.h" 11 #include "SkReadBuffer.h" 12 #include "SkWriteBuffer.h" 13 #include "SkGradientShader.h" 14 #include "SkPaint.h" 15 #include "SkVertices.h" 16 17 #include "sk_tool_utils.h" 18 19 #define BG_COLOR 0xFFDDDDDD 20 21 typedef void (*SlideProc)(SkCanvas*); 22 23 /////////////////////////////////////////////////////////////////////////////// 24 25 #include "Sk1DPathEffect.h" 26 #include "Sk2DPathEffect.h" 27 #include "SkCornerPathEffect.h" 28 #include "SkDashPathEffect.h" 29 #include "SkDiscretePathEffect.h" 30 31 static void compose_pe(SkPaint* paint) { 32 SkPathEffect* pe = paint->getPathEffect(); 33 sk_sp<SkPathEffect> corner = SkCornerPathEffect::Make(25); 34 sk_sp<SkPathEffect> compose; 35 if (pe) { 36 compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner); 37 } else { 38 compose = corner; 39 } 40 paint->setPathEffect(compose); 41 } 42 43 static void hair_pe(SkPaint* paint) { 44 paint->setStrokeWidth(0); 45 } 46 47 static void hair2_pe(SkPaint* paint) { 48 paint->setStrokeWidth(0); 49 compose_pe(paint); 50 } 51 52 static void stroke_pe(SkPaint* paint) { 53 paint->setStrokeWidth(12); 54 compose_pe(paint); 55 } 56 57 static void dash_pe(SkPaint* paint) { 58 SkScalar inter[] = { 20, 10, 10, 10 }; 59 paint->setStrokeWidth(12); 60 paint->setPathEffect(SkDashPathEffect::Make(inter, SK_ARRAY_COUNT(inter), 0)); 61 compose_pe(paint); 62 } 63 64 static const int gXY[] = { 65 4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4 66 }; 67 68 static void scale(SkPath* path, SkScalar scale) { 69 SkMatrix m; 70 m.setScale(scale, scale); 71 path->transform(m); 72 } 73 74 static void one_d_pe(SkPaint* paint) { 75 SkPath path; 76 path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1])); 77 for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2) 78 path.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1])); 79 path.close(); 80 path.offset(SkIntToScalar(-6), 0); 81 scale(&path, 1.5f); 82 83 paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0, 84 SkPath1DPathEffect::kRotate_Style)); 85 compose_pe(paint); 86 } 87 88 typedef void (*PE_Proc)(SkPaint*); 89 static const PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe }; 90 91 static void fill_pe(SkPaint* paint) { 92 paint->setStyle(SkPaint::kFill_Style); 93 paint->setPathEffect(nullptr); 94 } 95 96 static void discrete_pe(SkPaint* paint) { 97 paint->setPathEffect(SkDiscretePathEffect::Make(10, 4)); 98 } 99 100 static sk_sp<SkPathEffect> MakeTileEffect() { 101 SkMatrix m; 102 m.setScale(SkIntToScalar(12), SkIntToScalar(12)); 103 104 SkPath path; 105 path.addCircle(0, 0, SkIntToScalar(5)); 106 107 return SkPath2DPathEffect::Make(m, path); 108 } 109 110 static void tile_pe(SkPaint* paint) { 111 paint->setPathEffect(MakeTileEffect()); 112 } 113 114 static const PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe }; 115 116 static void patheffect_slide(SkCanvas* canvas) { 117 SkPaint paint; 118 paint.setAntiAlias(true); 119 paint.setStyle(SkPaint::kStroke_Style); 120 121 SkPath path; 122 path.moveTo(20, 20); 123 path.lineTo(70, 120); 124 path.lineTo(120, 30); 125 path.lineTo(170, 80); 126 path.lineTo(240, 50); 127 128 size_t i; 129 canvas->save(); 130 for (i = 0; i < SK_ARRAY_COUNT(gPE); i++) { 131 gPE[i](&paint); 132 canvas->drawPath(path, paint); 133 canvas->translate(0, 75); 134 } 135 canvas->restore(); 136 137 path.reset(); 138 SkRect r = { 0, 0, 250, 120 }; 139 path.addOval(r, SkPath::kCW_Direction); 140 r.inset(50, 50); 141 path.addRect(r, SkPath::kCCW_Direction); 142 143 canvas->translate(320, 20); 144 for (i = 0; i < SK_ARRAY_COUNT(gPE2); i++) { 145 gPE2[i](&paint); 146 canvas->drawPath(path, paint); 147 canvas->translate(0, 160); 148 } 149 } 150 151 /////////////////////////////////////////////////////////////////////////////// 152 153 #include "SkGradientShader.h" 154 155 struct GradData { 156 int fCount; 157 const SkColor* fColors; 158 const SkScalar* fPos; 159 }; 160 161 static const SkColor gColors[] = { 162 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK 163 }; 164 static const SkScalar gPos0[] = { 0, SK_Scalar1 }; 165 static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 }; 166 static const SkScalar gPos2[] = { 167 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1 168 }; 169 170 static const GradData gGradData[] = { 171 { 2, gColors, nullptr }, 172 { 2, gColors, gPos0 }, 173 { 2, gColors, gPos1 }, 174 { 5, gColors, nullptr }, 175 { 5, gColors, gPos2 } 176 }; 177 178 static sk_sp<SkShader> MakeLinear(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 179 return SkGradientShader::MakeLinear(pts, data.fColors, data.fPos, data.fCount, tm); 180 } 181 182 static sk_sp<SkShader> MakeRadial(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 183 SkPoint center; 184 center.set(SkScalarAve(pts[0].fX, pts[1].fX), 185 SkScalarAve(pts[0].fY, pts[1].fY)); 186 return SkGradientShader::MakeRadial(center, center.fX, data.fColors, 187 data.fPos, data.fCount, tm); 188 } 189 190 static sk_sp<SkShader> MakeSweep(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 191 SkPoint center; 192 center.set(SkScalarAve(pts[0].fX, pts[1].fX), 193 SkScalarAve(pts[0].fY, pts[1].fY)); 194 return SkGradientShader::MakeSweep(center.fX, center.fY, data.fColors, data.fPos, data.fCount); 195 } 196 197 static sk_sp<SkShader> Make2Conical(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm) { 198 SkPoint center0, center1; 199 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 200 SkScalarAve(pts[0].fY, pts[1].fY)); 201 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 202 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 203 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7, 204 center0, (pts[1].fX - pts[0].fX) / 2, 205 data.fColors, data.fPos, data.fCount, tm); 206 } 207 208 typedef sk_sp<SkShader> (*GradMaker)(const SkPoint pts[2], const GradData&, SkShader::TileMode); 209 static const GradMaker gGradMakers[] = { 210 MakeLinear, MakeRadial, MakeSweep, Make2Conical 211 }; 212 213 static void gradient_slide(SkCanvas* canvas) { 214 SkPoint pts[2] = { 215 { 0, 0 }, 216 { SkIntToScalar(100), SkIntToScalar(100) } 217 }; 218 SkShader::TileMode tm = SkShader::kClamp_TileMode; 219 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) }; 220 SkPaint paint; 221 paint.setAntiAlias(true); 222 paint.setDither(true); 223 224 canvas->translate(SkIntToScalar(20), SkIntToScalar(10)); 225 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) { 226 canvas->save(); 227 for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) { 228 paint.setShader(gGradMakers[j](pts, gGradData[i], tm)); 229 canvas->drawRect(r, paint); 230 canvas->translate(0, SkIntToScalar(120)); 231 } 232 canvas->restore(); 233 canvas->translate(SkIntToScalar(120), 0); 234 } 235 } 236 237 /////////////////////////////////////////////////////////////////////////////// 238 239 #include "DecodeFile.h" 240 #include "SkOSFile.h" 241 #include "SkRandom.h" 242 #include "SkStream.h" 243 244 static sk_sp<SkShader> make_shader0(SkIPoint* size) { 245 SkBitmap bm; 246 247 decode_file("/skimages/logo.gif", &bm); 248 size->set(bm.width(), bm.height()); 249 return SkShader::MakeBitmapShader(bm, SkShader::kClamp_TileMode, 250 SkShader::kClamp_TileMode); 251 } 252 253 static sk_sp<SkShader> make_shader1(const SkIPoint& size) { 254 SkPoint pts[] = { { 0, 0 }, 255 { SkIntToScalar(size.fX), SkIntToScalar(size.fY) } }; 256 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorRED }; 257 return SkGradientShader::MakeLinear(pts, colors, nullptr, 258 SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode); 259 } 260 261 class Rec { 262 public: 263 SkVertices::VertexMode fMode; 264 int fCount; 265 SkPoint* fVerts; 266 SkPoint* fTexs; 267 268 Rec() : fCount(0), fVerts(nullptr), fTexs(nullptr) {} 269 ~Rec() { delete[] fVerts; delete[] fTexs; } 270 }; 271 272 static void make_tris(Rec* rec) { 273 int n = 10; 274 SkRandom rand; 275 276 rec->fMode = SkVertices::kTriangles_VertexMode; 277 rec->fCount = n * 3; 278 rec->fVerts = new SkPoint[rec->fCount]; 279 280 for (int i = 0; i < n; i++) { 281 SkPoint* v = &rec->fVerts[i*3]; 282 for (int j = 0; j < 3; j++) { 283 v[j].set(rand.nextUScalar1() * 250, rand.nextUScalar1() * 250); 284 } 285 } 286 } 287 288 static void make_fan(Rec* rec, int texWidth, int texHeight) { 289 const SkScalar tx = SkIntToScalar(texWidth); 290 const SkScalar ty = SkIntToScalar(texHeight); 291 const int n = 24; 292 293 rec->fMode = SkVertices::kTriangleFan_VertexMode; 294 rec->fCount = n + 2; 295 rec->fVerts = new SkPoint[rec->fCount]; 296 rec->fTexs = new SkPoint[rec->fCount]; 297 298 SkPoint* v = rec->fVerts; 299 SkPoint* t = rec->fTexs; 300 301 v[0].set(0, 0); 302 t[0].set(0, 0); 303 for (int i = 0; i < n; i++) { 304 SkScalar cos; 305 SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos); 306 v[i+1].set(cos, sin); 307 t[i+1].set(i*tx/n, ty); 308 } 309 v[n+1] = v[1]; 310 t[n+1].set(tx, ty); 311 312 SkMatrix m; 313 m.setScale(SkIntToScalar(100), SkIntToScalar(100)); 314 m.postTranslate(SkIntToScalar(110), SkIntToScalar(110)); 315 m.mapPoints(v, rec->fCount); 316 } 317 318 static void make_strip(Rec* rec, int texWidth, int texHeight) { 319 const SkScalar tx = SkIntToScalar(texWidth); 320 const SkScalar ty = SkIntToScalar(texHeight); 321 const int n = 24; 322 323 rec->fMode = SkVertices::kTriangleStrip_VertexMode; 324 rec->fCount = 2 * (n + 1); 325 rec->fVerts = new SkPoint[rec->fCount]; 326 rec->fTexs = new SkPoint[rec->fCount]; 327 328 SkPoint* v = rec->fVerts; 329 SkPoint* t = rec->fTexs; 330 331 for (int i = 0; i < n; i++) { 332 SkScalar cos; 333 SkScalar sin = SkScalarSinCos(SK_ScalarPI * 2 * i / n, &cos); 334 v[i*2 + 0].set(cos/2, sin/2); 335 v[i*2 + 1].set(cos, sin); 336 337 t[i*2 + 0].set(tx * i / n, ty); 338 t[i*2 + 1].set(tx * i / n, 0); 339 } 340 v[2*n + 0] = v[0]; 341 v[2*n + 1] = v[1]; 342 343 t[2*n + 0].set(tx, ty); 344 t[2*n + 1].set(tx, 0); 345 346 SkMatrix m; 347 m.setScale(SkIntToScalar(100), SkIntToScalar(100)); 348 m.postTranslate(SkIntToScalar(110), SkIntToScalar(110)); 349 m.mapPoints(v, rec->fCount); 350 } 351 352 static void mesh_slide(SkCanvas* canvas) { 353 Rec fRecs[3]; 354 SkIPoint size; 355 356 auto fShader0 = make_shader0(&size); 357 auto fShader1 = make_shader1(size); 358 359 make_strip(&fRecs[0], size.fX, size.fY); 360 make_fan(&fRecs[1], size.fX, size.fY); 361 make_tris(&fRecs[2]); 362 363 SkPaint paint; 364 paint.setDither(true); 365 paint.setFilterQuality(kLow_SkFilterQuality); 366 367 for (size_t i = 0; i < SK_ARRAY_COUNT(fRecs); i++) { 368 auto verts = SkVertices::MakeCopy(fRecs[i].fMode, fRecs[i].fCount, 369 fRecs[i].fVerts, fRecs[i].fTexs, nullptr); 370 canvas->save(); 371 372 paint.setShader(nullptr); 373 canvas->drawVertices(verts, SkBlendMode::kModulate, paint); 374 375 canvas->translate(SkIntToScalar(210), 0); 376 377 paint.setShader(fShader0); 378 canvas->drawVertices(verts, SkBlendMode::kModulate, paint); 379 380 canvas->translate(SkIntToScalar(210), 0); 381 382 paint.setShader(fShader1); 383 canvas->drawVertices(verts, SkBlendMode::kModulate, paint); 384 canvas->restore(); 385 386 canvas->translate(0, SkIntToScalar(250)); 387 } 388 } 389 390 /////////////////////////////////////////////////////////////////////////////// 391 392 #include "SkTypeface.h" 393 394 /////////////////////////////////////////////////////////////////////////////// 395 396 #include "SkImageEncoder.h" 397 398 static const SlideProc gProc[] = { 399 patheffect_slide, 400 gradient_slide, 401 mesh_slide, 402 }; 403 404 class SlideView : public Sample { 405 int fIndex; 406 bool fOnce; 407 public: 408 SlideView() { 409 fOnce = false; 410 } 411 412 void init() { 413 if (fOnce) { 414 return; 415 } 416 fOnce = true; 417 418 fIndex = 0; 419 420 SkBitmap bm; 421 bm.allocN32Pixels(1024, 768); 422 SkCanvas canvas(bm); 423 SkScalar s = SkIntToScalar(1024) / 640; 424 canvas.scale(s, s); 425 for (size_t i = 0; i < SK_ARRAY_COUNT(gProc); i++) { 426 canvas.save(); 427 canvas.drawColor(BG_COLOR); 428 gProc[i](&canvas); 429 canvas.restore(); 430 SkString str; 431 str.printf("/skimages/slide_" SK_SIZE_T_SPECIFIER ".png", i); 432 sk_tool_utils::EncodeImageToFile(str.c_str(), bm, SkEncodedImageFormat::kPNG, 100); 433 } 434 this->setBGColor(BG_COLOR); 435 } 436 437 protected: 438 bool onQuery(Sample::Event* evt) override { 439 if (Sample::TitleQ(*evt)) { 440 Sample::TitleR(evt, "Slides"); 441 return true; 442 } 443 return this->INHERITED::onQuery(evt); 444 } 445 446 void onDrawContent(SkCanvas* canvas) override { 447 this->init(); 448 gProc[fIndex](canvas); 449 } 450 451 Sample::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned) override { 452 this->init(); 453 fIndex = (fIndex + 1) % SK_ARRAY_COUNT(gProc); 454 return nullptr; 455 } 456 457 private: 458 typedef Sample INHERITED; 459 }; 460 461 ////////////////////////////////////////////////////////////////////////////// 462 463 DEF_SAMPLE( return new SlideView(); ) 464