1 :
2 : /*
3 : * Copyright 2008 The Android Open Source Project
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 "SkPoint.h"
11 :
12 0 : void SkIPoint::rotateCW(SkIPoint* dst) const {
13 0 : SkASSERT(dst);
14 :
15 : // use a tmp in case this == dst
16 0 : int32_t tmp = fX;
17 0 : dst->fX = -fY;
18 0 : dst->fY = tmp;
19 0 : }
20 :
21 0 : void SkIPoint::rotateCCW(SkIPoint* dst) const {
22 0 : SkASSERT(dst);
23 :
24 : // use a tmp in case this == dst
25 0 : int32_t tmp = fX;
26 0 : dst->fX = fY;
27 0 : dst->fY = -tmp;
28 0 : }
29 :
30 : ///////////////////////////////////////////////////////////////////////////////
31 :
32 0 : void SkPoint::setIRectFan(int l, int t, int r, int b, size_t stride) {
33 0 : SkASSERT(stride >= sizeof(SkPoint));
34 :
35 : ((SkPoint*)((intptr_t)this + 0 * stride))->set(SkIntToScalar(l),
36 0 : SkIntToScalar(t));
37 : ((SkPoint*)((intptr_t)this + 1 * stride))->set(SkIntToScalar(l),
38 0 : SkIntToScalar(b));
39 : ((SkPoint*)((intptr_t)this + 2 * stride))->set(SkIntToScalar(r),
40 0 : SkIntToScalar(b));
41 : ((SkPoint*)((intptr_t)this + 3 * stride))->set(SkIntToScalar(r),
42 0 : SkIntToScalar(t));
43 0 : }
44 :
45 0 : void SkPoint::setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b,
46 : size_t stride) {
47 0 : SkASSERT(stride >= sizeof(SkPoint));
48 :
49 0 : ((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t);
50 0 : ((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b);
51 0 : ((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b);
52 0 : ((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t);
53 0 : }
54 :
55 0 : void SkPoint::rotateCW(SkPoint* dst) const {
56 0 : SkASSERT(dst);
57 :
58 : // use a tmp in case this == dst
59 0 : SkScalar tmp = fX;
60 0 : dst->fX = -fY;
61 0 : dst->fY = tmp;
62 0 : }
63 :
64 0 : void SkPoint::rotateCCW(SkPoint* dst) const {
65 0 : SkASSERT(dst);
66 :
67 : // use a tmp in case this == dst
68 0 : SkScalar tmp = fX;
69 0 : dst->fX = fY;
70 0 : dst->fY = -tmp;
71 0 : }
72 :
73 0 : void SkPoint::scale(SkScalar scale, SkPoint* dst) const {
74 0 : SkASSERT(dst);
75 0 : dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale));
76 0 : }
77 :
78 0 : bool SkPoint::normalize() {
79 0 : return this->setLength(fX, fY, SK_Scalar1);
80 : }
81 :
82 0 : bool SkPoint::setNormalize(SkScalar x, SkScalar y) {
83 0 : return this->setLength(x, y, SK_Scalar1);
84 : }
85 :
86 0 : bool SkPoint::setLength(SkScalar length) {
87 0 : return this->setLength(fX, fY, length);
88 : }
89 :
90 0 : SkScalar SkPoint::Normalize(SkPoint* pt) {
91 0 : SkScalar mag = SkPoint::Length(pt->fX, pt->fY);
92 0 : if (mag > SK_ScalarNearlyZero) {
93 0 : SkScalar scale = SkScalarInvert(mag);
94 0 : pt->fX = SkScalarMul(pt->fX, scale);
95 0 : pt->fY = SkScalarMul(pt->fY, scale);
96 0 : return mag;
97 : }
98 0 : return 0;
99 : }
100 :
101 : #ifdef SK_SCALAR_IS_FLOAT
102 :
103 0 : bool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) {
104 0 : float mag2 = dx * dx + dy * dy;
105 0 : return mag2 > SK_ScalarNearlyZero * SK_ScalarNearlyZero;
106 : }
107 :
108 0 : SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
109 0 : return sk_float_sqrt(dx * dx + dy * dy);
110 : }
111 :
112 0 : bool SkPoint::setLength(float x, float y, float length) {
113 0 : float mag2 = x * x + y * y;
114 0 : if (mag2 > SK_ScalarNearlyZero * SK_ScalarNearlyZero) {
115 0 : float scale = length / sk_float_sqrt(mag2);
116 0 : fX = x * scale;
117 0 : fY = y * scale;
118 0 : return true;
119 : }
120 0 : return false;
121 : }
122 :
123 : #else
124 :
125 : #include "Sk64.h"
126 :
127 : bool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) {
128 : Sk64 tmp1, tmp2, tolSqr;
129 :
130 : tmp1.setMul(dx, dx);
131 : tmp2.setMul(dy, dy);
132 : tmp1.add(tmp2);
133 :
134 : // we want nearlyzero^2, but to compute it fast we want to just do a
135 : // 32bit multiply, so we require that it not exceed 31bits. That is true
136 : // if nearlyzero is <= 0xB504, which should be trivial, since usually
137 : // nearlyzero is a very small fixed-point value.
138 : SkASSERT(SK_ScalarNearlyZero <= 0xB504);
139 :
140 : tolSqr.set(0, SK_ScalarNearlyZero * SK_ScalarNearlyZero);
141 : return tmp1 > tolSqr;
142 : }
143 :
144 : SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
145 : Sk64 tmp1, tmp2;
146 :
147 : tmp1.setMul(dx, dx);
148 : tmp2.setMul(dy, dy);
149 : tmp1.add(tmp2);
150 :
151 : return tmp1.getSqrt();
152 : }
153 :
154 : #ifdef SK_DEBUGx
155 : static SkFixed fixlen(SkFixed x, SkFixed y) {
156 : float fx = (float)x;
157 : float fy = (float)y;
158 :
159 : return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f);
160 : }
161 : #endif
162 :
163 : static inline uint32_t squarefixed(unsigned x) {
164 : x >>= 16;
165 : return x*x;
166 : }
167 :
168 : #if 1 // Newton iter for setLength
169 :
170 : static inline unsigned invsqrt_iter(unsigned V, unsigned U) {
171 : unsigned x = V * U >> 14;
172 : x = x * U >> 14;
173 : x = (3 << 14) - x;
174 : x = (U >> 1) * x >> 14;
175 : return x;
176 : }
177 :
178 : static const uint16_t gInvSqrt14GuessTable[] = {
179 : 0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061,
180 : 0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780,
181 : 0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235,
182 : 0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99,
183 : 0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee,
184 : 0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc,
185 : 0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830,
186 : 0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce
187 : };
188 :
189 : #define BUILD_INVSQRT_TABLEx
190 : #ifdef BUILD_INVSQRT_TABLE
191 : static void build_invsqrt14_guess_table() {
192 : for (int i = 8; i <= 63; i++) {
193 : unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25));
194 : printf("0x%x, ", x);
195 : }
196 : printf("\n");
197 : }
198 : #endif
199 :
200 : static unsigned fast_invsqrt(uint32_t x) {
201 : #ifdef BUILD_INVSQRT_TABLE
202 : unsigned top2 = x >> 25;
203 : SkASSERT(top2 >= 8 && top2 <= 63);
204 :
205 : static bool gOnce;
206 : if (!gOnce) {
207 : build_invsqrt14_guess_table();
208 : gOnce = true;
209 : }
210 : #endif
211 :
212 : unsigned V = x >> 14; // make V .14
213 :
214 : unsigned top = x >> 25;
215 : SkASSERT(top >= 8 && top <= 63);
216 : SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable));
217 : unsigned U = gInvSqrt14GuessTable[top - 8];
218 :
219 : U = invsqrt_iter(V, U);
220 : return invsqrt_iter(V, U);
221 : }
222 :
223 : /* We "normalize" x,y to be .14 values (so we can square them and stay 32bits.
224 : Then we Newton-iterate this in .14 space to compute the invser-sqrt, and
225 : scale by it at the end. The .14 space means we can execute our iterations
226 : and stay in 32bits as well, making the multiplies much cheaper than calling
227 : SkFixedMul.
228 : */
229 : bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
230 : if (ox == 0) {
231 : if (oy == 0) {
232 : return false;
233 : }
234 : this->set(0, SkApplySign(length, SkExtractSign(oy)));
235 : return true;
236 : }
237 : if (oy == 0) {
238 : this->set(SkApplySign(length, SkExtractSign(ox)), 0);
239 : return true;
240 : }
241 :
242 : unsigned x = SkAbs32(ox);
243 : unsigned y = SkAbs32(oy);
244 : int zeros = SkCLZ(x | y);
245 :
246 : // make x,y 1.14 values so our fast sqr won't overflow
247 : if (zeros > 17) {
248 : x <<= zeros - 17;
249 : y <<= zeros - 17;
250 : } else {
251 : x >>= 17 - zeros;
252 : y >>= 17 - zeros;
253 : }
254 : SkASSERT((x | y) <= 0x7FFF);
255 :
256 : unsigned invrt = fast_invsqrt(x*x + y*y);
257 :
258 : x = x * invrt >> 12;
259 : y = y * invrt >> 12;
260 :
261 : if (length != SK_Fixed1) {
262 : x = SkFixedMul(x, length);
263 : y = SkFixedMul(y, length);
264 : }
265 : this->set(SkApplySign(x, SkExtractSign(ox)),
266 : SkApplySign(y, SkExtractSign(oy)));
267 : return true;
268 : }
269 : #else
270 : /*
271 : Normalize x,y, and then scale them by length.
272 :
273 : The obvious way to do this would be the following:
274 : S64 tmp1, tmp2;
275 : tmp1.setMul(x,x);
276 : tmp2.setMul(y,y);
277 : tmp1.add(tmp2);
278 : len = tmp1.getSqrt();
279 : x' = SkFixedDiv(x, len);
280 : y' = SkFixedDiv(y, len);
281 : This is fine, but slower than what we do below.
282 :
283 : The present technique does not compute the starting length, but
284 : rather fiddles with x,y iteratively, all the while checking its
285 : magnitude^2 (avoiding a sqrt).
286 :
287 : We normalize by first shifting x,y so that at least one of them
288 : has bit 31 set (after taking the abs of them).
289 : Then we loop, refining x,y by squaring them and comparing
290 : against a very large 1.0 (1 << 28), and then adding or subtracting
291 : a delta (which itself is reduced by half each time through the loop).
292 : For speed we want the squaring to be with a simple integer mul. To keep
293 : that from overflowing we shift our coordinates down until we are dealing
294 : with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits)
295 : When our square is close to 1.0, we shift x,y down into fixed range.
296 : */
297 : bool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
298 : if (ox == 0) {
299 : if (oy == 0)
300 : return false;
301 : this->set(0, SkApplySign(length, SkExtractSign(oy)));
302 : return true;
303 : }
304 : if (oy == 0) {
305 : this->set(SkApplySign(length, SkExtractSign(ox)), 0);
306 : return true;
307 : }
308 :
309 : SkFixed x = SkAbs32(ox);
310 : SkFixed y = SkAbs32(oy);
311 :
312 : // shift x,y so that the greater of them is 15bits (1.14 fixed point)
313 : {
314 : int shift = SkCLZ(x | y);
315 : // make them .30
316 : x <<= shift - 1;
317 : y <<= shift - 1;
318 : }
319 :
320 : SkFixed dx = x;
321 : SkFixed dy = y;
322 :
323 : for (int i = 0; i < 17; i++) {
324 : dx >>= 1;
325 : dy >>= 1;
326 :
327 : U32 len2 = squarefixed(x) + squarefixed(y);
328 : if (len2 >> 28) {
329 : x -= dx;
330 : y -= dy;
331 : } else {
332 : x += dx;
333 : y += dy;
334 : }
335 : }
336 : x >>= 14;
337 : y >>= 14;
338 :
339 : #ifdef SK_DEBUGx // measure how far we are from unit-length
340 : {
341 : static int gMaxError;
342 : static int gMaxDiff;
343 :
344 : SkFixed len = fixlen(x, y);
345 : int err = len - SK_Fixed1;
346 : err = SkAbs32(err);
347 :
348 : if (err > gMaxError) {
349 : gMaxError = err;
350 : SkDebugf("gMaxError %d\n", err);
351 : }
352 :
353 : float fx = SkAbs32(ox)/65536.0f;
354 : float fy = SkAbs32(oy)/65536.0f;
355 : float mag = sqrtf(fx*fx + fy*fy);
356 : fx /= mag;
357 : fy /= mag;
358 : SkFixed xx = (int)floorf(fx * 65536 + 0.5f);
359 : SkFixed yy = (int)floorf(fy * 65536 + 0.5f);
360 : err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y));
361 : if (err > gMaxDiff) {
362 : gMaxDiff = err;
363 : SkDebugf("gMaxDiff %d\n", err);
364 : }
365 : }
366 : #endif
367 :
368 : x = SkApplySign(x, SkExtractSign(ox));
369 : y = SkApplySign(y, SkExtractSign(oy));
370 : if (length != SK_Fixed1) {
371 : x = SkFixedMul(x, length);
372 : y = SkFixedMul(y, length);
373 : }
374 :
375 : this->set(x, y);
376 : return true;
377 : }
378 : #endif
379 :
380 : #endif
381 :
382 : ///////////////////////////////////////////////////////////////////////////////
383 :
384 0 : SkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
385 : const SkPoint& b,
386 : Side* side) const {
387 :
388 0 : SkVector u = b - a;
389 0 : SkVector v = *this - a;
390 :
391 0 : SkScalar uLengthSqd = u.lengthSqd();
392 0 : SkScalar det = u.cross(v);
393 0 : if (NULL != side) {
394 : SkASSERT(-1 == SkPoint::kLeft_Side &&
395 : 0 == SkPoint::kOn_Side &&
396 : 1 == kRight_Side);
397 0 : *side = (Side) SkScalarSignAsInt(det);
398 : }
399 0 : return SkScalarMulDiv(det, det, uLengthSqd);
400 : }
401 :
402 0 : SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
403 : const SkPoint& b) const {
404 : // See comments to distanceToLineBetweenSqd. If the projection of c onto
405 : // u is between a and b then this returns the same result as that
406 : // function. Otherwise, it returns the distance to the closer of a and
407 : // b. Let the projection of v onto u be v'. There are three cases:
408 : // 1. v' points opposite to u. c is not between a and b and is closer
409 : // to a than b.
410 : // 2. v' points along u and has magnitude less than y. c is between
411 : // a and b and the distance to the segment is the same as distance
412 : // to the line ab.
413 : // 3. v' points along u and has greater magnitude than u. c is not
414 : // not between a and b and is closer to b than a.
415 : // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
416 : // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
417 : // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
418 : // avoid a sqrt to compute |u|.
419 :
420 0 : SkVector u = b - a;
421 0 : SkVector v = *this - a;
422 :
423 0 : SkScalar uLengthSqd = u.lengthSqd();
424 0 : SkScalar uDotV = SkPoint::DotProduct(u, v);
425 :
426 0 : if (uDotV <= 0) {
427 0 : return v.lengthSqd();
428 0 : } else if (uDotV > uLengthSqd) {
429 0 : return b.distanceToSqd(*this);
430 : } else {
431 0 : SkScalar det = u.cross(v);
432 0 : return SkScalarMulDiv(det, det, uLengthSqd);
433 : }
434 : }
|