180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2008 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPoint.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkIPoint::rotateCW(SkIPoint* dst) const {
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst);
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // use a tmp in case this == dst
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int32_t tmp = fX;
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fX = -fY;
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fY = tmp;
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkIPoint::rotateCCW(SkIPoint* dst) const {
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst);
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // use a tmp in case this == dst
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int32_t tmp = fX;
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fX = fY;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fY = -tmp;
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPoint::setIRectFan(int l, int t, int r, int b, size_t stride) {
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(stride >= sizeof(SkPoint));
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 0 * stride))->set(SkIntToScalar(l),
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   SkIntToScalar(t));
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 1 * stride))->set(SkIntToScalar(l),
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   SkIntToScalar(b));
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 2 * stride))->set(SkIntToScalar(r),
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   SkIntToScalar(b));
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 3 * stride))->set(SkIntToScalar(r),
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                   SkIntToScalar(t));
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPoint::setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b,
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                         size_t stride) {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(stride >= sizeof(SkPoint));
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t);
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b);
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t);
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPoint::rotateCW(SkPoint* dst) const {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // use a tmp in case this == dst
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar tmp = fX;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fX = -fY;
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fY = tmp;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPoint::rotateCCW(SkPoint* dst) const {
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst);
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // use a tmp in case this == dst
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar tmp = fX;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fX = fY;
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->fY = -tmp;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkPoint::scale(SkScalar scale, SkPoint* dst) const {
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst);
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale));
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::normalize() {
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->setLength(fX, fY, SK_Scalar1);
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setNormalize(SkScalar x, SkScalar y) {
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->setLength(x, y, SK_Scalar1);
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setLength(SkScalar length) {
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->setLength(fX, fY, length);
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Returns the square of the Euclidian distance to (dx,dy).
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline float getLengthSquared(float dx, float dy) {
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dx * dx + dy * dy;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This logic is encapsulated in a helper method to make it explicit that we
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// always perform this check in the same manner, to avoid inconsistencies
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (see http://code.google.com/p/skia/issues/detail?id=560 ).
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool isLengthNearlyZero(float dx, float dy,
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      float *lengthSquared) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *lengthSquared = getLengthSquared(dx, dy);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Normalize(SkPoint* pt) {
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    float x = pt->fX;
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    float y = pt->fY;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float mag2;
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (isLengthNearlyZero(x, y, &mag2)) {
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return 0;
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    float mag, scale;
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (SkScalarIsFinite(mag2)) {
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        mag = sk_float_sqrt(mag2);
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        scale = 1 / mag;
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // our mag2 step overflowed to infinity, so use doubles instead.
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // much slower, but needed when x or y are very large, other wise we
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // divide by inf. and return (0,0) vector.
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double xx = x;
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double yy = y;
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double magmag = sqrt(xx * xx + yy * yy);
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        mag = (float)magmag;
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // we perform the divide with the double magmag, to stay exactly the
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // same as setLength. It would be faster to perform the divide with
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // mag, but it is possible that mag has overflowed to inf. but still
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // have a non-zero value for scale (thanks to denormalized numbers).
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        scale = (float)(1 / magmag);
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    pt->set(x * scale, y * scale);
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return mag;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    float mag2 = dx * dx + dy * dy;
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (SkScalarIsFinite(mag2)) {
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return sk_float_sqrt(mag2);
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double xx = dx;
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double yy = dy;
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return (float)sqrt(xx * xx + yy * yy);
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  We have to worry about 2 tricky conditions:
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  1. underflow of mag2 (compared against nearlyzero^2)
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  2. overflow of mag2 (compared w/ isfinite)
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  If we underflow, we return false. If we overflow, we compute again using
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *  doubles, which is much slower (3x in a desktop test) but will not overflow.
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setLength(float x, float y, float length) {
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float mag2;
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (isLengthNearlyZero(x, y, &mag2)) {
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return false;
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    float scale;
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (SkScalarIsFinite(mag2)) {
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        scale = length / sk_float_sqrt(mag2);
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    } else {
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // our mag2 step overflowed to infinity, so use doubles instead.
1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // much slower, but needed when x or y are very large, other wise we
1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        // divide by inf. and return (0,0) vector.
1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double xx = x;
1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        double yy = y;
1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        scale = (float)(length / sqrt(xx * xx + yy * yy));
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fX = x * scale;
1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fY = y * scale;
1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return true;
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
178910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerbool SkPoint::setLengthFast(float length) {
179910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    return this->setLengthFast(fX, fY, length);
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
182910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerbool SkPoint::setLengthFast(float x, float y, float length) {
183910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    float mag2;
184910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (isLengthNearlyZero(x, y, &mag2)) {
185910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        return false;
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
188910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    float scale;
189910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    if (SkScalarIsFinite(mag2)) {
190910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        scale = length * sk_float_rsqrt(mag2);  // <--- this is the difference
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
192910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // our mag2 step overflowed to infinity, so use doubles instead.
193910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // much slower, but needed when x or y are very large, other wise we
194910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        // divide by inf. and return (0,0) vector.
195910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        double xx = x;
196910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        double yy = y;
197910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        scale = (float)(length / sqrt(xx * xx + yy * yy));
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
199910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    fX = x * scale;
200910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    fY = y * scale;
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           const SkPoint& b,
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           Side* side) const {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector u = b - a;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector v = *this - a;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uLengthSqd = u.lengthSqd();
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar det = u.cross(v);
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != side) {
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(-1 == SkPoint::kLeft_Side &&
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  0 == SkPoint::kOn_Side &&
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  1 == kRight_Side);
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *side = (Side) SkScalarSignAsInt(det);
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkScalarMulDiv(det, det, uLengthSqd);
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                  const SkPoint& b) const {
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // See comments to distanceToLineBetweenSqd. If the projection of c onto
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // u is between a and b then this returns the same result as that
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // function. Otherwise, it returns the distance to the closer of a and
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // b. Let the projection of v onto u be v'.  There are three cases:
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    1. v' points opposite to u. c is not between a and b and is closer
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       to a than b.
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    2. v' points along u and has magnitude less than y. c is between
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       a and b and the distance to the segment is the same as distance
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       to the line ab.
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    3. v' points along u and has greater magnitude than u. c is not
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       not between a and b and is closer to b than a.
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // avoid a sqrt to compute |u|.
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector u = b - a;
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector v = *this - a;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uLengthSqd = u.lengthSqd();
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uDotV = SkPoint::DotProduct(u, v);
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (uDotV <= 0) {
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return v.lengthSqd();
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (uDotV > uLengthSqd) {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return b.distanceToSqd(*this);
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar det = u.cross(v);
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkScalarMulDiv(det, det, uLengthSqd);
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
258