xref: /third_party/skia/include/core/SkPaint.h (revision cb93a386)
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
17class SkBlender;
18class SkColorFilter;
19class SkColorSpace;
20struct SkRect;
21class SkImageFilter;
22class SkMaskFilter;
23class SkMatrix;
24class SkPath;
25class SkPathEffect;
26class 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*/
38class SK_API SkPaint {
39public:
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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    */
255    float getAlphaf() const { return fColor4f.fA; }
256
257    // Helper that scales the alpha by 255.
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
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    */
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    */
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    */
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    */
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    */
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    */
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    */
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     */
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    */
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    */
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    */
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    */
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    */
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
694private:
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