1 /* 2 * Copyright 2006 The Android Open Source Project 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 8 #ifndef SkPaint_DEFINED 9 #define SkPaint_DEFINED 10 11 #include "include/core/SkBlendMode.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkRefCnt.h" 14 #include "include/private/SkTOptional.h" 15 #include "include/private/SkTo.h" 16 17 class SkBlender; 18 class SkColorFilter; 19 class SkColorSpace; 20 struct SkRect; 21 class SkImageFilter; 22 class SkMaskFilter; 23 class SkMatrix; 24 class SkPath; 25 class SkPathEffect; 26 class SkShader; 27 28 /** \class SkPaint 29 SkPaint controls options applied when drawing. SkPaint collects all 30 options outside of the SkCanvas clip and SkCanvas matrix. 31 32 Various options apply to strokes and fills, and images. 33 34 SkPaint collects effects and filters that describe single-pass and multiple-pass 35 algorithms that alter the drawing geometry, color, and transparency. For instance, 36 SkPaint does not directly implement dashing or blur, but contains the objects that do so. 37 */ 38 class SK_API SkPaint { 39 public: 40 41 /** Constructs SkPaint with default values. 42 43 @return default initialized SkPaint 44 45 example: https://fiddle.skia.org/c/@Paint_empty_constructor 46 */ 47 SkPaint(); 48 49 /** Constructs SkPaint with default values and the given color. 50 51 Sets alpha and RGB used when stroking and filling. The color is four floating 52 point values, unpremultiplied. The color values are interpreted as being in 53 the colorSpace. If colorSpace is nullptr, then color is assumed to be in the 54 sRGB color space. 55 56 @param color unpremultiplied RGBA 57 @param colorSpace SkColorSpace describing the encoding of color 58 @return SkPaint with the given color 59 */ 60 explicit SkPaint(const SkColor4f& color, SkColorSpace* colorSpace = nullptr); 61 62 /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader, 63 SkMaskFilter, SkColorFilter, and SkImageFilter are shared 64 between the original paint and the copy. Objects containing SkRefCnt increment 65 their references by one. 66 67 The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter, 68 and SkImageFilter cannot be modified after they are created. 69 This prevents objects with SkRefCnt from being modified once SkPaint refers to them. 70 71 @param paint original to copy 72 @return shallow copy of paint 73 74 example: https://fiddle.skia.org/c/@Paint_copy_const_SkPaint 75 */ 76 SkPaint(const SkPaint& paint); 77 78 /** Implements a move constructor to avoid increasing the reference counts 79 of objects referenced by the paint. 80 81 After the call, paint is undefined, and can be safely destructed. 82 83 @param paint original to move 84 @return content of paint 85 86 example: https://fiddle.skia.org/c/@Paint_move_SkPaint 87 */ 88 SkPaint(SkPaint&& paint); 89 90 /** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader, 91 SkMaskFilter, SkColorFilter, and SkImageFilter. If the 92 objects containing SkRefCnt go to zero, they are deleted. 93 */ 94 ~SkPaint(); 95 96 /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader, 97 SkMaskFilter, SkColorFilter, and SkImageFilter are shared 98 between the original paint and the copy. Objects containing SkRefCnt in the 99 prior destination are decreased by one, and the referenced objects are deleted if the 100 resulting count is zero. Objects containing SkRefCnt in the parameter paint 101 are increased by one. paint is unmodified. 102 103 @param paint original to copy 104 @return content of paint 105 106 example: https://fiddle.skia.org/c/@Paint_copy_operator 107 */ 108 SkPaint& operator=(const SkPaint& paint); 109 110 /** Moves the paint to avoid increasing the reference counts 111 of objects referenced by the paint parameter. Objects containing SkRefCnt in the 112 prior destination are decreased by one; those objects are deleted if the resulting count 113 is zero. 114 115 After the call, paint is undefined, and can be safely destructed. 116 117 @param paint original to move 118 @return content of paint 119 120 example: https://fiddle.skia.org/c/@Paint_move_operator 121 */ 122 SkPaint& operator=(SkPaint&& paint); 123 124 /** Compares a and b, and returns true if a and b are equivalent. May return false 125 if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter, 126 or SkImageFilter have identical contents but different pointers. 127 128 @param a SkPaint to compare 129 @param b SkPaint to compare 130 @return true if SkPaint pair are equivalent 131 */ 132 SK_API friend bool operator==(const SkPaint& a, const SkPaint& b); 133 134 /** Compares a and b, and returns true if a and b are not equivalent. May return true 135 if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter, 136 or SkImageFilter have identical contents but different pointers. 137 138 @param a SkPaint to compare 139 @param b SkPaint to compare 140 @return true if SkPaint pair are not equivalent 141 */ 142 friend bool operator!=(const SkPaint& a, const SkPaint& b) { 143 return !(a == b); 144 } 145 146 /** Sets all SkPaint contents to their initial values. This is equivalent to replacing 147 SkPaint with the result of SkPaint(). 148 149 example: https://fiddle.skia.org/c/@Paint_reset 150 */ 151 void reset(); 152 153 /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency. 154 @return antialiasing state 155 */ isAntiAlias()156 bool isAntiAlias() const { 157 return SkToBool(fBitfields.fAntiAlias); 158 } 159 160 /** Requests, but does not require, that edge pixels draw opaque or with 161 partial transparency. 162 @param aa setting for antialiasing 163 */ setAntiAlias(bool aa)164 void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); } 165 166 /** Returns true if color error may be distributed to smooth color transition. 167 @return dithering state 168 */ isDither()169 bool isDither() const { 170 return SkToBool(fBitfields.fDither); 171 } 172 173 /** Requests, but does not require, to distribute color error. 174 @param dither setting for ditering 175 */ setDither(bool dither)176 void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); } 177 178 /** \enum SkPaint::Style 179 Set Style to fill, stroke, or both fill and stroke geometry. 180 The stroke and fill 181 share all paint attributes; for instance, they are drawn with the same color. 182 183 Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and 184 a fill draw. 185 */ 186 enum Style : uint8_t { 187 kFill_Style, //!< set to fill geometry 188 kStroke_Style, //!< set to stroke geometry 189 kStrokeAndFill_Style, //!< sets to stroke and fill geometry 190 }; 191 192 /** May be used to verify that SkPaint::Style is a legal value. 193 */ 194 static constexpr int kStyleCount = kStrokeAndFill_Style + 1; 195 196 /** Returns whether the geometry is filled, stroked, or filled and stroked. 197 */ getStyle()198 Style getStyle() const { return (Style)fBitfields.fStyle; } 199 200 /** Sets whether the geometry is filled, stroked, or filled and stroked. 201 Has no effect if style is not a legal SkPaint::Style value. 202 203 example: https://fiddle.skia.org/c/@Paint_setStyle 204 example: https://fiddle.skia.org/c/@Stroke_Width 205 */ 206 void setStyle(Style style); 207 208 /** 209 * Set paint's style to kStroke if true, or kFill if false. 210 */ 211 void setStroke(bool); 212 213 /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits. 214 Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract 215 a color component. 216 217 @return unpremultiplied ARGB 218 */ getColor()219 SkColor getColor() const { return fColor4f.toSkColor(); } 220 221 /** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are 222 extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function). 223 224 @return unpremultiplied RGBA 225 */ getColor4f()226 SkColor4f getColor4f() const { return fColor4f; } 227 228 /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value, 229 unpremultiplied, packing 8-bit components for alpha, red, blue, and green. 230 231 @param color unpremultiplied ARGB 232 233 example: https://fiddle.skia.org/c/@Paint_setColor 234 */ 235 void setColor(SkColor color); 236 237 /** Sets alpha and RGB used when stroking and filling. The color is four floating 238 point values, unpremultiplied. The color values are interpreted as being in 239 the colorSpace. If colorSpace is nullptr, then color is assumed to be in the 240 sRGB color space. 241 242 @param color unpremultiplied RGBA 243 @param colorSpace SkColorSpace describing the encoding of color 244 */ 245 void setColor(const SkColor4f& color, SkColorSpace* colorSpace = nullptr); 246 247 void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace = nullptr) { 248 this->setColor(color, colorSpace); 249 } 250 251 /** Retrieves alpha from the color used when stroking and filling. 252 253 @return alpha ranging from zero, fully transparent, to 255, fully opaque 254 */ getAlphaf()255 float getAlphaf() const { return fColor4f.fA; } 256 257 // Helper that scales the alpha by 255. getAlpha()258 uint8_t getAlpha() const { return sk_float_round2int(this->getAlphaf() * 255); } 259 260 /** Replaces alpha, leaving RGB 261 unchanged. An out of range value triggers an assert in the debug 262 build. a is a value from 0.0 to 1.0. 263 a set to zero makes color fully transparent; a set to 1.0 makes color 264 fully opaque. 265 266 @param a alpha component of color 267 */ 268 void setAlphaf(float a); 269 270 // Helper that accepts an int between 0 and 255, and divides it by 255.0 setAlpha(U8CPU a)271 void setAlpha(U8CPU a) { 272 this->setAlphaf(a * (1.0f / 255)); 273 } 274 275 /** Sets color used when drawing solid fills. The color components range from 0 to 255. 276 The color is unpremultiplied; alpha sets the transparency independent of RGB. 277 278 @param a amount of alpha, from fully transparent (0) to fully opaque (255) 279 @param r amount of red, from no red (0) to full red (255) 280 @param g amount of green, from no green (0) to full green (255) 281 @param b amount of blue, from no blue (0) to full blue (255) 282 283 example: https://fiddle.skia.org/c/@Paint_setARGB 284 */ 285 void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b); 286 287 /** Returns the thickness of the pen used by SkPaint to 288 outline the shape. 289 290 @return zero for hairline, greater than zero for pen thickness 291 */ getStrokeWidth()292 SkScalar getStrokeWidth() const { return fWidth; } 293 294 /** Sets the thickness of the pen used by the paint to outline the shape. 295 A stroke-width of zero is treated as "hairline" width. Hairlines are always exactly one 296 pixel wide in device space (their thickness does not change as the canvas is scaled). 297 Negative stroke-widths are invalid; setting a negative width will have no effect. 298 299 @param width zero thickness for hairline; greater than zero for pen thickness 300 301 example: https://fiddle.skia.org/c/@Miter_Limit 302 example: https://fiddle.skia.org/c/@Paint_setStrokeWidth 303 */ 304 void setStrokeWidth(SkScalar width); 305 306 /** Returns the limit at which a sharp corner is drawn beveled. 307 308 @return zero and greater miter limit 309 */ getStrokeMiter()310 SkScalar getStrokeMiter() const { return fMiterLimit; } 311 312 /** Sets the limit at which a sharp corner is drawn beveled. 313 Valid values are zero and greater. 314 Has no effect if miter is less than zero. 315 316 @param miter zero and greater miter limit 317 318 example: https://fiddle.skia.org/c/@Paint_setStrokeMiter 319 */ 320 void setStrokeMiter(SkScalar miter); 321 322 /** \enum SkPaint::Cap 323 Cap draws at the beginning and end of an open path contour. 324 */ 325 enum Cap { 326 kButt_Cap, //!< no stroke extension 327 kRound_Cap, //!< adds circle 328 kSquare_Cap, //!< adds square 329 kLast_Cap = kSquare_Cap, //!< largest Cap value 330 kDefault_Cap = kButt_Cap, //!< equivalent to kButt_Cap 331 }; 332 333 /** May be used to verify that SkPaint::Cap is a legal value. 334 */ 335 static constexpr int kCapCount = kLast_Cap + 1; 336 337 /** \enum SkPaint::Join 338 Join specifies how corners are drawn when a shape is stroked. Join 339 affects the four corners of a stroked rectangle, and the connected segments in a 340 stroked path. 341 342 Choose miter join to draw sharp corners. Choose round join to draw a circle with a 343 radius equal to the stroke width on top of the corner. Choose bevel join to minimally 344 connect the thick strokes. 345 346 The fill path constructed to describe the stroked path respects the join setting but may 347 not contain the actual join. For instance, a fill path constructed with round joins does 348 not necessarily include circles at each connected segment. 349 */ 350 enum Join : uint8_t { 351 kMiter_Join, //!< extends to miter limit 352 kRound_Join, //!< adds circle 353 kBevel_Join, //!< connects outside edges 354 kLast_Join = kBevel_Join, //!< equivalent to the largest value for Join 355 kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join 356 }; 357 358 /** May be used to verify that SkPaint::Join is a legal value. 359 */ 360 static constexpr int kJoinCount = kLast_Join + 1; 361 362 /** Returns the geometry drawn at the beginning and end of strokes. 363 */ getStrokeCap()364 Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; } 365 366 /** Sets the geometry drawn at the beginning and end of strokes. 367 368 example: https://fiddle.skia.org/c/@Paint_setStrokeCap_a 369 example: https://fiddle.skia.org/c/@Paint_setStrokeCap_b 370 */ 371 void setStrokeCap(Cap cap); 372 373 /** Returns the geometry drawn at the corners of strokes. 374 */ getStrokeJoin()375 Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; } 376 377 /** Sets the geometry drawn at the corners of strokes. 378 379 example: https://fiddle.skia.org/c/@Paint_setStrokeJoin 380 */ 381 void setStrokeJoin(Join join); 382 383 /** Returns the filled equivalent of the stroked path. 384 385 @param src SkPath read to create a filled version 386 @param dst resulting SkPath; may be the same as src, but may not be nullptr 387 @param cullRect optional limit passed to SkPathEffect 388 @param resScale if > 1, increase precision, else if (0 < resScale < 1) reduce precision 389 to favor speed and size 390 @return true if the path represents style fill, or false if it represents hairline 391 */ 392 bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, 393 SkScalar resScale = 1) const; 394 395 bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect, 396 const SkMatrix& ctm) const; 397 398 /** Returns the filled equivalent of the stroked path. 399 400 Replaces dst with the src path modified by SkPathEffect and style stroke. 401 SkPathEffect, if any, is not culled. stroke width is created with default precision. 402 403 @param src SkPath read to create a filled version 404 @param dst resulting SkPath dst may be the same as src, but may not be nullptr 405 @return true if the path represents style fill, or false if it represents hairline 406 */ getFillPath(const SkPath & src,SkPath * dst)407 bool getFillPath(const SkPath& src, SkPath* dst) const { 408 return this->getFillPath(src, dst, nullptr, 1); 409 } 410 411 /** Returns optional colors used when filling a path, such as a gradient. 412 413 Does not alter SkShader SkRefCnt. 414 415 @return SkShader if previously set, nullptr otherwise 416 */ getShader()417 SkShader* getShader() const { return fShader.get(); } 418 419 /** Returns optional colors used when filling a path, such as a gradient. 420 421 Increases SkShader SkRefCnt by one. 422 423 @return SkShader if previously set, nullptr otherwise 424 425 example: https://fiddle.skia.org/c/@Paint_refShader 426 */ 427 sk_sp<SkShader> refShader() const; 428 429 /** Sets optional colors used when filling a path, such as a gradient. 430 431 Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader. 432 Increments shader SkRefCnt by one. 433 434 @param shader how geometry is filled with color; if nullptr, color is used instead 435 436 example: https://fiddle.skia.org/c/@Color_Filter_Methods 437 example: https://fiddle.skia.org/c/@Paint_setShader 438 */ 439 void setShader(sk_sp<SkShader> shader); 440 441 /** Returns SkColorFilter if set, or nullptr. 442 Does not alter SkColorFilter SkRefCnt. 443 444 @return SkColorFilter if previously set, nullptr otherwise 445 */ getColorFilter()446 SkColorFilter* getColorFilter() const { return fColorFilter.get(); } 447 448 /** Returns SkColorFilter if set, or nullptr. 449 Increases SkColorFilter SkRefCnt by one. 450 451 @return SkColorFilter if set, or nullptr 452 453 example: https://fiddle.skia.org/c/@Paint_refColorFilter 454 */ 455 sk_sp<SkColorFilter> refColorFilter() const; 456 457 /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous 458 SkColorFilter. Pass nullptr to clear SkColorFilter. 459 460 Increments filter SkRefCnt by one. 461 462 @param colorFilter SkColorFilter to apply to subsequent draw 463 464 example: https://fiddle.skia.org/c/@Blend_Mode_Methods 465 example: https://fiddle.skia.org/c/@Paint_setColorFilter 466 */ 467 void setColorFilter(sk_sp<SkColorFilter> colorFilter); 468 469 /** If the current blender can be represented as a SkBlendMode enum, this returns that 470 * enum in the optional's value(). If it cannot, then the returned optional does not 471 * contain a value. 472 */ 473 skstd::optional<SkBlendMode> asBlendMode() const; 474 475 /** 476 * Queries the blender, and if it can be represented as a SkBlendMode, return that mode, 477 * else return the defaultMode provided. 478 */ 479 SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const; 480 481 /** Returns true iff the current blender claims to be equivalent to SkBlendMode::kSrcOver. 482 * 483 * Also returns true of the current blender is nullptr. 484 */ 485 bool isSrcOver() const; 486 487 /** Helper method for calling setBlender(). 488 * 489 * This sets a blender that implements the specified blendmode enum. 490 */ 491 void setBlendMode(SkBlendMode mode); 492 493 /** Returns the user-supplied blend function, if one has been set. 494 * Does not alter SkBlender's SkRefCnt. 495 * 496 * A nullptr blender signifies the default SrcOver behavior. 497 * 498 * @return the SkBlender assigned to this paint, otherwise nullptr 499 */ getBlender()500 SkBlender* getBlender() const { return fBlender.get(); } 501 502 /** Returns the user-supplied blend function, if one has been set. 503 * Increments the SkBlender's SkRefCnt by one. 504 * 505 * A nullptr blender signifies the default SrcOver behavior. 506 * 507 * @return the SkBlender assigned to this paint, otherwise nullptr 508 */ 509 sk_sp<SkBlender> refBlender() const; 510 511 /** Sets the current blender, increasing its refcnt, and if a blender is already 512 * present, decreasing that object's refcnt. 513 * 514 * A nullptr blender signifies the default SrcOver behavior. 515 * 516 * For convenience, you can call setBlendMode() if the blend effect can be expressed 517 * as one of those values. 518 */ 519 void setBlender(sk_sp<SkBlender> blender); 520 521 /** Returns SkPathEffect if set, or nullptr. 522 Does not alter SkPathEffect SkRefCnt. 523 524 @return SkPathEffect if previously set, nullptr otherwise 525 */ getPathEffect()526 SkPathEffect* getPathEffect() const { return fPathEffect.get(); } 527 528 /** Returns SkPathEffect if set, or nullptr. 529 Increases SkPathEffect SkRefCnt by one. 530 531 @return SkPathEffect if previously set, nullptr otherwise 532 533 example: https://fiddle.skia.org/c/@Paint_refPathEffect 534 */ 535 sk_sp<SkPathEffect> refPathEffect() const; 536 537 /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous 538 SkPathEffect. Pass nullptr to leave the path geometry unaltered. 539 540 Increments pathEffect SkRefCnt by one. 541 542 @param pathEffect replace SkPath with a modification when drawn 543 544 example: https://fiddle.skia.org/c/@Mask_Filter_Methods 545 example: https://fiddle.skia.org/c/@Paint_setPathEffect 546 */ 547 void setPathEffect(sk_sp<SkPathEffect> pathEffect); 548 549 /** Returns SkMaskFilter if set, or nullptr. 550 Does not alter SkMaskFilter SkRefCnt. 551 552 @return SkMaskFilter if previously set, nullptr otherwise 553 */ getMaskFilter()554 SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); } 555 556 /** Returns SkMaskFilter if set, or nullptr. 557 558 Increases SkMaskFilter SkRefCnt by one. 559 560 @return SkMaskFilter if previously set, nullptr otherwise 561 562 example: https://fiddle.skia.org/c/@Paint_refMaskFilter 563 */ 564 sk_sp<SkMaskFilter> refMaskFilter() const; 565 566 /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous 567 SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on 568 mask alpha unaltered. 569 570 Increments maskFilter SkRefCnt by one. 571 572 @param maskFilter modifies clipping mask generated from drawn geometry 573 574 example: https://fiddle.skia.org/c/@Paint_setMaskFilter 575 example: https://fiddle.skia.org/c/@Typeface_Methods 576 */ 577 void setMaskFilter(sk_sp<SkMaskFilter> maskFilter); 578 579 /** Returns SkImageFilter if set, or nullptr. 580 Does not alter SkImageFilter SkRefCnt. 581 582 @return SkImageFilter if previously set, nullptr otherwise 583 */ getImageFilter()584 SkImageFilter* getImageFilter() const { return fImageFilter.get(); } 585 586 /** Returns SkImageFilter if set, or nullptr. 587 Increases SkImageFilter SkRefCnt by one. 588 589 @return SkImageFilter if previously set, nullptr otherwise 590 591 example: https://fiddle.skia.org/c/@Paint_refImageFilter 592 */ 593 sk_sp<SkImageFilter> refImageFilter() const; 594 595 /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous 596 SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect 597 on drawing. 598 599 Increments imageFilter SkRefCnt by one. 600 601 @param imageFilter how SkImage is sampled when transformed 602 603 example: https://fiddle.skia.org/c/@Paint_setImageFilter 604 */ 605 void setImageFilter(sk_sp<SkImageFilter> imageFilter); 606 607 /** Returns true if SkPaint prevents all drawing; 608 otherwise, the SkPaint may or may not allow drawing. 609 610 Returns true if, for example, SkBlendMode combined with alpha computes a 611 new alpha of zero. 612 613 @return true if SkPaint prevents all drawing 614 615 example: https://fiddle.skia.org/c/@Paint_nothingToDraw 616 */ 617 bool nothingToDraw() const; 618 619 /** (to be made private) 620 Returns true if SkPaint does not include elements requiring extensive computation 621 to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect 622 always returns false. 623 624 @return true if SkPaint allows for fast computation of bounds 625 */ 626 bool canComputeFastBounds() const; 627 628 /** (to be made private) 629 Only call this if canComputeFastBounds() returned true. This takes a 630 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic 631 effects in the paint (e.g. stroking). If needed, it uses the storage 632 parameter. It returns the adjusted bounds that can then be used 633 for SkCanvas::quickReject tests. 634 635 The returned SkRect will either be orig or storage, thus the caller 636 should not rely on storage being set to the result, but should always 637 use the returned value. It is legal for orig and storage to be the same 638 SkRect. 639 For example: 640 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 641 SkRect storage; 642 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) { 643 return; // do not draw the path 644 } 645 } 646 // draw the path 647 648 @param orig geometry modified by SkPaint when drawn 649 @param storage computed bounds of geometry; may not be nullptr 650 @return fast computed bounds 651 */ computeFastBounds(const SkRect & orig,SkRect * storage)652 const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const { 653 // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted. 654 SkASSERT(orig.isSorted()); 655 SkPaint::Style style = this->getStyle(); 656 // ultra fast-case: filling with no effects that affect geometry 657 if (kFill_Style == style) { 658 uintptr_t effects = 0; 659 effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter()); 660 effects |= reinterpret_cast<uintptr_t>(this->getPathEffect()); 661 effects |= reinterpret_cast<uintptr_t>(this->getImageFilter()); 662 if (!effects) { 663 return orig; 664 } 665 } 666 667 return this->doComputeFastBounds(orig, storage, style); 668 } 669 670 /** (to be made private) 671 672 @param orig geometry modified by SkPaint when drawn 673 @param storage computed bounds of geometry 674 @return fast computed bounds 675 */ computeFastStrokeBounds(const SkRect & orig,SkRect * storage)676 const SkRect& computeFastStrokeBounds(const SkRect& orig, 677 SkRect* storage) const { 678 return this->doComputeFastBounds(orig, storage, kStroke_Style); 679 } 680 681 /** (to be made private) 682 Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to 683 account for additional width required by stroking orig, without 684 altering SkPaint::Style set to fill. 685 686 @param orig geometry modified by SkPaint when drawn 687 @param storage computed bounds of geometry 688 @param style overrides SkPaint::Style 689 @return fast computed bounds 690 */ 691 const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage, 692 Style style) const; 693 694 private: 695 sk_sp<SkPathEffect> fPathEffect; 696 sk_sp<SkShader> fShader; 697 sk_sp<SkMaskFilter> fMaskFilter; 698 sk_sp<SkColorFilter> fColorFilter; 699 sk_sp<SkImageFilter> fImageFilter; 700 sk_sp<SkBlender> fBlender; 701 702 SkColor4f fColor4f; 703 SkScalar fWidth; 704 SkScalar fMiterLimit; 705 union { 706 struct { 707 unsigned fAntiAlias : 1; 708 unsigned fDither : 1; 709 unsigned fCapType : 2; 710 unsigned fJoinType : 2; 711 unsigned fStyle : 2; 712 unsigned fPadding : 24; // 24 == 32 -1-1-2-2-2 713 } fBitfields; 714 uint32_t fBitfieldsUInt; 715 }; 716 717 friend class SkPaintPriv; 718 }; 719 720 #endif 721