gfx/skia/trunk/src/effects/gradients/SkClampRange.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/src/effects/gradients/SkClampRange.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,165 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2011 Google Inc.
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#include "SkClampRange.h"
    1.14 +
    1.15 +/*
    1.16 + *  returns [0..count] for the number of steps (<= count) for which x0 <= edge
    1.17 + *  given each step is followed by x0 += dx
    1.18 + */
    1.19 +static int chop(int64_t x0, SkFixed edge, int64_t x1, int64_t dx, int count) {
    1.20 +    SkASSERT(dx > 0);
    1.21 +    SkASSERT(count >= 0);
    1.22 +
    1.23 +    if (x0 >= edge) {
    1.24 +        return 0;
    1.25 +    }
    1.26 +    if (x1 <= edge) {
    1.27 +        return count;
    1.28 +    }
    1.29 +    int64_t n = (edge - x0 + dx - 1) / dx;
    1.30 +    SkASSERT(n >= 0);
    1.31 +    SkASSERT(n <= count);
    1.32 +    return (int)n;
    1.33 +}
    1.34 +
    1.35 +static bool overflows_fixed(int64_t x) {
    1.36 +    return x < -SK_FixedMax || x > SK_FixedMax;
    1.37 +}
    1.38 +
    1.39 +void SkClampRange::initFor1(SkFixed fx) {
    1.40 +    fCount0 = fCount1 = fCount2 = 0;
    1.41 +    if (fx <= 0) {
    1.42 +        fCount0 = 1;
    1.43 +    } else if (fx < 0xFFFF) {
    1.44 +        fCount1 = 1;
    1.45 +        fFx1 = fx;
    1.46 +    } else {
    1.47 +        fCount2 = 1;
    1.48 +    }
    1.49 +}
    1.50 +
    1.51 +void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
    1.52 +    SkASSERT(count > 0);
    1.53 +
    1.54 +    fV0 = v0;
    1.55 +    fV1 = v1;
    1.56 +    fOverflowed = false;
    1.57 +
    1.58 +    // special case 1 == count, as it is slightly common for skia
    1.59 +    // and avoids us ever calling divide or 64bit multiply
    1.60 +    if (1 == count) {
    1.61 +        this->initFor1(fx0);
    1.62 +        return;
    1.63 +    }
    1.64 +
    1.65 +    int64_t fx = fx0;
    1.66 +    int64_t dx = dx0;
    1.67 +    // start with ex equal to the last computed value
    1.68 +    int64_t ex = fx + (count - 1) * dx;
    1.69 +    fOverflowed = overflows_fixed(ex);
    1.70 +
    1.71 +    if ((uint64_t)(fx | ex) <= 0xFFFF) {
    1.72 +        fCount0 = fCount2 = 0;
    1.73 +        fCount1 = count;
    1.74 +        fFx1 = fx0;
    1.75 +        return;
    1.76 +    }
    1.77 +    if (fx <= 0 && ex <= 0) {
    1.78 +        fCount1 = fCount2 = 0;
    1.79 +        fCount0 = count;
    1.80 +        return;
    1.81 +    }
    1.82 +    if (fx >= 0xFFFF && ex >= 0xFFFF) {
    1.83 +        fCount0 = fCount1 = 0;
    1.84 +        fCount2 = count;
    1.85 +        return;
    1.86 +    }
    1.87 +
    1.88 +    int extraCount = 0;
    1.89 +
    1.90 +    // now make ex be 1 past the last computed value
    1.91 +    ex += dx;
    1.92 +    fOverflowed = overflows_fixed(ex);
    1.93 +    // now check for over/under flow
    1.94 +    if (fOverflowed) {
    1.95 +        int originalCount = count;
    1.96 +        int64_t ccount;
    1.97 +        bool swap = dx < 0;
    1.98 +        if (swap) {
    1.99 +            dx = -dx;
   1.100 +            fx = -fx;
   1.101 +        }
   1.102 +        ccount = (SK_FixedMax - fx + dx - 1) / dx;
   1.103 +        if (swap) {
   1.104 +            dx = -dx;
   1.105 +            fx = -fx;
   1.106 +        }
   1.107 +        SkASSERT(ccount > 0 && ccount <= SK_FixedMax);
   1.108 +
   1.109 +        count = (int)ccount;
   1.110 +        if (0 == count) {
   1.111 +            this->initFor1(fx0);
   1.112 +            if (dx > 0) {
   1.113 +                fCount2 += originalCount - 1;
   1.114 +            } else {
   1.115 +                fCount0 += originalCount - 1;
   1.116 +            }
   1.117 +            return;
   1.118 +        }
   1.119 +        extraCount = originalCount - count;
   1.120 +        ex = fx + dx * count;
   1.121 +    }
   1.122 +
   1.123 +    bool doSwap = dx < 0;
   1.124 +
   1.125 +    if (doSwap) {
   1.126 +        ex -= dx;
   1.127 +        fx -= dx;
   1.128 +        SkTSwap(fx, ex);
   1.129 +        dx = -dx;
   1.130 +    }
   1.131 +
   1.132 +
   1.133 +    fCount0 = chop(fx, 0, ex, dx, count);
   1.134 +    count -= fCount0;
   1.135 +    fx += fCount0 * dx;
   1.136 +    SkASSERT(fx >= 0);
   1.137 +    SkASSERT(fCount0 == 0 || (fx - dx) < 0);
   1.138 +    fCount1 = chop(fx, 0xFFFF, ex, dx, count);
   1.139 +    count -= fCount1;
   1.140 +    fCount2 = count;
   1.141 +
   1.142 +#ifdef SK_DEBUG
   1.143 +    fx += fCount1 * dx;
   1.144 +    SkASSERT(fx <= ex);
   1.145 +    if (fCount2 > 0) {
   1.146 +        SkASSERT(fx >= 0xFFFF);
   1.147 +        if (fCount1 > 0) {
   1.148 +            SkASSERT(fx - dx < 0xFFFF);
   1.149 +        }
   1.150 +    }
   1.151 +#endif
   1.152 +
   1.153 +    if (doSwap) {
   1.154 +        SkTSwap(fCount0, fCount2);
   1.155 +        SkTSwap(fV0, fV1);
   1.156 +        dx = -dx;
   1.157 +    }
   1.158 +
   1.159 +    if (fCount1 > 0) {
   1.160 +        fFx1 = fx0 + fCount0 * (int)dx;
   1.161 +    }
   1.162 +
   1.163 +    if (dx > 0) {
   1.164 +        fCount2 += extraCount;
   1.165 +    } else {
   1.166 +        fCount0 += extraCount;
   1.167 +    }
   1.168 +}

mercurial