| 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 |