18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkPoint_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPoint_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11c12e1b138e736f70d698f14a3ffc74af6f3d8621tomhudson@google.com#include "SkMath.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalar.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips/** \struct SkIPoint16
15d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips
16d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    SkIPoint holds two 16 bit integer coordinates
17d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips*/
18d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillipsstruct SkIPoint16 {
19d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    int16_t fX, fY;
20d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips
21d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    static SkIPoint16 Make(int x, int y) {
22d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips        SkIPoint16 pt;
23d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips        pt.set(x, y);
24d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips        return pt;
25d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    }
26d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips
27d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    int16_t x() const { return fX; }
28d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    int16_t y() const { return fY; }
29d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips
30d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    void set(int x, int y) {
31d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips        fX = SkToS16(x);
32d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips        fY = SkToS16(y);
33d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips    }
34d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips};
35d537341e16524d1e22ac5e6c8b9c8f274ba1833crobertphillips
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \struct SkIPoint
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIPoint holds two 32 bit integer coordinates
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkIPoint {
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t fX, fY;
426f8f292aa768869a9e85c314b124875f57504f2creed@google.com
43ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    static SkIPoint Make(int32_t x, int32_t y) {
44ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        SkIPoint pt;
45ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        pt.set(x, y);
46ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        return pt;
47ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
496f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int32_t x() const { return fX; }
506f8f292aa768869a9e85c314b124875f57504f2creed@google.com    int32_t y() const { return fY; }
516f8f292aa768869a9e85c314b124875f57504f2creed@google.com    void setX(int32_t x) { fX = x; }
526f8f292aa768869a9e85c314b124875f57504f2creed@google.com    void setY(int32_t y) { fY = y; }
536f8f292aa768869a9e85c314b124875f57504f2creed@google.com
546f8f292aa768869a9e85c314b124875f57504f2creed@google.com    /**
556f8f292aa768869a9e85c314b124875f57504f2creed@google.com     *  Returns true iff fX and fY are both zero.
566f8f292aa768869a9e85c314b124875f57504f2creed@google.com     */
576f8f292aa768869a9e85c314b124875f57504f2creed@google.com    bool isZero() const { return (fX | fY) == 0; }
586f8f292aa768869a9e85c314b124875f57504f2creed@google.com
596f8f292aa768869a9e85c314b124875f57504f2creed@google.com    /**
606f8f292aa768869a9e85c314b124875f57504f2creed@google.com     *  Set both fX and fY to zero. Same as set(0, 0)
616f8f292aa768869a9e85c314b124875f57504f2creed@google.com     */
626f8f292aa768869a9e85c314b124875f57504f2creed@google.com    void setZero() { fX = fY = 0; }
636f8f292aa768869a9e85c314b124875f57504f2creed@google.com
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the x and y values of the point. */
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void set(int32_t x, int32_t y) { fX = x; fY = y; }
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point clockwise, writing the new point into dst
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        It is legal for dst == this
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCW(SkIPoint* dst) const;
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point clockwise, writing the new point back into the point
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCW() { this->rotateCW(this); }
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point counter-clockwise, writing the new point into dst.
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        It is legal for dst == this
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCCW(SkIPoint* dst) const;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point counter-clockwise, writing the new point back into
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the point
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCCW() { this->rotateCCW(this); }
866f8f292aa768869a9e85c314b124875f57504f2creed@google.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Negate the X and Y coordinates of the point.
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void negate() { fX = -fX; fY = -fY; }
906f8f292aa768869a9e85c314b124875f57504f2creed@google.com
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return a new point whose X and Y coordinates are the negative of the
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        original point's
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIPoint operator-() const {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkIPoint neg;
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        neg.fX = -fX;
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        neg.fY = -fY;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return neg;
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add v's coordinates to this point's */
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void operator+=(const SkIPoint& v) {
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX += v.fX;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY += v.fY;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1066f8f292aa768869a9e85c314b124875f57504f2creed@google.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Subtract v's coordinates from this point's */
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void operator-=(const SkIPoint& v) {
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX -= v.fX;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY -= v.fY;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns true if the point's coordinates equal (x,y) */
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool equals(int32_t x, int32_t y) const {
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fX == x && fY == y;
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX == b.fX && a.fY == b.fY;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1216f8f292aa768869a9e85c314b124875f57504f2creed@google.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX != b.fX || a.fY != b.fY;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a new point whose coordinates are the difference between
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a and b (i.e. a - b)
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkIPoint v;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        v.set(a.fX - b.fX, a.fY - b.fY);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return v;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a new point whose coordinates are the sum of a and b (a + b)
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkIPoint v;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        v.set(a.fX + b.fX, a.fY + b.fY);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return v;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1426f8f292aa768869a9e85c314b124875f57504f2creed@google.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the dot product of a and b, treating them as 2D vectors
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX * b.fX + a.fY * b.fY;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the cross product of a and b, treating them as 2D vectors
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX * b.fY - a.fY * b.fX;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1567ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgstruct SK_API SkPoint {
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar    fX, fY;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    static SkPoint Make(SkScalar x, SkScalar y) {
160ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        SkPoint pt;
161ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        pt.set(x, y);
162ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com        return pt;
163ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    }
1646f8f292aa768869a9e85c314b124875f57504f2creed@google.com
165b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org    SkScalar x() const { return fX; }
166b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org    SkScalar y() const { return fY; }
167b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org
168398b1bcb7d30f9e55504b6de37d31ccc1a26c876mike@reedtribe.org    /**
169398b1bcb7d30f9e55504b6de37d31ccc1a26c876mike@reedtribe.org     *  Returns true iff fX and fY are both zero.
170398b1bcb7d30f9e55504b6de37d31ccc1a26c876mike@reedtribe.org     */
171398b1bcb7d30f9e55504b6de37d31ccc1a26c876mike@reedtribe.org    bool isZero() const { return (0 == fX) & (0 == fY); }
172398b1bcb7d30f9e55504b6de37d31ccc1a26c876mike@reedtribe.org
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point's X and Y coordinates */
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
1756f8f292aa768869a9e85c314b124875f57504f2creed@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point's X and Y coordinates by automatically promoting (x,y) to
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar values.
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void iset(int32_t x, int32_t y) {
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX = SkIntToScalar(x);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY = SkIntToScalar(y);
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1836f8f292aa768869a9e85c314b124875f57504f2creed@google.com
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point's X and Y coordinates by automatically promoting p's
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        coordinates to SkScalar values.
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void iset(const SkIPoint& p) {
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX = SkIntToScalar(p.fX);
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY = SkIntToScalar(p.fY);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1927744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void setAbs(const SkPoint& pt) {
1937744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        fX = SkScalarAbs(pt.fX);
1947744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        fY = SkScalarAbs(pt.fY);
1957744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
196fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1977744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    // counter-clockwise fan
1987744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void setIRectFan(int l, int t, int r, int b) {
1997744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        SkPoint* v = this;
2007744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[0].set(SkIntToScalar(l), SkIntToScalar(t));
2017744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[1].set(SkIntToScalar(l), SkIntToScalar(b));
2027744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[2].set(SkIntToScalar(r), SkIntToScalar(b));
2037744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[3].set(SkIntToScalar(r), SkIntToScalar(t));
2047744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
2057744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void setIRectFan(int l, int t, int r, int b, size_t stride);
2067744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
2077744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    // counter-clockwise fan
2087744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
2097744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        SkPoint* v = this;
2107744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[0].set(l, t);
2117744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[1].set(l, b);
2127744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[2].set(r, b);
2137744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        v[3].set(r, t);
2147744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
2157744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride);
2167744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
217dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com    static void Offset(SkPoint points[], int count, const SkPoint& offset) {
218dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com        Offset(points, count, offset.fX, offset.fY);
219dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com    }
220dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com
221dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com    static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
222dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com        for (int i = 0; i < count; ++i) {
223dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com            points[i].offset(dx, dy);
224dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com        }
225dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com    }
226dbeeac33329f5fd7dbd3514cd7189ca6ed080476bsalomon@google.com
2277744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    void offset(SkScalar dx, SkScalar dy) {
2287744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        fX += dx;
2297744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        fY += dy;
2307744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
2317744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Return the euclidian distance from (0,0) to the point
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar length() const { return SkPoint::Length(fX, fY); }
2357744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    SkScalar distanceToOrigin() const { return this->length(); }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23755b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com    /**
23855b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com     *  Return true if the computed length of the vector is >= the internal
23955b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com     *  tolerance (used to avoid dividing by tiny values).
24055b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com     */
24111e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    static bool CanNormalize(SkScalar dx, SkScalar dy) {
24211e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org        // Simple enough (and performance critical sometimes) so we inline it.
24311e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org        return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
24411e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    }
24555b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com
24655b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com    bool canNormalize() const {
24755b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com        return CanNormalize(fX, fY);
24855b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com    }
24955b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point (vector) to be unit-length in the same direction as it
2511fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        already points.  If the point has a degenerate length (i.e. nearly 0)
2521fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        then return false and do nothing; otherwise return true.
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool normalize();
2556f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point (vector) to be unit-length in the same direction as the
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        then return false and do nothing, otherwise return true.
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool setNormalize(SkScalar x, SkScalar y);
2616f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Scale the point (vector) to have the specified length, and return that
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        length. If the original length is degenerately small (nearly zero),
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        do nothing and return false, otherwise return true.
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool setLength(SkScalar length);
2676f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Set the point (vector) to have the specified length in the same
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     direction as (x,y). If the vector (x,y) has a degenerate length
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     (i.e. nearly 0) then return false and do nothing, otherwise return true.
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool setLength(SkScalar x, SkScalar y, SkScalar length);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27411e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    /** Same as setLength, but favoring speed over accuracy.
27511e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    */
27611e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    bool setLengthFast(SkScalar length);
27711e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org
27811e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    /** Same as setLength, but favoring speed over accuracy.
27911e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    */
28011e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org    bool setLengthFast(SkScalar x, SkScalar y, SkScalar length);
28111e5b972a984c7b4e09ba4dfeacc7bd805107c5acommit-bot@chromium.org
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Scale the point's coordinates by scale, writing the answer into dst.
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        It is legal for dst == this.
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void scale(SkScalar scale, SkPoint* dst) const;
2866f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Scale the point's coordinates by scale, writing the answer back into
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the point.
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
290fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com    void scale(SkScalar value) { this->scale(value, this); }
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        It is legal for dst == this.
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCW(SkPoint* dst) const;
2966f8f292aa768869a9e85c314b124875f57504f2creed@google.com
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point clockwise by 90 degrees, writing the answer back into
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        the point.
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCW() { this->rotateCW(this); }
3016f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        into dst. It is legal for dst == this.
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCCW(SkPoint* dst) const;
3066f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        back into the point.
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void rotateCCW() { this->rotateCCW(this); }
3116f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Negate the point's coordinates
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void negate() {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX = -fX;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY = -fY;
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3186f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a new point whose coordinates are the negative of the point's
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPoint operator-() const {
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint neg;
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        neg.fX = -fX;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        neg.fY = -fY;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return neg;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Add v's coordinates to the point's
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void operator+=(const SkPoint& v) {
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX += v.fX;
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY += v.fY;
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3346f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Subtract v's coordinates from the point's
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void operator-=(const SkPoint& v) {
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX -= v.fX;
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fY -= v.fY;
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3420bb18bb264b26afca45452910437c09445e23a3creed@google.com    /**
3430bb18bb264b26afca45452910437c09445e23a3creed@google.com     *  Returns true if both X and Y are finite (not infinity or NaN)
3440bb18bb264b26afca45452910437c09445e23a3creed@google.com     */
3450bb18bb264b26afca45452910437c09445e23a3creed@google.com    bool isFinite() const {
3460bb18bb264b26afca45452910437c09445e23a3creed@google.com        SkScalar accum = 0;
3470bb18bb264b26afca45452910437c09445e23a3creed@google.com        accum *= fX;
3480bb18bb264b26afca45452910437c09445e23a3creed@google.com        accum *= fY;
349fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3500bb18bb264b26afca45452910437c09445e23a3creed@google.com        // accum is either NaN or it is finite (zero).
3510bb18bb264b26afca45452910437c09445e23a3creed@google.com        SkASSERT(0 == accum || !(accum == accum));
352fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3530bb18bb264b26afca45452910437c09445e23a3creed@google.com        // value==value will be true iff value is not NaN
3540bb18bb264b26afca45452910437c09445e23a3creed@google.com        // TODO: is it faster to say !accum or accum==accum?
3550bb18bb264b26afca45452910437c09445e23a3creed@google.com        return accum == accum;
3560bb18bb264b26afca45452910437c09445e23a3creed@google.com    }
3570bb18bb264b26afca45452910437c09445e23a3creed@google.com
35824d10cb635b002462dc503bf603d3ec487fcb557reed@google.com    /**
35924d10cb635b002462dc503bf603d3ec487fcb557reed@google.com     *  Returns true if the point's coordinates equal (x,y)
36024d10cb635b002462dc503bf603d3ec487fcb557reed@google.com     */
36124d10cb635b002462dc503bf603d3ec487fcb557reed@google.com    bool equals(SkScalar x, SkScalar y) const {
36224d10cb635b002462dc503bf603d3ec487fcb557reed@google.com        return fX == x && fY == y;
36324d10cb635b002462dc503bf603d3ec487fcb557reed@google.com    }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend bool operator==(const SkPoint& a, const SkPoint& b) {
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX == b.fX && a.fY == b.fY;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3686f8f292aa768869a9e85c314b124875f57504f2creed@google.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend bool operator!=(const SkPoint& a, const SkPoint& b) {
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a.fX != b.fX || a.fY != b.fY;
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37394fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com    /** Return true if this point and the given point are far enough apart
37494fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        such that a vector between them would be non-degenerate.
37594fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com
3764469938e92d779dff05e745559e67907bbf21e78reed@google.com        WARNING: Unlike the explicit tolerance version,
37794fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        this method does not use componentwise comparison.  Instead, it
37894fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        uses a comparison designed to match judgments elsewhere regarding
37994fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        degeneracy ("points A and B are so close that the vector between them
38094fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        is essentially zero").
3814da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    */
38294fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com    bool equalsWithinTolerance(const SkPoint& p) const {
38394fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        return !CanNormalize(fX - p.fX, fY - p.fY);
38494fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com    }
38594fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com
3864469938e92d779dff05e745559e67907bbf21e78reed@google.com    /** WARNING: There is no guarantee that the result will reflect judgments
38794fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        elsewhere regarding degeneracy ("points A and B are so close that the
38894fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        vector between them is essentially zero").
38994fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com    */
39094fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com    bool equalsWithinTolerance(const SkPoint& p, SkScalar tol) const {
39194fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com        return SkScalarNearlyZero(fX - p.fX, tol)
39294fa43c6255906660c2ff001fb462b6492cbdc07epoger@google.com               && SkScalarNearlyZero(fY - p.fY, tol);
3934da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org    }
3944da06ab3351f2a96f9216d96106db33a77b19644schenney@chromium.org
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a new point whose coordinates are the difference between
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        a's and b's (a - b)
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint v;
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        v.set(a.fX - b.fX, a.fY - b.fY);
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return v;
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPoint v;
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        v.set(a.fX + b.fX, a.fY + b.fY);
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return v;
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the euclidian distance from (0,0) to (x,y)
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkScalar Length(SkScalar x, SkScalar y);
415ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com
416ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    /** Normalize pt, returning its previous length. If the prev length is too
41755b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com        small (degenerate), return 0 and leave pt unchanged. This uses the same
41855b5f4bd6a69e70feeaf6018171882ab9cd250aereed@google.com        tolerance as CanNormalize.
4191fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com
4201fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        Note that this method may be significantly more expensive than
4211fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        the non-static normalize(), because it has to return the previous length
4221fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        of the point.  If you don't need the previous length, call the
4231fd56dc6e189ea0e94b5df9af959c243573f8883epoger@google.com        non-static normalize() method instead.
424ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com     */
425ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com    static SkScalar Normalize(SkPoint* pt);
426ac753098e8af4a17e5df97b3a4dd0ce123f8d70creed@android.com
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the euclidian distance between a and b
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return Length(a.fX - b.fX, a.fY - b.fY);
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the dot product of a and b, treating them as 2D vectors
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
4361a5e51f94ed8cb01600184119e52bb64bdb3dcccreed@google.com        return a.fX * b.fX + a.fY * b.fY;
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Returns the cross product of a and b, treating them as 2D vectors
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
4421a5e51f94ed8cb01600184119e52bb64bdb3dcccreed@google.com        return a.fX * b.fY - a.fY * b.fX;
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4447744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
4457744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    SkScalar cross(const SkPoint& vec) const {
4467744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        return CrossProduct(*this, vec);
4477744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
4487744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com
4497744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    SkScalar dot(const SkPoint& vec) const {
4507744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        return DotProduct(*this, vec);
4517744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
452fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4537744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    SkScalar lengthSqd() const {
4547744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        return DotProduct(*this, *this);
4557744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
456fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4577744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    SkScalar distanceToSqd(const SkPoint& pt) const {
4587744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        SkScalar dx = fX - pt.fX;
4597744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        SkScalar dy = fY - pt.fY;
4601a5e51f94ed8cb01600184119e52bb64bdb3dcccreed@google.com        return dx * dx + dy * dy;
4617744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
462647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
463647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
464647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * The side of a point relative to a line. If the line is from a to b then
465647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * the values are consistent with the sign of (b-a) cross (pt-a)
466647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
467647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    enum Side {
468647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        kLeft_Side  = -1,
469647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        kOn_Side    =  0,
470647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        kRight_Side =  1
471647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    };
472647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
473647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
474647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * Returns the squared distance to the infinite line between two pts. Also
475647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * optionally returns the side of the line that the pt falls on (looking
476647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * along line from a to b)
477647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
478647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    SkScalar distanceToLineBetweenSqd(const SkPoint& a,
479647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com                                      const SkPoint& b,
480647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com                                      Side* side = NULL) const;
481647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
482647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
483647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * Returns the distance to the infinite line between two pts. Also
484647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * optionally returns the side of the line that the pt falls on (looking
485647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * along the line from a to b)
486647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
487647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    SkScalar distanceToLineBetween(const SkPoint& a,
488647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com                                   const SkPoint& b,
489647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com                                   Side* side = NULL) const {
490647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
491647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    }
492647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
493647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
494647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * Returns the squared distance to the line segment between pts a and b
495647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
496647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
4977744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com                                             const SkPoint& b) const;
498647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
499647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
500647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * Returns the distance to the line segment between pts a and b.
501647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
502647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    SkScalar distanceToLineSegmentBetween(const SkPoint& a,
5037744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com                                          const SkPoint& b) const {
5047744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com        return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
5057744c205f20b5617e83d4af8f97b5771bfa8d671reed@google.com    }
506647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com
507647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    /**
508647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * Make this vector be orthogonal to vec. Looking down vec the
509647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * new vector will point in direction indicated by side (which
510647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     * must be kLeft_Side or kRight_Side).
511647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com     */
512647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
513647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        // vec could be this
514647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        SkScalar tmp = vec.fX;
515278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com        if (kRight_Side == side) {
516647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com            fX = -vec.fY;
517647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com            fY = tmp;
518647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        } else {
519278dc6929b6481204874dcfcc055e2aaa30a95b2bsalomon@google.com            SkASSERT(kLeft_Side == side);
520647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com            fX = vec.fY;
521647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com            fY = -tmp;
522647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com        }
523647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com    }
524c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com
525c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    /**
526c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     *  cast-safe way to treat the point as an array of (2) SkScalars.
527c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com     */
528c7d0ea3cd328566958bfcb86b4488dcbb94dd5ecreed@google.com    const SkScalar* asScalars() const { return &fX; }
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef SkPoint SkVector;
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
534