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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/pathops/SkIntersections.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,210 @@
     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 +
    1.11 +#include "SkIntersections.h"
    1.12 +
    1.13 +void SkIntersections::append(const SkIntersections& i) {
    1.14 +    for (int index = 0; index < i.fUsed; ++index) {
    1.15 +        insert(i[0][index], i[1][index], i.pt(index));
    1.16 +    }
    1.17 +}
    1.18 +
    1.19 +int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar, SkScalar, SkScalar, bool) = {
    1.20 +    NULL,
    1.21 +    &SkIntersections::verticalLine,
    1.22 +    &SkIntersections::verticalQuad,
    1.23 +    &SkIntersections::verticalCubic
    1.24 +};
    1.25 +
    1.26 +int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine&) = {
    1.27 +    NULL,
    1.28 +    &SkIntersections::lineRay,
    1.29 +    &SkIntersections::quadRay,
    1.30 +    &SkIntersections::cubicRay
    1.31 +};
    1.32 +
    1.33 +int SkIntersections::coincidentUsed() const {
    1.34 +    if (!fIsCoincident[0]) {
    1.35 +        SkASSERT(!fIsCoincident[1]);
    1.36 +        return 0;
    1.37 +    }
    1.38 +    int count = 0;
    1.39 +    SkDEBUGCODE(int count2 = 0;)
    1.40 +    for (int index = 0; index < fUsed; ++index) {
    1.41 +        if (fIsCoincident[0] & (1 << index)) {
    1.42 +            ++count;
    1.43 +        }
    1.44 +#ifdef SK_DEBUG
    1.45 +        if (fIsCoincident[1] & (1 << index)) {
    1.46 +            ++count2;
    1.47 +        }
    1.48 +#endif
    1.49 +    }
    1.50 +    SkASSERT(count == count2);
    1.51 +    return count;
    1.52 +}
    1.53 +
    1.54 +int SkIntersections::cubicRay(const SkPoint pts[4], const SkDLine& line) {
    1.55 +    SkDCubic cubic;
    1.56 +    cubic.set(pts);
    1.57 +    fMax = 3;
    1.58 +    return intersectRay(cubic, line);
    1.59 +}
    1.60 +
    1.61 +void SkIntersections::flip() {
    1.62 +    for (int index = 0; index < fUsed; ++index) {
    1.63 +        fT[1][index] = 1 - fT[1][index];
    1.64 +    }
    1.65 +}
    1.66 +
    1.67 +int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
    1.68 +    if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) {
    1.69 +        // For now, don't allow a mix of coincident and non-coincident intersections
    1.70 +        return -1;
    1.71 +    }
    1.72 +    SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
    1.73 +    int index;
    1.74 +    for (index = 0; index < fUsed; ++index) {
    1.75 +        double oldOne = fT[0][index];
    1.76 +        double oldTwo = fT[1][index];
    1.77 +        if (one == oldOne && two == oldTwo) {
    1.78 +            return -1;
    1.79 +        }
    1.80 +        if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
    1.81 +            if ((precisely_zero(one) && !precisely_zero(oldOne))
    1.82 +                    || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1))
    1.83 +                    || (precisely_zero(two) && !precisely_zero(oldTwo))
    1.84 +                    || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) {
    1.85 +                fT[0][index] = one;
    1.86 +                fT[1][index] = two;
    1.87 +                fPt[index] = pt;
    1.88 +            }
    1.89 +            return -1;
    1.90 +        }
    1.91 +    #if ONE_OFF_DEBUG
    1.92 +        if (pt.roughlyEqual(fPt[index])) {
    1.93 +            SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
    1.94 +        }
    1.95 +    #endif
    1.96 +        if (fT[0][index] > one) {
    1.97 +            break;
    1.98 +        }
    1.99 +    }
   1.100 +    if (fUsed >= fMax) {
   1.101 +        SkASSERT(0);  // FIXME : this error, if it is to be handled at runtime in release, must
   1.102 +                      // be propagated all the way back down to the caller, and return failure.
   1.103 +        fUsed = 0;
   1.104 +        return 0;
   1.105 +    }
   1.106 +    int remaining = fUsed - index;
   1.107 +    if (remaining > 0) {
   1.108 +        memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
   1.109 +        memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
   1.110 +        memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
   1.111 +        int clearMask = ~((1 << index) - 1);
   1.112 +        fIsCoincident[0] += fIsCoincident[0] & clearMask;
   1.113 +        fIsCoincident[1] += fIsCoincident[1] & clearMask;
   1.114 +    }
   1.115 +    fPt[index] = pt;
   1.116 +    fT[0][index] = one;
   1.117 +    fT[1][index] = two;
   1.118 +    ++fUsed;
   1.119 +    return index;
   1.120 +}
   1.121 +
   1.122 +void SkIntersections::insertCoincident(double one, double two, const SkDPoint& pt) {
   1.123 +    int index = insertSwap(one, two, pt);
   1.124 +    int bit = 1 << index;
   1.125 +    fIsCoincident[0] |= bit;
   1.126 +    fIsCoincident[1] |= bit;
   1.127 +}
   1.128 +
   1.129 +int SkIntersections::lineRay(const SkPoint pts[2], const SkDLine& line) {
   1.130 +    SkDLine l;
   1.131 +    l.set(pts);
   1.132 +    fMax = 2;
   1.133 +    return intersectRay(l, line);
   1.134 +}
   1.135 +
   1.136 +void SkIntersections::offset(int base, double start, double end) {
   1.137 +    for (int index = base; index < fUsed; ++index) {
   1.138 +        double val = fT[fSwap][index];
   1.139 +        val *= end - start;
   1.140 +        val += start;
   1.141 +        fT[fSwap][index] = val;
   1.142 +    }
   1.143 +}
   1.144 +
   1.145 +int SkIntersections::quadRay(const SkPoint pts[3], const SkDLine& line) {
   1.146 +    SkDQuad quad;
   1.147 +    quad.set(pts);
   1.148 +    fMax = 2;
   1.149 +    return intersectRay(quad, line);
   1.150 +}
   1.151 +
   1.152 +void SkIntersections::quickRemoveOne(int index, int replace) {
   1.153 +    if (index < replace) {
   1.154 +        fT[0][index] = fT[0][replace];
   1.155 +    }
   1.156 +}
   1.157 +
   1.158 +#if 0
   1.159 +void SkIntersections::remove(double one, double two, const SkDPoint& startPt,
   1.160 +        const SkDPoint& endPt) {
   1.161 +    for (int index = fUsed - 1; index >= 0; --index) {
   1.162 +        if (!(fIsCoincident[0] & (1 << index)) && (between(one, fT[fSwap][index], two)
   1.163 +                || startPt.approximatelyEqual(fPt[index])
   1.164 +                || endPt.approximatelyEqual(fPt[index]))) {
   1.165 +            SkASSERT(fUsed > 0);
   1.166 +            removeOne(index);
   1.167 +        }
   1.168 +    }
   1.169 +}
   1.170 +#endif
   1.171 +
   1.172 +void SkIntersections::removeOne(int index) {
   1.173 +    int remaining = --fUsed - index;
   1.174 +    if (remaining <= 0) {
   1.175 +        return;
   1.176 +    }
   1.177 +    memmove(&fPt[index], &fPt[index + 1], sizeof(fPt[0]) * remaining);
   1.178 +    memmove(&fT[0][index], &fT[0][index + 1], sizeof(fT[0][0]) * remaining);
   1.179 +    memmove(&fT[1][index], &fT[1][index + 1], sizeof(fT[1][0]) * remaining);
   1.180 +    SkASSERT(fIsCoincident[0] == 0);
   1.181 +    int coBit = fIsCoincident[0] & (1 << index);
   1.182 +    fIsCoincident[0] -= ((fIsCoincident[0] >> 1) & ~((1 << index) - 1)) + coBit;
   1.183 +    SkASSERT(!(coBit ^ (fIsCoincident[1] & (1 << index))));
   1.184 +    fIsCoincident[1] -= ((fIsCoincident[1] >> 1) & ~((1 << index) - 1)) + coBit;
   1.185 +}
   1.186 +
   1.187 +void SkIntersections::swapPts() {
   1.188 +    int index;
   1.189 +    for (index = 0; index < fUsed; ++index) {
   1.190 +        SkTSwap(fT[0][index], fT[1][index]);
   1.191 +    }
   1.192 +}
   1.193 +
   1.194 +int SkIntersections::verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom,
   1.195 +        SkScalar x, bool flipped) {
   1.196 +    SkDLine line;
   1.197 +    line.set(a);
   1.198 +    return vertical(line, top, bottom, x, flipped);
   1.199 +}
   1.200 +
   1.201 +int SkIntersections::verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom,
   1.202 +        SkScalar x, bool flipped) {
   1.203 +    SkDQuad quad;
   1.204 +    quad.set(a);
   1.205 +    return vertical(quad, top, bottom, x, flipped);
   1.206 +}
   1.207 +
   1.208 +int SkIntersections::verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom,
   1.209 +        SkScalar x, bool flipped) {
   1.210 +    SkDCubic cubic;
   1.211 +    cubic.set(a);
   1.212 +    return vertical(cubic, top, bottom, x, flipped);
   1.213 +}

mercurial