|
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 fOverflowed = false; |
|
54 |
|
55 // special case 1 == count, as it is slightly common for skia |
|
56 // and avoids us ever calling divide or 64bit multiply |
|
57 if (1 == count) { |
|
58 this->initFor1(fx0); |
|
59 return; |
|
60 } |
|
61 |
|
62 int64_t fx = fx0; |
|
63 int64_t dx = dx0; |
|
64 // start with ex equal to the last computed value |
|
65 int64_t ex = fx + (count - 1) * dx; |
|
66 fOverflowed = overflows_fixed(ex); |
|
67 |
|
68 if ((uint64_t)(fx | ex) <= 0xFFFF) { |
|
69 fCount0 = fCount2 = 0; |
|
70 fCount1 = count; |
|
71 fFx1 = fx0; |
|
72 return; |
|
73 } |
|
74 if (fx <= 0 && ex <= 0) { |
|
75 fCount1 = fCount2 = 0; |
|
76 fCount0 = count; |
|
77 return; |
|
78 } |
|
79 if (fx >= 0xFFFF && ex >= 0xFFFF) { |
|
80 fCount0 = fCount1 = 0; |
|
81 fCount2 = count; |
|
82 return; |
|
83 } |
|
84 |
|
85 int extraCount = 0; |
|
86 |
|
87 // now make ex be 1 past the last computed value |
|
88 ex += dx; |
|
89 fOverflowed = overflows_fixed(ex); |
|
90 // now check for over/under flow |
|
91 if (fOverflowed) { |
|
92 int originalCount = count; |
|
93 int64_t ccount; |
|
94 bool swap = dx < 0; |
|
95 if (swap) { |
|
96 dx = -dx; |
|
97 fx = -fx; |
|
98 } |
|
99 ccount = (SK_FixedMax - fx + dx - 1) / dx; |
|
100 if (swap) { |
|
101 dx = -dx; |
|
102 fx = -fx; |
|
103 } |
|
104 SkASSERT(ccount > 0 && ccount <= SK_FixedMax); |
|
105 |
|
106 count = (int)ccount; |
|
107 if (0 == count) { |
|
108 this->initFor1(fx0); |
|
109 if (dx > 0) { |
|
110 fCount2 += originalCount - 1; |
|
111 } else { |
|
112 fCount0 += originalCount - 1; |
|
113 } |
|
114 return; |
|
115 } |
|
116 extraCount = originalCount - count; |
|
117 ex = fx + dx * count; |
|
118 } |
|
119 |
|
120 bool doSwap = dx < 0; |
|
121 |
|
122 if (doSwap) { |
|
123 ex -= dx; |
|
124 fx -= dx; |
|
125 SkTSwap(fx, ex); |
|
126 dx = -dx; |
|
127 } |
|
128 |
|
129 |
|
130 fCount0 = chop(fx, 0, ex, dx, count); |
|
131 count -= fCount0; |
|
132 fx += fCount0 * dx; |
|
133 SkASSERT(fx >= 0); |
|
134 SkASSERT(fCount0 == 0 || (fx - dx) < 0); |
|
135 fCount1 = chop(fx, 0xFFFF, ex, dx, count); |
|
136 count -= fCount1; |
|
137 fCount2 = count; |
|
138 |
|
139 #ifdef SK_DEBUG |
|
140 fx += fCount1 * dx; |
|
141 SkASSERT(fx <= ex); |
|
142 if (fCount2 > 0) { |
|
143 SkASSERT(fx >= 0xFFFF); |
|
144 if (fCount1 > 0) { |
|
145 SkASSERT(fx - dx < 0xFFFF); |
|
146 } |
|
147 } |
|
148 #endif |
|
149 |
|
150 if (doSwap) { |
|
151 SkTSwap(fCount0, fCount2); |
|
152 SkTSwap(fV0, fV1); |
|
153 dx = -dx; |
|
154 } |
|
155 |
|
156 if (fCount1 > 0) { |
|
157 fFx1 = fx0 + fCount0 * (int)dx; |
|
158 } |
|
159 |
|
160 if (dx > 0) { |
|
161 fCount2 += extraCount; |
|
162 } else { |
|
163 fCount0 += extraCount; |
|
164 } |
|
165 } |