OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrPath.h" | 8 #include "GrPath.h" |
9 | 9 |
10 namespace { | 10 namespace { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 memcpy(&builder[1], &rect, sizeof(rect)); | 51 memcpy(&builder[1], &rect, sizeof(rect)); |
52 if (strokeDataCnt > 0) { | 52 if (strokeDataCnt > 0) { |
53 stroke.asUniqueKeyFragment(&builder[kBaseData32Cnt]); | 53 stroke.asUniqueKeyFragment(&builder[kBaseData32Cnt]); |
54 } | 54 } |
55 return true; | 55 return true; |
56 } | 56 } |
57 | 57 |
58 // Encodes the full path data to the unique key for very small, volatile paths.
This is typically | 58 // Encodes the full path data to the unique key for very small, volatile paths.
This is typically |
59 // hit when clipping stencils the clip stack. Intention is that this handles rec
ts too, since | 59 // hit when clipping stencils the clip stack. Intention is that this handles rec
ts too, since |
60 // SkPath::isRect seems to do non-trivial amount of work. | 60 // SkPath::isRect seems to do non-trivial amount of work. |
61 inline static bool compute_key_for_simple_path(const SkPath& path, const GrStrok
eInfo& stroke, | 61 inline static bool compute_key_for_simple_path(const SkPath& path, const SkPathR
ef* pathRef, |
62 GrUniqueKey* key) { | 62 const GrStrokeInfo& stroke, GrUni
queKey* key) { |
63 if (!path.isVolatile()) { | 63 if (!path.isVolatile()) { |
64 return false; | 64 return false; |
65 } | 65 } |
66 // The check below should take care of negative values casted positive. | 66 |
67 const int verbCnt = path.countVerbs(); | 67 const int verbCnt = path.countVerbs(); |
| 68 SkASSERT(verbCnt >= 0); |
68 if (verbCnt > kSimpleVolatilePathVerbLimit) { | 69 if (verbCnt > kSimpleVolatilePathVerbLimit) { |
69 return false; | 70 return false; |
70 } | 71 } |
71 | 72 |
72 // If somebody goes wild with the constant, it might cause an overflow. | 73 // If somebody goes wild with the constant, it might cause an overflow. |
73 static_assert(kSimpleVolatilePathVerbLimit <= 100, | 74 static_assert(kSimpleVolatilePathVerbLimit <= 100, |
74 "big_simple_volatile_path_verb_limit_may_cause_overflow"); | 75 "big_simple_volatile_path_verb_limit_may_cause_overflow"); |
75 | 76 |
76 const int pointCnt = path.countPoints(); | 77 const int pointCnt = path.countPoints(); |
77 if (pointCnt < 0) { | 78 SkASSERT(pointCnt >= 0); |
78 SkASSERT(false); | |
79 return false; | |
80 } | |
81 SkSTArray<16, SkScalar, true> conicWeights(16); | |
82 if ((path.getSegmentMasks() & SkPath::kConic_SegmentMask) != 0) { | |
83 SkPath::RawIter iter(path); | |
84 SkPath::Verb verb; | |
85 SkPoint points[4]; | |
86 while ((verb = iter.next(points)) != SkPath::kDone_Verb) { | |
87 if (verb == SkPath::kConic_Verb) { | |
88 conicWeights.push_back(iter.conicWeight()); | |
89 } | |
90 } | |
91 } | |
92 | 79 |
93 const int conicWeightCnt = conicWeights.count(); | 80 const int conicWeightCnt = pathRef ? pathRef->countWeights() : 0; |
| 81 SkASSERT(conicWeightCnt >= 0); |
94 | 82 |
95 // Construct counts that align as uint32_t counts. | 83 // Construct counts that align as uint32_t counts. |
96 #define ARRAY_DATA32_COUNT(array_type, count) \ | 84 #define ARRAY_DATA32_COUNT(array_type, count) \ |
97 static_cast<int>((((count) * sizeof(array_type) + sizeof(uint32_t) - 1) / si
zeof(uint32_t))) | 85 static_cast<int>((((count) * sizeof(array_type) + sizeof(uint32_t) - 1) / si
zeof(uint32_t))) |
98 | 86 |
99 const int verbData32Cnt = ARRAY_DATA32_COUNT(uint8_t, verbCnt); | 87 const int verbData32Cnt = ARRAY_DATA32_COUNT(uint8_t, verbCnt); |
100 const int pointData32Cnt = ARRAY_DATA32_COUNT(SkPoint, pointCnt); | 88 const int pointData32Cnt = ARRAY_DATA32_COUNT(SkPoint, pointCnt); |
101 const int conicWeightData32Cnt = ARRAY_DATA32_COUNT(SkScalar, conicWeightCnt
); | 89 const int conicWeightData32Cnt = ARRAY_DATA32_COUNT(SkScalar, conicWeightCnt
); |
102 | 90 |
103 #undef ARRAY_DATA32_COUNT | 91 #undef ARRAY_DATA32_COUNT |
(...skipping 15 matching lines...) Expand all Loading... |
119 // We serialize two variable length fragments to the message: | 107 // We serialize two variable length fragments to the message: |
120 // * verbs, point data and conic weights (fragment 1) | 108 // * verbs, point data and conic weights (fragment 1) |
121 // * stroke data (fragment 2) | 109 // * stroke data (fragment 2) |
122 // "Proof:" | 110 // "Proof:" |
123 // Verb count establishes unambiguous verb data. | 111 // Verb count establishes unambiguous verb data. |
124 // Verbs encode also point data size and conic weight size. | 112 // Verbs encode also point data size and conic weight size. |
125 // Thus the fragment 1 is unambiguous. | 113 // Thus the fragment 1 is unambiguous. |
126 // Unambiguous fragment 1 establishes unambiguous fragment 2, since the leng
th of the message | 114 // Unambiguous fragment 1 establishes unambiguous fragment 2, since the leng
th of the message |
127 // has been established. | 115 // has been established. |
128 | 116 |
129 builder[i++] = SkToU32(verbCnt); // The path limit is compile-asserted above
, so the cast is ok. | 117 builder[i++] = SkToU32(verbCnt); // The verb limit is asserted above, so the
cast is ok. |
130 | 118 |
131 // Fill the last uint32_t with 0 first, since the last uint8_ts of the uint3
2_t may be | 119 // Fill the last uint32_t with 0 first, since the last uint8_ts of the uint3
2_t may be |
132 // uninitialized. This does not produce ambiguous verb data, since we have s
erialized the exact | 120 // uninitialized. This does not produce ambiguous verb data, since we have s
erialized the exact |
133 // verb count. | 121 // verb count. |
134 if (verbData32Cnt != static_cast<int>((verbCnt * sizeof(uint8_t) / sizeof(ui
nt32_t)))) { | 122 if (verbData32Cnt != static_cast<int>((verbCnt * sizeof(uint8_t) / sizeof(ui
nt32_t)))) { |
135 builder[i + verbData32Cnt - 1] = 0; | 123 builder[i + verbData32Cnt - 1] = 0; |
136 } | 124 } |
137 path.getVerbs(reinterpret_cast<uint8_t*>(&builder[i]), verbCnt); | 125 path.getVerbs(reinterpret_cast<uint8_t*>(&builder[i]), verbCnt); |
138 i += verbData32Cnt; | 126 i += verbData32Cnt; |
139 | 127 |
140 static_assert(((sizeof(SkPoint) % sizeof(uint32_t)) == 0) && sizeof(SkPoint)
> sizeof(uint32_t), | 128 static_assert(((sizeof(SkPoint) % sizeof(uint32_t)) == 0) && sizeof(SkPoint)
> sizeof(uint32_t), |
141 "skpoint_array_needs_padding"); | 129 "skpoint_array_needs_padding"); |
142 | 130 |
143 // Here we assume getPoints does a memcpy, so that we do not need to worry a
bout the alignment. | 131 // Here we assume getPoints does a memcpy, so that we do not need to worry a
bout the alignment. |
144 path.getPoints(reinterpret_cast<SkPoint*>(&builder[i]), pointCnt); | 132 path.getPoints(reinterpret_cast<SkPoint*>(&builder[i]), pointCnt); |
145 i += pointData32Cnt; | 133 i += pointData32Cnt; |
146 | 134 |
147 if (conicWeightCnt > 0) { | 135 if (conicWeightCnt > 0) { |
148 if (conicWeightData32Cnt != static_cast<int>( | 136 if (conicWeightData32Cnt != static_cast<int>( |
149 (conicWeightCnt * sizeof(SkScalar) / sizeof(uint32_t)))) { | 137 (conicWeightCnt * sizeof(SkScalar) / sizeof(uint32_t)))) { |
150 builder[i + conicWeightData32Cnt - 1] = 0; | 138 builder[i + conicWeightData32Cnt - 1] = 0; |
151 } | 139 } |
152 memcpy(&builder[i], conicWeights.begin(), conicWeightCnt * sizeof(SkScal
ar)); | 140 memcpy(&builder[i], pathRef->conicWeights(), conicWeightCnt * sizeof(SkS
calar)); |
153 SkDEBUGCODE(i += conicWeightData32Cnt); | 141 SkDEBUGCODE(i += conicWeightData32Cnt); |
154 } | 142 } |
155 SkASSERT(i == baseData32Cnt); | 143 SkASSERT(i == baseData32Cnt); |
156 if (strokeDataCnt > 0) { | 144 if (strokeDataCnt > 0) { |
157 stroke.asUniqueKeyFragment(&builder[baseData32Cnt]); | 145 stroke.asUniqueKeyFragment(&builder[baseData32Cnt]); |
158 } | 146 } |
159 return true; | 147 return true; |
160 } | 148 } |
161 | 149 |
162 inline static void compute_key_for_general_path(const SkPath& path, const GrStro
keInfo& stroke, | 150 inline static void compute_key_for_general_path(const SkPath& path, const GrStro
keInfo& stroke, |
(...skipping 16 matching lines...) Expand all Loading... |
179 if (compute_key_for_line_path(path, stroke, key)) { | 167 if (compute_key_for_line_path(path, stroke, key)) { |
180 *outIsVolatile = false; | 168 *outIsVolatile = false; |
181 return; | 169 return; |
182 } | 170 } |
183 | 171 |
184 if (compute_key_for_oval_path(path, stroke, key)) { | 172 if (compute_key_for_oval_path(path, stroke, key)) { |
185 *outIsVolatile = false; | 173 *outIsVolatile = false; |
186 return; | 174 return; |
187 } | 175 } |
188 | 176 |
189 if (compute_key_for_simple_path(path, stroke, key)) { | 177 if (compute_key_for_simple_path(path, path.fPathRef, stroke, key)) { |
190 *outIsVolatile = false; | 178 *outIsVolatile = false; |
191 return; | 179 return; |
192 } | 180 } |
193 | 181 |
194 compute_key_for_general_path(path, stroke, key); | 182 compute_key_for_general_path(path, stroke, key); |
195 *outIsVolatile = path.isVolatile(); | 183 *outIsVolatile = path.isVolatile(); |
196 } | 184 } |
197 | 185 |
198 #ifdef SK_DEBUG | 186 #ifdef SK_DEBUG |
199 bool GrPath::isEqualTo(const SkPath& path, const GrStrokeInfo& stroke) const { | 187 bool GrPath::isEqualTo(const SkPath& path, const GrStrokeInfo& stroke) const { |
200 if (!fStroke.hasEqualEffect(stroke)) { | 188 if (!fStroke.hasEqualEffect(stroke)) { |
201 return false; | 189 return false; |
202 } | 190 } |
203 | 191 |
204 // We treat same-rect ovals as identical - but only when not dashing. | 192 // We treat same-rect ovals as identical - but only when not dashing. |
205 SkRect ovalBounds; | 193 SkRect ovalBounds; |
206 if (!fStroke.isDashed() && fSkPath.isOval(&ovalBounds)) { | 194 if (!fStroke.isDashed() && fSkPath.isOval(&ovalBounds)) { |
207 SkRect otherOvalBounds; | 195 SkRect otherOvalBounds; |
208 return path.isOval(&otherOvalBounds) && ovalBounds == otherOvalBounds; | 196 return path.isOval(&otherOvalBounds) && ovalBounds == otherOvalBounds; |
209 } | 197 } |
210 | 198 |
211 return fSkPath == path; | 199 return fSkPath == path; |
212 } | 200 } |
213 #endif | 201 #endif |
214 | 202 |
OLD | NEW |