1 SkPaint 2 ======= 3 4 *color, stroke, font, effects* 5 6 - [SkXfermode](#SkXfermode) - transfer modes 7 - [ShShader](#ShShader) - gradients and patterns 8 - [SkMaskFilter](#SkMaskFilter) - modifications to the alpha mask 9 - [SkColorFilter](#SkColorFilter) - modify the source color before applying the 10 - [SkPathEffect](#SkPathEffect) - modify to the geometry before it 11 generates an alpha mask. 12 13 Anytime you draw something in Skia, and want to specify what color it 14 is, or how it blends with the background, or what style or font to 15 draw it in, you specify those attributes in a paint. 16 17 Unlike `SkCanvas`, paints do not maintain an internal stack of state 18 (i.e. there is no save/restore on a paint). However, paints are 19 relatively light-weight, so the client may create and maintain any 20 number of paint objects, each set up for a particular use. Factoring 21 all of these color and stylistic attribute out of the canvas state, 22 and into (multiple) paint objects, allows canvas' save/restore to be 23 that much more efficient, as all they have to do is maintain the stack 24 of matrix and clip settings. 25 26 <!--?prettify lang=cc?--> 27 28 void draw(SkCanvas* canvas) { 29 canvas->clear(SK_ColorWHITE); 30 31 SkPaint paint1, paint2, paint3; 32 33 paint1.setTextSize(64.0f); 34 paint1.setAntiAlias(true); 35 paint1.setColor(SkColorSetRGB(255, 0, 0); 36 paint1.setStyle(SkPaint::kFill_Style); 37 38 paint2.setTextSize(64.f); 39 paint2.setAntiAlias(true); 40 paint2.setColor(SkColorSetRGB(0, 136, 0); 41 paint2.setStyle(SkPaint::kStroke_Style); 42 paint2.setStrokeWidth(SkIntToScalar(3)); 43 44 paint3.setTextSize(64.0f); 45 paint3.setAntiAlias(true); 46 paint3.setColor(SkColorSetRGB(136, 136, 136)); 47 paint3.setTextScaleX(SkFloatToScalar(1.5f)); 48 49 const char text[] = "Skia!"; 50 canvas->drawText(text, strlen(text), 20.0f, 64.0f, paint1); 51 canvas->drawText(text, strlen(text), 20.0f, 144.0f, paint2); 52 canvas->drawText(text, strlen(text), 20.0f, 224.0f, paint3); 53 } 54 55 <a href="https://fiddle.skia.org/c/c4cfc71ed9232dac9c0d6518311b386e"> 56 <img src="https://fiddle.skia.org/i/c4cfc71ed9232dac9c0d6518311b386e_raster.png"></a> 57 58 This shows three different paints, each set up to draw in a different 59 style. Now the caller can intermix these paints freely, either using 60 them as is, or modifying them as the drawing proceeds. 61 62 <!--?prettify lang=cc?--> 63 64 SkPaint paint1, paint2, paint3; 65 paint2.setStyle(SkPaint::kStroke_Style); 66 paint2.setStrokeWidth(3); 67 paint3.setAntiAlias(true); 68 paint3.setColor(SK_ColorRED); 69 paint3.setTextSize(80); 70 71 canvas->drawRect(SkRect::MakeXYWH(10,10,60,20), paint1); 72 canvas->drawRect(SkRect::MakeXYWH(80,10,60,20), paint2); 73 74 paint2.setStrokeWidth(SkIntToScalar(5)); 75 canvas->drawOval(SkRect::MakeXYWH(150,10,60,20), paint2); 76 77 canvas->drawText("SKIA", 4, 20, 120, paint3); 78 paint3.setColor(SK_ColorBLUE); 79 canvas->drawText("SKIA", 4, 20, 220, paint3); 80 81 <a href="https://fiddle.skia.org/c/5203b17103f487dd33965b4211d80956"> 82 <img src="https://fiddle.skia.org/i/5203b17103f487dd33965b4211d80956_raster.png"></a> 83 84 Beyond simple attributes such as color, strokes, and text values, 85 paints support effects. These are subclasses of different aspects of 86 the drawing pipeline, that when referenced by a paint (each of them is 87 reference-counted), are called to override some part of the drawing 88 pipeline. 89 90 For example, to draw using a gradient instead of a single color, 91 assign a SkShader to the paint. 92 93 <!--?prettify lang=cc?--> 94 95 SkPoint points[2] = { 96 SkPoint::Make(0.0f, 0.0f), 97 SkPoint::Make(256.0f, 256.0f) 98 }; 99 SkColor colors[2] = {SK_ColorBLUE, SK_ColorYELLOW}; 100 SkShader* shader = 101 SkGradientShader::CreateLinear( 102 points, colors, nullptr, 2, 103 SkShader::kClamp_TileMode, 0, nullptr); 104 SkPaint paint; 105 paint.setShader(shader); 106 shader->unref(); 107 canvas->drawPaint(paint); 108 109 <a href="https://fiddle.skia.org/c/f91b5310d57744a5a1475b7e47d4a172"> 110 <img src="https://fiddle.skia.org/i/f91b5310d57744a5a1475b7e47d4a172_raster.png"></a> 111 112 Now, anything drawn with that paint will be drawn with the gradient 113 specified in the call to `CreateLinear()`. The shader object that is 114 returned is reference-counted. Whenever any effects object, like a 115 shader, is assigned to a paint, its reference-count is increased by 116 the paint. To balance this, the caller in the above example calls 117 `unref()` on the shader once it has assigned it to the paint. Now the 118 paint is the only "owner" of that shader, and it will automatically 119 call `unref()` on the shader when either the paint goes out of scope, or 120 if another shader (or null) is assigned to it. 121 122 There are 6 types of effects that can be assigned to a paint: 123 124 * **SkPathEffect** - modifications to the geometry (path) before it 125 generates an alpha mask (e.g. dashing) 126 * **SkRasterizer** - composing custom mask layers (e.g. shadows) 127 * **SkMaskFilter** - modifications to the alpha mask before it is 128 colorized and drawn (e.g. blur, emboss) 129 * **SkShader** - e.g. gradients (linear, radial, sweep), bitmap patterns 130 (clamp, repeat, mirror) 131 * **SkColorFilter** - modify the source color(s) before applying the 132 xfermode (e.g. color matrix) 133 * **SkXfermode** - e.g. porter-duff transfermodes, blend modes 134 135 Paints also hold a reference to a SkTypeface. The typeface represents 136 a specific font style, to be used for measuring and drawing 137 text. Speaking of which, paints are used not only for drawing text, 138 but also for measuring it. 139 140 <!--?prettify lang=cc?--> 141 142 paint.measureText(...); 143 paint.getTextBounds(...); 144 paint.textToGlyphs(...); 145 paint.getFontMetrics(...); 146 147 <span id="SkXfermode"></span> 148 149 SkXfermode 150 ---------- 151 152 The following example demonstrates all of the Skia's standard transfer 153 modes. In this example the source is a solid magenta color with a 154 horizontal alpha gradient and the destination is a solid cyan color 155 with a vertical alpha gradient. 156 157 <!--?prettify lang=cc?--> 158 159 SkXfermode::Mode modes[] = { 160 SkXfermode::kClear_Mode, 161 SkXfermode::kSrc_Mode, 162 SkXfermode::kDst_Mode, 163 SkXfermode::kSrcOver_Mode, 164 SkXfermode::kDstOver_Mode, 165 SkXfermode::kSrcIn_Mode, 166 SkXfermode::kDstIn_Mode, 167 SkXfermode::kSrcOut_Mode, 168 SkXfermode::kDstOut_Mode, 169 SkXfermode::kSrcATop_Mode, 170 SkXfermode::kDstATop_Mode, 171 SkXfermode::kXor_Mode, 172 SkXfermode::kPlus_Mode, 173 SkXfermode::kModulate_Mode, 174 SkXfermode::kScreen_Mode, 175 SkXfermode::kOverlay_Mode, 176 SkXfermode::kDarken_Mode, 177 SkXfermode::kLighten_Mode, 178 SkXfermode::kColorDodge_Mode, 179 SkXfermode::kColorBurn_Mode, 180 SkXfermode::kHardLight_Mode, 181 SkXfermode::kSoftLight_Mode, 182 SkXfermode::kDifference_Mode, 183 SkXfermode::kExclusion_Mode, 184 SkXfermode::kMultiply_Mode, 185 SkXfermode::kHue_Mode, 186 SkXfermode::kSaturation_Mode, 187 SkXfermode::kColor_Mode, 188 SkXfermode::kLuminosity_Mode, 189 }; 190 SkRect rect = SkRect::MakeWH(64.0f, 64.0f); 191 SkPaint text, stroke, src, dst; 192 stroke.setStyle(SkPaint::kStroke_Style); 193 text.setTextSize(24.0f); 194 text.setAntiAlias(true); 195 SkPoint srcPoints[2] = { 196 SkPoint::Make(0.0f, 0.0f), 197 SkPoint::Make(64.0f, 0.0f) 198 }; 199 SkColor srcColors[2] = { 200 SK_ColorMAGENTA & 0x00FFFFFF, 201 SK_ColorMAGENTA}; 202 SkAutoTUnref<SkShader> srcShader( 203 SkGradientShader::CreateLinear( 204 srcPoints, srcColors, nullptr, 2, 205 SkShader::kClamp_TileMode, 0, nullptr)); 206 src.setShader(srcShader); 207 208 SkPoint dstPoints[2] = { 209 SkPoint::Make(0.0f, 0.0f), 210 SkPoint::Make(0.0f, 64.0f) 211 }; 212 SkColor dstColors[2] = { 213 SK_ColorCYAN & 0x00FFFFFF, 214 SK_ColorCYAN}; 215 SkAutoTUnref<SkShader> dstShader( 216 SkGradientShader::CreateLinear( 217 dstPoints, dstColors, nullptr, 2, 218 SkShader::kClamp_TileMode, 0, nullptr)); 219 dst.setShader(dstShader); 220 canvas->clear(SK_ColorWHITE); 221 size_t N = sizeof(modes) / sizeof(modes[0]); 222 size_t K = (N - 1) / 3 + 1; 223 SkASSERT(K * 64 == 640); // tall enough 224 for (size_t i = 0; i < N; ++i) { 225 SkAutoCanvasRestore autoCanvasRestore(canvas, true); 226 canvas->translate(192.0f * (i / K), 64.0f * (i % K)); 227 const char* desc = SkXfermode::ModeName(modes[i]); 228 canvas->drawText(desc, strlen(desc), 68.0f, 30.0f, text); 229 canvas->clipRect(SkRect::MakeWH(64.0f, 64.0f)); 230 canvas->drawColor(SK_ColorLTGRAY); 231 (void)canvas->saveLayer(nullptr, nullptr); 232 canvas->clear(SK_ColorTRANSPARENT); 233 canvas->drawPaint(dst); 234 src.setXfermodeMode(modes[i]); 235 canvas->drawPaint(src); 236 canvas->drawRect(rect, stroke); 237 } 238 239 <a href="https://fiddle.skia.org/c/0a2392be5adf339ce6537799f2807f3c"><img src="https://fiddle.skia.org/i/0a2392be5adf339ce6537799f2807f3c_raster.png" alt=""></a> 240 241 <span id="ShShader"></span> 242 243 ShShader 244 -------- 245 246 Several shaders are defined (besides the linear gradient already mentioned): 247 248 * Bitmap Shader 249 250 <!--?prettify lang=cc?--> 251 252 canvas->clear(SK_ColorWHITE); 253 SkMatrix matrix; 254 matrix.setScale(0.75f, 0.75f); 255 matrix.preRotate(30.0f); 256 SkShader* shader = 257 SkShader::CreateBitmapShader( 258 source, 259 SkShader::kRepeat_TileMode , 260 SkShader::kRepeat_TileMode , 261 &matrix); 262 SkPaint paint; 263 paint.setShader(shader); 264 shader->unref(); 265 canvas->drawPaint(paint); 266 267 <a href="https://fiddle.skia.org/c/0e8d08e0a0b342e9e45c364d0e5cea8a"> 268 <img src="https://fiddle.skia.org/i/0e8d08e0a0b342e9e45c364d0e5cea8a_raster.png"></a> 269 270 * Radial Gradient Shader 271 272 <!--?prettify lang=cc?--> 273 274 SkColor colors[2] = {SK_ColorBLUE, SK_ColorYELLOW}; 275 SkShader* shader = 276 SkGradientShader::CreateRadial( 277 SkPoint::Make(128.0f, 128.0f), 180.0f, 278 colors, nullptr, 2, SkShader::kClamp_TileMode, 0, nullptr); 279 SkPaint paint; 280 paint.setShader(shader); 281 shader->unref(); 282 canvas->drawPaint(paint); 283 284 <a href="https://fiddle.skia.org/c/601abd2819e38365900bf62286986024"> 285 <img src="https://fiddle.skia.org/i/601abd2819e38365900bf62286986024_raster.png"></a> 286 287 * Two-Point Conical Gradient Shader 288 289 <!--?prettify lang=cc?--> 290 291 SkColor colors[2] = {SK_ColorBLUE, SK_ColorYELLOW}; 292 SkShader* shader = 293 SkGradientShader::CreateTwoPointConical( 294 SkPoint::Make(128.0f, 128.0f), 128.0f, 295 SkPoint::Make(128.0f, 16.0f), 16.0f, 296 colors, nullptr, 2, SkShader::kClamp_TileMode, 0, nullptr); 297 SkPaint paint; 298 paint.setShader(shader); 299 shader->unref(); 300 canvas->drawPaint(paint); 301 302 <a href="https://fiddle.skia.org/c/991f7d67ff1ccebd6c2c4fab18a76edc"> 303 <img src="https://fiddle.skia.org/i/991f7d67ff1ccebd6c2c4fab18a76edc_raster.png"></a> 304 305 306 * Sweep Gradient Shader 307 308 <!--?prettify lang=cc?--> 309 310 SkColor colors[4] = { 311 SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW, SK_ColorCYAN}; 312 SkShader* shader = 313 SkGradientShader::CreateSweep( 314 128.0f, 128.0f, colors, nullptr, 4, 0, nullptr); 315 SkPaint paint; 316 paint.setShader(shader); 317 shader->unref(); 318 canvas->drawPaint(paint); 319 320 <a href="https://fiddle.skia.org/c/cee9d1831f6679c3d88170f857995d12"> 321 <img src="https://fiddle.skia.org/i/cee9d1831f6679c3d88170f857995d12_raster.png"></a> 322 323 * Fractal Perlin Noise Shader 324 325 <!--?prettify lang=cc?--> 326 327 canvas->clear(SK_ColorWHITE); 328 SkShader* shader = SkPerlinNoiseShader::CreateFractalNoise( 329 0.05f, 0.05f, 4, 0.0f, nullptr); 330 SkPaint paint; 331 paint.setShader(shader); 332 shader->unref(); 333 canvas->drawPaint(paint); 334 335 <a href="https://fiddle.skia.org/c/cc45c5349c3b31f97da7c1af7f84162a"> 336 <img src="https://fiddle.skia.org/i/cc45c5349c3b31f97da7c1af7f84162a_raster.png"></a> 337 338 * Turbulence Perlin Noise Shader 339 340 <!--?prettify lang=cc?--> 341 342 canvas->clear(SK_ColorWHITE); 343 SkShader* shader = SkPerlinNoiseShader::CreateTurbulence( 344 0.05f, 0.05f, 4, 0.0f, nullptr); 345 SkPaint paint; 346 paint.setShader(shader); 347 shader->unref(); 348 canvas->drawPaint(paint); 349 350 <a href="https://fiddle.skia.org/c/52729ed3a71b89a6dba4f60e8eb67727"> 351 <img src="https://fiddle.skia.org/i/52729ed3a71b89a6dba4f60e8eb67727_raster.png"></a> 352 353 * Compose Shader 354 355 <!--?prettify lang=cc?--> 356 357 SkColor colors[2] = {SK_ColorBLUE, SK_ColorYELLOW}; 358 SkShader* shader1 = 359 SkGradientShader::CreateRadial( 360 SkPoint::Make(128.0f, 128.0f), 180.0f, 361 colors, nullptr, 2, SkShader::kClamp_TileMode, 0, nullptr); 362 SkShader* shader2 = SkPerlinNoiseShader::CreateTurbulence( 363 0.025f, 0.025f, 2, 0.0f, nullptr); 364 SkShader* shader = 365 new SkComposeShader(shader1, shader2); 366 SkPaint paint; 367 paint.setShader(shader); 368 shader->unref(); 369 shader2->unref(); 370 shader1->unref(); 371 canvas->drawPaint(paint); 372 373 <a href="https://fiddle.skia.org/c/1209b7a29d870302edcc43dc0916e8d5"> 374 <img src="https://fiddle.skia.org/i/1209b7a29d870302edcc43dc0916e8d5_raster.png"></a> 375 376 377 <span id="SkMaskFilter"></span> 378 379 SkMaskFilter 380 ------------ 381 382 * Blur Mask Filter 383 384 <!--?prettify lang=cc?--> 385 386 canvas->drawColor(SK_ColorWHITE); 387 SkPaint paint; 388 paint.setAntiAlias(true); 389 paint.setTextSize(120); 390 SkMaskFilter* filter = 391 SkBlurMaskFilter::Create( 392 kNormal_SkBlurStyle, 5.0f, 0); 393 paint.setMaskFilter(filter); 394 filter->unref(); 395 const char text[] = "Skia"; 396 canvas->drawText(text, strlen(text), 0, 160, paint); 397 398 <a href="https://fiddle.skia.org/c/0e004664122851691d67a291007b64d7"> 399 <img src="https://fiddle.skia.org/i/0e004664122851691d67a291007b64d7_raster.png"></a> 400 401 * Emboss Mask Filter 402 403 <!--?prettify lang=cc?--> 404 405 canvas->drawColor(SK_ColorWHITE); 406 SkPaint paint; 407 paint.setAntiAlias(true); 408 paint.setTextSize(120); 409 SkScalar direction[3] = {1.0f, 1.0f, 1.0f}; 410 SkMaskFilter* filter = 411 SkBlurMaskFilter::CreateEmboss( 412 2.0f, direction, 0.3f, 0.1f); 413 paint.setMaskFilter(filter); 414 filter->unref(); 415 const char text[] = "Skia"; 416 canvas->drawText(text, strlen(text), 0, 160, paint); 417 418 <a href="https://fiddle.skia.org/c/1ef71be7fb749a2d81a55721b2d2c77d"> 419 <img src="https://fiddle.skia.org/i/1ef71be7fb749a2d81a55721b2d2c77d_raster.png"></a> 420 421 422 <span id="SkColorFilter"></span> 423 424 SkColorFilter 425 ------------- 426 427 * Color Matrix Color Filter 428 429 <!--?prettify lang=cc?--> 430 431 void f(SkCanvas* c, SkScalar x, SkScalar y, SkScalar colorMatrix[20]) { 432 SkColorFilter* cf = SkColorMatrixFilter::Create(colorMatrix); 433 SkPaint paint; 434 paint.setColorFilter(cf); 435 cf->unref(); 436 c->drawBitmap(source, x, y, &paint); 437 } 438 void draw(SkCanvas* c) { 439 c->scale(0.25, 0.25); 440 SkScalar colorMatrix1[20] = { 441 0, 1, 0, 0, 0, 442 0, 0, 1, 0, 0, 443 1, 0, 0, 0, 0, 444 0, 0, 0, 1, 0}; 445 f(c, 0, 0, colorMatrix1); 446 447 SkScalar grayscale[20] = { 448 0.21, 0.72, 0.07, 0.0, 0.0, 449 0.21, 0.72, 0.07, 0.0, 0.0, 450 0.21, 0.72, 0.07, 0.0, 0.0, 451 0.0, 0.0, 0.0, 1.0, 0.0}; 452 f(c, 512, 0, grayscale); 453 454 SkScalar colorMatrix3[20] = { 455 -1, 1, 1, 0, 0, 456 1, -1, 1, 0, 0, 457 1, 1, -1, 0, 0, 458 0, 0, 0, 1, 0}; 459 f(c, 0, 512, colorMatrix3); 460 461 SkScalar colorMatrix4[20] = { 462 0.0, 0.5, 0.5, 0, 0, 463 0.5, 0.0, 0.5, 0, 0, 464 0.5, 0.5, 0.0, 0, 0, 465 0.0, 0.0, 0.0, 1, 0}; 466 f(c, 512, 512, colorMatrix4); 467 468 SkScalar highContrast[20] = { 469 4.0, 0.0, 0.0, 0.0, -4.0 * 255 / (4.0 - 1), 470 0.0, 4.0, 0.0, 0.0, -4.0 * 255 / (4.0 - 1), 471 0.0, 0.0, 4.0, 0.0, -4.0 * 255 / (4.0 - 1), 472 0.0, 0.0, 0.0, 1.0, 0.0}; 473 f(c, 1024, 0, highContrast); 474 475 SkScalar colorMatrix6[20] = { 476 0, 0, 1, 0, 0, 477 1, 0, 0, 0, 0, 478 0, 1, 0, 0, 0, 479 0, 0, 0, 1, 0}; 480 f(c, 1024, 512, colorMatrix6); 481 482 SkScalar sepia[20] = { 483 0.393, 0.769, 0.189, 0.0, 0.0, 484 0.349, 0.686, 0.168, 0.0, 0.0, 485 0.272, 0.534, 0.131, 0.0, 0.0, 486 0.0, 0.0, 0.0, 1.0, 0.0}; 487 f(c, 1536, 0, sepia); 488 489 SkScalar inverter[20] = { 490 -1, 0, 0, 0, 255, 491 0, -1, 0, 0, 255, 492 0, 0, -1, 0, 255, 493 0, 0, 0, 1, 0}; 494 f(c, 1536, 512, inverter); 495 } 496 497 <a href="https://fiddle.skia.org/c/91fb5341ee7903c9682df20bb3d73dbb"> 498 <img src="https://fiddle.skia.org/i/91fb5341ee7903c9682df20bb3d73dbb_raster.png"></a> 499 500 * Color Table Color Filter 501 502 <!--?prettify lang=cc?--> 503 504 canvas->scale(0.5, 0.5); 505 uint8_t ct[256]; 506 for (int i = 0; i < 256; ++i) { 507 int x = (i - 96) * 255 / 64; 508 ct[i] = x < 0 ? 0 : x > 255 ? 255 : x; 509 } 510 SkColorFilter* cf = SkTableColorFilter::CreateARGB(nullptr, ct, ct, ct); 511 SkPaint paint; 512 paint.setColorFilter(cf); 513 cf->unref(); 514 canvas->drawBitmap(source, 0, 0, &paint); 515 516 <a href="https://fiddle.skia.org/c/0d3d339543afa1b10c60f9826f264c3f"> 517 <img src="https://fiddle.skia.org/i/0d3d339543afa1b10c60f9826f264c3f_raster.png"></a> 518 519 520 <span id="SkPathEffect"></span> 521 522 SkPathEffect 523 ------------ 524 525 * SkPath2DPathEffect: Stamp the specified path to fill the shape, 526 using the matrix to define the latice. 527 528 <!--?prettify lang=cc?--> 529 530 void draw(SkCanvas* canvas) { 531 SkScalar scale = 10.0f; 532 SkPath path; 533 static const int8_t pts[] = { 2, 2, 1, 3, 0, 3, 2, 1, 3, 1, 534 4, 0, 4, 1, 5, 1, 4, 2, 4, 3, 2, 5, 2, 4, 3, 3, 2, 3 }; 535 path.moveTo(2 * scale, 3 * scale); 536 for (size_t i = 0 ; i < sizeof(pts)/sizeof(pts[0]); i += 2) { 537 path.lineTo(pts[i] * scale, pts[i + 1] * scale); 538 } 539 path.close(); 540 SkMatrix matrix = SkMatrix::MakeScale(4 * scale); 541 SkAutoTUnref<SkPathEffect> pathEffect( 542 SkPath2DPathEffect::Create(matrix, path)); 543 SkPaint paint; 544 paint.setPathEffect(pathEffect); 545 paint.setAntiAlias(true); 546 canvas->clear(SK_ColorWHITE); 547 SkRect bounds; 548 (void)canvas->getClipBounds(&bounds); 549 bounds.outset(2 * scale, 2 * scale); 550 canvas->drawRect(bounds, paint); 551 } 552 553 <a href="https://fiddle.skia.org/c/aae271e4f0178455f0e128981d714d73"><img src="https://fiddle.skia.org/i/aae271e4f0178455f0e128981d714d73_raster.png" alt=""></a> 554 555 * SkLine2DPathEffect: a special case of SkPath2DPathEffect where the 556 path is a straight line to be stroked, not a path to be filled. 557 558 <!--?prettify lang=cc?--> 559 560 void draw(SkCanvas* canvas) { 561 SkPaint paint; 562 SkMatrix lattice; 563 lattice.setScale(8.0f, 8.0f); 564 lattice.preRotate(30.0f); 565 SkAutoTUnref<SkPathEffect> pe( 566 SkLine2DPathEffect::Create(0.0f, lattice)); 567 paint.setPathEffect(pe); 568 paint.setAntiAlias(true); 569 SkRect bounds; 570 (void)canvas->getClipBounds(&bounds); 571 bounds.outset(8.0f, 8.0f); 572 canvas->clear(SK_ColorWHITE); 573 canvas->drawRect(bounds, paint); 574 } 575 576 <a href="https://fiddle.skia.org/c/3f49502145886920f95d43912e0f550d"><img src="https://fiddle.skia.org/i/3f49502145886920f95d43912e0f550d_raster.png" alt=""></a> 577 578 * SkPath1DPathEffect: create dash-like effects by replicating the specified path along the drawn path. 579 580 <!--?prettify lang=cc?--> 581 582 void draw(SkCanvas* canvas) { 583 SkPaint paint; 584 SkPath path; 585 path.addOval(SkRect::MakeWH(16.0f, 6.0f)); 586 SkAutoTUnref<SkPathEffect> pe( 587 SkPath1DPathEffect::Create( 588 path, 32.0f, 0.0f, SkPath1DPathEffect::kRotate_Style)); 589 paint.setPathEffect(pe); 590 paint.setAntiAlias(true); 591 canvas->clear(SK_ColorWHITE); 592 canvas->drawCircle(128.0f, 128.0f, 122.0f, paint); 593 } 594 595 <a href="https://fiddle.skia.org/c/756a8cdb9458c05f6c1c7c398d979dac"><img src="https://fiddle.skia.org/i/756a8cdb9458c05f6c1c7c398d979dac_raster.png" alt=""></a> 596 597 * SkArcToPathEffect 598 599 The following few examples use this function: 600 601 <!--?prettify lang=cc?--> 602 603 SkPath star() { 604 const SkScalar R = 115.2f, C = 128.0f; 605 SkPath path; 606 path.moveTo(C + R, C); 607 for (int i = 1; i < 7; ++i) { 608 SkScalar a = 2.6927937f * i; 609 path.lineTo(C + R * cos(a), C + R * sin(a)); 610 } 611 path.close(); 612 return path; 613 } 614 615 <!--?prettify lang=cc?--> 616 617 void draw(SkCanvas* canvas) { 618 SkPaint paint; 619 SkAutoTUnref<SkPathEffect> pe( 620 SkArcToPathEffect::Create(8.0f)); 621 paint.setPathEffect(pe); 622 paint.setStyle(SkPaint::kStroke_Style); 623 paint.setAntiAlias(true); 624 canvas->clear(SK_ColorWHITE); 625 SkPath path(star()); 626 canvas->drawPath(path, paint); 627 } 628 629 <a href="https://fiddle.skia.org/c/1cc2a1363dd0e96954e084f7ca29aa5f"><img src="https://fiddle.skia.org/i/1cc2a1363dd0e96954e084f7ca29aa5f_raster.png" alt=""></a> 630 631 * SkCornerPathEffect: a path effect that can turn sharp corners into 632 various treatments (e.g. rounded corners). 633 634 <!--?prettify lang=cc?--> 635 636 void draw(SkCanvas* canvas) { 637 SkPaint paint; 638 SkAutoTUnref<SkPathEffect> pe( 639 SkCornerPathEffect::Create(32.0f)); 640 paint.setPathEffect(pe); 641 paint.setStyle(SkPaint::kStroke_Style); 642 paint.setAntiAlias(true); 643 canvas->clear(SK_ColorWHITE); 644 const SkScalar R = 115.2f; 645 SkPath path(star()); 646 canvas->drawPath(path, paint); 647 } 648 649 <a href="https://fiddle.skia.org/c/f5361bbb33ad43c656dd40bb03ee2114"><img src="https://fiddle.skia.org/i/f5361bbb33ad43c656dd40bb03ee2114_raster.png" alt=""></a> 650 651 * SkDashPathEffect: a path effect that implements dashing. 652 653 <!--?prettify lang=cc?--> 654 655 void draw(SkCanvas* canvas) { 656 const SkScalar intervals[] = { 10.0f, 5.0f, 2.0f, 5.0f }; 657 size_t count = sizeof(intervals) / sizeof(intervals[0]); 658 SkAutoTUnref<SkPathEffect> pe( 659 SkDashPathEffect::Create(intervals, count, 0.0f)); 660 SkPaint paint; 661 paint.setPathEffect(pe); 662 paint.setStyle(SkPaint::kStroke_Style); 663 paint.setStrokeWidth(2.0f); 664 paint.setAntiAlias(true); 665 canvas->clear(SK_ColorWHITE); 666 SkPath path(star()); 667 canvas->drawPath(path, paint); 668 } 669 670 <a href="https://fiddle.skia.org/c/d221ced999a80ac23870d0301ffeedad"><img src="https://fiddle.skia.org/i/d221ced999a80ac23870d0301ffeedad_raster.png" alt=""></a> 671 672 * SkDiscretePathEffect: This path effect chops a path into discrete 673 segments, and randomly displaces them. 674 675 <!--?prettify lang=cc?--> 676 677 void draw(SkCanvas* canvas) { 678 SkAutoTUnref<SkPathEffect> pe( 679 SkDiscretePathEffect::Create(10.0f, 4.0f)); 680 SkPaint paint; 681 paint.setPathEffect(pe); 682 paint.setStyle(SkPaint::kStroke_Style); 683 paint.setStrokeWidth(2.0f); 684 paint.setAntiAlias(true); 685 canvas->clear(SK_ColorWHITE); 686 SkPath path(star()); 687 canvas->drawPath(path, paint); 688 } 689 690 <a href="https://fiddle.skia.org/c/af2f177438b376ca45cfffc29cc0177a"><img src="https://fiddle.skia.org/i/af2f177438b376ca45cfffc29cc0177a_raster.png" alt=""></a> 691 692 * SkComposePathEffect: a pathEffect whose effect is to apply 693 first the inner pathEffect and the the outer pathEffect (i.e. 694 outer(inner(path))). 695 696 <!--?prettify lang=cc?--> 697 698 void draw(SkCanvas* canvas) { 699 SkAutoTUnref<SkPathEffect> pe0( 700 SkDiscretePathEffect::Create(10.0f, 4.0f)); 701 const SkScalar intervals[] = { 10.0f, 5.0f, 2.0f, 5.0f }; 702 size_t count = sizeof(intervals) / sizeof(intervals[0]); 703 SkAutoTUnref<SkPathEffect> pe1( 704 SkDashPathEffect::Create(intervals, count, 0.0f)); 705 SkAutoTUnref<SkPathEffect> pe( 706 SkComposePathEffect::Create(pe1, pe0)); 707 SkPaint paint; 708 paint.setPathEffect(pe); 709 paint.setStyle(SkPaint::kStroke_Style); 710 paint.setStrokeWidth(2.0f); 711 paint.setAntiAlias(true); 712 canvas->clear(SK_ColorWHITE); 713 SkPath path(star()); 714 canvas->drawPath(path, paint); 715 } 716 717 <a href="https://fiddle.skia.org/c/39a644161da79e8b5e49c193adac7173"><img src="https://fiddle.skia.org/i/39a644161da79e8b5e49c193adac7173_raster.png" alt=""></a> 718 719 * SkSumPathEffect: a pathEffect whose effect is to apply two effects, 720 in sequence (i.e. first(path) + second(path)). 721 722 <!--?prettify lang=cc?--> 723 724 void draw(SkCanvas* canvas) { 725 SkAutoTUnref<SkPathEffect> pe0( 726 SkDiscretePathEffect::Create(10.0f, 4.0f)); 727 SkAutoTUnref<SkPathEffect> pe1( 728 SkDiscretePathEffect::Create(10.0f, 4.0f, 1245u)); 729 SkAutoTUnref<SkPathEffect> pe( 730 SkSumPathEffect::Create(pe1, pe0)); 731 SkPaint paint; 732 paint.setPathEffect(pe); 733 paint.setStyle(SkPaint::kStroke_Style); 734 paint.setStrokeWidth(2.0f); 735 paint.setAntiAlias(true); 736 canvas->clear(SK_ColorWHITE); 737 SkPath path(star()); 738 canvas->drawPath(path, paint); 739 } 740 741 <a href="https://fiddle.skia.org/c/e5f7861072893bd08c305a076bf32958"><img src="https://fiddle.skia.org/i/e5f7861072893bd08c305a076bf32958_raster.png" alt=""></a> 742 743 <!-- 744 <a href="https://fiddle.skia.org/c/"><img src="https://fiddle.skia.org/i/_raster.png" alt=""></a> 745 --> 746 747