gfx/skia/trunk/src/pathops/SkOpContour.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/pathops/SkOpContour.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,269 @@
     1.4 +/*
     1.5 + * Copyright 2013 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 +#ifndef SkOpContour_DEFINED
    1.11 +#define SkOpContour_DEFINED
    1.12 +
    1.13 +#include "SkOpSegment.h"
    1.14 +#include "SkTArray.h"
    1.15 +
    1.16 +class SkIntersections;
    1.17 +class SkOpContour;
    1.18 +class SkPathWriter;
    1.19 +
    1.20 +struct SkCoincidence {
    1.21 +    SkOpContour* fOther;
    1.22 +    int fSegments[2];
    1.23 +    double fTs[2][2];
    1.24 +    SkPoint fPts[2];
    1.25 +};
    1.26 +
    1.27 +class SkOpContour {
    1.28 +public:
    1.29 +    SkOpContour() {
    1.30 +        reset();
    1.31 +#ifdef SK_DEBUG
    1.32 +        fID = ++SkPathOpsDebug::gContourID;
    1.33 +#endif
    1.34 +    }
    1.35 +
    1.36 +    bool operator<(const SkOpContour& rh) const {
    1.37 +        return fBounds.fTop == rh.fBounds.fTop
    1.38 +                ? fBounds.fLeft < rh.fBounds.fLeft
    1.39 +                : fBounds.fTop < rh.fBounds.fTop;
    1.40 +    }
    1.41 +
    1.42 +    bool addCoincident(int index, SkOpContour* other, int otherIndex,
    1.43 +                       const SkIntersections& ts, bool swap);
    1.44 +    void addCoincidentPoints();
    1.45 +
    1.46 +    void addCross(const SkOpContour* crosser) {
    1.47 +#ifdef DEBUG_CROSS
    1.48 +        for (int index = 0; index < fCrosses.count(); ++index) {
    1.49 +            SkASSERT(fCrosses[index] != crosser);
    1.50 +        }
    1.51 +#endif
    1.52 +        fCrosses.push_back(crosser);
    1.53 +    }
    1.54 +
    1.55 +    void addCubic(const SkPoint pts[4]) {
    1.56 +        fSegments.push_back().addCubic(pts, fOperand, fXor);
    1.57 +        fContainsCurves = fContainsCubics = true;
    1.58 +    }
    1.59 +
    1.60 +    int addLine(const SkPoint pts[2]) {
    1.61 +        fSegments.push_back().addLine(pts, fOperand, fXor);
    1.62 +        return fSegments.count();
    1.63 +    }
    1.64 +
    1.65 +    void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) {
    1.66 +        fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex);
    1.67 +    }
    1.68 +
    1.69 +    bool addPartialCoincident(int index, SkOpContour* other, int otherIndex,
    1.70 +                       const SkIntersections& ts, int ptIndex, bool swap);
    1.71 +
    1.72 +    int addQuad(const SkPoint pts[3]) {
    1.73 +        fSegments.push_back().addQuad(pts, fOperand, fXor);
    1.74 +        fContainsCurves = true;
    1.75 +        return fSegments.count();
    1.76 +    }
    1.77 +
    1.78 +    int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
    1.79 +        setContainsIntercepts();
    1.80 +        return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT);
    1.81 +    }
    1.82 +
    1.83 +    int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt, double newT) {
    1.84 +        setContainsIntercepts();
    1.85 +        return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, newT);
    1.86 +    }
    1.87 +
    1.88 +    const SkPathOpsBounds& bounds() const {
    1.89 +        return fBounds;
    1.90 +    }
    1.91 +
    1.92 +    void calcCoincidentWinding();
    1.93 +    void calcPartialCoincidentWinding();
    1.94 +
    1.95 +    void checkEnds() {
    1.96 +        if (!fContainsCurves) {
    1.97 +            return;
    1.98 +        }
    1.99 +        int segmentCount = fSegments.count();
   1.100 +        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
   1.101 +            SkOpSegment* segment = &fSegments[sIndex];
   1.102 +            if (segment->verb() == SkPath::kLine_Verb) {
   1.103 +                continue;
   1.104 +            }
   1.105 +            if (segment->done()) {
   1.106 +                continue;   // likely coincident, nothing to do
   1.107 +            }
   1.108 +            segment->checkEnds();
   1.109 +        }
   1.110 +    }
   1.111 +
   1.112 +    // if same point has different T values, choose a common T
   1.113 +    void checkTiny() {
   1.114 +        int segmentCount = fSegments.count();
   1.115 +        if (segmentCount <= 2) {
   1.116 +            return;
   1.117 +        }
   1.118 +        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
   1.119 +            fSegments[sIndex].checkTiny();
   1.120 +        }
   1.121 +    }
   1.122 +
   1.123 +    void complete() {
   1.124 +        setBounds();
   1.125 +        fContainsIntercepts = false;
   1.126 +    }
   1.127 +
   1.128 +    bool containsCubics() const {
   1.129 +        return fContainsCubics;
   1.130 +    }
   1.131 +
   1.132 +    bool crosses(const SkOpContour* crosser) const {
   1.133 +        for (int index = 0; index < fCrosses.count(); ++index) {
   1.134 +            if (fCrosses[index] == crosser) {
   1.135 +                return true;
   1.136 +            }
   1.137 +        }
   1.138 +        return false;
   1.139 +    }
   1.140 +
   1.141 +    bool done() const {
   1.142 +        return fDone;
   1.143 +    }
   1.144 +
   1.145 +    const SkPoint& end() const {
   1.146 +        const SkOpSegment& segment = fSegments.back();
   1.147 +        return segment.pts()[SkPathOpsVerbToPoints(segment.verb())];
   1.148 +    }
   1.149 +
   1.150 +    void fixOtherTIndex() {
   1.151 +        int segmentCount = fSegments.count();
   1.152 +        for (int sIndex = 0; sIndex < segmentCount; ++sIndex) {
   1.153 +            fSegments[sIndex].fixOtherTIndex();
   1.154 +        }
   1.155 +    }
   1.156 +
   1.157 +    void joinCoincidence() {
   1.158 +        joinCoincidence(fCoincidences, false);
   1.159 +        joinCoincidence(fPartialCoincidences, true);
   1.160 +    }
   1.161 +
   1.162 +    SkOpSegment* nonVerticalSegment(int* start, int* end);
   1.163 +
   1.164 +    bool operand() const {
   1.165 +        return fOperand;
   1.166 +    }
   1.167 +
   1.168 +    void reset() {
   1.169 +        fSegments.reset();
   1.170 +        fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
   1.171 +        fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false;
   1.172 +    }
   1.173 +
   1.174 +    SkTArray<SkOpSegment>& segments() {
   1.175 +        return fSegments;
   1.176 +    }
   1.177 +
   1.178 +    void setContainsIntercepts() {
   1.179 +        fContainsIntercepts = true;
   1.180 +    }
   1.181 +
   1.182 +    void setOperand(bool isOp) {
   1.183 +        fOperand = isOp;
   1.184 +    }
   1.185 +
   1.186 +    void setOppXor(bool isOppXor) {
   1.187 +        fOppXor = isOppXor;
   1.188 +        int segmentCount = fSegments.count();
   1.189 +        for (int test = 0; test < segmentCount; ++test) {
   1.190 +            fSegments[test].setOppXor(isOppXor);
   1.191 +        }
   1.192 +    }
   1.193 +
   1.194 +    void setXor(bool isXor) {
   1.195 +        fXor = isXor;
   1.196 +    }
   1.197 +
   1.198 +    void sortSegments();
   1.199 +
   1.200 +    const SkPoint& start() const {
   1.201 +        return fSegments.front().pts()[0];
   1.202 +    }
   1.203 +
   1.204 +    void toPath(SkPathWriter* path) const;
   1.205 +
   1.206 +    void toPartialBackward(SkPathWriter* path) const {
   1.207 +        int segmentCount = fSegments.count();
   1.208 +        for (int test = segmentCount - 1; test >= 0; --test) {
   1.209 +            fSegments[test].addCurveTo(1, 0, path, true);
   1.210 +        }
   1.211 +    }
   1.212 +
   1.213 +    void toPartialForward(SkPathWriter* path) const {
   1.214 +        int segmentCount = fSegments.count();
   1.215 +        for (int test = 0; test < segmentCount; ++test) {
   1.216 +            fSegments[test].addCurveTo(0, 1, path, true);
   1.217 +        }
   1.218 +    }
   1.219 +
   1.220 +    void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment** topStart);
   1.221 +    SkOpSegment* undoneSegment(int* start, int* end);
   1.222 +
   1.223 +    int updateSegment(int index, const SkPoint* pts) {
   1.224 +        SkOpSegment& segment = fSegments[index];
   1.225 +        segment.updatePts(pts);
   1.226 +        return SkPathOpsVerbToPoints(segment.verb()) + 1;
   1.227 +    }
   1.228 +
   1.229 +#if DEBUG_TEST
   1.230 +    SkTArray<SkOpSegment>& debugSegments() {
   1.231 +        return fSegments;
   1.232 +    }
   1.233 +#endif
   1.234 +
   1.235 +#if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
   1.236 +    void debugShowActiveSpans() {
   1.237 +        for (int index = 0; index < fSegments.count(); ++index) {
   1.238 +            fSegments[index].debugShowActiveSpans();
   1.239 +        }
   1.240 +    }
   1.241 +#endif
   1.242 +
   1.243 +#if DEBUG_SHOW_WINDING
   1.244 +    int debugShowWindingValues(int totalSegments, int ofInterest);
   1.245 +    static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList);
   1.246 +#endif
   1.247 +
   1.248 +private:
   1.249 +    void calcCommonCoincidentWinding(const SkCoincidence& );
   1.250 +    void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial);
   1.251 +    void setBounds();
   1.252 +
   1.253 +    SkTArray<SkOpSegment> fSegments;
   1.254 +    SkTArray<SkOpSegment*, true> fSortedSegments;
   1.255 +    int fFirstSorted;
   1.256 +    SkTArray<SkCoincidence, true> fCoincidences;
   1.257 +    SkTArray<SkCoincidence, true> fPartialCoincidences;
   1.258 +    SkTArray<const SkOpContour*, true> fCrosses;
   1.259 +    SkPathOpsBounds fBounds;
   1.260 +    bool fContainsIntercepts;  // FIXME: is this used by anybody?
   1.261 +    bool fContainsCubics;
   1.262 +    bool fContainsCurves;
   1.263 +    bool fDone;
   1.264 +    bool fOperand;  // true for the second argument to a binary operator
   1.265 +    bool fXor;
   1.266 +    bool fOppXor;
   1.267 +#ifdef SK_DEBUG
   1.268 +    int fID;
   1.269 +#endif
   1.270 +};
   1.271 +
   1.272 +#endif

mercurial