Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: src/effects/gradients/SkClampRange.cpp

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

Powered by Google App Engine
This is Rietveld 408576698