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

Side by Side Diff: skia/corecg/SkPoint.cpp

Issue 113827: Remove the remainder of the skia source code from the Chromium repo.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months 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 | Annotate | Revision Log
« no previous file with comments | « skia/corecg/SkPageFlipper.cpp ('k') | skia/corecg/SkRect.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006-2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "SkPoint.h"
18
19 void SkIPoint::rotateCW(SkIPoint* dst) const {
20 SkASSERT(dst);
21
22 // use a tmp in case this == dst
23 int32_t tmp = fX;
24 dst->fX = -fY;
25 dst->fY = tmp;
26 }
27
28 void SkIPoint::rotateCCW(SkIPoint* dst) const {
29 SkASSERT(dst);
30
31 // use a tmp in case this == dst
32 int32_t tmp = fX;
33 dst->fX = fY;
34 dst->fY = -tmp;
35 }
36
37 ///////////////////////////////////////////////////////////////////////////////
38
39 void SkPoint::rotateCW(SkPoint* dst) const {
40 SkASSERT(dst);
41
42 // use a tmp in case this == dst
43 SkScalar tmp = fX;
44 dst->fX = -fY;
45 dst->fY = tmp;
46 }
47
48 void SkPoint::rotateCCW(SkPoint* dst) const {
49 SkASSERT(dst);
50
51 // use a tmp in case this == dst
52 SkScalar tmp = fX;
53 dst->fX = fY;
54 dst->fY = -tmp;
55 }
56
57 void SkPoint::scale(SkScalar scale, SkPoint* dst) const {
58 SkASSERT(dst);
59 dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale));
60 }
61
62 #define kNearlyZero (SK_Scalar1 / 8092)
63
64 bool SkPoint::normalize() {
65 return this->setLength(fX, fY, SK_Scalar1);
66 }
67
68 bool SkPoint::setNormalize(SkScalar x, SkScalar y) {
69 return this->setLength(x, y, SK_Scalar1);
70 }
71
72 bool SkPoint::setLength(SkScalar length) {
73 return this->setLength(fX, fY, length);
74 }
75
76 #ifdef SK_SCALAR_IS_FLOAT
77
78 SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
79 return sk_float_sqrt(dx * dx + dy * dy);
80 }
81
82 bool SkPoint::setLength(float x, float y, float length) {
83 float mag = sk_float_sqrt(x * x + y * y);
84 if (mag > kNearlyZero) {
85 length /= mag;
86 fX = x * length;
87 fY = y * length;
88 return true;
89 }
90 return false;
91 }
92
93 #else
94
95 #include "Sk64.h"
96
97 SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
98 Sk64 tmp1, tmp2;
99
100 tmp1.setMul(dx, dx);
101 tmp2.setMul(dy, dy);
102 tmp1.add(tmp2);
103
104 return tmp1.getSqrt();
105 }
106
107 #ifdef SK_DEBUGx
108 static SkFixed fixlen(SkFixed x, SkFixed y) {
109 float fx = (float)x;
110 float fy = (float)y;
111
112 return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f);
113 }
114 #endif
115
116 static inline uint32_t squarefixed(unsigned x) {
117 x >>= 16;
118 return x*x;
119 }
120
121 #if 1 // Newton iter for setLength
122
123 static inline unsigned invsqrt_iter(unsigned V, unsigned U) {
124 unsigned x = V * U >> 14;
125 x = x * U >> 14;
126 x = (3 << 14) - x;
127 x = (U >> 1) * x >> 14;
128 return x;
129 }
130
131 static const uint16_t gInvSqrt14GuessTable[] = {
132 0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061,
133 0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780,
134 0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235,
135 0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99,
136 0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee,
137 0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc,
138 0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830,
139 0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce
140 };
141
142 #define BUILD_INVSQRT_TABLEx
143 #ifdef BUILD_INVSQRT_TABLE
144 static void build_invsqrt14_guess_table() {
145 for (int i = 8; i <= 63; i++) {
146 unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25));
147 printf("0x%x, ", x);
148 }
149 printf("\n");
150 }
151 #endif
152
153 static unsigned fast_invsqrt(uint32_t x) {
154 #ifdef BUILD_INVSQRT_TABLE
155 unsigned top2 = x >> 25;
156 SkASSERT(top2 >= 8 && top2 <= 63);
157
158 static bool gOnce;
159 if (!gOnce) {
160 build_invsqrt14_guess_table();
161 gOnce = true;
162 }
163 #endif
164
165 unsigned V = x >> 14; // make V .14
166
167 unsigned top = x >> 25;
168 SkASSERT(top >= 8 && top <= 63);
169 SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable));
170 unsigned U = gInvSqrt14GuessTable[top - 8];
171
172 U = invsqrt_iter(V, U);
173 return invsqrt_iter(V, U);
174 }
175
176 /* We "normalize" x,y to be .14 values (so we can square them and stay 32bits.
177 Then we Newton-iterate this in .14 space to compute the invser-sqrt, and
178 scale by it at the end. The .14 space means we can execute our iterations
179 and stay in 32bits as well, making the multiplies much cheaper than calling
180 SkFixedMul.
181 */
182 bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
183 if (ox == 0) {
184 if (oy == 0) {
185 return false;
186 }
187 this->set(0, SkApplySign(length, SkExtractSign(oy)));
188 return true;
189 }
190 if (oy == 0) {
191 this->set(SkApplySign(length, SkExtractSign(ox)), 0);
192 return true;
193 }
194
195 unsigned x = SkAbs32(ox);
196 unsigned y = SkAbs32(oy);
197 int zeros = SkCLZ(x | y);
198
199 // make x,y 1.14 values so our fast sqr won't overflow
200 if (zeros > 17) {
201 x <<= zeros - 17;
202 y <<= zeros - 17;
203 } else {
204 x >>= 17 - zeros;
205 y >>= 17 - zeros;
206 }
207 SkASSERT((x | y) <= 0x7FFF);
208
209 unsigned invrt = fast_invsqrt(x*x + y*y);
210
211 x = x * invrt >> 12;
212 y = y * invrt >> 12;
213
214 if (length != SK_Fixed1) {
215 x = SkFixedMul(x, length);
216 y = SkFixedMul(y, length);
217 }
218 this->set(SkApplySign(x, SkExtractSign(ox)),
219 SkApplySign(y, SkExtractSign(oy)));
220 return true;
221 }
222 #else
223 /*
224 Normalize x,y, and then scale them by length.
225
226 The obvious way to do this would be the following:
227 S64 tmp1, tmp2;
228 tmp1.setMul(x,x);
229 tmp2.setMul(y,y);
230 tmp1.add(tmp2);
231 len = tmp1.getSqrt();
232 x' = SkFixedDiv(x, len);
233 y' = SkFixedDiv(y, len);
234 This is fine, but slower than what we do below.
235
236 The present technique does not compute the starting length, but
237 rather fiddles with x,y iteratively, all the while checking its
238 magnitude^2 (avoiding a sqrt).
239
240 We normalize by first shifting x,y so that at least one of them
241 has bit 31 set (after taking the abs of them).
242 Then we loop, refining x,y by squaring them and comparing
243 against a very large 1.0 (1 << 28), and then adding or subtracting
244 a delta (which itself is reduced by half each time through the loop).
245 For speed we want the squaring to be with a simple integer mul. To keep
246 that from overflowing we shift our coordinates down until we are dealing
247 with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits)
248 When our square is close to 1.0, we shift x,y down into fixed range.
249 */
250 bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
251 if (ox == 0) {
252 if (oy == 0)
253 return false;
254 this->set(0, SkApplySign(length, SkExtractSign(oy)));
255 return true;
256 }
257 if (oy == 0) {
258 this->set(SkApplySign(length, SkExtractSign(ox)), 0);
259 return true;
260 }
261
262 SkFixed x = SkAbs32(ox);
263 SkFixed y = SkAbs32(oy);
264
265 // shift x,y so that the greater of them is 15bits (1.14 fixed point)
266 {
267 int shift = SkCLZ(x | y);
268 // make them .30
269 x <<= shift - 1;
270 y <<= shift - 1;
271 }
272
273 SkFixed dx = x;
274 SkFixed dy = y;
275
276 for (int i = 0; i < 17; i++) {
277 dx >>= 1;
278 dy >>= 1;
279
280 U32 len2 = squarefixed(x) + squarefixed(y);
281 if (len2 >> 28) {
282 x -= dx;
283 y -= dy;
284 } else {
285 x += dx;
286 y += dy;
287 }
288 }
289 x >>= 14;
290 y >>= 14;
291
292 #ifdef SK_DEBUGx // measure how far we are from unit-length
293 {
294 static int gMaxError;
295 static int gMaxDiff;
296
297 SkFixed len = fixlen(x, y);
298 int err = len - SK_Fixed1;
299 err = SkAbs32(err);
300
301 if (err > gMaxError) {
302 gMaxError = err;
303 SkDebugf("gMaxError %d\n", err);
304 }
305
306 float fx = SkAbs32(ox)/65536.0f;
307 float fy = SkAbs32(oy)/65536.0f;
308 float mag = sqrtf(fx*fx + fy*fy);
309 fx /= mag;
310 fy /= mag;
311 SkFixed xx = (int)floorf(fx * 65536 + 0.5f);
312 SkFixed yy = (int)floorf(fy * 65536 + 0.5f);
313 err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y));
314 if (err > gMaxDiff) {
315 gMaxDiff = err;
316 SkDebugf("gMaxDiff %d\n", err);
317 }
318 }
319 #endif
320
321 x = SkApplySign(x, SkExtractSign(ox));
322 y = SkApplySign(y, SkExtractSign(oy));
323 if (length != SK_Fixed1) {
324 x = SkFixedMul(x, length);
325 y = SkFixedMul(y, length);
326 }
327
328 this->set(x, y);
329 return true;
330 }
331 #endif
332
333 #endif
334
OLDNEW
« no previous file with comments | « skia/corecg/SkPageFlipper.cpp ('k') | skia/corecg/SkRect.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698