| OLD | NEW |
| 1 | |
| 2 /* | 1 /* |
| 3 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 4 * | 3 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 7 */ | 6 */ |
| 8 | 7 |
| 8 #include "SkClampRange.h" |
| 9 #include "SkMath.h" |
| 9 | 10 |
| 10 #include "SkClampRange.h" | 11 static int SkCLZ64(uint64_t value) { |
| 12 int count = 0; |
| 13 if (value >> 32) { |
| 14 value >>= 32; |
| 15 } else { |
| 16 count += 32; |
| 17 } |
| 18 return count + SkCLZ(SkToU32(value)); |
| 19 } |
| 20 |
| 21 static bool sk_64_smul_check(int64_t a, int64_t b, int64_t* result) { |
| 22 // Do it the slow way until we have some assembly. |
| 23 int64_t ua = SkTAbs(a); |
| 24 int64_t ub = SkTAbs(b); |
| 25 int zeros = SkCLZ64(ua) + SkCLZ64(ub); |
| 26 // this is a conservative check: it may return false when in fact it would n
ot have overflowed. |
| 27 // Hackers Delight uses 34 as its convervative check, but that is for 32x32
multiplies. |
| 28 // Since we are looking at 64x64 muls, we add 32 to the check. |
| 29 if (zeros < (32 + 34)) { |
| 30 return false; |
| 31 } |
| 32 *result = a * b; |
| 33 return true; |
| 34 } |
| 11 | 35 |
| 12 /* | 36 /* |
| 13 * returns [0..count] for the number of steps (<= count) for which x0 <= edge | 37 * returns [0..count] for the number of steps (<= count) for which x0 <= edge |
| 14 * given each step is followed by x0 += dx | 38 * given each step is followed by x0 += dx |
| 15 */ | 39 */ |
| 16 static int chop(int64_t x0, SkGradFixed edge, int64_t x1, int64_t dx, int count)
{ | 40 static int chop(int64_t x0, SkGradFixed edge, int64_t x1, int64_t dx, int count)
{ |
| 17 SkASSERT(dx > 0); | 41 SkASSERT(dx > 0); |
| 18 SkASSERT(count >= 0); | 42 SkASSERT(count >= 0); |
| 19 | 43 |
| 20 if (x0 >= edge) { | 44 if (x0 >= edge) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 51 // and avoids us ever calling divide or 64bit multiply | 75 // and avoids us ever calling divide or 64bit multiply |
| 52 if (1 == count) { | 76 if (1 == count) { |
| 53 this->initFor1(fx0); | 77 this->initFor1(fx0); |
| 54 return; | 78 return; |
| 55 } | 79 } |
| 56 | 80 |
| 57 int64_t fx = fx0; | 81 int64_t fx = fx0; |
| 58 int64_t dx = dx0; | 82 int64_t dx = dx0; |
| 59 | 83 |
| 60 // start with ex equal to the last computed value | 84 // start with ex equal to the last computed value |
| 85 int64_t count_times_dx; |
| 86 if (!sk_64_smul_check(count - 1, dx, &count_times_dx)) { |
| 87 // we can't represent the computed end in 32.32, so just draw something
(first color) |
| 88 fCount1 = fCount2 = 0; |
| 89 fCount0 = count; |
| 90 return; |
| 91 } |
| 92 |
| 61 int64_t ex = fx + (count - 1) * dx; | 93 int64_t ex = fx + (count - 1) * dx; |
| 62 | 94 |
| 63 if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) { | 95 if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) { |
| 64 fCount0 = fCount2 = 0; | 96 fCount0 = fCount2 = 0; |
| 65 fCount1 = count; | 97 fCount1 = count; |
| 66 fFx1 = fx0; | 98 fFx1 = fx0; |
| 67 return; | 99 return; |
| 68 } | 100 } |
| 69 if (fx <= 0 && ex <= 0) { | 101 if (fx <= 0 && ex <= 0) { |
| 70 fCount1 = fCount2 = 0; | 102 fCount1 = fCount2 = 0; |
| 71 fCount0 = count; | 103 fCount0 = count; |
| 72 return; | 104 return; |
| 73 } | 105 } |
| 74 if (fx >= kFracMax_SkGradFixed && ex >= kFracMax_SkGradFixed) { | 106 if (fx >= kFracMax_SkGradFixed && ex >= kFracMax_SkGradFixed) { |
| 75 fCount0 = fCount1 = 0; | 107 fCount0 = fCount1 = 0; |
| 76 fCount2 = count; | 108 fCount2 = count; |
| 77 return; | 109 return; |
| 78 } | 110 } |
| 79 | 111 |
| 80 int extraCount = 0; | |
| 81 | |
| 82 // now make ex be 1 past the last computed value | 112 // now make ex be 1 past the last computed value |
| 83 ex += dx; | 113 ex += dx; |
| 84 | 114 |
| 85 bool doSwap = dx < 0; | 115 bool doSwap = dx < 0; |
| 86 | 116 |
| 87 if (doSwap) { | 117 if (doSwap) { |
| 88 ex -= dx; | 118 ex -= dx; |
| 89 fx -= dx; | 119 fx -= dx; |
| 90 SkTSwap(fx, ex); | 120 SkTSwap(fx, ex); |
| 91 dx = -dx; | 121 dx = -dx; |
| 92 } | 122 } |
| 93 | 123 |
| 94 | 124 |
| 95 fCount0 = chop(fx, 0, ex, dx, count); | 125 fCount0 = chop(fx, 0, ex, dx, count); |
| 126 SkASSERT(fCount0 >= 0); |
| 127 SkASSERT(fCount0 <= count); |
| 96 count -= fCount0; | 128 count -= fCount0; |
| 97 fx += fCount0 * dx; | 129 fx += fCount0 * dx; |
| 98 SkASSERT(fx >= 0); | 130 SkASSERT(fx >= 0); |
| 99 SkASSERT(fCount0 == 0 || (fx - dx) < 0); | 131 SkASSERT(fCount0 == 0 || (fx - dx) < 0); |
| 100 fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count); | 132 fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count); |
| 133 SkASSERT(fCount1 >= 0); |
| 134 SkASSERT(fCount1 <= count); |
| 101 count -= fCount1; | 135 count -= fCount1; |
| 102 fCount2 = count; | 136 fCount2 = count; |
| 103 | 137 |
| 104 #ifdef SK_DEBUG | 138 #ifdef SK_DEBUG |
| 105 fx += fCount1 * dx; | 139 fx += fCount1 * dx; |
| 106 SkASSERT(fx <= ex); | 140 SkASSERT(fx <= ex); |
| 107 if (fCount2 > 0) { | 141 if (fCount2 > 0) { |
| 108 SkASSERT(fx >= kFracMax_SkGradFixed); | 142 SkASSERT(fx >= kFracMax_SkGradFixed); |
| 109 if (fCount1 > 0) { | 143 if (fCount1 > 0) { |
| 110 SkASSERT(fx - dx < kFracMax_SkGradFixed); | 144 SkASSERT(fx - dx < kFracMax_SkGradFixed); |
| 111 } | 145 } |
| 112 } | 146 } |
| 113 #endif | 147 #endif |
| 114 | 148 |
| 115 if (doSwap) { | 149 if (doSwap) { |
| 116 SkTSwap(fCount0, fCount2); | 150 SkTSwap(fCount0, fCount2); |
| 117 SkTSwap(fV0, fV1); | 151 SkTSwap(fV0, fV1); |
| 118 dx = -dx; | 152 dx = -dx; |
| 119 } | 153 } |
| 120 | 154 |
| 121 if (fCount1 > 0) { | 155 if (fCount1 > 0) { |
| 122 fFx1 = fx0 + fCount0 * dx; | 156 fFx1 = fx0 + fCount0 * dx; |
| 123 } | 157 } |
| 124 | |
| 125 if (dx > 0) { | |
| 126 fCount2 += extraCount; | |
| 127 } else { | |
| 128 fCount0 += extraCount; | |
| 129 } | |
| 130 } | 158 } |
| OLD | NEW |