gfx/skia/trunk/src/pathops/SkOpEdgeBuilder.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/pathops/SkOpEdgeBuilder.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,194 @@
     1.4 +/*
     1.5 + * Copyright 2012 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +#include "SkGeometry.h"
    1.11 +#include "SkOpEdgeBuilder.h"
    1.12 +#include "SkReduceOrder.h"
    1.13 +
    1.14 +void SkOpEdgeBuilder::init() {
    1.15 +    fCurrentContour = NULL;
    1.16 +    fOperand = false;
    1.17 +    fXorMask[0] = fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
    1.18 +            : kWinding_PathOpsMask;
    1.19 +#ifdef SK_DEBUG
    1.20 +    SkPathOpsDebug::gContourID = 0;
    1.21 +    SkPathOpsDebug::gSegmentID = 0;
    1.22 +#endif
    1.23 +    fUnparseable = false;
    1.24 +    fSecondHalf = preFetch();
    1.25 +}
    1.26 +
    1.27 +void SkOpEdgeBuilder::addOperand(const SkPath& path) {
    1.28 +    SkASSERT(fPathVerbs.count() > 0 && fPathVerbs.end()[-1] == SkPath::kDone_Verb);
    1.29 +    fPathVerbs.pop_back();
    1.30 +    fPath = &path;
    1.31 +    fXorMask[1] = (fPath->getFillType() & 1) ? kEvenOdd_PathOpsMask
    1.32 +            : kWinding_PathOpsMask;
    1.33 +    preFetch();
    1.34 +}
    1.35 +
    1.36 +bool SkOpEdgeBuilder::finish() {
    1.37 +    if (fUnparseable || !walk()) {
    1.38 +        return false;
    1.39 +    }
    1.40 +    complete();
    1.41 +    if (fCurrentContour && !fCurrentContour->segments().count()) {
    1.42 +        fContours.pop_back();
    1.43 +    }
    1.44 +    return true;
    1.45 +}
    1.46 +
    1.47 +void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curveStart) {
    1.48 +    if (!SkDPoint::ApproximatelyEqual(curveEnd, curveStart)) {
    1.49 +        fPathVerbs.push_back(SkPath::kLine_Verb);
    1.50 +        fPathPts.push_back_n(1, &curveStart);
    1.51 +    } else {
    1.52 +        fPathPts[fPathPts.count() - 1] = curveStart;
    1.53 +    }
    1.54 +    fPathVerbs.push_back(SkPath::kClose_Verb);
    1.55 +}
    1.56 +
    1.57 +int SkOpEdgeBuilder::preFetch() {
    1.58 +    if (!fPath->isFinite()) {
    1.59 +        fUnparseable = true;
    1.60 +        return 0;
    1.61 +    }
    1.62 +    SkAutoConicToQuads quadder;
    1.63 +    const SkScalar quadderTol = SK_Scalar1 / 16;
    1.64 +    SkPath::RawIter iter(*fPath);
    1.65 +    SkPoint curveStart;
    1.66 +    SkPoint curve[4];
    1.67 +    SkPoint pts[4];
    1.68 +    SkPath::Verb verb;
    1.69 +    bool lastCurve = false;
    1.70 +    do {
    1.71 +        verb = iter.next(pts);
    1.72 +        switch (verb) {
    1.73 +            case SkPath::kMove_Verb:
    1.74 +                if (!fAllowOpenContours && lastCurve) {
    1.75 +                    closeContour(curve[0], curveStart);
    1.76 +                }
    1.77 +                fPathVerbs.push_back(verb);
    1.78 +                fPathPts.push_back(pts[0]);
    1.79 +                curveStart = curve[0] = pts[0];
    1.80 +                lastCurve = false;
    1.81 +                continue;
    1.82 +            case SkPath::kLine_Verb:
    1.83 +                if (SkDPoint::ApproximatelyEqual(curve[0], pts[1])) {
    1.84 +                    uint8_t lastVerb = fPathVerbs.back();
    1.85 +                    if (lastVerb != SkPath::kLine_Verb && lastVerb != SkPath::kMove_Verb) {
    1.86 +                        fPathPts.back() = pts[1];
    1.87 +                    }
    1.88 +                    continue;  // skip degenerate points
    1.89 +                }
    1.90 +                break;
    1.91 +            case SkPath::kQuad_Verb:
    1.92 +                curve[1] = pts[1];
    1.93 +                curve[2] = pts[2];
    1.94 +                verb = SkReduceOrder::Quad(curve, pts);
    1.95 +                if (verb == SkPath::kMove_Verb) {
    1.96 +                    continue;  // skip degenerate points
    1.97 +                }
    1.98 +                break;
    1.99 +            case SkPath::kConic_Verb: {
   1.100 +                    const SkPoint* quadPts = quadder.computeQuads(pts, iter.conicWeight(),
   1.101 +                            quadderTol);
   1.102 +                    const int nQuads = quadder.countQuads();
   1.103 +                    for (int i = 0; i < nQuads; ++i) {
   1.104 +                       fPathVerbs.push_back(SkPath::kQuad_Verb);
   1.105 +                    }
   1.106 +                    fPathPts.push_back_n(nQuads * 2, quadPts);
   1.107 +                    curve[0] = quadPts[nQuads * 2 - 1];
   1.108 +                    lastCurve = true;
   1.109 +                }
   1.110 +                continue;
   1.111 +            case SkPath::kCubic_Verb:
   1.112 +                curve[1] = pts[1];
   1.113 +                curve[2] = pts[2];
   1.114 +                curve[3] = pts[3];
   1.115 +                verb = SkReduceOrder::Cubic(curve, pts);
   1.116 +                if (verb == SkPath::kMove_Verb) {
   1.117 +                    continue;  // skip degenerate points
   1.118 +                }
   1.119 +                break;
   1.120 +            case SkPath::kClose_Verb:
   1.121 +                closeContour(curve[0], curveStart);
   1.122 +                lastCurve = false;
   1.123 +                continue;
   1.124 +            case SkPath::kDone_Verb:
   1.125 +                continue;
   1.126 +        }
   1.127 +        fPathVerbs.push_back(verb);
   1.128 +        int ptCount = SkPathOpsVerbToPoints(verb);
   1.129 +        fPathPts.push_back_n(ptCount, &pts[1]);
   1.130 +        curve[0] = pts[ptCount];
   1.131 +        lastCurve = true;
   1.132 +    } while (verb != SkPath::kDone_Verb);
   1.133 +    if (!fAllowOpenContours && lastCurve) {
   1.134 +        closeContour(curve[0], curveStart);
   1.135 +    }
   1.136 +    fPathVerbs.push_back(SkPath::kDone_Verb);
   1.137 +    return fPathVerbs.count() - 1;
   1.138 +}
   1.139 +
   1.140 +bool SkOpEdgeBuilder::close() {
   1.141 +    complete();
   1.142 +    return true;
   1.143 +}
   1.144 +
   1.145 +bool SkOpEdgeBuilder::walk() {
   1.146 +    uint8_t* verbPtr = fPathVerbs.begin();
   1.147 +    uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
   1.148 +    const SkPoint* pointsPtr = fPathPts.begin() - 1;
   1.149 +    SkPath::Verb verb;
   1.150 +    while ((verb = (SkPath::Verb) *verbPtr) != SkPath::kDone_Verb) {
   1.151 +        if (verbPtr == endOfFirstHalf) {
   1.152 +            fOperand = true;
   1.153 +        }
   1.154 +        verbPtr++;
   1.155 +        switch (verb) {
   1.156 +            case SkPath::kMove_Verb:
   1.157 +                if (fCurrentContour) {
   1.158 +                    if (fAllowOpenContours) {
   1.159 +                        complete();
   1.160 +                    } else if (!close()) {
   1.161 +                        return false;
   1.162 +                    }
   1.163 +                }
   1.164 +                if (!fCurrentContour) {
   1.165 +                    fCurrentContour = fContours.push_back_n(1);
   1.166 +                    fCurrentContour->setOperand(fOperand);
   1.167 +                    fCurrentContour->setXor(fXorMask[fOperand] == kEvenOdd_PathOpsMask);
   1.168 +                }
   1.169 +                pointsPtr += 1;
   1.170 +                continue;
   1.171 +            case SkPath::kLine_Verb:
   1.172 +                fCurrentContour->addLine(pointsPtr);
   1.173 +                break;
   1.174 +            case SkPath::kQuad_Verb:
   1.175 +                fCurrentContour->addQuad(pointsPtr);
   1.176 +                break;
   1.177 +            case SkPath::kCubic_Verb:
   1.178 +                fCurrentContour->addCubic(pointsPtr);
   1.179 +                break;
   1.180 +            case SkPath::kClose_Verb:
   1.181 +                SkASSERT(fCurrentContour);
   1.182 +                if (!close()) {
   1.183 +                    return false;
   1.184 +                }
   1.185 +                continue;
   1.186 +            default:
   1.187 +                SkDEBUGFAIL("bad verb");
   1.188 +                return false;
   1.189 +        }
   1.190 +        pointsPtr += SkPathOpsVerbToPoints(verb);
   1.191 +        SkASSERT(fCurrentContour);
   1.192 +    }
   1.193 +   if (fCurrentContour && !fAllowOpenContours && !close()) {
   1.194 +       return false;
   1.195 +   }
   1.196 +   return true;
   1.197 +}

mercurial