Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrStyle.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2016 Google Inc.
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
10
11int GrStyle::KeySize(const GrStyle &style, Apply apply, uint32_t flags) {
12 static_assert(sizeof(uint32_t) == sizeof(SkScalar));
13 int size = 0;
14 if (style.isDashed()) {
15 // One scalar for scale, one for dash phase, and one for each dash value.
16 size += 2 + style.dashIntervalCnt();
17 } else if (style.pathEffect()) {
18 // No key for a generic path effect.
19 return -1;
20 }
21
23 return size;
24 }
25
26 if (style.strokeRec().needToApply()) {
27 // One for res scale, one for style/cap/join, one for miter limit, and one for width.
28 size += 4;
29 }
30 return size;
31}
32
33void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply, SkScalar scale,
34 uint32_t flags) {
36 SkASSERT(KeySize(style, apply) >= 0);
37 static_assert(sizeof(uint32_t) == sizeof(SkScalar));
38
39 int i = 0;
40 // The scale can influence both the path effect and stroking. We want to preserve the
41 // property that the following two are equal:
42 // 1. WriteKey with apply == kPathEffectAndStrokeRec
43 // 2. WriteKey with apply == kPathEffectOnly followed by WriteKey of a GrStyle made
44 // from SkStrokeRec output by the the path effect (and no additional path effect).
45 // Since the scale can affect both parts of 2 we write it into the key twice.
46 if (style.isDashed()) {
47 static_assert(sizeof(style.dashPhase()) == sizeof(uint32_t));
48 SkScalar phase = style.dashPhase();
49 memcpy(&key[i++], &scale, sizeof(SkScalar));
50 memcpy(&key[i++], &phase, sizeof(SkScalar));
51
52 int32_t count = style.dashIntervalCnt();
53 // Dash count should always be even.
54 SkASSERT(0 == (count & 0x1));
55 const SkScalar *intervals = style.dashIntervals();
56 int intervalByteCnt = count * sizeof(SkScalar);
57 memcpy(&key[i], intervals, intervalByteCnt);
58 i += count;
59 } else {
60 SkASSERT(!style.pathEffect());
61 }
62
64 memcpy(&key[i++], &scale, sizeof(SkScalar));
65 enum {
66 kStyleBits = 2,
67 kJoinBits = 2,
68 kCapBits = 32 - kStyleBits - kJoinBits,
69
70 kJoinShift = kStyleBits,
71 kCapShift = kJoinShift + kJoinBits,
72 };
73 static_assert(SkStrokeRec::kStyleCount <= (1 << kStyleBits));
74 static_assert(SkPaint::kJoinCount <= (1 << kJoinBits));
75 static_assert(SkPaint::kCapCount <= (1 << kCapBits));
76 // The cap type only matters for unclosed shapes. However, a path effect could unclose
77 // the shape before it is stroked.
79 if (!(flags & kClosed_KeyFlag) || style.pathEffect()) {
80 cap = style.strokeRec().getCap();
81 }
82 SkScalar miter = -1.f;
84
85 // Dashing will not insert joins but other path effects may.
86 if (!(flags & kNoJoins_KeyFlag) || style.hasNonDashPathEffect()) {
87 join = style.strokeRec().getJoin();
88 // Miter limit only affects miter joins
89 if (SkPaint::kMiter_Join == join) {
90 miter = style.strokeRec().getMiter();
91 }
92 }
93
94 key[i++] = style.strokeRec().getStyle() |
95 join << kJoinShift |
96 cap << kCapShift;
97
98 memcpy(&key[i++], &miter, sizeof(miter));
99
100 SkScalar width = style.strokeRec().getWidth();
101 memcpy(&key[i++], &width, sizeof(width));
102 }
103 SkASSERT(KeySize(style, apply) == i);
104}
105
106void GrStyle::initPathEffect(sk_sp<SkPathEffect> pe) {
107 SkASSERT(!fPathEffect);
108 SkASSERT(SkPathEffect::kNone_DashType == fDashInfo.fType);
109 SkASSERT(0 == fDashInfo.fIntervals.count());
110 if (!pe) {
111 return;
112 }
114 if (SkPathEffect::kDash_DashType == pe->asADash(&info)) {
115 SkStrokeRec::Style recStyle = fStrokeRec.getStyle();
116 if (recStyle != SkStrokeRec::kFill_Style && recStyle != SkStrokeRec::kStrokeAndFill_Style) {
117 fDashInfo.fType = SkPathEffect::kDash_DashType;
118 fDashInfo.fIntervals.reset(info.fCount);
119 fDashInfo.fPhase = info.fPhase;
120 info.fIntervals = fDashInfo.fIntervals.get();
121 pe->asADash(&info);
122 fPathEffect = std::move(pe);
123 }
124 } else {
125 fPathEffect = std::move(pe);
126 }
127}
128
129bool GrStyle::applyPathEffect(SkPath* dst, SkStrokeRec* strokeRec, const SkPath& src) const {
130 if (!fPathEffect) {
131 return false;
132 }
133
134 // TODO: [skbug.com/11957] Plumb CTM callers and pass it to filterPath().
135 SkASSERT(!fPathEffect->needsCTM());
136
137 if (SkPathEffect::kDash_DashType == fDashInfo.fType) {
138 // We apply the dash ourselves here rather than using the path effect. This is so that
139 // we can control whether the dasher applies the strokeRec for special cases. Our keying
140 // depends on the strokeRec being applied separately.
141 SkASSERT(!fPathEffect->needsCTM()); // Make sure specified PE doesn't need CTM
142 SkScalar phase = fDashInfo.fPhase;
143 const SkScalar* intervals = fDashInfo.fIntervals.get();
144 int intervalCnt = fDashInfo.fIntervals.count();
145 SkScalar initialLength;
146 int initialIndex;
147 SkScalar intervalLength;
148 SkDashPath::CalcDashParameters(phase, intervals, intervalCnt, &initialLength,
149 &initialIndex, &intervalLength);
151 nullptr, intervals, intervalCnt,
152 initialLength, initialIndex, intervalLength, phase,
154 return false;
155 }
156 } else if (!fPathEffect->filterPath(dst, src, strokeRec, nullptr)) {
157 return false;
158 }
159 dst->setIsVolatile(true);
160 return true;
161}
162
164 const SkPath &src, SkScalar resScale) const {
165 SkASSERT(dst);
166 SkStrokeRec strokeRec = fStrokeRec;
167 strokeRec.setResScale(resScale);
168 if (!this->applyPathEffect(dst, &strokeRec, src)) {
169 return false;
170 }
171 *remainingStroke = strokeRec;
172 return true;
173}
174
176 SkScalar resScale) const {
177 SkASSERT(style);
178 SkASSERT(dst);
179 SkStrokeRec strokeRec = fStrokeRec;
180 strokeRec.setResScale(resScale);
181 const SkPath* pathForStrokeRec = &src;
182 if (this->applyPathEffect(dst, &strokeRec, src)) {
183 pathForStrokeRec = dst;
184 } else if (fPathEffect) {
185 return false;
186 }
187 if (strokeRec.needToApply()) {
188 if (!strokeRec.applyToPath(dst, *pathForStrokeRec)) {
189 return false;
190 }
191 dst->setIsVolatile(true);
193 } else if (!fPathEffect) {
194 // Nothing to do for path effect or stroke, fail.
195 return false;
196 } else {
202 }
203 return true;
204}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
int count
#define SkASSERT(cond)
Definition SkAssert.h:116
static bool apply(Pass *pass, SkRecord *record)
bool isDashed() const
Definition GrStyle.h:126
@ kNoJoins_KeyFlag
Definition GrStyle.h:57
@ kClosed_KeyFlag
Definition GrStyle.h:55
const SkScalar * dashIntervals() const
Definition GrStyle.h:135
bool applyToPath(SkPath *dst, SkStrokeRec::InitStyle *fillOrHairline, const SkPath &src, SkScalar scale) const
Definition GrStyle.cpp:175
SkPathEffect * pathEffect() const
Definition GrStyle.h:119
static void WriteKey(uint32_t *, const GrStyle &, Apply, SkScalar scale, uint32_t flags=0)
Definition GrStyle.cpp:33
bool hasNonDashPathEffect() const
Definition GrStyle.h:124
int dashIntervalCnt() const
Definition GrStyle.h:131
bool applyPathEffectToPath(SkPath *dst, SkStrokeRec *remainingStoke, const SkPath &src, SkScalar scale) const
Definition GrStyle.cpp:163
SkScalar dashPhase() const
Definition GrStyle.h:127
static int KeySize(const GrStyle &, Apply, uint32_t flags=0)
Definition GrStyle.cpp:11
const SkStrokeRec & strokeRec() const
Definition GrStyle.h:140
@ kDefault_Cap
equivalent to kButt_Cap
Definition SkPaint.h:338
static constexpr int kCapCount
Definition SkPaint.h:343
static constexpr int kJoinCount
Definition SkPaint.h:368
@ kDefault_Join
equivalent to kMiter_Join
Definition SkPaint.h:363
@ kMiter_Join
extends to miter limit
Definition SkPaint.h:359
@ kNone_DashType
ignores the info parameter
@ kDash_DashType
fills in all of the info parameter
bool needsCTM() const
bool filterPath(SkPath *dst, const SkPath &src, SkStrokeRec *, const SkRect *cullR) const
@ kHairline_InitStyle
Definition SkStrokeRec.h:25
static constexpr int kStyleCount
Definition SkStrokeRec.h:39
Style getStyle() const
bool needToApply() const
Definition SkStrokeRec.h:84
@ kStrokeAndFill_Style
Definition SkStrokeRec.h:36
bool applyToPath(SkPath *dst, const SkPath &src) const
SkScalar getWidth() const
Definition SkStrokeRec.h:42
SkPaint::Join getJoin() const
Definition SkStrokeRec.h:45
SkPaint::Cap getCap() const
Definition SkStrokeRec.h:44
void setResScale(SkScalar rs)
Definition SkStrokeRec.h:75
SkScalar getMiter() const
Definition SkStrokeRec.h:43
float SkScalar
Definition extension.cpp:12
FlutterSemanticsFlag flags
bool InternalFilter(SkPath *dst, const SkPath &src, SkStrokeRec *rec, const SkRect *cullRect, const SkScalar aIntervals[], int32_t count, SkScalar initialDashLength, int32_t initialDashIndex, SkScalar intervalLength, SkScalar startPhase, StrokeRecApplication=StrokeRecApplication::kAllow)
void CalcDashParameters(SkScalar phase, const SkScalar intervals[], int32_t count, SkScalar *initialDashLength, int32_t *initialDashIndex, SkScalar *intervalLength, SkScalar *adjustedPhase=nullptr)
dst
Definition cp.py:12
int32_t width
const Scalar scale