static AngleType Dot2AngleType(SkScalar dot) { // need more precise fixed normalization // SkASSERT(SkScalarAbs(dot) <= SK_Scalar1 + SK_ScalarNearlyZero);
if (dot >= 0) { // shallow or line return SkScalarNearlyZero(SK_Scalar1 - dot) ? kNearlyLine_AngleType : kShallow_AngleType;
} else { // sharp or 180 return SkScalarNearlyZero(SK_Scalar1 + dot) ? kNearly180_AngleType : kSharp_AngleType;
}
}
staticvoid HandleInnerJoin(SkPathBuilder* inner, const SkPoint& pivot, const SkVector& after) { #if1 /* In the degenerate case that the stroke radius is larger than our segments justconnectingthetwoinnersegmentsmay"showthrough"asafunny diagonal.Topseudo-fixthis,wegothroughthepivotpoint.Thisadds anextrapoint/edge,butIcan'tseeacheapwaytoknowwhenthisis notneeded:(
*/
inner->lineTo(pivot.fX, pivot.fY); #endif
SkVector before = beforeUnitNormal;
SkVector after = afterUnitNormal;
SkPathDirection dir = SkPathDirection::kCW;
if (!is_clockwise(before, after)) {
using std::swap;
swap(outer, inner);
before.negate();
after.negate();
dir = SkPathDirection::kCCW;
}
SkMatrix matrix;
matrix.setScale(radius, radius);
matrix.postTranslate(pivot.fX, pivot.fY);
SkConic conics[SkConic::kMaxConicsForArc]; int count = SkConic::BuildUnitArc(before, after, dir, &matrix, conics); if (count > 0) { for (int i = 0; i < count; ++i) {
outer->conicTo(conics[i].fPts[1], conics[i].fPts[2], conics[i].fW);
}
after.scale(radius);
HandleInnerJoin(inner, pivot, after);
}
}
#define kOneOverSqrt2 (0.707106781f)
staticvoid MiterJoiner(SkPathBuilder* outer, SkPathBuilder* inner, const SkVector& beforeUnitNormal, const SkPoint& pivot, const SkVector& afterUnitNormal,
SkScalar radius, SkScalar invMiterLimit, bool prevIsLine, bool currIsLine) { // negate the dot since we're using normals instead of tangents
SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal);
AngleType angleType = Dot2AngleType(dotProd);
SkVector before = beforeUnitNormal;
SkVector after = afterUnitNormal;
SkVector mid;
SkScalar sinHalfAngle; bool ccw;
if (angleType == kNearlyLine_AngleType) { return;
} if (angleType == kNearly180_AngleType) {
currIsLine = false; goto DO_BLUNT;
}
ccw = !is_clockwise(before, after); if (ccw) {
using std::swap;
swap(outer, inner);
before.negate();
after.negate();
}
/* Before we enter the world of square-roots and divides, checkifwe'retryingtojoinanuprightrightangle (commoncaseforstrokingrectangles).Ifso,specialcase that(forspeedanaccuracy). Note:weonlyneedtocheckonenormalifdot==0
*/ if (0 == dotProd && invMiterLimit <= kOneOverSqrt2) {
mid = (before + after) * radius; goto DO_MITER;
}
// choose the most accurate way to form the initial mid-vector if (angleType == kSharp_AngleType) {
mid.set(after.fY - before.fY, before.fX - after.fX); if (ccw) {
mid.negate();
}
} else {
mid = before + after;
}
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.