107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#ifndef SkPathOpsPoint_DEFINED
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#define SkPathOpsPoint_DEFINED
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathOpsTypes.h"
1107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPoint.h"
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
13a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.cominline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
14a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY);
15a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com}
16a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstruct SkDVector {
184431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double fX;
194431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double fY;
204431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
214431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void set(const SkVector& pt) {
224431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        fX = pt.fX;
234431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        fY = pt.fY;
244431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b);
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator+=(const SkDVector& v) {
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX += v.fX;
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY += v.fY;
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator-=(const SkDVector& v) {
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX -= v.fX;
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY -= v.fY;
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator/=(const double s) {
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX /= s;
4007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY /= s;
4107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
4207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator*=(const double s) {
4407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX *= s;
4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY *= s;
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkVector asSkVector() const {
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return v;
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double cross(const SkDVector& a) const {
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fX * a.fY - fY * a.fX;
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // similar to cross, this bastardization considers nearly coincident to be zero
584431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    double crossCheck(const SkDVector& a) const {
594431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        double xy = fX * a.fY;
604431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        double yx = fY * a.fX;
614431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return AlmostEqualUlps(xy, yx) ? 0 : xy - yx;
624431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
634431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double dot(const SkDVector& a) const {
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fX * a.fX + fY * a.fY;
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double length() const {
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return sqrt(lengthSquared());
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double lengthSquared() const {
7307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return fX * fX + fY * fY;
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comstruct SkDPoint {
7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double fX;
7907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double fY;
8007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void set(const SkPoint& pt) {
8207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX = pt.fX;
8307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY = pt.fY;
8407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b);
8707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    friend bool operator==(const SkDPoint& a, const SkDPoint& b) {
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return a.fX == b.fX && a.fY == b.fY;
9007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    friend bool operator!=(const SkDPoint& a, const SkDPoint& b) {
9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return a.fX != b.fX || a.fY != b.fY;
9407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator=(const SkPoint& pt) {
9707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX = pt.fX;
9807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY = pt.fY;
9907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
10007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator+=(const SkDVector& v) {
10207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX += v.fX;
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY += v.fY;
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
10507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    void operator-=(const SkDVector& v) {
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fX -= v.fX;
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fY -= v.fY;
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // note: this can not be implemented with
11207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
113a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    // because that will not take the magnitude of the values into account
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool approximatelyEqual(const SkDPoint& a) const {
1157eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            return true;
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1187eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
1197eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com            return false;
1207eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        }
1217eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
1227eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
1237eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
1247eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        largest = SkTMax(largest, -tiniest);
1257eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        return AlmostBequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool approximatelyEqual(const SkPoint& a) const {
1297eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        SkDPoint dA;
1307eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        dA.set(a);
1317eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        return approximatelyEqual(dA);
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1347eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
1357eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            return true;
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        }
1387eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) {
1397eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com            return false;
1407eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        }
1417eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        SkDPoint dA, dB;
1427eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        dA.set(a);
1437eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        dB.set(b);
1447eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double dist = dA.distance(dB);  // OPTIMIZATION: can we compare against distSq instead ?
1457eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY);
1467eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY);
1477eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        largest = SkTMax(largest, -tiniest);
1487eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
14907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1514431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
1524431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
1534431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return true;
1544431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1554431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return RoughlyEqualUlps(a.fX, b.fX) && RoughlyEqualUlps(a.fY, b.fY);
1564431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1574431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
158a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    bool approximatelyPEqual(const SkDPoint& a) const {
159a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
160a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com            return true;
161a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        }
162a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
163a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com            return false;
164a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        }
165a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
166a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
167a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
168a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        largest = SkTMax(largest, -tiniest);
169a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com        return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
170a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com    }
171a2bbc6e19d5332e81784e582c290cc060f40c4c7caryclark@google.com
1724431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    bool approximatelyDEqual(const SkDPoint& a) const {
1734431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
1744431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return true;
1754431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1764431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
1774431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org            return false;
1784431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        }
1794431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
1804431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
1814431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
1824431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        largest = SkTMax(largest, -tiniest);
1834431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org        return AlmostDequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
1844431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    }
1854431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org
18607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool approximatelyZero() const {
18707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return approximately_zero(fX) && approximately_zero(fY);
18807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
18907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
19007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkPoint asSkPoint() const {
19107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
19207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return pt;
19307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
19507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double distance(const SkDPoint& a) const {
19607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDVector temp = *this - a;
19707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return temp.length();
19807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
19907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
20007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    double distanceSquared(const SkDPoint& a) const {
20107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDVector temp = *this - a;
20207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return temp.lengthSquared();
20307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
20407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
205cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) {
206cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        SkDPoint result;
207cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        result.fX = (a.fX + b.fX) / 2;
208cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        result.fY = (a.fY + b.fY) / 2;
209cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com        return result;
210cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com    }
211cffbcc3b9665f2c928544b6fc6b8a0e22a4210fbcaryclark@google.com
2127eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    bool moreRoughlyEqual(const SkDPoint& a) const {
2137eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) {
2147eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com            return true;
2157eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        }
2167eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
2177eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
2187eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
2197eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        largest = SkTMax(largest, -tiniest);
2207eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com        return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance?
22107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
22207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
2237eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    bool roughlyEqual(const SkDPoint& a) const {
22407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
22507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
226570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
2274431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // utilities callable by the user from the debugger when the implementation code is linked in
2284431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    void dump() const;
2294431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    static void Dump(const SkPoint& pt);
23007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com};
23107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
23207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
233