| Index: src/pathops/SkOpEdgeBuilder.cpp
|
| diff --git a/src/pathops/SkOpEdgeBuilder.cpp b/src/pathops/SkOpEdgeBuilder.cpp
|
| index 31a446b32b38fa89a61444c0ca7229cd586dcce4..8503af301d5d2f4ff60aec8e94bd3f1ea566a16e 100644
|
| --- a/src/pathops/SkOpEdgeBuilder.cpp
|
| +++ b/src/pathops/SkOpEdgeBuilder.cpp
|
| @@ -47,6 +47,17 @@ void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curve
|
| fPathVerbs.push_back(SkPath::kClose_Verb);
|
| }
|
|
|
| +// very tiny points cause numerical instability : don't allow them
|
| +static void force_small_to_zero(SkPoint* pt) {
|
| + if (SkScalarAbs(pt->fX) < FLT_EPSILON_ORDERABLE_ERR) {
|
| + pt->fX = 0;
|
| + }
|
| + if (SkScalarAbs(pt->fY) < FLT_EPSILON_ORDERABLE_ERR) {
|
| + pt->fY = 0;
|
| + }
|
| +}
|
| +
|
| +
|
| int SkOpEdgeBuilder::preFetch() {
|
| if (!fPath->isFinite()) {
|
| fUnparseable = true;
|
| @@ -68,11 +79,13 @@ int SkOpEdgeBuilder::preFetch() {
|
| closeContour(curve[0], curveStart);
|
| }
|
| fPathVerbs.push_back(verb);
|
| + force_small_to_zero(&pts[0]);
|
| fPathPts.push_back(pts[0]);
|
| curveStart = curve[0] = pts[0];
|
| lastCurve = false;
|
| continue;
|
| case SkPath::kLine_Verb:
|
| + force_small_to_zero(&pts[1]);
|
| if (SkDPoint::ApproximatelyEqual(curve[0], pts[1])) {
|
| uint8_t lastVerb = fPathVerbs.back();
|
| if (lastVerb != SkPath::kLine_Verb && lastVerb != SkPath::kMove_Verb) {
|
| @@ -82,6 +95,8 @@ int SkOpEdgeBuilder::preFetch() {
|
| }
|
| break;
|
| case SkPath::kQuad_Verb:
|
| + force_small_to_zero(&pts[1]);
|
| + force_small_to_zero(&pts[2]);
|
| curve[1] = pts[1];
|
| curve[2] = pts[2];
|
| verb = SkReduceOrder::Quad(curve, pts);
|
| @@ -102,6 +117,9 @@ int SkOpEdgeBuilder::preFetch() {
|
| }
|
| continue;
|
| case SkPath::kCubic_Verb:
|
| + force_small_to_zero(&pts[1]);
|
| + force_small_to_zero(&pts[2]);
|
| + force_small_to_zero(&pts[3]);
|
| curve[1] = pts[1];
|
| curve[2] = pts[2];
|
| curve[3] = pts[3];
|
|
|