LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/pathops - SkPathOpsTypes.h (source / functions) Hit Total Coverage
Test: output.info Lines: 21 162 13.0 %
Date: 2017-07-14 16:53:18 Functions: 10 67 14.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Google Inc.
       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             : #ifndef SkPathOpsTypes_DEFINED
       8             : #define SkPathOpsTypes_DEFINED
       9             : 
      10             : #include <float.h>  // for FLT_EPSILON
      11             : 
      12             : #include "SkFloatingPoint.h"
      13             : #include "SkPath.h"
      14             : #include "SkPathOps.h"
      15             : #include "SkPathOpsDebug.h"
      16             : #include "SkSafe_math.h"  // for fabs, sqrt
      17             : #include "SkScalar.h"
      18             : 
      19             : enum SkPathOpsMask {
      20             :     kWinding_PathOpsMask = -1,
      21             :     kNo_PathOpsMask = 0,
      22             :     kEvenOdd_PathOpsMask = 1
      23             : };
      24             : 
      25             : class SkArenaAlloc;
      26             : class SkOpCoincidence;
      27             : class SkOpContour;
      28             : class SkOpContourHead;
      29             : class SkIntersections;
      30             : class SkIntersectionHelper;
      31             : 
      32             : enum class SkOpPhase : char {
      33             :     kNoChange,
      34             :     kIntersecting,
      35             :     kWalking,
      36             :     kFixWinding,
      37             : };
      38             : 
      39             : class SkOpGlobalState {
      40             : public:
      41             :     SkOpGlobalState(SkOpContourHead* head,
      42             :                     SkArenaAlloc* allocator SkDEBUGPARAMS(bool debugSkipAssert)
      43             :                     SkDEBUGPARAMS(const char* testName));
      44             : 
      45             :     enum {
      46             :         kMaxWindingTries = 10
      47             :     };
      48             : 
      49           0 :     bool allocatedOpSpan() const {
      50           0 :         return fAllocatedOpSpan;
      51             :     }
      52             : 
      53           0 :     SkArenaAlloc* allocator() {
      54           0 :         return fAllocator;
      55             :     }
      56             : 
      57           0 :     void bumpNested() {
      58           0 :         ++fNested;
      59           0 :     }
      60             : 
      61           0 :     void clearNested() {
      62           0 :         fNested = 0;
      63           0 :     }
      64             : 
      65           0 :     SkOpCoincidence* coincidence() {
      66           0 :         return fCoincidence;
      67             :     }
      68             : 
      69           0 :     SkOpContourHead* contourHead() {
      70           0 :         return fContourHead;
      71             :     }
      72             : 
      73             : #ifdef SK_DEBUG
      74             :     const class SkOpAngle* debugAngle(int id) const;
      75             :     const SkOpCoincidence* debugCoincidence() const;
      76             :     SkOpContour* debugContour(int id) const;
      77             :     const class SkOpPtT* debugPtT(int id) const;
      78             : #endif
      79             : 
      80             :     static bool DebugRunFail();
      81             : 
      82             : #ifdef SK_DEBUG
      83             :     const class SkOpSegment* debugSegment(int id) const;
      84           0 :     bool debugSkipAssert() const { return fDebugSkipAssert; }
      85             :     const class SkOpSpanBase* debugSpan(int id) const;
      86             :     const char* debugTestName() const { return fDebugTestName; }
      87             : #endif
      88             : 
      89             : #if DEBUG_T_SECT_LOOP_COUNT
      90             :     void debugAddLoopCount(SkIntersections* , const SkIntersectionHelper& ,
      91             :         const SkIntersectionHelper& );
      92             :     void debugDoYourWorst(SkOpGlobalState* );
      93             :     void debugLoopReport();
      94             :     void debugResetLoopCounts();
      95             : #endif
      96             : 
      97             : #if DEBUG_COINCIDENCE
      98             :     void debugSetCheckHealth(bool check) { fDebugCheckHealth = check; }
      99             :     bool debugCheckHealth() const { return fDebugCheckHealth; }
     100             : #endif
     101             : 
     102             : #if DEBUG_VALIDATE || DEBUG_COIN
     103             :     void debugSetPhase(const char* funcName  DEBUG_COIN_DECLARE_PARAMS()) const;
     104             : #endif
     105             : 
     106             : #if DEBUG_COIN
     107             :     void debugAddToCoinChangedDict();
     108             :     void debugAddToGlobalCoinDicts();
     109             :     SkPathOpsDebug::CoinDict* debugCoinChangedDict() { return &fCoinChangedDict; }
     110             :     const SkPathOpsDebug::CoinDictEntry& debugCoinDictEntry() const { return fCoinDictEntry; }
     111             : 
     112             :     static void DumpCoinDict();
     113             : #endif
     114             : 
     115             : 
     116           0 :     int nested() const {
     117           0 :         return fNested;
     118             :     }
     119             : 
     120             : #ifdef SK_DEBUG
     121           0 :     int nextAngleID() {
     122           0 :         return ++fAngleID;
     123             :     }
     124             : 
     125             :     int nextCoinID() {
     126             :         return ++fCoinID;
     127             :     }
     128             : 
     129           0 :     int nextContourID() {
     130           0 :         return ++fContourID;
     131             :     }
     132             : 
     133           0 :     int nextPtTID() {
     134           0 :         return ++fPtTID;
     135             :     }
     136             : 
     137           0 :     int nextSegmentID() {
     138           0 :         return ++fSegmentID;
     139             :     }
     140             : 
     141           0 :     int nextSpanID() {
     142           0 :         return ++fSpanID;
     143             :     }
     144             : #endif
     145             : 
     146           0 :     SkOpPhase phase() const {
     147           0 :         return fPhase;
     148             :     }
     149             : 
     150           0 :     void resetAllocatedOpSpan() {
     151           0 :         fAllocatedOpSpan = false;
     152           0 :     }
     153             : 
     154           0 :     void setAllocatedOpSpan() {
     155           0 :         fAllocatedOpSpan = true;
     156           0 :     }
     157             : 
     158           0 :     void setCoincidence(SkOpCoincidence* coincidence) {
     159           0 :         fCoincidence = coincidence;
     160           0 :     }
     161             : 
     162           0 :     void setContourHead(SkOpContourHead* contourHead) {
     163           0 :         fContourHead = contourHead;
     164           0 :     }
     165             : 
     166           0 :     void setPhase(SkOpPhase phase) {
     167           0 :         if (SkOpPhase::kNoChange == phase) {
     168           0 :             return;
     169             :         }
     170           0 :         SkASSERT(fPhase != phase);
     171           0 :         fPhase = phase;
     172             :     }
     173             : 
     174             :     // called in very rare cases where angles are sorted incorrectly -- signfies op will fail
     175           0 :     void setWindingFailed() {
     176           0 :         fWindingFailed = true;
     177           0 :     }
     178             : 
     179             :     bool windingFailed() const {
     180             :         return fWindingFailed;
     181             :     }
     182             : 
     183             : private:
     184             :     SkArenaAlloc* fAllocator;
     185             :     SkOpCoincidence* fCoincidence;
     186             :     SkOpContourHead* fContourHead;
     187             :     int fNested;
     188             :     bool fAllocatedOpSpan;
     189             :     bool fWindingFailed;
     190             :     SkOpPhase fPhase;
     191             : #ifdef SK_DEBUG
     192             :     const char* fDebugTestName;
     193             :     void* fDebugReporter;
     194             :     int fAngleID;
     195             :     int fCoinID;
     196             :     int fContourID;
     197             :     int fPtTID;
     198             :     int fSegmentID;
     199             :     int fSpanID;
     200             :     bool fDebugSkipAssert;
     201             : #endif
     202             : #if DEBUG_T_SECT_LOOP_COUNT
     203             :     int fDebugLoopCount[3];
     204             :     SkPath::Verb fDebugWorstVerb[6];
     205             :     SkPoint fDebugWorstPts[24];
     206             :     float fDebugWorstWeight[6];
     207             : #endif
     208             : #if DEBUG_COIN
     209             :     SkPathOpsDebug::CoinDict fCoinChangedDict;
     210             :     SkPathOpsDebug::CoinDict fCoinVisitedDict;
     211             :     SkPathOpsDebug::CoinDictEntry fCoinDictEntry;
     212             :     const char* fPreviousFuncName;
     213             : #endif
     214             : #if DEBUG_COINCIDENCE
     215             :     bool fDebugCheckHealth;
     216             : #endif
     217             : };
     218             : 
     219             : #ifdef SK_DEBUG
     220             : #if DEBUG_COINCIDENCE
     221             : #define SkOPASSERT(cond) SkASSERT((this->globalState() && \
     222             :         (this->globalState()->debugCheckHealth() || \
     223             :         this->globalState()->debugSkipAssert())) || (cond))
     224             : #else
     225             : #define SkOPASSERT(cond) SkASSERT((this->globalState() && \
     226             :         this->globalState()->debugSkipAssert()) || (cond))
     227             : #endif
     228             : #define SkOPOBJASSERT(obj, cond) SkASSERT((obj->globalState() && \
     229             :         obj->globalState()->debugSkipAssert()) || (cond))
     230             : #else
     231             : #define SkOPASSERT(cond)
     232             : #define SkOPOBJASSERT(obj, cond)
     233             : #endif
     234             : 
     235             : // Use Almost Equal when comparing coordinates. Use epsilon to compare T values.
     236             : bool AlmostEqualUlps(float a, float b);
     237           0 : inline bool AlmostEqualUlps(double a, double b) {
     238           0 :     return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     239             : }
     240             : 
     241             : bool AlmostEqualUlpsNoNormalCheck(float a, float b);
     242           0 : inline bool AlmostEqualUlpsNoNormalCheck(double a, double b) {
     243           0 :     return AlmostEqualUlpsNoNormalCheck(SkDoubleToScalar(a), SkDoubleToScalar(b));
     244             : }
     245             : 
     246             : bool AlmostEqualUlps_Pin(float a, float b);
     247           0 : inline bool AlmostEqualUlps_Pin(double a, double b) {
     248           0 :     return AlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
     249             : }
     250             : 
     251             : // Use Almost Dequal when comparing should not special case denormalized values.
     252             : bool AlmostDequalUlps(float a, float b);
     253             : bool AlmostDequalUlps(double a, double b);
     254             : 
     255             : bool NotAlmostEqualUlps(float a, float b);
     256           0 : inline bool NotAlmostEqualUlps(double a, double b) {
     257           0 :     return NotAlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     258             : }
     259             : 
     260             : bool NotAlmostEqualUlps_Pin(float a, float b);
     261           0 : inline bool NotAlmostEqualUlps_Pin(double a, double b) {
     262           0 :     return NotAlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
     263             : }
     264             : 
     265             : bool NotAlmostDequalUlps(float a, float b);
     266           0 : inline bool NotAlmostDequalUlps(double a, double b) {
     267           0 :     return NotAlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     268             : }
     269             : 
     270             : // Use Almost Bequal when comparing coordinates in conjunction with between.
     271             : bool AlmostBequalUlps(float a, float b);
     272           0 : inline bool AlmostBequalUlps(double a, double b) {
     273           0 :     return AlmostBequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     274             : }
     275             : 
     276             : bool AlmostPequalUlps(float a, float b);
     277           0 : inline bool AlmostPequalUlps(double a, double b) {
     278           0 :     return AlmostPequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     279             : }
     280             : 
     281             : bool RoughlyEqualUlps(float a, float b);
     282           0 : inline bool RoughlyEqualUlps(double a, double b) {
     283           0 :     return RoughlyEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     284             : }
     285             : 
     286             : bool AlmostLessUlps(float a, float b);
     287             : inline bool AlmostLessUlps(double a, double b) {
     288             :     return AlmostLessUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     289             : }
     290             : 
     291             : bool AlmostLessOrEqualUlps(float a, float b);
     292             : inline bool AlmostLessOrEqualUlps(double a, double b) {
     293             :     return AlmostLessOrEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
     294             : }
     295             : 
     296             : bool AlmostBetweenUlps(float a, float b, float c);
     297           0 : inline bool AlmostBetweenUlps(double a, double b, double c) {
     298           0 :     return AlmostBetweenUlps(SkDoubleToScalar(a), SkDoubleToScalar(b), SkDoubleToScalar(c));
     299             : }
     300             : 
     301             : int UlpsDistance(float a, float b);
     302             : inline int UlpsDistance(double a, double b) {
     303             :     return UlpsDistance(SkDoubleToScalar(a), SkDoubleToScalar(b));
     304             : }
     305             : 
     306             : // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
     307             : // DBL_EPSILON == 2.22045e-16
     308             : const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
     309             : const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
     310             : const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2;
     311             : const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16;
     312             : const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
     313             : // Use a compile-time constant for FLT_EPSILON_SQRT to avoid initializers.
     314             : // A 17 digit constant guarantees exact results.
     315             : const double FLT_EPSILON_SQRT = 0.00034526697709225118; // sqrt(FLT_EPSILON);
     316             : const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
     317             : const double DBL_EPSILON_ERR = DBL_EPSILON * 4;  // FIXME: tune -- allow a few bits of error
     318             : const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16;
     319             : const double ROUGH_EPSILON = FLT_EPSILON * 64;
     320             : const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
     321             : const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048;
     322             : const double BUMP_EPSILON = FLT_EPSILON * 4096;
     323             : 
     324             : const SkScalar INVERSE_NUMBER_RANGE = FLT_EPSILON_ORDERABLE_ERR;
     325             : 
     326           0 : inline bool zero_or_one(double x) {
     327           0 :     return x == 0 || x == 1;
     328             : }
     329             : 
     330         101 : inline bool approximately_zero(double x) {
     331         101 :     return fabs(x) < FLT_EPSILON;
     332             : }
     333             : 
     334           0 : inline bool precisely_zero(double x) {
     335           0 :     return fabs(x) < DBL_EPSILON_ERR;
     336             : }
     337             : 
     338             : inline bool precisely_subdivide_zero(double x) {
     339             :     return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR;
     340             : }
     341             : 
     342             : inline bool approximately_zero(float x) {
     343             :     return fabs(x) < FLT_EPSILON;
     344             : }
     345             : 
     346           2 : inline bool approximately_zero_cubed(double x) {
     347           2 :     return fabs(x) < FLT_EPSILON_CUBED;
     348             : }
     349             : 
     350           0 : inline bool approximately_zero_half(double x) {
     351           0 :     return fabs(x) < FLT_EPSILON_HALF;
     352             : }
     353             : 
     354             : inline bool approximately_zero_double(double x) {
     355             :     return fabs(x) < FLT_EPSILON_DOUBLE;
     356             : }
     357             : 
     358           0 : inline bool approximately_zero_orderable(double x) {
     359           0 :     return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
     360             : }
     361             : 
     362             : inline bool approximately_zero_squared(double x) {
     363             :     return fabs(x) < FLT_EPSILON_SQUARED;
     364             : }
     365             : 
     366             : inline bool approximately_zero_sqrt(double x) {
     367             :     return fabs(x) < FLT_EPSILON_SQRT;
     368             : }
     369             : 
     370             : inline bool roughly_zero(double x) {
     371             :     return fabs(x) < ROUGH_EPSILON;
     372             : }
     373             : 
     374           0 : inline bool approximately_zero_inverse(double x) {
     375           0 :     return fabs(x) > FLT_EPSILON_INVERSE;
     376             : }
     377             : 
     378          39 : inline bool approximately_zero_when_compared_to(double x, double y) {
     379          39 :     return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
     380             : }
     381             : 
     382           0 : inline bool precisely_zero_when_compared_to(double x, double y) {
     383           0 :     return x == 0 || fabs(x) < fabs(y * DBL_EPSILON);
     384             : }
     385             : 
     386           0 : inline bool roughly_zero_when_compared_to(double x, double y) {
     387           0 :     return x == 0 || fabs(x) < fabs(y * ROUGH_EPSILON);
     388             : }
     389             : 
     390             : // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
     391             : // AlmostEqualUlps instead.
     392          33 : inline bool approximately_equal(double x, double y) {
     393          33 :     return approximately_zero(x - y);
     394             : }
     395             : 
     396           0 : inline bool precisely_equal(double x, double y) {
     397           0 :     return precisely_zero(x - y);
     398             : }
     399             : 
     400             : inline bool precisely_subdivide_equal(double x, double y) {
     401             :     return precisely_subdivide_zero(x - y);
     402             : }
     403             : 
     404           0 : inline bool approximately_equal_half(double x, double y) {
     405           0 :     return approximately_zero_half(x - y);
     406             : }
     407             : 
     408             : inline bool approximately_equal_double(double x, double y) {
     409             :     return approximately_zero_double(x - y);
     410             : }
     411             : 
     412           0 : inline bool approximately_equal_orderable(double x, double y) {
     413           0 :     return approximately_zero_orderable(x - y);
     414             : }
     415             : 
     416             : inline bool approximately_equal_squared(double x, double y) {
     417             :     return approximately_equal(x, y);
     418             : }
     419             : 
     420             : inline bool approximately_greater(double x, double y) {
     421             :     return x - FLT_EPSILON >= y;
     422             : }
     423             : 
     424             : inline bool approximately_greater_double(double x, double y) {
     425             :     return x - FLT_EPSILON_DOUBLE >= y;
     426             : }
     427             : 
     428             : inline bool approximately_greater_orderable(double x, double y) {
     429             :     return x - FLT_EPSILON_ORDERABLE_ERR >= y;
     430             : }
     431             : 
     432             : inline bool approximately_greater_or_equal(double x, double y) {
     433             :     return x + FLT_EPSILON > y;
     434             : }
     435             : 
     436             : inline bool approximately_greater_or_equal_double(double x, double y) {
     437             :     return x + FLT_EPSILON_DOUBLE > y;
     438             : }
     439             : 
     440             : inline bool approximately_greater_or_equal_orderable(double x, double y) {
     441             :     return x + FLT_EPSILON_ORDERABLE_ERR > y;
     442             : }
     443             : 
     444             : inline bool approximately_lesser(double x, double y) {
     445             :     return x + FLT_EPSILON <= y;
     446             : }
     447             : 
     448             : inline bool approximately_lesser_double(double x, double y) {
     449             :     return x + FLT_EPSILON_DOUBLE <= y;
     450             : }
     451             : 
     452             : inline bool approximately_lesser_orderable(double x, double y) {
     453             :     return x + FLT_EPSILON_ORDERABLE_ERR <= y;
     454             : }
     455             : 
     456             : inline bool approximately_lesser_or_equal(double x, double y) {
     457             :     return x - FLT_EPSILON < y;
     458             : }
     459             : 
     460             : inline bool approximately_lesser_or_equal_double(double x, double y) {
     461             :     return x - FLT_EPSILON_DOUBLE < y;
     462             : }
     463             : 
     464             : inline bool approximately_lesser_or_equal_orderable(double x, double y) {
     465             :     return x - FLT_EPSILON_ORDERABLE_ERR < y;
     466             : }
     467             : 
     468          30 : inline bool approximately_greater_than_one(double x) {
     469          30 :     return x > 1 - FLT_EPSILON;
     470             : }
     471             : 
     472           0 : inline bool precisely_greater_than_one(double x) {
     473           0 :     return x > 1 - DBL_EPSILON_ERR;
     474             : }
     475             : 
     476          33 : inline bool approximately_less_than_zero(double x) {
     477          33 :     return x < FLT_EPSILON;
     478             : }
     479             : 
     480           0 : inline bool precisely_less_than_zero(double x) {
     481           0 :     return x < DBL_EPSILON_ERR;
     482             : }
     483             : 
     484           0 : inline bool approximately_negative(double x) {
     485           0 :     return x < FLT_EPSILON;
     486             : }
     487             : 
     488           0 : inline bool approximately_negative_orderable(double x) {
     489           0 :     return x < FLT_EPSILON_ORDERABLE_ERR;
     490             : }
     491             : 
     492           0 : inline bool precisely_negative(double x) {
     493           0 :     return x < DBL_EPSILON_ERR;
     494             : }
     495             : 
     496         162 : inline bool approximately_one_or_less(double x) {
     497         162 :     return x < 1 + FLT_EPSILON;
     498             : }
     499             : 
     500           0 : inline bool approximately_one_or_less_double(double x) {
     501           0 :     return x < 1 + FLT_EPSILON_DOUBLE;
     502             : }
     503             : 
     504             : inline bool approximately_positive(double x) {
     505             :     return x > -FLT_EPSILON;
     506             : }
     507             : 
     508             : inline bool approximately_positive_squared(double x) {
     509             :     return x > -(FLT_EPSILON_SQUARED);
     510             : }
     511             : 
     512         194 : inline bool approximately_zero_or_more(double x) {
     513         194 :     return x > -FLT_EPSILON;
     514             : }
     515             : 
     516           0 : inline bool approximately_zero_or_more_double(double x) {
     517           0 :     return x > -FLT_EPSILON_DOUBLE;
     518             : }
     519             : 
     520           0 : inline bool approximately_between_orderable(double a, double b, double c) {
     521             :     return a <= c
     522           0 :             ? approximately_negative_orderable(a - b) && approximately_negative_orderable(b - c)
     523           0 :             : approximately_negative_orderable(b - a) && approximately_negative_orderable(c - b);
     524             : }
     525             : 
     526           0 : inline bool approximately_between(double a, double b, double c) {
     527           0 :     return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
     528           0 :             : approximately_negative(b - a) && approximately_negative(c - b);
     529             : }
     530             : 
     531           0 : inline bool precisely_between(double a, double b, double c) {
     532           0 :     return a <= c ? precisely_negative(a - b) && precisely_negative(b - c)
     533           0 :             : precisely_negative(b - a) && precisely_negative(c - b);
     534             : }
     535             : 
     536             : // returns true if (a <= b <= c) || (a >= b >= c)
     537          64 : inline bool between(double a, double b, double c) {
     538          64 :     SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)
     539             :             || (precisely_zero(a) && precisely_zero(b) && precisely_zero(c)));
     540          64 :     return (a - b) * (c - b) <= 0;
     541             : }
     542             : 
     543           0 : inline bool roughly_equal(double x, double y) {
     544           0 :     return fabs(x - y) < ROUGH_EPSILON;
     545             : }
     546             : 
     547           0 : inline bool roughly_negative(double x) {
     548           0 :     return x < ROUGH_EPSILON;
     549             : }
     550             : 
     551           0 : inline bool roughly_between(double a, double b, double c) {
     552           0 :     return a <= c ? roughly_negative(a - b) && roughly_negative(b - c)
     553           0 :             : roughly_negative(b - a) && roughly_negative(c - b);
     554             : }
     555             : 
     556           0 : inline bool more_roughly_equal(double x, double y) {
     557           0 :     return fabs(x - y) < MORE_ROUGH_EPSILON;
     558             : }
     559             : 
     560             : struct SkDPoint;
     561             : struct SkDVector;
     562             : struct SkDLine;
     563             : struct SkDQuad;
     564             : struct SkDConic;
     565             : struct SkDCubic;
     566             : struct SkDRect;
     567             : 
     568           0 : inline SkPath::Verb SkPathOpsPointsToVerb(int points) {
     569           0 :     int verb = (1 << points) >> 1;
     570             : #ifdef SK_DEBUG
     571           0 :     switch (points) {
     572           0 :         case 0: SkASSERT(SkPath::kMove_Verb == verb); break;
     573           0 :         case 1: SkASSERT(SkPath::kLine_Verb == verb); break;
     574           0 :         case 2: SkASSERT(SkPath::kQuad_Verb == verb); break;
     575           0 :         case 3: SkASSERT(SkPath::kCubic_Verb == verb); break;
     576           0 :         default: SkDEBUGFAIL("should not be here");
     577             :     }
     578             : #endif
     579           0 :     return (SkPath::Verb)verb;
     580             : }
     581             : 
     582           0 : inline int SkPathOpsVerbToPoints(SkPath::Verb verb) {
     583           0 :     int points = (int) verb - (((int) verb + 1) >> 2);
     584             : #ifdef SK_DEBUG
     585           0 :     switch (verb) {
     586           0 :         case SkPath::kLine_Verb: SkASSERT(1 == points); break;
     587           0 :         case SkPath::kQuad_Verb: SkASSERT(2 == points); break;
     588           0 :         case SkPath::kConic_Verb: SkASSERT(2 == points); break;
     589           0 :         case SkPath::kCubic_Verb: SkASSERT(3 == points); break;
     590           0 :         default: SkDEBUGFAIL("should not get here");
     591             :     }
     592             : #endif
     593           0 :     return points;
     594             : }
     595             : 
     596         396 : inline double SkDInterp(double A, double B, double t) {
     597         396 :     return A + (B - A) * t;
     598             : }
     599             : 
     600             : double SkDCubeRoot(double x);
     601             : 
     602             : /* Returns -1 if negative, 0 if zero, 1 if positive
     603             : */
     604             : inline int SkDSign(double x) {
     605             :     return (x > 0) - (x < 0);
     606             : }
     607             : 
     608             : /* Returns 0 if negative, 1 if zero, 2 if positive
     609             : */
     610             : inline int SKDSide(double x) {
     611             :     return (x > 0) + (x >= 0);
     612             : }
     613             : 
     614             : /* Returns 1 if negative, 2 if zero, 4 if positive
     615             : */
     616             : inline int SkDSideBit(double x) {
     617             :     return 1 << SKDSide(x);
     618             : }
     619             : 
     620           0 : inline double SkPinT(double t) {
     621           0 :     return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 : t;
     622             : }
     623             : 
     624             : #endif

Generated by: LCOV version 1.13