1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkClampRange.h" 11 12 /* 13 * returns [0..count] for the number of steps (<= count) for which x0 <= edge 14 * given each step is followed by x0 += dx 15 */ 16 static int chop(int64_t x0, SkFixed edge, int64_t x1, int64_t dx, int count) { 17 SkASSERT(dx > 0); 18 SkASSERT(count >= 0); 19 20 if (x0 >= edge) { 21 return 0; 22 } 23 if (x1 <= edge) { 24 return count; 25 } 26 int64_t n = (edge - x0 + dx - 1) / dx; 27 SkASSERT(n >= 0); 28 SkASSERT(n <= count); 29 return (int)n; 30 } 31 32 static bool overflows_fixed(int64_t x) { 33 return x < -SK_FixedMax || x > SK_FixedMax; 34 } 35 36 void SkClampRange::initFor1(SkFixed fx) { 37 fCount0 = fCount1 = fCount2 = 0; 38 if (fx <= 0) { 39 fCount0 = 1; 40 } else if (fx < 0xFFFF) { 41 fCount1 = 1; 42 fFx1 = fx; 43 } else { 44 fCount2 = 1; 45 } 46 } 47 48 void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) { 49 SkASSERT(count > 0); 50 51 fV0 = v0; 52 fV1 = v1; 53 54 // special case 1 == count, as it is slightly common for skia 55 // and avoids us ever calling divide or 64bit multiply 56 if (1 == count) { 57 this->initFor1(fx0); 58 return; 59 } 60 61 int64_t fx = fx0; 62 int64_t dx = dx0; 63 // start with ex equal to the last computed value 64 int64_t ex = fx + (count - 1) * dx; 65 66 if ((uint64_t)(fx | ex) <= 0xFFFF) { 67 fCount0 = fCount2 = 0; 68 fCount1 = count; 69 fFx1 = fx0; 70 return; 71 } 72 if (fx <= 0 && ex <= 0) { 73 fCount1 = fCount2 = 0; 74 fCount0 = count; 75 return; 76 } 77 if (fx >= 0xFFFF && ex >= 0xFFFF) { 78 fCount0 = fCount1 = 0; 79 fCount2 = count; 80 return; 81 } 82 83 int extraCount = 0; 84 85 // now make ex be 1 past the last computed value 86 ex += dx; 87 // now check for over/under flow 88 if (overflows_fixed(ex)) { 89 int originalCount = count; 90 int64_t ccount; 91 bool swap = dx < 0; 92 if (swap) { 93 dx = -dx; 94 fx = -fx; 95 } 96 ccount = (SK_FixedMax - fx + dx - 1) / dx; 97 if (swap) { 98 dx = -dx; 99 fx = -fx; 100 } 101 SkASSERT(ccount > 0 && ccount <= SK_FixedMax); 102 103 count = (int)ccount; 104 if (0 == count) { 105 this->initFor1(fx0); 106 if (dx > 0) { 107 fCount2 += originalCount - 1; 108 } else { 109 fCount0 += originalCount - 1; 110 } 111 return; 112 } 113 extraCount = originalCount - count; 114 ex = fx + dx * count; 115 } 116 117 bool doSwap = dx < 0; 118 119 if (doSwap) { 120 ex -= dx; 121 fx -= dx; 122 SkTSwap(fx, ex); 123 dx = -dx; 124 } 125 126 127 fCount0 = chop(fx, 0, ex, dx, count); 128 count -= fCount0; 129 fx += fCount0 * dx; 130 SkASSERT(fx >= 0); 131 SkASSERT(fCount0 == 0 || (fx - dx) < 0); 132 fCount1 = chop(fx, 0xFFFF, ex, dx, count); 133 count -= fCount1; 134 fCount2 = count; 135 136 #ifdef SK_DEBUG 137 fx += fCount1 * dx; 138 SkASSERT(fx <= ex); 139 if (fCount2 > 0) { 140 SkASSERT(fx >= 0xFFFF); 141 if (fCount1 > 0) { 142 SkASSERT(fx - dx < 0xFFFF); 143 } 144 } 145 #endif 146 147 if (doSwap) { 148 SkTSwap(fCount0, fCount2); 149 SkTSwap(fV0, fV1); 150 dx = -dx; 151 } 152 153 if (fCount1 > 0) { 154 fFx1 = fx0 + fCount0 * (int)dx; 155 } 156 157 if (dx > 0) { 158 fCount2 += extraCount; 159 } else { 160 fCount0 += extraCount; 161 } 162 } 163