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