Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkPaint.cpp
Go to the documentation of this file.
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
9
17#include "include/core/SkRect.h"
30
31#include <utility>
32
33// define this to get a printf for out-of-range parameter in setters
34// e.g. setTextSize(-1)
35//#define SK_REPORT_API_RANGE_CHECK
36
37
39 : fColor4f{0, 0, 0, 1} // opaque black
40 , fWidth{0}
41 , fMiterLimit{SkPaintDefaults_MiterLimit}
42 , fBitfields{(unsigned)false, // fAntiAlias
43 (unsigned)false, // fDither
44 (unsigned)SkPaint::kDefault_Cap, // fCapType
45 (unsigned)SkPaint::kDefault_Join, // fJoinType
46 (unsigned)SkPaint::kFill_Style, // fStyle
47 0} // fPadding
48{
49 static_assert(sizeof(fBitfields) == sizeof(fBitfieldsUInt), "");
50}
51
53 this->setColor(color, colorSpace);
54}
55
56SkPaint::SkPaint(const SkPaint& src) = default;
57
58SkPaint::SkPaint(SkPaint&& src) = default;
59
60SkPaint::~SkPaint() = default;
61
62SkPaint& SkPaint::operator=(const SkPaint& src) = default;
63
64SkPaint& SkPaint::operator=(SkPaint&& src) = default;
65
66bool operator==(const SkPaint& a, const SkPaint& b) {
67#define EQUAL(field) (a.field == b.field)
68 return EQUAL(fPathEffect)
69 && EQUAL(fShader)
70 && EQUAL(fMaskFilter)
71 && EQUAL(fColorFilter)
72 && EQUAL(fBlender)
73 && EQUAL(fImageFilter)
74 && EQUAL(fColor4f)
75 && EQUAL(fWidth)
76 && EQUAL(fMiterLimit)
77 && EQUAL(fBitfieldsUInt)
78 ;
79#undef EQUAL
80}
81
82#define DEFINE_FIELD_REF(type) \
83 sk_sp<Sk##type> SkPaint::ref##type() const { return f##type; }
84DEFINE_FIELD_REF(ColorFilter)
85DEFINE_FIELD_REF(Blender)
86DEFINE_FIELD_REF(ImageFilter)
87DEFINE_FIELD_REF(MaskFilter)
88DEFINE_FIELD_REF(PathEffect)
89DEFINE_FIELD_REF(Shader)
90#undef DEFINE_FIELD_REF
91
92#define DEFINE_FIELD_SET(Field) \
93 void SkPaint::set##Field(sk_sp<Sk##Field> f) { f##Field = std::move(f); }
94DEFINE_FIELD_SET(ColorFilter)
95DEFINE_FIELD_SET(ImageFilter)
96DEFINE_FIELD_SET(MaskFilter)
97DEFINE_FIELD_SET(PathEffect)
98DEFINE_FIELD_SET(Shader)
99#undef DEFINE_FIELD_SET
100
101///////////////////////////////////////////////////////////////////////////////
102
103void SkPaint::reset() { *this = SkPaint(); }
104
106 if ((unsigned)style < kStyleCount) {
107 fBitfields.fStyle = style;
108 } else {
109#ifdef SK_REPORT_API_RANGE_CHECK
110 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
111#endif
112 }
113}
114
115void SkPaint::setStroke(bool isStroke) {
116 fBitfields.fStyle = isStroke ? kStroke_Style : kFill_Style;
117}
118
122
126 fColor4f = {color.fR, color.fG, color.fB, SkTPin(color.fA, 0.0f, 1.0f)};
127 steps.apply(fColor4f.vec());
128}
129
131 fColor4f.fA = SkTPin(a, 0.0f, 1.0f);
132}
133
135 this->setColor(SkColorSetARGB(a, r, g, b));
136}
137
138std::optional<SkBlendMode> SkPaint::asBlendMode() const {
139 return fBlender ? as_BB(fBlender)->asBlendMode()
141}
142
144 return this->asBlendMode().value_or(defaultMode);
145}
146
147bool SkPaint::isSrcOver() const {
148 return !fBlender || as_BB(fBlender)->asBlendMode() == SkBlendMode::kSrcOver;
149}
150
152 this->setBlender(mode == SkBlendMode::kSrcOver ? nullptr : SkBlender::Mode(mode));
153}
154
156 fBlender = std::move(blender);
157}
158
160 if (width >= 0) {
161 fWidth = width;
162 } else {
163#ifdef SK_REPORT_API_RANGE_CHECK
164 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
165#endif
166 }
167}
168
170 if (limit >= 0) {
171 fMiterLimit = limit;
172 } else {
173#ifdef SK_REPORT_API_RANGE_CHECK
174 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
175#endif
176 }
177}
178
180 if ((unsigned)ct < kCapCount) {
181 fBitfields.fCapType = SkToU8(ct);
182 } else {
183#ifdef SK_REPORT_API_RANGE_CHECK
184 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
185#endif
186 }
187}
188
190 if ((unsigned)jt < kJoinCount) {
191 fBitfields.fJoinType = SkToU8(jt);
192 } else {
193#ifdef SK_REPORT_API_RANGE_CHECK
194 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
195#endif
196 }
197}
198
199///////////////////////////////////////////////////////////////////////////////
200
202 if (this->getImageFilter() && !this->getImageFilter()->canComputeFastBounds()) {
203 return false;
204 }
205 // Pass nullptr for the bounds to determine if they can be computed
206 if (this->getPathEffect() &&
207 !as_PEB(this->getPathEffect())->computeFastBounds(nullptr)) {
208 return false;
209 }
210 return true;
211}
212
213const SkRect& SkPaint::computeFastBounds(const SkRect& orig, SkRect* storage) const {
214 // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.
215 SkASSERT(orig.isSorted());
216 SkPaint::Style style = this->getStyle();
217 // ultra fast-case: filling with no effects that affect geometry
218 if (kFill_Style == style) {
219 uintptr_t effects = 0;
220 effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
221 effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
222 effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
223 if (!effects) {
224 return orig;
225 }
226 }
227
228 return this->doComputeFastBounds(orig, storage, style);
229}
230
232 SkRect* storage,
233 Style style) const {
234 SkASSERT(storage);
235
236 const SkRect* src = &origSrc;
237
238 SkRect tmpSrc;
239 if (this->getPathEffect()) {
240 tmpSrc = origSrc;
242 src = &tmpSrc;
243 }
244
245 SkScalar radius = SkStrokeRec::GetInflationRadius(*this, style);
246 *storage = src->makeOutset(radius, radius);
247
248 if (this->getMaskFilter()) {
249 as_MFB(this->getMaskFilter())->computeFastBounds(*storage, storage);
250 }
251
252 if (this->getImageFilter()) {
253 *storage = this->getImageFilter()->computeFastBounds(*storage);
254 }
255
256 return *storage;
257}
258
259///////////////////////////////////////////////////////////////////////////////
260
261// return true if the filter exists, and may affect alpha
262static bool affects_alpha(const SkColorFilter* cf) {
263 return cf && !as_CFB(cf)->isAlphaUnchanged();
264}
265
266// return true if the filter exists, and may affect alpha
267static bool affects_alpha(const SkImageFilter* imf) {
268 // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
269 // ala colorfilters
270 return imf != nullptr;
271}
272
274 auto bm = this->asBlendMode();
275 if (!bm) {
276 return false;
277 }
278 switch (bm.value()) {
284 if (0 == this->getAlpha()) {
285 return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get());
286 }
287 break;
289 return true;
290 default:
291 break;
292 }
293 return false;
294}
SkColor4f color
#define SkPaintDefaults_MiterLimit
kUnpremul_SkAlphaType
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
@ kPlus
r = min(s + d, 1)
@ kSrcOver
r = s + (1-sa)*d
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstOver
r = d + (1-da)*s
@ kDstOut
r = d * (1-sa)
SkBlenderBase * as_BB(SkBlender *blend)
unsigned U8CPU
Definition SkCPUTypes.h:18
static SkColorFilterBase * as_CFB(SkColorFilter *filter)
SkColorSpace * sk_srgb_singleton()
uint32_t SkColor
Definition SkColor.h:37
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SkMaskFilterBase * as_MFB(SkMaskFilter *mf)
#define DEFINE_FIELD_REF(type)
Definition SkPaint.cpp:82
#define EQUAL(field)
static bool affects_alpha(const SkColorFilter *cf)
Definition SkPaint.cpp:262
#define DEFINE_FIELD_SET(Field)
Definition SkPaint.cpp:92
bool operator==(const SkPaint &a, const SkPaint &b)
Definition SkPaint.cpp:66
static SkPathEffectBase * as_PEB(SkPathEffect *effect)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition SkTPin.h:19
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22
virtual std::optional< SkBlendMode > asBlendMode() const
static sk_sp< SkBlender > Mode(SkBlendMode mode)
bool isAlphaUnchanged() const
virtual SkRect computeFastBounds(const SkRect &bounds) const
virtual void computeFastBounds(const SkRect &src, SkRect *dest) const
struct SkPaint::@278::@280 fBitfields
const SkRect & doComputeFastBounds(const SkRect &orig, SkRect *storage, Style style) const
Definition SkPaint.cpp:231
void setStyle(Style style)
Definition SkPaint.cpp:105
Style getStyle() const
Definition SkPaint.h:204
static constexpr int kCapCount
Definition SkPaint.h:343
static constexpr int kStyleCount
Definition SkPaint.h:200
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setStrokeMiter(SkScalar miter)
Definition SkPaint.cpp:169
SkPathEffect * getPathEffect() const
Definition SkPaint.h:506
bool isSrcOver() const
Definition SkPaint.cpp:147
void setStrokeCap(Cap cap)
Definition SkPaint.cpp:179
const SkRect & computeFastBounds(const SkRect &orig, SkRect *storage) const
Definition SkPaint.cpp:213
SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const
Definition SkPaint.cpp:143
void reset()
Definition SkPaint.cpp:103
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
void setStrokeJoin(Join join)
Definition SkPaint.cpp:189
SkPaint & operator=(const SkPaint &paint)
bool nothingToDraw() const
Definition SkPaint.cpp:273
static constexpr int kJoinCount
Definition SkPaint.h:368
void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkPaint.cpp:134
SkMaskFilter * getMaskFilter() const
Definition SkPaint.h:534
uint32_t fBitfieldsUInt
Definition SkPaint.h:680
void setBlendMode(SkBlendMode mode)
Definition SkPaint.cpp:151
SkPaint()
Definition SkPaint.cpp:38
SkImageFilter * getImageFilter() const
Definition SkPaint.h:564
uint8_t getAlpha() const
Definition SkPaint.h:264
void setBlender(sk_sp< SkBlender > blender)
Definition SkPaint.cpp:155
void setStroke(bool)
Definition SkPaint.cpp:115
bool canComputeFastBounds() const
Definition SkPaint.cpp:201
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
std::optional< SkBlendMode > asBlendMode() const
Definition SkPaint.cpp:138
void setAlphaf(float a)
Definition SkPaint.cpp:130
static SkScalar GetInflationRadius(const SkPaint &, SkPaint::Style)
T * get() const
Definition SkRefCnt.h:303
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct a[10]
int32_t width
static SkRGBA4f FromColor(SkColor color)
bool isSorted() const
Definition SkRect.h:705