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