• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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