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

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
« no previous file with comments | « src/effects/gradients/SkClampRange.h ('k') | src/effects/gradients/SkLinearGradient.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PRECISION
33 static bool overflows_gradfixed(int64_t x) {
33 return x < -SK_FixedMax || x > SK_FixedMax; 34 return x < -SK_FixedMax || x > SK_FixedMax;
34 } 35 }
36 #endif
35 37
36 void SkClampRange::initFor1(SkFixed fx) { 38 void SkClampRange::initFor1(SkGradFixed fx) {
37 fCount0 = fCount1 = fCount2 = 0; 39 fCount0 = fCount1 = fCount2 = 0;
38 if (fx <= 0) { 40 if (fx <= 0) {
39 fCount0 = 1; 41 fCount0 = 1;
40 } else if (fx < 0xFFFF) { 42 } else if (fx < kFracMax_SkGradFixed) {
41 fCount1 = 1; 43 fCount1 = 1;
42 fFx1 = fx; 44 fFx1 = fx;
43 } else { 45 } else {
44 fCount2 = 1; 46 fCount2 = 1;
45 } 47 }
46 } 48 }
47 49
48 void SkClampRange::init(SkFixed fx0, SkFixed dx0, int count, int v0, int v1) { 50 void SkClampRange::init(SkGradFixed fx0, SkGradFixed dx0, int count, int v0, int v1) {
49 SkASSERT(count > 0); 51 SkASSERT(count > 0);
50 52
51 fV0 = v0; 53 fV0 = v0;
52 fV1 = v1; 54 fV1 = v1;
53 55
54 // special case 1 == count, as it is slightly common for skia 56 // special case 1 == count, as it is slightly common for skia
55 // and avoids us ever calling divide or 64bit multiply 57 // and avoids us ever calling divide or 64bit multiply
56 if (1 == count) { 58 if (1 == count) {
57 this->initFor1(fx0); 59 this->initFor1(fx0);
58 return; 60 return;
59 } 61 }
60 62
61 int64_t fx = fx0; 63 int64_t fx = fx0;
62 int64_t dx = dx0; 64 int64_t dx = dx0;
65
63 // start with ex equal to the last computed value 66 // start with ex equal to the last computed value
64 int64_t ex = fx + (count - 1) * dx; 67 int64_t ex = fx + (count - 1) * dx;
65 68
66 if ((uint64_t)(fx | ex) <= 0xFFFF) { 69 if ((uint64_t)(fx | ex) <= kFracMax_SkGradFixed) {
67 fCount0 = fCount2 = 0; 70 fCount0 = fCount2 = 0;
68 fCount1 = count; 71 fCount1 = count;
69 fFx1 = fx0; 72 fFx1 = fx0;
70 return; 73 return;
71 } 74 }
72 if (fx <= 0 && ex <= 0) { 75 if (fx <= 0 && ex <= 0) {
73 fCount1 = fCount2 = 0; 76 fCount1 = fCount2 = 0;
74 fCount0 = count; 77 fCount0 = count;
75 return; 78 return;
76 } 79 }
77 if (fx >= 0xFFFF && ex >= 0xFFFF) { 80 if (fx >= kFracMax_SkGradFixed && ex >= kFracMax_SkGradFixed) {
78 fCount0 = fCount1 = 0; 81 fCount0 = fCount1 = 0;
79 fCount2 = count; 82 fCount2 = count;
80 return; 83 return;
81 } 84 }
82 85
83 int extraCount = 0; 86 int extraCount = 0;
84 87
85 // now make ex be 1 past the last computed value 88 // now make ex be 1 past the last computed value
86 ex += dx; 89 ex += dx;
90
91 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PRECISION
87 // now check for over/under flow 92 // now check for over/under flow
88 if (overflows_fixed(ex)) { 93 if (overflows_gradfixed(ex)) {
89 int originalCount = count; 94 int originalCount = count;
90 int64_t ccount; 95 int64_t ccount;
91 bool swap = dx < 0; 96 bool swap = dx < 0;
92 if (swap) { 97 if (swap) {
93 dx = -dx; 98 dx = -dx;
94 fx = -fx; 99 fx = -fx;
95 } 100 }
96 ccount = (SK_FixedMax - fx + dx - 1) / dx; 101
102 int shift = 0;
103 if (sizeof(SkGradFixed) == 8) {
104 shift = 16;
105 }
106
107 ccount = ((SK_FixedMax << shift) - fx + dx - 1) / dx;
97 if (swap) { 108 if (swap) {
98 dx = -dx; 109 dx = -dx;
99 fx = -fx; 110 fx = -fx;
100 } 111 }
101 SkASSERT(ccount > 0 && ccount <= SK_FixedMax); 112 SkASSERT(ccount > 0 && ccount <= SK_FixedMax);
102 113
103 count = (int)ccount; 114 count = (int)ccount;
104 if (0 == count) { 115 if (0 == count) {
105 this->initFor1(fx0); 116 this->initFor1(fx0);
106 if (dx > 0) { 117 if (dx > 0) {
107 fCount2 += originalCount - 1; 118 fCount2 += originalCount - 1;
108 } else { 119 } else {
109 fCount0 += originalCount - 1; 120 fCount0 += originalCount - 1;
110 } 121 }
111 return; 122 return;
112 } 123 }
113 extraCount = originalCount - count; 124 extraCount = originalCount - count;
114 ex = fx + dx * count; 125 ex = fx + dx * count;
115 } 126 }
127 #endif
116 128
117 bool doSwap = dx < 0; 129 bool doSwap = dx < 0;
118 130
119 if (doSwap) { 131 if (doSwap) {
120 ex -= dx; 132 ex -= dx;
121 fx -= dx; 133 fx -= dx;
122 SkTSwap(fx, ex); 134 SkTSwap(fx, ex);
123 dx = -dx; 135 dx = -dx;
124 } 136 }
125 137
126 138
127 fCount0 = chop(fx, 0, ex, dx, count); 139 fCount0 = chop(fx, 0, ex, dx, count);
128 count -= fCount0; 140 count -= fCount0;
129 fx += fCount0 * dx; 141 fx += fCount0 * dx;
130 SkASSERT(fx >= 0); 142 SkASSERT(fx >= 0);
131 SkASSERT(fCount0 == 0 || (fx - dx) < 0); 143 SkASSERT(fCount0 == 0 || (fx - dx) < 0);
132 fCount1 = chop(fx, 0xFFFF, ex, dx, count); 144 fCount1 = chop(fx, kFracMax_SkGradFixed, ex, dx, count);
133 count -= fCount1; 145 count -= fCount1;
134 fCount2 = count; 146 fCount2 = count;
135 147
136 #ifdef SK_DEBUG 148 #ifdef SK_DEBUG
137 fx += fCount1 * dx; 149 fx += fCount1 * dx;
138 SkASSERT(fx <= ex); 150 SkASSERT(fx <= ex);
139 if (fCount2 > 0) { 151 if (fCount2 > 0) {
140 SkASSERT(fx >= 0xFFFF); 152 SkASSERT(fx >= kFracMax_SkGradFixed);
141 if (fCount1 > 0) { 153 if (fCount1 > 0) {
142 SkASSERT(fx - dx < 0xFFFF); 154 SkASSERT(fx - dx < kFracMax_SkGradFixed);
143 } 155 }
144 } 156 }
145 #endif 157 #endif
146 158
147 if (doSwap) { 159 if (doSwap) {
148 SkTSwap(fCount0, fCount2); 160 SkTSwap(fCount0, fCount2);
149 SkTSwap(fV0, fV1); 161 SkTSwap(fV0, fV1);
150 dx = -dx; 162 dx = -dx;
151 } 163 }
152 164
153 if (fCount1 > 0) { 165 if (fCount1 > 0) {
154 fFx1 = fx0 + fCount0 * (int)dx; 166 fFx1 = fx0 + fCount0 * (int)dx;
155 } 167 }
156 168
157 if (dx > 0) { 169 if (dx > 0) {
158 fCount2 += extraCount; 170 fCount2 += extraCount;
159 } else { 171 } else {
160 fCount0 += extraCount; 172 fCount0 += extraCount;
161 } 173 }
162 } 174 }
OLDNEW
« no previous file with comments | « src/effects/gradients/SkClampRange.h ('k') | src/effects/gradients/SkLinearGradient.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698