SkPoint.cpp revision 80bacfeb4bda06541e8695bd502229727bccfea
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#ifdef SK_SCALAR_IS_FLOAT
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Returns the square of the Euclidian distance to (dx,dy).
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline float getLengthSquared(float dx, float dy) {
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dx * dx + dy * dy;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This logic is encapsulated in a helper method to make it explicit that we
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// always perform this check in the same manner, to avoid inconsistencies
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (see http://code.google.com/p/skia/issues/detail?id=560 ).
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool isLengthNearlyZero(float dx, float dy,
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      float *lengthSquared) {
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *lengthSquared = getLengthSquared(dx, dy);
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *lengthSquared <= (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Normalize(SkPoint* pt) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float mag2;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) {
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float mag = sk_float_sqrt(mag2);
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float scale = 1.0f / mag;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt->fX = pt->fX * scale;
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt->fY = pt->fY * scale;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return mag;
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sk_float_sqrt(getLengthSquared(dx, dy));
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setLength(float x, float y, float length) {
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float mag2;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!isLengthNearlyZero(x, y, &mag2)) {
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float scale = length / sk_float_sqrt(mag2);
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fX = x * scale;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fY = y * scale;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "Sk64.h"
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Returns the square of the Euclidian distance to (dx,dy) in *result.
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void getLengthSquared(SkScalar dx, SkScalar dy, Sk64 *result) {
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64    dySqr;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    result->setMul(dx, dx);
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dySqr.setMul(dy, dy);
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    result->add(dySqr);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Calculates the square of the Euclidian distance to (dx,dy) and stores it in
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// *lengthSquared.  Returns true if the distance is judged to be "nearly zero".
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// This logic is encapsulated in a helper method to make it explicit that we
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// always perform this check in the same manner, to avoid inconsistencies
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (see http://code.google.com/p/skia/issues/detail?id=560 ).
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline bool isLengthNearlyZero(SkScalar dx, SkScalar dy,
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                      Sk64 *lengthSquared) {
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64 tolSqr;
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    getLengthSquared(dx, dy, lengthSquared);
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we want nearlyzero^2, but to compute it fast we want to just do a
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // 32bit multiply, so we require that it not exceed 31bits. That is true
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if nearlyzero is <= 0xB504, which should be trivial, since usually
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // nearlyzero is a very small fixed-point value.
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SK_ScalarNearlyZero <= 0xB504);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    tolSqr.set(0, SK_ScalarNearlyZero * SK_ScalarNearlyZero);
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *lengthSquared <= tolSqr;
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Normalize(SkPoint* pt) {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64 mag2;
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!isLengthNearlyZero(pt->fX, pt->fY, &mag2)) {
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar mag = mag2.getSqrt();
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar scale = SkScalarInvert(mag);
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt->fX = SkScalarMul(pt->fX, scale);
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        pt->fY = SkScalarMul(pt->fY, scale);
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return mag;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::CanNormalize(SkScalar dx, SkScalar dy) {
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64 mag2_unused;
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return !isLengthNearlyZero(dx, dy, &mag2_unused);
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Sk64    tmp;
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    getLengthSquared(dx, dy, &tmp);
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return tmp.getSqrt();
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUGx
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkFixed fixlen(SkFixed x, SkFixed y) {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float fx = (float)x;
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    float fy = (float)y;
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return (int)floorf(sqrtf(fx*fx + fy*fy) + 0.5f);
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t squarefixed(unsigned x) {
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x >>= 16;
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return x*x;
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 1   // Newton iter for setLength
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned invsqrt_iter(unsigned V, unsigned U) {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned x = V * U >> 14;
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x = x * U >> 14;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x = (3 << 14) - x;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x = (U >> 1) * x >> 14;
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return x;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const uint16_t gInvSqrt14GuessTable[] = {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x4000, 0x3c57, 0x393e, 0x3695, 0x3441, 0x3235, 0x3061,
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x2ebd, 0x2d41, 0x2be7, 0x2aaa, 0x2987, 0x287a, 0x2780,
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x2698, 0x25be, 0x24f3, 0x2434, 0x2380, 0x22d6, 0x2235,
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x219d, 0x210c, 0x2083, 0x2000, 0x1f82, 0x1f0b, 0x1e99,
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x1e2b, 0x1dc2, 0x1d5d, 0x1cfc, 0x1c9f, 0x1c45, 0x1bee,
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x1b9b, 0x1b4a, 0x1afc, 0x1ab0, 0x1a67, 0x1a20, 0x19dc,
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x1999, 0x1959, 0x191a, 0x18dd, 0x18a2, 0x1868, 0x1830,
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    0x17fa, 0x17c4, 0x1791, 0x175e, 0x172d, 0x16fd, 0x16ce
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define BUILD_INVSQRT_TABLEx
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef BUILD_INVSQRT_TABLE
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void build_invsqrt14_guess_table() {
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 8; i <= 63; i++) {
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned x = SkToU16((1 << 28) / SkSqrt32(i << 25));
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        printf("0x%x, ", x);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    printf("\n");
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic unsigned fast_invsqrt(uint32_t x) {
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef BUILD_INVSQRT_TABLE
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned top2 = x >> 25;
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(top2 >= 8 && top2 <= 63);
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static bool gOnce;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!gOnce) {
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        build_invsqrt14_guess_table();
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        gOnce = true;
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned V = x >> 14;   // make V .14
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned top = x >> 25;
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(top >= 8 && top <= 63);
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(top - 8 < SK_ARRAY_COUNT(gInvSqrt14GuessTable));
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned U = gInvSqrt14GuessTable[top - 8];
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    U = invsqrt_iter(V, U);
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return invsqrt_iter(V, U);
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*  We "normalize" x,y to be .14 values (so we can square them and stay 32bits.
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Then we Newton-iterate this in .14 space to compute the invser-sqrt, and
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    scale by it at the end. The .14 space means we can execute our iterations
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    and stay in 32bits as well, making the multiplies much cheaper than calling
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixedMul.
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ox == 0) {
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (oy == 0) {
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->set(0, SkApplySign(length, SkExtractSign(oy)));
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (oy == 0) {
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->set(SkApplySign(length, SkExtractSign(ox)), 0);
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned x = SkAbs32(ox);
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned y = SkAbs32(oy);
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int zeros = SkCLZ(x | y);
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // make x,y 1.14 values so our fast sqr won't overflow
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (zeros > 17) {
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x <<= zeros - 17;
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y <<= zeros - 17;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x >>= 17 - zeros;
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y >>= 17 - zeros;
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((x | y) <= 0x7FFF);
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned invrt = fast_invsqrt(x*x + y*y);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x = x * invrt >> 12;
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y = y * invrt >> 12;
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (length != SK_Fixed1) {
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x = SkFixedMul(x, length);
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y = SkFixedMul(y, length);
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->set(SkApplySign(x, SkExtractSign(ox)),
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru              SkApplySign(y, SkExtractSign(oy)));
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Normalize x,y, and then scale them by length.
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    The obvious way to do this would be the following:
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        S64 tmp1, tmp2;
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.setMul(x,x);
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp2.setMul(y,y);
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tmp1.add(tmp2);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        len = tmp1.getSqrt();
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x' = SkFixedDiv(x, len);
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y' = SkFixedDiv(y, len);
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    This is fine, but slower than what we do below.
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    The present technique does not compute the starting length, but
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    rather fiddles with x,y iteratively, all the while checking its
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    magnitude^2 (avoiding a sqrt).
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    We normalize by first shifting x,y so that at least one of them
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    has bit 31 set (after taking the abs of them).
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Then we loop, refining x,y by squaring them and comparing
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    against a very large 1.0 (1 << 28), and then adding or subtracting
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    a delta (which itself is reduced by half each time through the loop).
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    For speed we want the squaring to be with a simple integer mul. To keep
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    that from overflowing we shift our coordinates down until we are dealing
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    with at most 15 bits (2^15-1)^2 * 2 says withing 32 bits)
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    When our square is close to 1.0, we shift x,y down into fixed range.
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkPoint::setLength(SkFixed ox, SkFixed oy, SkFixed length) {
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (ox == 0) {
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (oy == 0)
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->set(0, SkApplySign(length, SkExtractSign(oy)));
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (oy == 0) {
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->set(SkApplySign(length, SkExtractSign(ox)), 0);
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed x = SkAbs32(ox);
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed y = SkAbs32(oy);
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // shift x,y so that the greater of them is 15bits (1.14 fixed point)
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int shift = SkCLZ(x | y);
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // make them .30
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x <<= shift - 1;
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y <<= shift - 1;
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed dx = x;
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkFixed dy = y;
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < 17; i++) {
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dx >>= 1;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dy >>= 1;
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        U32 len2 = squarefixed(x) + squarefixed(y);
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (len2 >> 28) {
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x -= dx;
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            y -= dy;
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            x += dx;
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            y += dy;
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x >>= 14;
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y >>= 14;
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUGx    // measure how far we are from unit-length
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static int gMaxError;
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        static int gMaxDiff;
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed len = fixlen(x, y);
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int err = len - SK_Fixed1;
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        err = SkAbs32(err);
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (err > gMaxError) {
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            gMaxError = err;
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("gMaxError %d\n", err);
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float fx = SkAbs32(ox)/65536.0f;
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float fy = SkAbs32(oy)/65536.0f;
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float mag = sqrtf(fx*fx + fy*fy);
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fx /= mag;
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fy /= mag;
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed xx = (int)floorf(fx * 65536 + 0.5f);
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkFixed yy = (int)floorf(fy * 65536 + 0.5f);
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        err = SkMax32(SkAbs32(xx-x), SkAbs32(yy-y));
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (err > gMaxDiff) {
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            gMaxDiff = err;
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("gMaxDiff %d\n", err);
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    x = SkApplySign(x, SkExtractSign(ox));
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    y = SkApplySign(y, SkExtractSign(oy));
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (length != SK_Fixed1) {
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        x = SkFixedMul(x, length);
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        y = SkFixedMul(y, length);
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->set(x, y);
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::distanceToLineBetweenSqd(const SkPoint& a,
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           const SkPoint& b,
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                           Side* side) const {
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector u = b - a;
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector v = *this - a;
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uLengthSqd = u.lengthSqd();
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar det = u.cross(v);
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != side) {
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(-1 == SkPoint::kLeft_Side &&
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  0 == SkPoint::kOn_Side &&
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                  1 == kRight_Side);
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *side = (Side) SkScalarSignAsInt(det);
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkScalarMulDiv(det, det, uLengthSqd);
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a,
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                  const SkPoint& b) const {
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // See comments to distanceToLineBetweenSqd. If the projection of c onto
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // u is between a and b then this returns the same result as that
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // function. Otherwise, it returns the distance to the closer of a and
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // b. Let the projection of v onto u be v'.  There are three cases:
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    1. v' points opposite to u. c is not between a and b and is closer
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       to a than b.
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    2. v' points along u and has magnitude less than y. c is between
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       a and b and the distance to the segment is the same as distance
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       to the line ab.
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //    3. v' points along u and has greater magnitude than u. c is not
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //       not between a and b and is closer to b than a.
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // v' = (u dot v) * u / |u|. So if (u dot v)/|u| is less than zero we're
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // in case 1. If (u dot v)/|u| is > |u| we are in case 3. Otherwise
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // we're in case 2. We actually compare (u dot v) to 0 and |u|^2 to
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // avoid a sqrt to compute |u|.
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector u = b - a;
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkVector v = *this - a;
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uLengthSqd = u.lengthSqd();
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkScalar uDotV = SkPoint::DotProduct(u, v);
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (uDotV <= 0) {
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return v.lengthSqd();
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (uDotV > uLengthSqd) {
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return b.distanceToSqd(*this);
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkScalar det = u.cross(v);
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkScalarMulDiv(det, det, uLengthSqd);
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
474