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