diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/pathops/SkPathOpsPoint.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/pathops/SkPathOpsPoint.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,213 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef SkPathOpsPoint_DEFINED +#define SkPathOpsPoint_DEFINED + +#include "SkPathOpsTypes.h" +#include "SkPoint.h" + +inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) { + return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY); +} + +struct SkDVector { + double fX, fY; + + friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b); + + void operator+=(const SkDVector& v) { + fX += v.fX; + fY += v.fY; + } + + void operator-=(const SkDVector& v) { + fX -= v.fX; + fY -= v.fY; + } + + void operator/=(const double s) { + fX /= s; + fY /= s; + } + + void operator*=(const double s) { + fX *= s; + fY *= s; + } + + SkVector asSkVector() const { + SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; + return v; + } + + double cross(const SkDVector& a) const { + return fX * a.fY - fY * a.fX; + } + + double dot(const SkDVector& a) const { + return fX * a.fX + fY * a.fY; + } + + double length() const { + return sqrt(lengthSquared()); + } + + double lengthSquared() const { + return fX * fX + fY * fY; + } +}; + +struct SkDPoint { + double fX; + double fY; + + void set(const SkPoint& pt) { + fX = pt.fX; + fY = pt.fY; + } + + friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b); + + friend bool operator==(const SkDPoint& a, const SkDPoint& b) { + return a.fX == b.fX && a.fY == b.fY; + } + + friend bool operator!=(const SkDPoint& a, const SkDPoint& b) { + return a.fX != b.fX || a.fY != b.fY; + } + + void operator=(const SkPoint& pt) { + fX = pt.fX; + fY = pt.fY; + } + + + void operator+=(const SkDVector& v) { + fX += v.fX; + fY += v.fY; + } + + void operator-=(const SkDVector& v) { + fX -= v.fX; + fY -= v.fY; + } + + // note: this can not be implemented with + // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX); + // because that will not take the magnitude of the values into account + bool approximatelyEqual(const SkDPoint& a) const { + if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) { + return true; + } + if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) { + return false; + } + double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? + double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); + double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); + largest = SkTMax(largest, -tiniest); + return AlmostBequalUlps(largest, largest + dist); // is the dist within ULPS tolerance? + } + + bool approximatelyEqual(const SkPoint& a) const { + SkDPoint dA; + dA.set(a); + return approximatelyEqual(dA); + } + + static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) { + if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) { + return true; + } + if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) { + return false; + } + SkDPoint dA, dB; + dA.set(a); + dB.set(b); + double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ? + float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY); + float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY); + largest = SkTMax(largest, -tiniest); + return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance? + } + + bool approximatelyPEqual(const SkDPoint& a) const { + if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) { + return true; + } + if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) { + return false; + } + double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? + double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); + double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); + largest = SkTMax(largest, -tiniest); + return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance? + } + + bool approximatelyZero() const { + return approximately_zero(fX) && approximately_zero(fY); + } + + SkPoint asSkPoint() const { + SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)}; + return pt; + } + + double distance(const SkDPoint& a) const { + SkDVector temp = *this - a; + return temp.length(); + } + + double distanceSquared(const SkDPoint& a) const { + SkDVector temp = *this - a; + return temp.lengthSquared(); + } + + static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) { + SkDPoint result; + result.fX = (a.fX + b.fX) / 2; + result.fY = (a.fY + b.fY) / 2; + return result; + } + + bool moreRoughlyEqual(const SkDPoint& a) const { + if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) { + return true; + } + double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ? + double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY); + double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY); + largest = SkTMax(largest, -tiniest); + return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? + } + + bool roughlyEqual(const SkDPoint& a) const { + return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX); + } + + #ifdef SK_DEBUG + void dump() { + SkDebugf("{"); + DebugDumpDouble(fX); + SkDebugf(", "); + DebugDumpDouble(fY); + SkDebugf("}"); + } + + static void dump(const SkPoint& pt) { + SkDebugf("{"); + DebugDumpFloat(pt.fX); + SkDebugf(", "); + DebugDumpFloat(pt.fY); + SkDebugf("}"); + } + #endif +}; + +#endif