Flutter Engine
The Flutter Engine
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
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 }
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
Definition: FontMgrTest.cpp:50
#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
DashType asADash(DashInfo *info) const
@ kNone_DashType
ignores the info parameter
Definition: SkPathEffect.h:61
@ kDash_DashType
fills in all of the info parameter
Definition: SkPathEffect.h:62
bool needsCTM() const
bool filterPath(SkPath *dst, const SkPath &src, SkStrokeRec *, const SkRect *cullR) const
Definition: SkPath.h:59
@ kHairline_InitStyle
Definition: SkStrokeRec.h:25
static constexpr int kStyleCount
Definition: SkStrokeRec.h:39
Style getStyle() const
Definition: SkStrokeRec.cpp:71
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)
Definition: SkDashPath.cpp:309
void CalcDashParameters(SkScalar phase, const SkScalar intervals[], int32_t count, SkScalar *initialDashLength, int32_t *initialDashIndex, SkScalar *intervalLength, SkScalar *adjustedPhase=nullptr)
Definition: SkDashPath.cpp:54
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
int32_t width
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
const Scalar scale