2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkPaint_DEFINED
9 #define SkPaint_DEFINED
11 #include "include/core/SkBlendMode.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/private/SkTo.h"
30 SkPaint controls options applied when drawing. SkPaint collects all
31 options outside of the SkCanvas clip and SkCanvas matrix.
33 Various options apply to strokes and fills, and images.
35 SkPaint collects effects and filters that describe single-pass and multiple-pass
36 algorithms that alter the drawing geometry, color, and transparency. For instance,
37 SkPaint does not directly implement dashing or blur, but contains the objects that do so.
39 class SK_API SkPaint {
42 /** Constructs SkPaint with default values.
44 @return default initialized SkPaint
46 example: https://fiddle.skia.org/c/@Paint_empty_constructor
50 /** Constructs SkPaint with default values and the given color.
52 Sets alpha and RGB used when stroking and filling. The color is four floating
53 point values, unpremultiplied. The color values are interpreted as being in
54 the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
57 @param color unpremultiplied RGBA
58 @param colorSpace SkColorSpace describing the encoding of color
59 @return SkPaint with the given color
61 explicit SkPaint(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
63 /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
64 SkMaskFilter, SkColorFilter, and SkImageFilter are shared
65 between the original paint and the copy. Objects containing SkRefCnt increment
66 their references by one.
68 The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
69 and SkImageFilter cannot be modified after they are created.
70 This prevents objects with SkRefCnt from being modified once SkPaint refers to them.
72 @param paint original to copy
73 @return shallow copy of paint
75 example: https://fiddle.skia.org/c/@Paint_copy_const_SkPaint
77 SkPaint(const SkPaint& paint);
79 /** Implements a move constructor to avoid increasing the reference counts
80 of objects referenced by the paint.
82 After the call, paint is undefined, and can be safely destructed.
84 @param paint original to move
85 @return content of paint
87 example: https://fiddle.skia.org/c/@Paint_move_SkPaint
89 SkPaint(SkPaint&& paint);
91 /** Decreases SkPaint SkRefCnt of owned objects: SkPathEffect, SkShader,
92 SkMaskFilter, SkColorFilter, and SkImageFilter. If the
93 objects containing SkRefCnt go to zero, they are deleted.
97 /** Makes a shallow copy of SkPaint. SkPathEffect, SkShader,
98 SkMaskFilter, SkColorFilter, and SkImageFilter are shared
99 between the original paint and the copy. Objects containing SkRefCnt in the
100 prior destination are decreased by one, and the referenced objects are deleted if the
101 resulting count is zero. Objects containing SkRefCnt in the parameter paint
102 are increased by one. paint is unmodified.
104 @param paint original to copy
105 @return content of paint
107 example: https://fiddle.skia.org/c/@Paint_copy_operator
109 SkPaint& operator=(const SkPaint& paint);
111 /** Moves the paint to avoid increasing the reference counts
112 of objects referenced by the paint parameter. Objects containing SkRefCnt in the
113 prior destination are decreased by one; those objects are deleted if the resulting count
116 After the call, paint is undefined, and can be safely destructed.
118 @param paint original to move
119 @return content of paint
121 example: https://fiddle.skia.org/c/@Paint_move_operator
123 SkPaint& operator=(SkPaint&& paint);
125 /** Compares a and b, and returns true if a and b are equivalent. May return false
126 if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
127 or SkImageFilter have identical contents but different pointers.
129 @param a SkPaint to compare
130 @param b SkPaint to compare
131 @return true if SkPaint pair are equivalent
133 SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
135 /** Compares a and b, and returns true if a and b are not equivalent. May return true
136 if SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
137 or SkImageFilter have identical contents but different pointers.
139 @param a SkPaint to compare
140 @param b SkPaint to compare
141 @return true if SkPaint pair are not equivalent
143 friend bool operator!=(const SkPaint& a, const SkPaint& b) {
147 /** Sets all SkPaint contents to their initial values. This is equivalent to replacing
148 SkPaint with the result of SkPaint().
150 example: https://fiddle.skia.org/c/@Paint_reset
154 /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
155 @return antialiasing state
157 bool isAntiAlias() const {
158 return SkToBool(fBitfields.fAntiAlias);
161 /** Requests, but does not require, that edge pixels draw opaque or with
162 partial transparency.
163 @param aa setting for antialiasing
165 void setAntiAlias(bool aa) { fBitfields.fAntiAlias = static_cast<unsigned>(aa); }
167 /** Returns true if color error may be distributed to smooth color transition.
168 @return dithering state
170 bool isDither() const {
171 return SkToBool(fBitfields.fDither);
174 /** Requests, but does not require, to distribute color error.
175 @param dither setting for ditering
177 void setDither(bool dither) { fBitfields.fDither = static_cast<unsigned>(dither); }
179 /** \enum SkPaint::Style
180 Set Style to fill, stroke, or both fill and stroke geometry.
182 share all paint attributes; for instance, they are drawn with the same color.
184 Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
187 enum Style : uint8_t {
188 kFill_Style, //!< set to fill geometry
189 kStroke_Style, //!< set to stroke geometry
190 kStrokeAndFill_Style, //!< sets to stroke and fill geometry
193 /** May be used to verify that SkPaint::Style is a legal value.
195 static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
197 /** Returns whether the geometry is filled, stroked, or filled and stroked.
199 Style getStyle() const { return (Style)fBitfields.fStyle; }
201 /** Sets whether the geometry is filled, stroked, or filled and stroked.
202 Has no effect if style is not a legal SkPaint::Style value.
204 example: https://fiddle.skia.org/c/@Paint_setStyle
205 example: https://fiddle.skia.org/c/@Stroke_Width
207 void setStyle(Style style);
210 * Set paint's style to kStroke if true, or kFill if false.
212 void setStroke(bool);
214 /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
215 Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
218 @return unpremultiplied ARGB
220 SkColor getColor() const { return fColor4f.toSkColor(); }
222 /** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are
223 extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
225 @return unpremultiplied RGBA
227 SkColor4f getColor4f() const { return fColor4f; }
229 /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
230 unpremultiplied, packing 8-bit components for alpha, red, blue, and green.
232 @param color unpremultiplied ARGB
234 example: https://fiddle.skia.org/c/@Paint_setColor
236 void setColor(SkColor color);
238 /** Sets alpha and RGB used when stroking and filling. The color is four floating
239 point values, unpremultiplied. The color values are interpreted as being in
240 the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
243 @param color unpremultiplied RGBA
244 @param colorSpace SkColorSpace describing the encoding of color
246 void setColor(const SkColor4f& color, SkColorSpace* colorSpace = nullptr);
248 void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace = nullptr) {
249 this->setColor(color, colorSpace);
252 /** Retrieves alpha from the color used when stroking and filling.
254 @return alpha ranging from zero, fully transparent, to 255, fully opaque
256 float getAlphaf() const { return fColor4f.fA; }
258 // Helper that scales the alpha by 255.
259 uint8_t getAlpha() const { return sk_float_round2int(this->getAlphaf() * 255); }
261 /** Replaces alpha, leaving RGB
262 unchanged. An out of range value triggers an assert in the debug
263 build. a is a value from 0.0 to 1.0.
264 a set to zero makes color fully transparent; a set to 1.0 makes color
267 @param a alpha component of color
269 void setAlphaf(float a);
271 // Helper that accepts an int between 0 and 255, and divides it by 255.0
272 void setAlpha(U8CPU a) {
273 this->setAlphaf(a * (1.0f / 255));
276 /** Sets color used when drawing solid fills. The color components range from 0 to 255.
277 The color is unpremultiplied; alpha sets the transparency independent of RGB.
279 @param a amount of alpha, from fully transparent (0) to fully opaque (255)
280 @param r amount of red, from no red (0) to full red (255)
281 @param g amount of green, from no green (0) to full green (255)
282 @param b amount of blue, from no blue (0) to full blue (255)
284 example: https://fiddle.skia.org/c/@Paint_setARGB
286 void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
288 /** Returns the thickness of the pen used by SkPaint to
291 @return zero for hairline, greater than zero for pen thickness
293 SkScalar getStrokeWidth() const { return fWidth; }
295 /** Sets the thickness of the pen used by the paint to outline the shape.
296 A stroke-width of zero is treated as "hairline" width. Hairlines are always exactly one
297 pixel wide in device space (their thickness does not change as the canvas is scaled).
298 Negative stroke-widths are invalid; setting a negative width will have no effect.
300 @param width zero thickness for hairline; greater than zero for pen thickness
302 example: https://fiddle.skia.org/c/@Miter_Limit
303 example: https://fiddle.skia.org/c/@Paint_setStrokeWidth
305 void setStrokeWidth(SkScalar width);
307 /** Returns the limit at which a sharp corner is drawn beveled.
309 @return zero and greater miter limit
311 SkScalar getStrokeMiter() const { return fMiterLimit; }
313 /** Sets the limit at which a sharp corner is drawn beveled.
314 Valid values are zero and greater.
315 Has no effect if miter is less than zero.
317 @param miter zero and greater miter limit
319 example: https://fiddle.skia.org/c/@Paint_setStrokeMiter
321 void setStrokeMiter(SkScalar miter);
323 /** \enum SkPaint::Cap
324 Cap draws at the beginning and end of an open path contour.
327 kButt_Cap, //!< no stroke extension
328 kRound_Cap, //!< adds circle
329 kSquare_Cap, //!< adds square
330 kLast_Cap = kSquare_Cap, //!< largest Cap value
331 kDefault_Cap = kButt_Cap, //!< equivalent to kButt_Cap
334 /** May be used to verify that SkPaint::Cap is a legal value.
336 static constexpr int kCapCount = kLast_Cap + 1;
338 /** \enum SkPaint::Join
339 Join specifies how corners are drawn when a shape is stroked. Join
340 affects the four corners of a stroked rectangle, and the connected segments in a
343 Choose miter join to draw sharp corners. Choose round join to draw a circle with a
344 radius equal to the stroke width on top of the corner. Choose bevel join to minimally
345 connect the thick strokes.
347 The fill path constructed to describe the stroked path respects the join setting but may
348 not contain the actual join. For instance, a fill path constructed with round joins does
349 not necessarily include circles at each connected segment.
351 enum Join : uint8_t {
352 kMiter_Join, //!< extends to miter limit
353 kRound_Join, //!< adds circle
354 kBevel_Join, //!< connects outside edges
355 kLast_Join = kBevel_Join, //!< equivalent to the largest value for Join
356 kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
359 /** May be used to verify that SkPaint::Join is a legal value.
361 static constexpr int kJoinCount = kLast_Join + 1;
363 /** Returns the geometry drawn at the beginning and end of strokes.
365 Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
367 /** Sets the geometry drawn at the beginning and end of strokes.
369 example: https://fiddle.skia.org/c/@Paint_setStrokeCap_a
370 example: https://fiddle.skia.org/c/@Paint_setStrokeCap_b
372 void setStrokeCap(Cap cap);
374 /** Returns the geometry drawn at the corners of strokes.
376 Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
378 /** Sets the geometry drawn at the corners of strokes.
380 example: https://fiddle.skia.org/c/@Paint_setStrokeJoin
382 void setStrokeJoin(Join join);
384 /** Returns the filled equivalent of the stroked path.
386 @param src SkPath read to create a filled version
387 @param dst resulting SkPath; may be the same as src, but may not be nullptr
388 @param cullRect optional limit passed to SkPathEffect
389 @param resScale if > 1, increase precision, else if (0 < resScale < 1) reduce precision
390 to favor speed and size
391 @return true if the path represents style fill, or false if it represents hairline
393 bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
394 SkScalar resScale = 1) const;
396 bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
397 const SkMatrix& ctm) const;
399 /** Returns the filled equivalent of the stroked path.
401 Replaces dst with the src path modified by SkPathEffect and style stroke.
402 SkPathEffect, if any, is not culled. stroke width is created with default precision.
404 @param src SkPath read to create a filled version
405 @param dst resulting SkPath dst may be the same as src, but may not be nullptr
406 @return true if the path represents style fill, or false if it represents hairline
408 bool getFillPath(const SkPath& src, SkPath* dst) const {
409 return this->getFillPath(src, dst, nullptr, 1);
412 /** Returns optional colors used when filling a path, such as a gradient.
414 Does not alter SkShader SkRefCnt.
416 @return SkShader if previously set, nullptr otherwise
418 SkShader* getShader() const { return fShader.get(); }
420 /** Returns optional colors used when filling a path, such as a gradient.
422 Increases SkShader SkRefCnt by one.
424 @return SkShader if previously set, nullptr otherwise
426 example: https://fiddle.skia.org/c/@Paint_refShader
428 sk_sp<SkShader> refShader() const;
430 /** Sets optional colors used when filling a path, such as a gradient.
432 Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.
433 Increments shader SkRefCnt by one.
435 @param shader how geometry is filled with color; if nullptr, color is used instead
437 example: https://fiddle.skia.org/c/@Color_Filter_Methods
438 example: https://fiddle.skia.org/c/@Paint_setShader
440 void setShader(sk_sp<SkShader> shader);
442 /** Returns SkColorFilter if set, or nullptr.
443 Does not alter SkColorFilter SkRefCnt.
445 @return SkColorFilter if previously set, nullptr otherwise
447 SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
449 /** Returns SkColorFilter if set, or nullptr.
450 Increases SkColorFilter SkRefCnt by one.
452 @return SkColorFilter if set, or nullptr
454 example: https://fiddle.skia.org/c/@Paint_refColorFilter
456 sk_sp<SkColorFilter> refColorFilter() const;
458 /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous
459 SkColorFilter. Pass nullptr to clear SkColorFilter.
461 Increments filter SkRefCnt by one.
463 @param colorFilter SkColorFilter to apply to subsequent draw
465 example: https://fiddle.skia.org/c/@Blend_Mode_Methods
466 example: https://fiddle.skia.org/c/@Paint_setColorFilter
468 void setColorFilter(sk_sp<SkColorFilter> colorFilter);
470 /** If the current blender can be represented as a SkBlendMode enum, this returns that
471 * enum in the optional's value(). If it cannot, then the returned optional does not
474 std::optional<SkBlendMode> asBlendMode() const;
477 * Queries the blender, and if it can be represented as a SkBlendMode, return that mode,
478 * else return the defaultMode provided.
480 SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const;
482 /** Returns true iff the current blender claims to be equivalent to SkBlendMode::kSrcOver.
484 * Also returns true of the current blender is nullptr.
486 bool isSrcOver() const;
488 /** Helper method for calling setBlender().
490 * This sets a blender that implements the specified blendmode enum.
492 void setBlendMode(SkBlendMode mode);
494 /** Returns the user-supplied blend function, if one has been set.
495 * Does not alter SkBlender's SkRefCnt.
497 * A nullptr blender signifies the default SrcOver behavior.
499 * @return the SkBlender assigned to this paint, otherwise nullptr
501 SkBlender* getBlender() const { return fBlender.get(); }
503 /** Returns the user-supplied blend function, if one has been set.
504 * Increments the SkBlender's SkRefCnt by one.
506 * A nullptr blender signifies the default SrcOver behavior.
508 * @return the SkBlender assigned to this paint, otherwise nullptr
510 sk_sp<SkBlender> refBlender() const;
512 /** Sets the current blender, increasing its refcnt, and if a blender is already
513 * present, decreasing that object's refcnt.
515 * A nullptr blender signifies the default SrcOver behavior.
517 * For convenience, you can call setBlendMode() if the blend effect can be expressed
518 * as one of those values.
520 void setBlender(sk_sp<SkBlender> blender);
522 /** Returns SkPathEffect if set, or nullptr.
523 Does not alter SkPathEffect SkRefCnt.
525 @return SkPathEffect if previously set, nullptr otherwise
527 SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
529 /** Returns SkPathEffect if set, or nullptr.
530 Increases SkPathEffect SkRefCnt by one.
532 @return SkPathEffect if previously set, nullptr otherwise
534 example: https://fiddle.skia.org/c/@Paint_refPathEffect
536 sk_sp<SkPathEffect> refPathEffect() const;
538 /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous
539 SkPathEffect. Pass nullptr to leave the path geometry unaltered.
541 Increments pathEffect SkRefCnt by one.
543 @param pathEffect replace SkPath with a modification when drawn
545 example: https://fiddle.skia.org/c/@Mask_Filter_Methods
546 example: https://fiddle.skia.org/c/@Paint_setPathEffect
548 void setPathEffect(sk_sp<SkPathEffect> pathEffect);
550 /** Returns SkMaskFilter if set, or nullptr.
551 Does not alter SkMaskFilter SkRefCnt.
553 @return SkMaskFilter if previously set, nullptr otherwise
555 SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
557 /** Returns SkMaskFilter if set, or nullptr.
559 Increases SkMaskFilter SkRefCnt by one.
561 @return SkMaskFilter if previously set, nullptr otherwise
563 example: https://fiddle.skia.org/c/@Paint_refMaskFilter
565 sk_sp<SkMaskFilter> refMaskFilter() const;
567 /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous
568 SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on
569 mask alpha unaltered.
571 Increments maskFilter SkRefCnt by one.
573 @param maskFilter modifies clipping mask generated from drawn geometry
575 example: https://fiddle.skia.org/c/@Paint_setMaskFilter
576 example: https://fiddle.skia.org/c/@Typeface_Methods
578 void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
580 /** Returns SkImageFilter if set, or nullptr.
581 Does not alter SkImageFilter SkRefCnt.
583 @return SkImageFilter if previously set, nullptr otherwise
585 SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
587 /** Returns SkImageFilter if set, or nullptr.
588 Increases SkImageFilter SkRefCnt by one.
590 @return SkImageFilter if previously set, nullptr otherwise
592 example: https://fiddle.skia.org/c/@Paint_refImageFilter
594 sk_sp<SkImageFilter> refImageFilter() const;
596 /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous
597 SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect
600 Increments imageFilter SkRefCnt by one.
602 @param imageFilter how SkImage is sampled when transformed
604 example: https://fiddle.skia.org/c/@Paint_setImageFilter
606 void setImageFilter(sk_sp<SkImageFilter> imageFilter);
608 /** Returns true if SkPaint prevents all drawing;
609 otherwise, the SkPaint may or may not allow drawing.
611 Returns true if, for example, SkBlendMode combined with alpha computes a
614 @return true if SkPaint prevents all drawing
616 example: https://fiddle.skia.org/c/@Paint_nothingToDraw
618 bool nothingToDraw() const;
620 /** (to be made private)
621 Returns true if SkPaint does not include elements requiring extensive computation
622 to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect
623 always returns false.
625 @return true if SkPaint allows for fast computation of bounds
627 bool canComputeFastBounds() const;
629 /** (to be made private)
630 Only call this if canComputeFastBounds() returned true. This takes a
631 raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
632 effects in the paint (e.g. stroking). If needed, it uses the storage
633 parameter. It returns the adjusted bounds that can then be used
634 for SkCanvas::quickReject tests.
636 The returned SkRect will either be orig or storage, thus the caller
637 should not rely on storage being set to the result, but should always
638 use the returned value. It is legal for orig and storage to be the same
641 if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
643 if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
644 return; // do not draw the path
649 @param orig geometry modified by SkPaint when drawn
650 @param storage computed bounds of geometry; may not be nullptr
651 @return fast computed bounds
653 const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const;
655 /** (to be made private)
657 @param orig geometry modified by SkPaint when drawn
658 @param storage computed bounds of geometry
659 @return fast computed bounds
661 const SkRect& computeFastStrokeBounds(const SkRect& orig,
662 SkRect* storage) const {
663 return this->doComputeFastBounds(orig, storage, kStroke_Style);
666 /** (to be made private)
667 Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to
668 account for additional width required by stroking orig, without
669 altering SkPaint::Style set to fill.
671 @param orig geometry modified by SkPaint when drawn
672 @param storage computed bounds of geometry
673 @param style overrides SkPaint::Style
674 @return fast computed bounds
676 const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
680 sk_sp<SkPathEffect> fPathEffect;
681 sk_sp<SkShader> fShader;
682 sk_sp<SkMaskFilter> fMaskFilter;
683 sk_sp<SkColorFilter> fColorFilter;
684 sk_sp<SkImageFilter> fImageFilter;
685 sk_sp<SkBlender> fBlender;
689 SkScalar fMiterLimit;
692 unsigned fAntiAlias : 1;
693 unsigned fDither : 1;
694 unsigned fCapType : 2;
695 unsigned fJoinType : 2;
697 unsigned fPadding : 24; // 24 == 32 -1-1-2-2-2
699 uint32_t fBitfieldsUInt;
702 friend class SkPaintPriv;