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