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 +}