1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project
4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPoint.h"
11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkIPoint::rotateCW(SkIPoint* dst) const {
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(dst);
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // use a tmp in case this == dst
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int32_t tmp = fX;
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fX = -fY;
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fY = tmp;
19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkIPoint::rotateCCW(SkIPoint* dst) const {
22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(dst);
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // use a tmp in case this == dst
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int32_t tmp = fX;
26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fX = fY;
27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fY = -tmp;
28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
3298a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.comvoid SkPoint::setIRectFan(int l, int t, int r, int b, size_t stride) {
3398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkASSERT(stride >= sizeof(SkPoint));
34935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
35935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    ((SkPoint*)((intptr_t)this + 0 * stride))->set(SkIntToScalar(l),
3698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                                                   SkIntToScalar(t));
37935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    ((SkPoint*)((intptr_t)this + 1 * stride))->set(SkIntToScalar(l),
3898a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                                                   SkIntToScalar(b));
39935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    ((SkPoint*)((intptr_t)this + 2 * stride))->set(SkIntToScalar(r),
4098a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                                                   SkIntToScalar(b));
41935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    ((SkPoint*)((intptr_t)this + 3 * stride))->set(SkIntToScalar(r),
4298a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                                                   SkIntToScalar(t));
4398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com}
4498a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com
4598a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.comvoid SkPoint::setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b,
4698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                         size_t stride) {
4798a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkASSERT(stride >= sizeof(SkPoint));
48935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
4998a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    ((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t);
5098a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    ((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b);
5198a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    ((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b);
5298a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    ((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t);
5398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com}
5498a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com
55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPoint::rotateCW(SkPoint* dst) const {
56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(dst);
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // use a tmp in case this == dst
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar tmp = fX;
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fX = -fY;
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fY = tmp;
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPoint::rotateCCW(SkPoint* dst) const {
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(dst);
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // use a tmp in case this == dst
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkScalar tmp = fX;
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fX = fY;
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->fY = -tmp;
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPoint::scale(SkScalar scale, SkPoint* dst) const {
74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(dst);
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale));
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::normalize() {
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->setLength(fX, fY, SK_Scalar1);
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::setNormalize(SkScalar x, SkScalar y) {
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->setLength(x, y, SK_Scalar1);
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::setLength(SkScalar length) {
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return this->setLength(fX, fY, length);
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
90f12192ecf527ca966f370bee9c421a0720180787epoger@google.com#ifdef SK_SCALAR_IS_FLOAT
91f12192ecf527ca966f370bee9c421a0720180787epoger@google.com
92f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// Returns the square of the Euclidian distance to (dx,dy).
93f12192ecf527ca966f370bee9c421a0720180787epoger@google.comstatic inline float getLengthSquared(float dx, float dy) {
94f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return dx * dx + dy * dy;
95f12192ecf527ca966f370bee9c421a0720180787epoger@google.com}
96f12192ecf527ca966f370bee9c421a0720180787epoger@google.com
97f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
98f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
99f12192ecf527ca966f370bee9c421a0720180787epoger@google.com//
100f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// This logic is encapsulated in a helper method to make it explicit that we
101f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// always perform this check in the same manner, to avoid inconsistencies
102f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// (see http://code.google.com/p/skia/issues/detail?id=560 ).
103f12192ecf527ca966f370bee9c421a0720180787epoger@google.comstatic inline bool isLengthNearlyZero(float dx, float dy,
104f12192ecf527ca966f370bee9c421a0720180787epoger@google.com                                      float *lengthSquared) {
105f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    *lengthSquared = getLengthSquared(dx, dy);
106f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
107f12192ecf527ca966f370bee9c421a0720180787epoger@google.com}
108f12192ecf527ca966f370bee9c421a0720180787epoger@google.com
109ab898c759db71175742dfe8a743680f03aa57bb2reed@android.comSkScalar SkPoint::Normalize(SkPoint* pt) {
1103134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    float x = pt->fX;
1113134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    float y = pt->fY;
112f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    float mag2;
1133134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    if (isLengthNearlyZero(x, y, &mag2)) {
1143134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        return 0;
115ab898c759db71175742dfe8a743680f03aa57bb2reed@android.com    }
1163134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com
1173134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    float mag, scale;
1183134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    if (SkScalarIsFinite(mag2)) {
1193134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        mag = sk_float_sqrt(mag2);
1203134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        scale = 1 / mag;
1213134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    } else {
1223134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // our mag2 step overflowed to infinity, so use doubles instead.
1233134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // much slower, but needed when x or y are very large, other wise we
1243134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // divide by inf. and return (0,0) vector.
1253134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double xx = x;
1263134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double yy = y;
1273134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double magmag = sqrt(xx * xx + yy * yy);
1283134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        mag = (float)magmag;
1293134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // we perform the divide with the double magmag, to stay exactly the
1303134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // same as setLength. It would be faster to perform the divide with
1313134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // mag, but it is possible that mag has overflowed to inf. but still
1323134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // have a non-zero value for scale (thanks to denormalized numbers).
1333134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        scale = (float)(1 / magmag);
1343134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    }
1353134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    pt->set(x * scale, y * scale);
1363134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    return mag;
137ab898c759db71175742dfe8a743680f03aa57bb2reed@android.com}
138ab898c759db71175742dfe8a743680f03aa57bb2reed@android.com
13904f0846e042c7334039ed6d2d03df604c6a2f6cdepoger@google.comSkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
1403134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    float mag2 = dx * dx + dy * dy;
1413134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    if (SkScalarIsFinite(mag2)) {
1423134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        return sk_float_sqrt(mag2);
1433134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    } else {
1443134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double xx = dx;
1453134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double yy = dy;
1463134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        return (float)sqrt(xx * xx + yy * yy);
1473134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    }
14804f0846e042c7334039ed6d2d03df604c6a2f6cdepoger@google.com}
14904f0846e042c7334039ed6d2d03df604c6a2f6cdepoger@google.com
1503134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com/*
1513134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *  We have to worry about 2 tricky conditions:
1523134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *  1. underflow of mag2 (compared against nearlyzero^2)
1533134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *  2. overflow of mag2 (compared w/ isfinite)
1543134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *
1553134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *  If we underflow, we return false. If we overflow, we compute again using
1563134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com *  doubles, which is much slower (3x in a desktop test) but will not overflow.
1573134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com */
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::setLength(float x, float y, float length) {
159f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    float mag2;
1603134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    if (isLengthNearlyZero(x, y, &mag2)) {
1613134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        return false;
1623134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    }
1633134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com
1643134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    float scale;
1653134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    if (SkScalarIsFinite(mag2)) {
1663134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        scale = length / sk_float_sqrt(mag2);
1673134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    } else {
1683134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // our mag2 step overflowed to infinity, so use doubles instead.
1693134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // much slower, but needed when x or y are very large, other wise we
1703134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        // divide by inf. and return (0,0) vector.
1713134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double xx = x;
1723134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        double yy = y;
1733134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com        scale = (float)(length / sqrt(xx * xx + yy * yy));
174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
1753134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    fX = x * scale;
1763134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    fY = y * scale;
1773134e174c7d9b2b1d999bc7f212be91769a5ed5breed@google.com    return true;
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else
181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "Sk64.h"
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
184f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// Returns the square of the Euclidian distance to (dx,dy) in *result.
185f12192ecf527ca966f370bee9c421a0720180787epoger@google.comstatic inline void getLengthSquared(SkScalar dx, SkScalar dy, Sk64 *result) {
186f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    Sk64    dySqr;
187f12192ecf527ca966f370bee9c421a0720180787epoger@google.com
188f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    result->setMul(dx, dx);
189f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    dySqr.setMul(dy, dy);
190f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    result->add(dySqr);
191f12192ecf527ca966f370bee9c421a0720180787epoger@google.com}
192f12192ecf527ca966f370bee9c421a0720180787epoger@google.com
193f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
194f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
195f12192ecf527ca966f370bee9c421a0720180787epoger@google.com//
196f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// This logic is encapsulated in a helper method to make it explicit that we
197f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// always perform this check in the same manner, to avoid inconsistencies
198f12192ecf527ca966f370bee9c421a0720180787epoger@google.com// (see http://code.google.com/p/skia/issues/detail?id=560 ).
199f12192ecf527ca966f370bee9c421a0720180787epoger@google.comstatic inline bool isLengthNearlyZero(SkScalar dx, SkScalar dy,
200f12192ecf527ca966f370bee9c421a0720180787epoger@google.com                                      Sk64 *lengthSquared) {
201f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    Sk64 tolSqr;
202f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    getLengthSquared(dx, dy, lengthSquared);
20301bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com
20401bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    // we want nearlyzero^2, but to compute it fast we want to just do a
20501bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    // 32bit multiply, so we require that it not exceed 31bits. That is true
20601bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    // if nearlyzero is <= 0xB504, which should be trivial, since usually
20701bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    // nearlyzero is a very small fixed-point value.
20801bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    SkASSERT(SK_ScalarNearlyZero <= 0xB504);
20901bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com
21001bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com    tolSqr.set(0, SK_ScalarNearlyZero * SK_ScalarNearlyZero);
211f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return *lengthSquared <= tolSqr;
21201bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com}
21301bd0f5b8a35c311d619c16bea516b67e5d243c6reed@google.com
214f12192ecf527ca966f370bee9c421a0720180787epoger@google.comSkScalar SkPoint::Normalize(SkPoint* pt) {
215f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    Sk64 mag2;
216f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) {
217f12192ecf527ca966f370bee9c421a0720180787epoger@google.com        SkScalar mag = mag2.getSqrt();
218f12192ecf527ca966f370bee9c421a0720180787epoger@google.com        SkScalar scale = SkScalarInvert(mag);
219f12192ecf527ca966f370bee9c421a0720180787epoger@google.com        pt->fX = SkScalarMul(pt->fX, scale);
220f12192ecf527ca966f370bee9c421a0720180787epoger@google.com        pt->fY = SkScalarMul(pt->fY, scale);
221f12192ecf527ca966f370bee9c421a0720180787epoger@google.com        return mag;
222f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    }
223f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return 0;
224f12192ecf527ca966f370bee9c421a0720180787epoger@google.com}
225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
226f12192ecf527ca966f370bee9c421a0720180787epoger@google.combool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) {
227f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    Sk64 mag2_unused;
228f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return !isLengthNearlyZero(dx, dy, &mag2_unused);
229f12192ecf527ca966f370bee9c421a0720180787epoger@google.com}
230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
231f12192ecf527ca966f370bee9c421a0720180787epoger@google.comSkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
232f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    Sk64    tmp;
233f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    getLengthSquared(dx, dy, &tmp);
234f12192ecf527ca966f370bee9c421a0720180787epoger@google.com    return tmp.getSqrt();
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUGx
238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic SkFixed fixlen(SkFixed x, SkFixed y) {
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    float fx = (float)x;
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    float fy = (float)y;
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f);
243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline uint32_t squarefixed(unsigned x) {
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x >>= 16;
248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return x*x;
249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if 1   // Newton iter for setLength
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline unsigned invsqrt_iter(unsigned V, unsigned U) {
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned x = V * U >> 14;
255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x = x * U >> 14;
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x = (3 << 14) - x;
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x = (U >> 1) * x >> 14;
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return x;
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic const uint16_t gInvSqrt14GuessTable[] = {
262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061,
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780,
264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235,
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99,
266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee,
267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc,
268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830,
269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce
270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define BUILD_INVSQRT_TABLEx
273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef BUILD_INVSQRT_TABLE
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void build_invsqrt14_guess_table() {
275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int i = 8; i <= 63; i++) {
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25));
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        printf("0x%x, ", x);
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    printf("\n");
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic unsigned fast_invsqrt(uint32_t x) {
284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef BUILD_INVSQRT_TABLE
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned top2 = x >> 25;
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(top2 >= 8 && top2 <= 63);
287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    static bool gOnce;
289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (!gOnce) {
290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        build_invsqrt14_guess_table();
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        gOnce = true;
292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned V = x >> 14;   // make V .14
296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned top = x >> 25;
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(top >= 8 && top <= 63);
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable));
300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned U = gInvSqrt14GuessTable[top - 8];
301935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    U = invsqrt_iter(V, U);
303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return invsqrt_iter(V, U);
304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/*  We "normalize" x,y to be .14 values (so we can square them and stay 32bits.
307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Then we Newton-iterate this in .14 space to compute the invser-sqrt, and
308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    scale by it at the end. The .14 space means we can execute our iterations
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    and stay in 32bits as well, making the multiplies much cheaper than calling
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixedMul.
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (ox == 0) {
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (oy == 0) {
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return false;
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(0, SkApplySign(length, SkExtractSign(oy)));
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true;
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (oy == 0) {
321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(SkApplySign(length, SkExtractSign(ox)), 0);
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true;
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned x = SkAbs32(ox);
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned y = SkAbs32(oy);
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int zeros = SkCLZ(x | y);
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // make x,y 1.14 values so our fast sqr won't overflow
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (zeros > 17) {
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x <<= zeros - 17;
332935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        y <<= zeros - 17;
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } else {
334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x >>= 17 - zeros;
335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y >>= 17 - zeros;
336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT((x | y) <= 0x7FFF);
338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned invrt = fast_invsqrt(x*x + y*y);
340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x = x * invrt >> 12;
342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    y = y * invrt >> 12;
343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (length != SK_Fixed1) {
345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x = SkFixedMul(x, length);
346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y = SkFixedMul(y, length);
347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->set(SkApplySign(x, SkExtractSign(ox)),
349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com              SkApplySign(y, SkExtractSign(oy)));
350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return true;
351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else
353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/*
354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Normalize x,y, and then scale them by length.
355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    The obvious way to do this would be the following:
357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        S64 tmp1, tmp2;
358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        tmp1.setMul(x,x);
359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        tmp2.setMul(y,y);
360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        tmp1.add(tmp2);
361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        len = tmp1.getSqrt();
362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x' = SkFixedDiv(x, len);
363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y' = SkFixedDiv(y, len);
364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    This is fine, but slower than what we do below.
365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    The present technique does not compute the starting length, but
367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    rather fiddles with x,y iteratively, all the while checking its
368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    magnitude^2 (avoiding a sqrt).
369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    We normalize by first shifting x,y so that at least one of them
371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    has bit 31 set (after taking the abs of them).
372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Then we loop, refining x,y by squaring them and comparing
373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    against a very large 1.0 (1 << 28), and then adding or subtracting
374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    a delta (which itself is reduced by half each time through the loop).
375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    For speed we want the squaring to be with a simple integer mul. To keep
376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    that from overflowing we shift our coordinates down until we are dealing
377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits)
378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    When our square is close to 1.0, we shift x,y down into fixed range.
379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/
380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (ox == 0) {
382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (oy == 0)
383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return false;
384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(0, SkApplySign(length, SkExtractSign(oy)));
385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true;
386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (oy == 0) {
388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->set(SkApplySign(length, SkExtractSign(ox)), 0);
389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return true;
390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixed x = SkAbs32(ox);
393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixed y = SkAbs32(oy);
394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // shift x,y so that the greater of them is 15bits (1.14 fixed point)
396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int shift = SkCLZ(x | y);
398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // make them .30
399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x <<= shift - 1;
400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y <<= shift - 1;
401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixed dx = x;
404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkFixed dy = y;
405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (int i = 0; i < 17; i++) {
407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dx >>= 1;
408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        dy >>= 1;
409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        U32 len2 = squarefixed(x) + squarefixed(y);
411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (len2 >> 28) {
412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x -= dx;
413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            y -= dy;
414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        } else {
415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += dx;
416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            y += dy;
417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x >>= 14;
420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    y >>= 14;
421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUGx    // measure how far we are from unit-length
423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    {
424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        static int gMaxError;
425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        static int gMaxDiff;
426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkFixed len = fixlen(x, y);
428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int err = len - SK_Fixed1;
429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        err = SkAbs32(err);
430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (err > gMaxError) {
432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            gMaxError = err;
433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkDebugf("gMaxError %d\n", err);
434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        float fx = SkAbs32(ox)/65536.0f;
437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        float fy = SkAbs32(oy)/65536.0f;
438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        float mag = sqrtf(fx*fx + fy*fy);
439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fx /= mag;
440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fy /= mag;
441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkFixed xx = (int)floorf(fx * 65536 + 0.5f);
442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkFixed yy = (int)floorf(fy * 65536 + 0.5f);
443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y));
444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (err > gMaxDiff) {
445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            gMaxDiff = err;
446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkDebugf("gMaxDiff %d\n", err);
447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    x = SkApplySign(x, SkExtractSign(ox));
452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    y = SkApplySign(y, SkExtractSign(oy));
453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (length != SK_Fixed1) {
454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x = SkFixedMul(x, length);
455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y = SkFixedMul(y, length);
456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
457935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    this->set(x, y);
459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return true;
460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
46598a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com///////////////////////////////////////////////////////////////////////////////
46698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com
46794fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.comSkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
46894fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com                                           const SkPoint& b,
46994fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com                                           Side* side) const {
47094fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com
47194fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    SkVector u = b - a;
47294fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    SkVector v = *this - a;
473935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
47494fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    SkScalar uLengthSqd = u.lengthSqd();
47594fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    SkScalar det = u.cross(v);
47694fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    if (NULL != side) {
47794fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com        SkASSERT(-1 == SkPoint::kLeft_Side &&
47894fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com                  0 == SkPoint::kOn_Side &&
47994fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com                  1 == kRight_Side);
48094fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com        *side = (Side) SkScalarSignAsInt(det);
48194fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    }
48294fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com    return SkScalarMulDiv(det, det, uLengthSqd);
48394fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com}
48494fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.com
48594fb6900ae582251ee637f46d47702e9e0f38ef7bsalomon@google.comSkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
48698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com                                                  const SkPoint& b) const {
48798a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    // See comments to distanceToLineBetweenSqd. If the projection of c onto
488935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // u is between a and b then this returns the same result as that
48998a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    // function. Otherwise, it returns the distance to the closer of a and
49098a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    // b. Let the projection of v onto u be v'.  There are three cases:
49198a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //    1. v' points opposite to u. c is not between a and b and is closer
49298a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //       to a than b.
49398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //    2. v' points along u and has magnitude less than y. c is between
49498a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //       a and b and the distance to the segment is the same as distance
49598a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //       to the line ab.
49698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //    3. v' points along u and has greater magnitude than u. c is not
49798a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    //       not between a and b and is closer to b than a.
498935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
49998a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
500935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
50198a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    // avoid a sqrt to compute |u|.
502935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
50398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkVector u = b - a;
50498a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkVector v = *this - a;
505935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
50698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkScalar uLengthSqd = u.lengthSqd();
50798a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    SkScalar uDotV = SkPoint::DotProduct(u, v);
508935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
50998a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    if (uDotV <= 0) {
51098a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com        return v.lengthSqd();
51198a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    } else if (uDotV > uLengthSqd) {
51298a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com        return b.distanceToSqd(*this);
51398a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    } else {
51498a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com        SkScalar det = u.cross(v);
51598a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com        return SkScalarMulDiv(det, det, uLengthSqd);
51698a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com    }
51798a5211c4b27cf865eade6696ce3cf5ff8b95bafreed@google.com}
518