/* * 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); }