123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "include/core/SkPathMeasure.h"
- #include "include/effects/SkTrimPathEffect.h"
- #include "src/core/SkReadBuffer.h"
- #include "src/core/SkWriteBuffer.h"
- #include "src/effects/SkTrimPE.h"
- namespace {
- class Segmentator : public SkNoncopyable {
- public:
- Segmentator(const SkPath& src, SkPath* dst)
- : fMeasure(src, false)
- , fDst(dst) {}
- void add(SkScalar start, SkScalar stop) {
- SkASSERT(start < stop);
- // TODO: we appear to skip zero-length contours.
- do {
- const auto nextOffset = fCurrentSegmentOffset + fMeasure.getLength();
- if (start < nextOffset) {
- fMeasure.getSegment(start - fCurrentSegmentOffset,
- stop - fCurrentSegmentOffset,
- fDst, true);
- if (stop < nextOffset)
- break;
- }
- fCurrentSegmentOffset = nextOffset;
- } while (fMeasure.nextContour());
- }
- private:
- SkPathMeasure fMeasure;
- SkPath* fDst;
- SkScalar fCurrentSegmentOffset = 0;
- using INHERITED = SkNoncopyable;
- };
- } // namespace
- SkTrimPE::SkTrimPE(SkScalar startT, SkScalar stopT, SkTrimPathEffect::Mode mode)
- : fStartT(startT), fStopT(stopT), fMode(mode) {}
- bool SkTrimPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
- const SkRect* cullRect) const {
- if (fStartT >= fStopT) {
- SkASSERT(fMode == SkTrimPathEffect::Mode::kNormal);
- return true;
- }
- // First pass: compute the total len.
- SkScalar len = 0;
- SkPathMeasure meas(src, false);
- do {
- len += meas.getLength();
- } while (meas.nextContour());
- const auto arcStart = len * fStartT,
- arcStop = len * fStopT;
- // Second pass: actually add segments.
- Segmentator segmentator(src, dst);
- if (fMode == SkTrimPathEffect::Mode::kNormal) {
- if (arcStart < arcStop) segmentator.add(arcStart, arcStop);
- } else {
- if (0 < arcStart) segmentator.add(0, arcStart);
- if (arcStop < len) segmentator.add(arcStop, len);
- }
- return true;
- }
- void SkTrimPE::flatten(SkWriteBuffer& buffer) const {
- buffer.writeScalar(fStartT);
- buffer.writeScalar(fStopT);
- buffer.writeUInt(static_cast<uint32_t>(fMode));
- }
- sk_sp<SkFlattenable> SkTrimPE::CreateProc(SkReadBuffer& buffer) {
- const auto start = buffer.readScalar(),
- stop = buffer.readScalar();
- const auto mode = buffer.readUInt();
- return SkTrimPathEffect::Make(start, stop,
- (mode & 1) ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal);
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////
- sk_sp<SkPathEffect> SkTrimPathEffect::Make(SkScalar startT, SkScalar stopT, Mode mode) {
- if (!SkScalarsAreFinite(startT, stopT)) {
- return nullptr;
- }
- if (startT <= 0 && stopT >= 1 && mode == Mode::kNormal) {
- return nullptr;
- }
- startT = SkTPin(startT, 0.f, 1.f);
- stopT = SkTPin(stopT, 0.f, 1.f);
- if (startT >= stopT && mode == Mode::kInverted) {
- return nullptr;
- }
- return sk_sp<SkPathEffect>(new SkTrimPE(startT, stopT, mode));
- }
|