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 |