LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkPoint.h (source / functions) Hit Total Coverage
Test: output.info Lines: 61 130 46.9 %
Date: 2017-07-14 16:53:18 Functions: 28 48 58.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkPoint_DEFINED
       9             : #define SkPoint_DEFINED
      10             : 
      11             : #include "SkMath.h"
      12             : #include "SkScalar.h"
      13             : 
      14             : /** \struct SkIPoint16
      15             : 
      16             :     SkIPoint holds two 16 bit integer coordinates
      17             : */
      18             : struct SkIPoint16 {
      19             :     int16_t fX, fY;
      20             : 
      21           0 :     static SkIPoint16 Make(int x, int y) {
      22             :         SkIPoint16 pt;
      23           0 :         pt.set(x, y);
      24           0 :         return pt;
      25             :     }
      26             : 
      27             :     int16_t x() const { return fX; }
      28             :     int16_t y() const { return fY; }
      29             : 
      30           0 :     void set(int x, int y) {
      31           0 :         fX = SkToS16(x);
      32           0 :         fY = SkToS16(y);
      33           0 :     }
      34             : };
      35             : 
      36             : /** \struct SkIPoint
      37             : 
      38             :     SkIPoint holds two 32 bit integer coordinates
      39             : */
      40             : struct SkIPoint {
      41             :     int32_t fX, fY;
      42             : 
      43           0 :     static SkIPoint Make(int32_t x, int32_t y) {
      44             :         SkIPoint pt;
      45           0 :         pt.set(x, y);
      46           0 :         return pt;
      47             :     }
      48             : 
      49        1228 :     int32_t x() const { return fX; }
      50        1228 :     int32_t y() const { return fY; }
      51             :     void setX(int32_t x) { fX = x; }
      52             :     void setY(int32_t y) { fY = y; }
      53             : 
      54             :     /**
      55             :      *  Returns true iff fX and fY are both zero.
      56             :      */
      57          19 :     bool isZero() const { return (fX | fY) == 0; }
      58             : 
      59             :     /**
      60             :      *  Set both fX and fY to zero. Same as set(0, 0)
      61             :      */
      62         826 :     void setZero() { fX = fY = 0; }
      63             : 
      64             :     /** Set the x and y values of the point. */
      65         627 :     void set(int32_t x, int32_t y) { fX = x; fY = y; }
      66             : 
      67             :     /** Rotate the point clockwise, writing the new point into dst
      68             :         It is legal for dst == this
      69             :     */
      70             :     void rotateCW(SkIPoint* dst) const;
      71             : 
      72             :     /** Rotate the point clockwise, writing the new point back into the point
      73             :     */
      74             : 
      75             :     void rotateCW() { this->rotateCW(this); }
      76             : 
      77             :     /** Rotate the point counter-clockwise, writing the new point into dst.
      78             :         It is legal for dst == this
      79             :     */
      80             :     void rotateCCW(SkIPoint* dst) const;
      81             : 
      82             :     /** Rotate the point counter-clockwise, writing the new point back into
      83             :         the point
      84             :     */
      85             :     void rotateCCW() { this->rotateCCW(this); }
      86             : 
      87             :     /** Negate the X and Y coordinates of the point.
      88             :     */
      89             :     void negate() { fX = -fX; fY = -fY; }
      90             : 
      91             :     /** Return a new point whose X and Y coordinates are the negative of the
      92             :         original point's
      93             :     */
      94           0 :     SkIPoint operator-() const {
      95             :         SkIPoint neg;
      96           0 :         neg.fX = -fX;
      97           0 :         neg.fY = -fY;
      98           0 :         return neg;
      99             :     }
     100             : 
     101             :     /** Add v's coordinates to this point's */
     102             :     void operator+=(const SkIPoint& v) {
     103             :         fX += v.fX;
     104             :         fY += v.fY;
     105             :     }
     106             : 
     107             :     /** Subtract v's coordinates from this point's */
     108             :     void operator-=(const SkIPoint& v) {
     109             :         fX -= v.fX;
     110             :         fY -= v.fY;
     111             :     }
     112             : 
     113             :     /** Returns true if the point's coordinates equal (x,y) */
     114             :     bool equals(int32_t x, int32_t y) const {
     115             :         return fX == x && fY == y;
     116             :     }
     117             : 
     118           0 :     friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
     119           0 :         return a.fX == b.fX && a.fY == b.fY;
     120             :     }
     121             : 
     122             :     friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
     123             :         return a.fX != b.fX || a.fY != b.fY;
     124             :     }
     125             : 
     126             :     /** Returns a new point whose coordinates are the difference between
     127             :         a and b (i.e. a - b)
     128             :     */
     129             :     friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
     130             :         SkIPoint v;
     131             :         v.set(a.fX - b.fX, a.fY - b.fY);
     132             :         return v;
     133             :     }
     134             : 
     135             :     /** Returns a new point whose coordinates are the sum of a and b (a + b)
     136             :     */
     137             :     friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
     138             :         SkIPoint v;
     139             :         v.set(a.fX + b.fX, a.fY + b.fY);
     140             :         return v;
     141             :     }
     142             : 
     143             :     /** Returns the dot product of a and b, treating them as 2D vectors
     144             :     */
     145             :     static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
     146             :         return a.fX * b.fX + a.fY * b.fY;
     147             :     }
     148             : 
     149             :     /** Returns the cross product of a and b, treating them as 2D vectors
     150             :     */
     151             :     static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
     152             :         return a.fX * b.fY - a.fY * b.fX;
     153             :     }
     154             : };
     155             : 
     156             : struct SK_API SkPoint {
     157             :     SkScalar    fX, fY;
     158             : 
     159         523 :     static SkPoint Make(SkScalar x, SkScalar y) {
     160             :         SkPoint pt;
     161         523 :         pt.set(x, y);
     162         523 :         return pt;
     163             :     }
     164             : 
     165        3723 :     SkScalar x() const { return fX; }
     166        3146 :     SkScalar y() const { return fY; }
     167             : 
     168             :     /**
     169             :      *  Returns true iff fX and fY are both zero.
     170             :      */
     171           0 :     bool isZero() const { return (0 == fX) & (0 == fY); }
     172             : 
     173             :     /** Set the point's X and Y coordinates */
     174        7036 :     void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
     175             : 
     176             :     /** Set the point's X and Y coordinates by automatically promoting (x,y) to
     177             :         SkScalar values.
     178             :     */
     179             :     void iset(int32_t x, int32_t y) {
     180             :         fX = SkIntToScalar(x);
     181             :         fY = SkIntToScalar(y);
     182             :     }
     183             : 
     184             :     /** Set the point's X and Y coordinates by automatically promoting p's
     185             :         coordinates to SkScalar values.
     186             :     */
     187             :     void iset(const SkIPoint& p) {
     188             :         fX = SkIntToScalar(p.fX);
     189             :         fY = SkIntToScalar(p.fY);
     190             :     }
     191             : 
     192           0 :     void setAbs(const SkPoint& pt) {
     193           0 :         fX = SkScalarAbs(pt.fX);
     194           0 :         fY = SkScalarAbs(pt.fY);
     195           0 :     }
     196             : 
     197             :     // counter-clockwise fan
     198             :     void setIRectFan(int l, int t, int r, int b) {
     199             :         SkPoint* v = this;
     200             :         v[0].set(SkIntToScalar(l), SkIntToScalar(t));
     201             :         v[1].set(SkIntToScalar(l), SkIntToScalar(b));
     202             :         v[2].set(SkIntToScalar(r), SkIntToScalar(b));
     203             :         v[3].set(SkIntToScalar(r), SkIntToScalar(t));
     204             :     }
     205             :     void setIRectFan(int l, int t, int r, int b, size_t stride);
     206             : 
     207             :     // counter-clockwise fan
     208           0 :     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b) {
     209           0 :         SkPoint* v = this;
     210           0 :         v[0].set(l, t);
     211           0 :         v[1].set(l, b);
     212           0 :         v[2].set(r, b);
     213           0 :         v[3].set(r, t);
     214           0 :     }
     215             : 
     216           0 :     void setRectFan(SkScalar l, SkScalar t, SkScalar r, SkScalar b, size_t stride) {
     217           0 :         SkASSERT(stride >= sizeof(SkPoint));
     218             :         
     219           0 :         ((SkPoint*)((intptr_t)this + 0 * stride))->set(l, t);
     220           0 :         ((SkPoint*)((intptr_t)this + 1 * stride))->set(l, b);
     221           0 :         ((SkPoint*)((intptr_t)this + 2 * stride))->set(r, b);
     222           0 :         ((SkPoint*)((intptr_t)this + 3 * stride))->set(r, t);
     223           0 :     }
     224             :     
     225             : 
     226             :     static void Offset(SkPoint points[], int count, const SkPoint& offset) {
     227             :         Offset(points, count, offset.fX, offset.fY);
     228             :     }
     229             : 
     230             :     static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {
     231             :         for (int i = 0; i < count; ++i) {
     232             :             points[i].offset(dx, dy);
     233             :         }
     234             :     }
     235             : 
     236           0 :     void offset(SkScalar dx, SkScalar dy) {
     237           0 :         fX += dx;
     238           0 :         fY += dy;
     239           0 :     }
     240             : 
     241             :     /** Return the euclidian distance from (0,0) to the point
     242             :     */
     243          50 :     SkScalar length() const { return SkPoint::Length(fX, fY); }
     244             :     SkScalar distanceToOrigin() const { return this->length(); }
     245             : 
     246             :     /**
     247             :      *  Return true if the computed length of the vector is >= the internal
     248             :      *  tolerance (used to avoid dividing by tiny values).
     249             :      */
     250          48 :     static bool CanNormalize(SkScalar dx, SkScalar dy) {
     251             :         // Simple enough (and performance critical sometimes) so we inline it.
     252          48 :         return (dx*dx + dy*dy) > (SK_ScalarNearlyZero * SK_ScalarNearlyZero);
     253             :     }
     254             : 
     255             :     bool canNormalize() const {
     256             :         return CanNormalize(fX, fY);
     257             :     }
     258             : 
     259             :     /** Set the point (vector) to be unit-length in the same direction as it
     260             :         already points.  If the point has a degenerate length (i.e. nearly 0)
     261             :         then set it to (0,0) and return false; otherwise return true.
     262             :     */
     263             :     bool normalize();
     264             : 
     265             :     /** Set the point (vector) to be unit-length in the same direction as the
     266             :         x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
     267             :         then set it to (0,0) and return false, otherwise return true.
     268             :     */
     269             :     bool setNormalize(SkScalar x, SkScalar y);
     270             : 
     271             :     /** Scale the point (vector) to have the specified length, and return that
     272             :         length. If the original length is degenerately small (nearly zero),
     273             :         set it to (0,0) and return false, otherwise return true.
     274             :     */
     275             :     bool setLength(SkScalar length);
     276             : 
     277             :     /** Set the point (vector) to have the specified length in the same
     278             :      direction as (x,y). If the vector (x,y) has a degenerate length
     279             :      (i.e. nearly 0) then set it to (0,0) and return false, otherwise return true.
     280             :     */
     281             :     bool setLength(SkScalar x, SkScalar y, SkScalar length);
     282             : 
     283             :     /** Same as setLength, but favoring speed over accuracy.
     284             :     */
     285             :     bool setLengthFast(SkScalar length);
     286             : 
     287             :     /** Same as setLength, but favoring speed over accuracy.
     288             :     */
     289             :     bool setLengthFast(SkScalar x, SkScalar y, SkScalar length);
     290             : 
     291             :     /** Scale the point's coordinates by scale, writing the answer into dst.
     292             :         It is legal for dst == this.
     293             :     */
     294             :     void scale(SkScalar scale, SkPoint* dst) const;
     295             : 
     296             :     /** Scale the point's coordinates by scale, writing the answer back into
     297             :         the point.
     298             :     */
     299          25 :     void scale(SkScalar value) { this->scale(value, this); }
     300             : 
     301             :     /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
     302             :         It is legal for dst == this.
     303             :     */
     304             :     void rotateCW(SkPoint* dst) const;
     305             : 
     306             :     /** Rotate the point clockwise by 90 degrees, writing the answer back into
     307             :         the point.
     308             :     */
     309             :     void rotateCW() { this->rotateCW(this); }
     310             : 
     311             :     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
     312             :         into dst. It is legal for dst == this.
     313             :     */
     314             :     void rotateCCW(SkPoint* dst) const;
     315             : 
     316             :     /** Rotate the point counter-clockwise by 90 degrees, writing the answer
     317             :         back into the point.
     318             :     */
     319          37 :     void rotateCCW() { this->rotateCCW(this); }
     320             : 
     321             :     /** Negate the point's coordinates
     322             :     */
     323           0 :     void negate() {
     324           0 :         fX = -fX;
     325           0 :         fY = -fY;
     326           0 :     }
     327             : 
     328             :     /** Returns a new point whose coordinates are the negative of the point's
     329             :     */
     330          13 :     SkPoint operator-() const {
     331             :         SkPoint neg;
     332          13 :         neg.fX = -fX;
     333          13 :         neg.fY = -fY;
     334          13 :         return neg;
     335             :     }
     336             : 
     337             :     /** Add v's coordinates to the point's
     338             :     */
     339         422 :     void operator+=(const SkPoint& v) {
     340         422 :         fX += v.fX;
     341         422 :         fY += v.fY;
     342         422 :     }
     343             : 
     344             :     /** Subtract v's coordinates from the point's
     345             :     */
     346         422 :     void operator-=(const SkPoint& v) {
     347         422 :         fX -= v.fX;
     348         422 :         fY -= v.fY;
     349         422 :     }
     350             : 
     351           0 :     SkPoint operator*(SkScalar scale) const {
     352           0 :         return Make(fX * scale, fY * scale);
     353             :     }
     354             :     
     355           0 :     SkPoint& operator*=(SkScalar scale) {
     356           0 :         fX *= scale;
     357           0 :         fY *= scale;
     358           0 :         return *this;
     359             :     }
     360             :     
     361             :     /**
     362             :      *  Returns true if both X and Y are finite (not infinity or NaN)
     363             :      */
     364      152331 :     bool isFinite() const {
     365      152331 :         SkScalar accum = 0;
     366      152331 :         accum *= fX;
     367      152331 :         accum *= fY;
     368             : 
     369             :         // accum is either NaN or it is finite (zero).
     370      152331 :         SkASSERT(0 == accum || SkScalarIsNaN(accum));
     371             : 
     372             :         // value==value will be true iff value is not NaN
     373             :         // TODO: is it faster to say !accum or accum==accum?
     374      152331 :         return !SkScalarIsNaN(accum);
     375             :     }
     376             : 
     377             :     /**
     378             :      *  Returns true if the point's coordinates equal (x,y)
     379             :      */
     380             :     bool equals(SkScalar x, SkScalar y) const {
     381             :         return fX == x && fY == y;
     382             :     }
     383             : 
     384         816 :     friend bool operator==(const SkPoint& a, const SkPoint& b) {
     385         816 :         return a.fX == b.fX && a.fY == b.fY;
     386             :     }
     387             : 
     388         627 :     friend bool operator!=(const SkPoint& a, const SkPoint& b) {
     389         627 :         return a.fX != b.fX || a.fY != b.fY;
     390             :     }
     391             : 
     392             :     /** Return true if this point and the given point are far enough apart
     393             :         such that a vector between them would be non-degenerate.
     394             : 
     395             :         WARNING: Unlike the explicit tolerance version,
     396             :         this method does not use componentwise comparison.  Instead, it
     397             :         uses a comparison designed to match judgments elsewhere regarding
     398             :         degeneracy ("points A and B are so close that the vector between them
     399             :         is essentially zero").
     400             :     */
     401           0 :     bool equalsWithinTolerance(const SkPoint& p) const {
     402           0 :         return !CanNormalize(fX - p.fX, fY - p.fY);
     403             :     }
     404             : 
     405             :     /** WARNING: There is no guarantee that the result will reflect judgments
     406             :         elsewhere regarding degeneracy ("points A and B are so close that the
     407             :         vector between them is essentially zero").
     408             :     */
     409          21 :     bool equalsWithinTolerance(const SkPoint& p, SkScalar tol) const {
     410          21 :         return SkScalarNearlyZero(fX - p.fX, tol)
     411          21 :                && SkScalarNearlyZero(fY - p.fY, tol);
     412             :     }
     413             : 
     414             :     /** Returns a new point whose coordinates are the difference between
     415             :         a's and b's (a - b)
     416             :     */
     417        1238 :     friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
     418             :         SkPoint v;
     419        1238 :         v.set(a.fX - b.fX, a.fY - b.fY);
     420        1238 :         return v;
     421             :     }
     422             : 
     423             :     /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
     424             :     */
     425         448 :     friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
     426             :         SkPoint v;
     427         448 :         v.set(a.fX + b.fX, a.fY + b.fY);
     428         448 :         return v;
     429             :     }
     430             : 
     431             :     /** Returns the euclidian distance from (0,0) to (x,y)
     432             :     */
     433             :     static SkScalar Length(SkScalar x, SkScalar y);
     434             : 
     435             :     /** Normalize pt, returning its previous length. If the prev length is too
     436             :         small (degenerate), set pt to (0,0) and return 0. This uses the same
     437             :         tolerance as CanNormalize.
     438             : 
     439             :         Note that this method may be significantly more expensive than
     440             :         the non-static normalize(), because it has to return the previous length
     441             :         of the point.  If you don't need the previous length, call the
     442             :         non-static normalize() method instead.
     443             :      */
     444             :     static SkScalar Normalize(SkPoint* pt);
     445             : 
     446             :     /** Returns the euclidian distance between a and b
     447             :     */
     448           0 :     static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
     449           0 :         return Length(a.fX - b.fX, a.fY - b.fY);
     450             :     }
     451             : 
     452             :     /** Returns the dot product of a and b, treating them as 2D vectors
     453             :     */
     454        1981 :     static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
     455        1981 :         return a.fX * b.fX + a.fY * b.fY;
     456             :     }
     457             : 
     458             :     /** Returns the cross product of a and b, treating them as 2D vectors
     459             :     */
     460        1030 :     static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
     461        1030 :         return a.fX * b.fY - a.fY * b.fX;
     462             :     }
     463             : 
     464          96 :     SkScalar cross(const SkPoint& vec) const {
     465          96 :         return CrossProduct(*this, vec);
     466             :     }
     467             : 
     468         347 :     SkScalar dot(const SkPoint& vec) const {
     469         347 :         return DotProduct(*this, vec);
     470             :     }
     471             : 
     472        1618 :     SkScalar lengthSqd() const {
     473        1618 :         return DotProduct(*this, *this);
     474             :     }
     475             : 
     476          24 :     SkScalar distanceToSqd(const SkPoint& pt) const {
     477          24 :         SkScalar dx = fX - pt.fX;
     478          24 :         SkScalar dy = fY - pt.fY;
     479          24 :         return dx * dx + dy * dy;
     480             :     }
     481             : 
     482             :     /**
     483             :      * The side of a point relative to a line. If the line is from a to b then
     484             :      * the values are consistent with the sign of (b-a) cross (pt-a)
     485             :      */
     486             :     enum Side {
     487             :         kLeft_Side  = -1,
     488             :         kOn_Side    =  0,
     489             :         kRight_Side =  1
     490             :     };
     491             : 
     492             :     /**
     493             :      * Returns the squared distance to the infinite line between two pts. Also
     494             :      * optionally returns the side of the line that the pt falls on (looking
     495             :      * along line from a to b)
     496             :      */
     497             :     SkScalar distanceToLineBetweenSqd(const SkPoint& a,
     498             :                                       const SkPoint& b,
     499             :                                       Side* side = NULL) const;
     500             : 
     501             :     /**
     502             :      * Returns the distance to the infinite line between two pts. Also
     503             :      * optionally returns the side of the line that the pt falls on (looking
     504             :      * along the line from a to b)
     505             :      */
     506           0 :     SkScalar distanceToLineBetween(const SkPoint& a,
     507             :                                    const SkPoint& b,
     508             :                                    Side* side = NULL) const {
     509           0 :         return SkScalarSqrt(this->distanceToLineBetweenSqd(a, b, side));
     510             :     }
     511             : 
     512             :     /**
     513             :      * Returns the squared distance to the line segment between pts a and b
     514             :      */
     515             :     SkScalar distanceToLineSegmentBetweenSqd(const SkPoint& a,
     516             :                                              const SkPoint& b) const;
     517             : 
     518             :     /**
     519             :      * Returns the distance to the line segment between pts a and b.
     520             :      */
     521           0 :     SkScalar distanceToLineSegmentBetween(const SkPoint& a,
     522             :                                           const SkPoint& b) const {
     523           0 :         return SkScalarSqrt(this->distanceToLineSegmentBetweenSqd(a, b));
     524             :     }
     525             : 
     526             :     /**
     527             :      * Make this vector be orthogonal to vec. Looking down vec the
     528             :      * new vector will point in direction indicated by side (which
     529             :      * must be kLeft_Side or kRight_Side).
     530             :      */
     531           0 :     void setOrthog(const SkPoint& vec, Side side = kLeft_Side) {
     532             :         // vec could be this
     533           0 :         SkScalar tmp = vec.fX;
     534           0 :         if (kRight_Side == side) {
     535           0 :             fX = -vec.fY;
     536           0 :             fY = tmp;
     537             :         } else {
     538           0 :             SkASSERT(kLeft_Side == side);
     539           0 :             fX = vec.fY;
     540           0 :             fY = -tmp;
     541             :         }
     542           0 :     }
     543             : 
     544             :     /**
     545             :      *  cast-safe way to treat the point as an array of (2) SkScalars.
     546             :      */
     547           0 :     const SkScalar* asScalars() const { return &fX; }
     548             : };
     549             : 
     550             : typedef SkPoint SkVector;
     551             : 
     552           0 : static inline bool SkPointsAreFinite(const SkPoint array[], int count) {
     553           0 :     return SkScalarsAreFinite(&array[0].fX, count << 1);
     554             : }
     555             : 
     556             : #endif

Generated by: LCOV version 1.13