Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2015 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 
      8 #ifndef SkPathPriv_DEFINED
      9 #define SkPathPriv_DEFINED
     10 
     11 #include "SkPath.h"
     12 
     13 class SkPathPriv {
     14 public:
     15     enum FirstDirection {
     16         kCW_FirstDirection,         // == SkPath::kCW_Direction
     17         kCCW_FirstDirection,        // == SkPath::kCCW_Direction
     18         kUnknown_FirstDirection,
     19     };
     20 
     21     static FirstDirection AsFirstDirection(SkPath::Direction dir) {
     22         // since we agree numerically for the values in Direction, we can just cast.
     23         return (FirstDirection)dir;
     24     }
     25 
     26     /**
     27      *  Return the opposite of the specified direction. kUnknown is its own
     28      *  opposite.
     29      */
     30     static FirstDirection OppositeFirstDirection(FirstDirection dir) {
     31         static const FirstDirection gOppositeDir[] = {
     32             kCCW_FirstDirection, kCW_FirstDirection, kUnknown_FirstDirection,
     33         };
     34         return gOppositeDir[dir];
     35     }
     36 
     37     /**
     38      *  Tries to quickly compute the direction of the first non-degenerate
     39      *  contour. If it can be computed, return true and set dir to that
     40      *  direction. If it cannot be (quickly) determined, return false and ignore
     41      *  the dir parameter. If the direction was determined, it is cached to make
     42      *  subsequent calls return quickly.
     43      */
     44     static bool CheapComputeFirstDirection(const SkPath&, FirstDirection* dir);
     45 
     46     /**
     47      *  Returns true if the path's direction can be computed via
     48      *  cheapComputDirection() and if that computed direction matches the
     49      *  specified direction. If dir is kUnknown, returns true if the direction
     50      *  cannot be computed.
     51      */
     52     static bool CheapIsFirstDirection(const SkPath& path, FirstDirection dir) {
     53         FirstDirection computedDir = kUnknown_FirstDirection;
     54         (void)CheapComputeFirstDirection(path, &computedDir);
     55         return computedDir == dir;
     56     }
     57 
     58     static bool IsClosedSingleContour(const SkPath& path) {
     59         int verbCount = path.countVerbs();
     60         if (verbCount == 0)
     61             return false;
     62         int moveCount = 0;
     63         auto verbs = path.fPathRef->verbs();
     64         for (int i = 0; i < verbCount; i++) {
     65             switch (verbs[~i]) { // verbs are stored backwards; we use [~i] to get the i'th verb
     66                 case SkPath::Verb::kMove_Verb:
     67                     moveCount += 1;
     68                     if (moveCount > 1) {
     69                         return false;
     70                     }
     71                     break;
     72                 case SkPath::Verb::kClose_Verb:
     73                     if (i == verbCount - 1) {
     74                         return true;
     75                     }
     76                     return false;
     77                 default: break;
     78             }
     79         }
     80         return false;
     81     }
     82 
     83     static void AddGenIDChangeListener(const SkPath& path, SkPathRef::GenIDChangeListener* listener) {
     84         path.fPathRef->addGenIDChangeListener(listener);
     85     }
     86 
     87     /**
     88      * This returns true for a rect that begins and ends at the same corner and has either a move
     89      * followed by four lines or a move followed by 3 lines and a close. None of the parameters are
     90      * optional. This does not permit degenerate line or point rectangles.
     91      */
     92     static bool IsSimpleClosedRect(const SkPath& path, SkRect* rect, SkPath::Direction* direction,
     93                                    unsigned* start);
     94 
     95     /**
     96      * Creates a path from arc params using the semantics of SkCanvas::drawArc. This function
     97      * assumes empty ovals and zero sweeps have already been filtered out.
     98      */
     99     static void CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar startAngle,
    100                                   SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect);
    101 
    102     /**
    103      * Returns a C++11-iterable object that traverses a path's verbs in order. e.g:
    104      *
    105      *   for (SkPath::Verb verb : SkPathPriv::Verbs(path)) {
    106      *       ...
    107      *   }
    108      */
    109     struct Verbs {
    110     public:
    111         Verbs(const SkPath& path) : fPathRef(path.fPathRef.get()) {}
    112         struct Iter {
    113             void operator++() { --fVerb; } // verbs are laid out backwards in memory.
    114             bool operator!=(const Iter& b) { return fVerb != b.fVerb; }
    115             SkPath::Verb operator*() { return static_cast<SkPath::Verb>(*fVerb); }
    116             const uint8_t* fVerb;
    117         };
    118         Iter begin() { return Iter{fPathRef->verbs() - 1}; }
    119         Iter end() { return Iter{fPathRef->verbs() - fPathRef->countVerbs() - 1}; }
    120     private:
    121         Verbs(const Verbs&) = delete;
    122         Verbs& operator=(const Verbs&) = delete;
    123         SkPathRef* fPathRef;
    124     };
    125 
    126     /**
    127      * Returns a pointer to the verb data. Note that the verbs are stored backwards in memory and
    128      * thus the returned pointer is the last verb.
    129      */
    130     static const uint8_t* VerbData(const SkPath& path) {
    131         return path.fPathRef->verbsMemBegin();
    132     }
    133 
    134     /** Returns a raw pointer to the path points */
    135     static const SkPoint* PointData(const SkPath& path) {
    136         return path.fPathRef->points();
    137     }
    138 
    139     /** Returns the number of conic weights in the path */
    140     static int ConicWeightCnt(const SkPath& path) {
    141         return path.fPathRef->countWeights();
    142     }
    143 
    144     /** Returns a raw pointer to the path conic weights. */
    145     static const SkScalar* ConicWeightData(const SkPath& path) {
    146         return path.fPathRef->conicWeights();
    147     }
    148 };
    149 
    150 #endif
    151