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 0 : static int chop(int64_t x0, SkFixed edge, int64_t x1, int64_t dx, int count) {
17 0 : SkASSERT(dx > 0);
18 0 : SkASSERT(count >= 0);
19 :
20 0 : if (x0 >= edge) {
21 0 : return 0;
22 : }
23 0 : if (x1 <= edge) {
24 0 : return count;
25 : }
26 0 : int64_t n = (edge - x0 + dx - 1) / dx;
27 0 : SkASSERT(n >= 0);
28 0 : SkASSERT(n <= count);
29 0 : return (int)n;
30 : }
31 :
32 0 : static bool overflows_fixed(int64_t x) {
33 0 : return x < -SK_FixedMax || x > SK_FixedMax;
34 : }
35 :
36 0 : void SkClampRange::initFor1(SkFixed fx) {
37 0 : fCount0 = fCount1 = fCount2 = 0;
38 0 : if (fx <= 0) {
39 0 : fCount0 = 1;
40 0 : } else if (fx < 0xFFFF) {
41 0 : fCount1 = 1;
42 0 : fFx1 = fx;
43 : } else {
44 0 : fCount2 = 1;
45 : }
46 0 : }
47 :
48 0 : void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) {
49 0 : SkASSERT(count > 0);
50 :
51 0 : fV0 = v0;
52 0 : fV1 = v1;
53 0 : 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 0 : if (1 == count) {
58 0 : this->initFor1(fx0);
59 0 : return;
60 : }
61 :
62 0 : int64_t fx = fx0;
63 0 : int64_t dx = dx0;
64 : // start with ex equal to the last computed value
65 0 : int64_t ex = fx + (count - 1) * dx;
66 0 : fOverflowed = overflows_fixed(ex);
67 :
68 0 : if ((uint64_t)(fx | ex) <= 0xFFFF) {
69 0 : fCount0 = fCount2 = 0;
70 0 : fCount1 = count;
71 0 : fFx1 = fx0;
72 0 : return;
73 : }
74 0 : if (fx <= 0 && ex <= 0) {
75 0 : fCount1 = fCount2 = 0;
76 0 : fCount0 = count;
77 0 : return;
78 : }
79 0 : if (fx >= 0xFFFF && ex >= 0xFFFF) {
80 0 : fCount0 = fCount1 = 0;
81 0 : fCount2 = count;
82 0 : return;
83 : }
84 :
85 0 : int extraCount = 0;
86 :
87 : // now make ex be 1 past the last computed value
88 0 : ex += dx;
89 0 : fOverflowed = overflows_fixed(ex);
90 : // now check for over/under flow
91 0 : if (fOverflowed) {
92 0 : int originalCount = count;
93 : int64_t ccount;
94 0 : bool swap = dx < 0;
95 0 : if (swap) {
96 0 : dx = -dx;
97 0 : fx = -fx;
98 : }
99 0 : ccount = (SK_FixedMax - fx + dx - 1) / dx;
100 0 : if (swap) {
101 0 : dx = -dx;
102 0 : fx = -fx;
103 : }
104 0 : SkASSERT(ccount > 0 && ccount <= SK_FixedMax);
105 :
106 0 : count = (int)ccount;
107 0 : if (0 == count) {
108 0 : this->initFor1(fx0);
109 0 : if (dx > 0) {
110 0 : fCount2 += originalCount - 1;
111 : } else {
112 0 : fCount0 += originalCount - 1;
113 : }
114 0 : return;
115 : }
116 0 : extraCount = originalCount - count;
117 0 : ex = fx + dx * count;
118 : }
119 :
120 0 : bool doSwap = dx < 0;
121 :
122 0 : if (doSwap) {
123 0 : ex -= dx;
124 0 : fx -= dx;
125 0 : SkTSwap(fx, ex);
126 0 : dx = -dx;
127 : }
128 :
129 :
130 0 : fCount0 = chop(fx, 0, ex, dx, count);
131 0 : count -= fCount0;
132 0 : fx += fCount0 * dx;
133 0 : SkASSERT(fx >= 0);
134 0 : SkASSERT(fCount0 == 0 || (fx - dx) < 0);
135 0 : fCount1 = chop(fx, 0xFFFF, ex, dx, count);
136 0 : count -= fCount1;
137 0 : fCount2 = count;
138 :
139 : #ifdef SK_DEBUG
140 0 : fx += fCount1 * dx;
141 0 : SkASSERT(fx <= ex);
142 0 : if (fCount2 > 0) {
143 0 : SkASSERT(fx >= 0xFFFF);
144 0 : if (fCount1 > 0) {
145 0 : SkASSERT(fx - dx < 0xFFFF);
146 : }
147 : }
148 : #endif
149 :
150 0 : if (doSwap) {
151 0 : SkTSwap(fCount0, fCount2);
152 0 : SkTSwap(fV0, fV1);
153 0 : dx = -dx;
154 : }
155 :
156 0 : if (fCount1 > 0) {
157 0 : fFx1 = fx0 + fCount0 * (int)dx;
158 : }
159 :
160 0 : if (dx > 0) {
161 0 : fCount2 += extraCount;
162 : } else {
163 0 : fCount0 += extraCount;
164 : }
165 : }
166 :
|