/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
// Since we are stepping by a float, the do/while loop might go on forever (or nearly so). // Put in a governor to limit crash values from looping too long (and allocating too much ram). #define MAX_REASONABLE_ITERATIONS 100000
class Sk1DPathEffect : public SkPathEffectBase { public: protected: bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*, const SkMatrix&) const override {
SkPathMeasure meas(src, false); do { int governor = MAX_REASONABLE_ITERATIONS;
SkScalar length = meas.getLength();
SkScalar distance = this->begin(length); while (distance < length && --governor >= 0) {
SkScalar delta = this->next(dst, distance, meas); if (delta <= 0) { break;
}
distance += delta;
} if (governor < 0) { returnfalse;
}
} while (meas.nextContour()); returntrue;
}
/** Called at the start of each contour, returns the initial offset into that contour.
*/ virtual SkScalar begin(SkScalar contourLength) const = 0; /** Called with the current distance along the path, with the current matrix for the point/tangent at the specified distance. Return the distance to travel for the next call. If return <= 0, then that contour is done.
*/ virtual SkScalar next(SkPath* dst, SkScalar dist, SkPathMeasure&) const = 0;
private: // For simplicity, assume fast bounds cannot be computed bool computeFastBounds(SkRect*) const override { returnfalse; }
};
// Make the path thread-safe.
fPath.updateBoundsCache();
(void)fPath.getGenerationID();
// cleanup their phase parameter, inverting it so that it becomes an // offset along the path (to match the interpretation in PostScript) if (phase < 0) {
phase = -phase; if (phase > advance) {
phase = SkScalarMod(phase, advance);
}
} else { if (phase > advance) {
phase = SkScalarMod(phase, advance);
}
phase = advance - phase;
} // now catch the edge case where phase == advance (within epsilon) if (phase >= advance) {
phase = 0;
}
SkASSERT(phase >= 0);
Need differentially more subdivisions when the follow-path is curvy. Not sure how to determine that, but we need it. I guess a cheap answer is let the caller tell us, but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
*/ staticvoid morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
SkScalar dist) {
SkPath::Iter iter(src, false);
SkPoint srcP[4], dstP[3];
SkPath::Verb verb;
while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { switch (verb) { case SkPath::kMove_Verb: if (morphpoints(dstP, srcP, 1, meas, dist)) {
dst->moveTo(dstP[0]);
} break; case SkPath::kLine_Verb:
srcP[2] = srcP[1];
srcP[1].set(SkScalarAve(srcP[0].fX, srcP[2].fX),
SkScalarAve(srcP[0].fY, srcP[2].fY));
[[fallthrough]]; case SkPath::kQuad_Verb: if (morphpoints(dstP, &srcP[1], 2, meas, dist)) {
dst->quadTo(dstP[0], dstP[1]);
} break; case SkPath::kConic_Verb: if (morphpoints(dstP, &srcP[1], 2, meas, dist)) {
dst->conicTo(dstP[0], dstP[1], iter.conicWeight());
} break; case SkPath::kCubic_Verb: if (morphpoints(dstP, &srcP[1], 3, meas, dist)) {
dst->cubicTo(dstP[0], dstP[1], dstP[2]);
} break; case SkPath::kClose_Verb:
dst->close(); break; default:
SkDEBUGFAIL("unknown verb"); break;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.