2008-12-17 15:59:43 +00:00
|
|
|
/*
|
2011-07-28 14:26:00 +00:00
|
|
|
* Copyright 2006 The Android Open Source Project
|
2008-12-17 15:59:43 +00:00
|
|
|
*
|
2011-07-28 14:26:00 +00:00
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SkPoint_DEFINED
|
|
|
|
#define SkPoint_DEFINED
|
|
|
|
|
2011-09-27 18:03:23 +00:00
|
|
|
#include "SkMath.h"
|
2008-12-17 15:59:43 +00:00
|
|
|
#include "SkScalar.h"
|
|
|
|
|
2014-06-02 17:20:14 +00:00
|
|
|
/** \struct SkIPoint16
|
|
|
|
|
|
|
|
SkIPoint holds two 16 bit integer coordinates
|
|
|
|
*/
|
|
|
|
struct SkIPoint16 {
|
2017-11-03 12:06:09 +00:00
|
|
|
int16_t fX;
|
|
|
|
int16_t fY;
|
2014-06-02 17:20:14 +00:00
|
|
|
|
2017-11-08 16:44:31 +00:00
|
|
|
static constexpr SkIPoint16 Make(int x, int y) {
|
|
|
|
return {SkToS16(x), SkToS16(y)};
|
2014-06-02 17:20:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int16_t x() const { return fX; }
|
|
|
|
int16_t y() const { return fY; }
|
|
|
|
|
|
|
|
void set(int x, int y) {
|
|
|
|
fX = SkToS16(x);
|
|
|
|
fY = SkToS16(y);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-11-09 21:03:40 +00:00
|
|
|
struct SkIPoint;
|
|
|
|
typedef SkIPoint SkIVector;
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** \struct SkIPoint
|
|
|
|
|
|
|
|
SkIPoint holds two 32 bit integer coordinates
|
|
|
|
*/
|
|
|
|
struct SkIPoint {
|
2017-11-03 12:06:09 +00:00
|
|
|
int32_t fX;
|
|
|
|
int32_t fY;
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2017-11-08 16:44:31 +00:00
|
|
|
static constexpr SkIPoint Make(int32_t x, int32_t y) {
|
|
|
|
return {x, y};
|
2010-01-28 21:34:33 +00:00
|
|
|
}
|
2008-12-17 15:59:43 +00:00
|
|
|
|
2011-03-04 22:27:10 +00:00
|
|
|
int32_t x() const { return fX; }
|
|
|
|
int32_t y() const { return fY; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true iff fX and fY are both zero.
|
|
|
|
*/
|
|
|
|
bool isZero() const { return (fX | fY) == 0; }
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the x and y values of the point. */
|
2017-11-08 16:44:31 +00:00
|
|
|
void set(int32_t x, int32_t y) {
|
|
|
|
fX = x;
|
|
|
|
fY = y;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Return a new point whose X and Y coordinates are the negative of the
|
|
|
|
original point's
|
|
|
|
*/
|
|
|
|
SkIPoint operator-() const {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {-fX, -fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Add v's coordinates to this point's */
|
2017-11-09 21:03:40 +00:00
|
|
|
void operator+=(const SkIVector& v) {
|
2008-12-17 15:59:43 +00:00
|
|
|
fX += v.fX;
|
|
|
|
fY += v.fY;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Subtract v's coordinates from this point's */
|
2017-11-09 21:03:40 +00:00
|
|
|
void operator-=(const SkIVector& v) {
|
2008-12-17 15:59:43 +00:00
|
|
|
fX -= v.fX;
|
|
|
|
fY -= v.fY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns true if the point's coordinates equal (x,y) */
|
|
|
|
bool equals(int32_t x, int32_t y) const {
|
|
|
|
return fX == x && fY == y;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
|
|
|
|
return a.fX == b.fX && a.fY == b.fY;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
|
|
|
|
return a.fX != b.fX || a.fY != b.fY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a new point whose coordinates are the difference between
|
|
|
|
a and b (i.e. a - b)
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
friend SkIVector operator-(const SkIPoint& a, const SkIPoint& b) {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {a.fX - b.fX, a.fY - b.fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a new point whose coordinates are the sum of a and b (a + b)
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
friend SkIPoint operator+(const SkIPoint& a, const SkIVector& b) {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {a.fX + b.fX, a.fY + b.fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-11-09 21:03:40 +00:00
|
|
|
struct SkPoint;
|
|
|
|
typedef SkPoint SkVector;
|
|
|
|
|
2011-03-15 21:27:08 +00:00
|
|
|
struct SK_API SkPoint {
|
2017-11-03 12:06:09 +00:00
|
|
|
SkScalar fX;
|
|
|
|
SkScalar fY;
|
2008-12-17 15:59:43 +00:00
|
|
|
|
2017-11-08 16:44:31 +00:00
|
|
|
static constexpr SkPoint Make(SkScalar x, SkScalar y) {
|
|
|
|
return {x, y};
|
2010-01-28 21:34:33 +00:00
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2011-03-20 20:19:16 +00:00
|
|
|
SkScalar x() const { return fX; }
|
|
|
|
SkScalar y() const { return fY; }
|
|
|
|
|
2012-05-29 01:40:15 +00:00
|
|
|
/**
|
|
|
|
* Returns true iff fX and fY are both zero.
|
|
|
|
*/
|
|
|
|
bool isZero() const { return (0 == fX) & (0 == fY); }
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the point's X and Y coordinates */
|
2017-11-08 16:44:31 +00:00
|
|
|
void set(SkScalar x, SkScalar y) {
|
|
|
|
fX = x;
|
|
|
|
fY = y;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the point's X and Y coordinates by automatically promoting (x,y) to
|
|
|
|
SkScalar values.
|
|
|
|
*/
|
|
|
|
void iset(int32_t x, int32_t y) {
|
|
|
|
fX = SkIntToScalar(x);
|
|
|
|
fY = SkIntToScalar(y);
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the point's X and Y coordinates by automatically promoting p's
|
|
|
|
coordinates to SkScalar values.
|
|
|
|
*/
|
|
|
|
void iset(const SkIPoint& p) {
|
|
|
|
fX = SkIntToScalar(p.fX);
|
|
|
|
fY = SkIntToScalar(p.fY);
|
|
|
|
}
|
|
|
|
|
2011-05-06 19:26:26 +00:00
|
|
|
void setAbs(const SkPoint& pt) {
|
|
|
|
fX = SkScalarAbs(pt.fX);
|
|
|
|
fY = SkScalarAbs(pt.fY);
|
|
|
|
}
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2017-11-09 21:03:40 +00:00
|
|
|
static void Offset(SkPoint points[], int count, const SkVector& offset) {
|
2011-09-12 14:59:34 +00:00
|
|
|
Offset(points, count, offset.fX, offset.fY);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
points[i].offset(dx, dy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-06 19:26:26 +00:00
|
|
|
void offset(SkScalar dx, SkScalar dy) {
|
|
|
|
fX += dx;
|
|
|
|
fY += dy;
|
|
|
|
}
|
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Return the euclidian distance from (0,0) to the point
|
|
|
|
*/
|
|
|
|
SkScalar length() const { return SkPoint::Length(fX, fY); }
|
2011-05-06 19:26:26 +00:00
|
|
|
SkScalar distanceToOrigin() const { return this->length(); }
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
/** Set the point (vector) to be unit-length in the same direction as it
|
2011-06-15 18:04:58 +00:00
|
|
|
already points. If the point has a degenerate length (i.e. nearly 0)
|
2014-12-09 19:50:32 +00:00
|
|
|
then set it to (0,0) and return false; otherwise return true.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
bool normalize();
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the point (vector) to be unit-length in the same direction as the
|
|
|
|
x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
|
2014-12-09 19:50:32 +00:00
|
|
|
then set it to (0,0) and return false, otherwise return true.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
bool setNormalize(SkScalar x, SkScalar y);
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Scale the point (vector) to have the specified length, and return that
|
|
|
|
length. If the original length is degenerately small (nearly zero),
|
2014-12-09 19:50:32 +00:00
|
|
|
set it to (0,0) and return false, otherwise return true.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
bool setLength(SkScalar length);
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Set the point (vector) to have the specified length in the same
|
|
|
|
direction as (x,y). If the vector (x,y) has a degenerate length
|
2014-12-09 19:50:32 +00:00
|
|
|
(i.e. nearly 0) then set it to (0,0) and return false, otherwise return true.
|
2008-12-17 15:59:43 +00:00
|
|
|
*/
|
|
|
|
bool setLength(SkScalar x, SkScalar y, SkScalar length);
|
|
|
|
|
|
|
|
/** Scale the point's coordinates by scale, writing the answer into dst.
|
|
|
|
It is legal for dst == this.
|
|
|
|
*/
|
|
|
|
void scale(SkScalar scale, SkPoint* dst) const;
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Scale the point's coordinates by scale, writing the answer back into
|
|
|
|
the point.
|
|
|
|
*/
|
2009-01-15 14:38:33 +00:00
|
|
|
void scale(SkScalar value) { this->scale(value, this); }
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
/** Negate the point's coordinates
|
|
|
|
*/
|
|
|
|
void negate() {
|
|
|
|
fX = -fX;
|
|
|
|
fY = -fY;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Returns a new point whose coordinates are the negative of the point's
|
|
|
|
*/
|
|
|
|
SkPoint operator-() const {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {-fX, -fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Add v's coordinates to the point's
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
void operator+=(const SkVector& v) {
|
2008-12-17 15:59:43 +00:00
|
|
|
fX += v.fX;
|
|
|
|
fY += v.fY;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Subtract v's coordinates from the point's
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
void operator-=(const SkVector& v) {
|
2008-12-17 15:59:43 +00:00
|
|
|
fX -= v.fX;
|
|
|
|
fY -= v.fY;
|
|
|
|
}
|
|
|
|
|
2015-05-12 17:37:34 +00:00
|
|
|
SkPoint operator*(SkScalar scale) const {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {fX * scale, fY * scale};
|
2015-05-12 17:37:34 +00:00
|
|
|
}
|
2017-10-09 19:45:33 +00:00
|
|
|
|
2015-05-12 17:37:34 +00:00
|
|
|
SkPoint& operator*=(SkScalar scale) {
|
|
|
|
fX *= scale;
|
|
|
|
fY *= scale;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-10-09 19:45:33 +00:00
|
|
|
|
2012-07-26 15:20:36 +00:00
|
|
|
/**
|
|
|
|
* Returns true if both X and Y are finite (not infinity or NaN)
|
|
|
|
*/
|
|
|
|
bool isFinite() const {
|
|
|
|
SkScalar accum = 0;
|
|
|
|
accum *= fX;
|
|
|
|
accum *= fY;
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2012-07-26 15:20:36 +00:00
|
|
|
// accum is either NaN or it is finite (zero).
|
2014-12-15 20:08:47 +00:00
|
|
|
SkASSERT(0 == accum || SkScalarIsNaN(accum));
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2012-07-26 15:20:36 +00:00
|
|
|
// value==value will be true iff value is not NaN
|
|
|
|
// TODO: is it faster to say !accum or accum==accum?
|
2014-12-15 20:08:47 +00:00
|
|
|
return !SkScalarIsNaN(accum);
|
2012-07-26 15:20:36 +00:00
|
|
|
}
|
|
|
|
|
2013-01-28 22:36:34 +00:00
|
|
|
/**
|
|
|
|
* Returns true if the point's coordinates equal (x,y)
|
|
|
|
*/
|
|
|
|
bool equals(SkScalar x, SkScalar y) const {
|
|
|
|
return fX == x && fY == y;
|
|
|
|
}
|
2008-12-17 15:59:43 +00:00
|
|
|
|
|
|
|
friend bool operator==(const SkPoint& a, const SkPoint& b) {
|
|
|
|
return a.fX == b.fX && a.fY == b.fY;
|
|
|
|
}
|
2011-03-04 22:27:10 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
friend bool operator!=(const SkPoint& a, const SkPoint& b) {
|
|
|
|
return a.fX != b.fX || a.fY != b.fY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a new point whose coordinates are the difference between
|
|
|
|
a's and b's (a - b)
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
friend SkVector operator-(const SkPoint& a, const SkPoint& b) {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {a.fX - b.fX, a.fY - b.fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a new point whose coordinates are the sum of a's and b's (a + b)
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
friend SkPoint operator+(const SkPoint& a, const SkVector& b) {
|
2017-11-08 16:44:31 +00:00
|
|
|
return {a.fX + b.fX, a.fY + b.fY};
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the euclidian distance from (0,0) to (x,y)
|
|
|
|
*/
|
|
|
|
static SkScalar Length(SkScalar x, SkScalar y);
|
2010-01-28 21:34:33 +00:00
|
|
|
|
|
|
|
/** Normalize pt, returning its previous length. If the prev length is too
|
2014-12-09 19:50:32 +00:00
|
|
|
small (degenerate), set pt to (0,0) and return 0. This uses the same
|
2011-09-07 12:23:41 +00:00
|
|
|
tolerance as CanNormalize.
|
2011-06-15 18:04:58 +00:00
|
|
|
|
|
|
|
Note that this method may be significantly more expensive than
|
|
|
|
the non-static normalize(), because it has to return the previous length
|
|
|
|
of the point. If you don't need the previous length, call the
|
|
|
|
non-static normalize() method instead.
|
2010-01-28 21:34:33 +00:00
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
static SkScalar Normalize(SkVector* vec);
|
2010-01-28 21:34:33 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
/** Returns the euclidian distance between a and b
|
|
|
|
*/
|
|
|
|
static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
|
|
|
|
return Length(a.fX - b.fX, a.fY - b.fY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the dot product of a and b, treating them as 2D vectors
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
static SkScalar DotProduct(const SkVector& a, const SkVector& b) {
|
2014-01-27 13:41:02 +00:00
|
|
|
return a.fX * b.fX + a.fY * b.fY;
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the cross product of a and b, treating them as 2D vectors
|
|
|
|
*/
|
2017-11-09 21:03:40 +00:00
|
|
|
static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {
|
2014-01-27 13:41:02 +00:00
|
|
|
return a.fX * b.fY - a.fY * b.fX;
|
2008-12-17 15:59:43 +00:00
|
|
|
}
|
2011-05-06 19:26:26 +00:00
|
|
|
|
2017-11-09 21:03:40 +00:00
|
|
|
SkScalar cross(const SkVector& vec) const {
|
2011-05-06 19:26:26 +00:00
|
|
|
return CrossProduct(*this, vec);
|
|
|
|
}
|
|
|
|
|
2017-11-09 21:03:40 +00:00
|
|
|
SkScalar dot(const SkVector& vec) const {
|
2011-05-06 19:26:26 +00:00
|
|
|
return DotProduct(*this, vec);
|
|
|
|
}
|
2012-08-23 18:09:54 +00:00
|
|
|
|
2008-12-17 15:59:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|