Index: src/gpu/GrStrokeInfo.cpp |
diff --git a/src/gpu/GrStrokeInfo.cpp b/src/gpu/GrStrokeInfo.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b37c6601081df587cb9f9888b2d55cad0a85ad63 |
--- /dev/null |
+++ b/src/gpu/GrStrokeInfo.cpp |
@@ -0,0 +1,93 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "GrStrokeInfo.h" |
+#include "GrResourceKey.h" |
+#include "SkDashPathPriv.h" |
+ |
+bool all_dash_intervals_zero(const SkScalar* intervals, int count) { |
+ for (int i = 0 ; i < count; ++i) { |
+ if (intervals[i] != 0) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+bool GrStrokeInfo::applyDashToPath(SkPath* dst, GrStrokeInfo* dstStrokeInfo, |
+ const SkPath& src) const { |
+ if (this->isDashed()) { |
+ SkPathEffect::DashInfo info; |
+ info.fIntervals = fIntervals.get(); |
+ info.fCount = fIntervals.count(); |
+ info.fPhase = fDashPhase; |
+ GrStrokeInfo filteredStroke(*this, false); |
+ // Handle the case where all intervals are 0 and we simply drop the dash effect |
+ if (all_dash_intervals_zero(fIntervals.get(), fIntervals.count())) { |
+ *dstStrokeInfo = filteredStroke; |
+ *dst = src; |
+ return true; |
+ } |
+ // See if we can filter the dash into a path on cpu |
+ if (SkDashPath::FilterDashPath(dst, src, &filteredStroke, nullptr, info)) { |
+ *dstStrokeInfo = filteredStroke; |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+void GrStrokeInfo::asUniqueKeyFragment(uint32_t* data) const { |
+ const int kSkScalarData32Cnt = sizeof(SkScalar) / sizeof(uint32_t); |
+ enum { |
+ kStyleBits = 2, |
+ kJoinBits = 2, |
+ kCapBits = 32 - kStyleBits - kJoinBits, |
+ |
+ kJoinShift = kStyleBits, |
+ kCapShift = kJoinShift + kJoinBits, |
+ }; |
+ |
+ static_assert(SkStrokeRec::kStyleCount <= (1 << kStyleBits), "style_shift_will_be_wrong"); |
+ static_assert(SkPaint::kJoinCount <= (1 << kJoinBits), "cap_shift_will_be_wrong"); |
+ static_assert(SkPaint::kCapCount <= (1 << kCapBits), "cap_does_not_fit"); |
+ uint32_t styleKey = this->getStyle(); |
+ if (this->needToApply()) { |
+ styleKey |= this->getJoin() << kJoinShift; |
+ styleKey |= this->getCap() << kCapShift; |
+ } |
+ int i = 0; |
+ data[i++] = styleKey; |
+ |
+ // Memcpy the scalar fields. Does not "reinterpret_cast<SkScalar&>(data[i]) = ..." due to |
+ // scalars having more strict alignment requirements than what data can guarantee. The |
+ // compiler should optimize memcpys to assignments. |
+ SkScalar scalar; |
+ scalar = this->getMiter(); |
+ memcpy(&data[i], &scalar, sizeof(scalar)); |
+ i += kSkScalarData32Cnt; |
+ |
+ scalar = this->getWidth(); |
+ memcpy(&data[i], &scalar, sizeof(scalar)); |
+ i += kSkScalarData32Cnt; |
+ |
+ if (this->isDashed()) { |
+ SkScalar phase = this->getDashPhase(); |
+ memcpy(&data[i], &phase, sizeof(phase)); |
+ i += kSkScalarData32Cnt; |
+ |
+ int32_t count = this->getDashCount() & static_cast<int32_t>(~1); |
+ SkASSERT(count == this->getDashCount()); |
+ const SkScalar* intervals = this->getDashIntervals(); |
+ int intervalByteCnt = count * sizeof(SkScalar); |
+ memcpy(&data[i], intervals, intervalByteCnt); |
+ // Enable the line below if fields are added after dashing. |
+ SkDEBUGCODE(i += kSkScalarData32Cnt * count); |
+ } |
+ |
+ SkASSERT(this->computeUniqueKeyFragmentData32Cnt() == i); |
+} |