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