Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2011 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 SkEdgeBuilder_DEFINED
      8 #define SkEdgeBuilder_DEFINED
      9 
     10 #include "SkArenaAlloc.h"
     11 #include "SkRect.h"
     12 #include "SkTDArray.h"
     13 #include "SkEdge.h"
     14 #include "SkAnalyticEdge.h"
     15 
     16 struct SkEdge;
     17 struct SkAnalyticEdge;
     18 class SkEdgeClipper;
     19 class SkPath;
     20 
     21 class SkEdgeBuilder {
     22 public:
     23     enum EdgeType {
     24         // Used in supersampling or non-AA scan coverter; it stores only integral y coordinates.
     25         kEdge,
     26 
     27         // Used in Analytic AA scan converter; it uses SkFixed to store fractional y.
     28         kAnalyticEdge,
     29 
     30         // Used in Delta AA scan converter; it's a super-light wrapper of SkPoint, which can then be
     31         // used to construct SkAnalyticEdge (kAnalyticEdge) later. We use kBezier to save the memory
     32         // allocation time (a SkBezier is much lighter than SkAnalyticEdge or SkEdge). Note that
     33         // Delta AA only has to deal with one SkAnalyticEdge at a time (whereas Analytic AA has to
     34         // deal with all SkAnalyticEdges at the same time). Thus for Delta AA, we only need to
     35         // allocate memory for n SkBeziers and 1 SkAnalyticEdge. (Analytic AA need to allocate
     36         // memory for n SkAnalyticEdges.)
     37         kBezier
     38     };
     39 
     40     // static constexpr int kEdgeSizes[3] = {sizeof(SkEdge), sizeof(SkAnalyticEdge), sizeof(SkBezier)};
     41 
     42     SkEdgeBuilder();
     43 
     44     // returns the number of built edges. The array of those edge pointers
     45     // is returned from edgeList().
     46     int build(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight,
     47               EdgeType edgeType = kEdge);
     48 
     49     int build_edges(const SkPath& path, const SkIRect* shiftedClip,
     50             int shiftEdgesUp, bool pathContainedInClip, EdgeType edgeType = kEdge);
     51 
     52     SkEdge** edgeList() { return (SkEdge**)fEdgeList; }
     53     SkAnalyticEdge** analyticEdgeList() { return (SkAnalyticEdge**)fEdgeList; }
     54     SkBezier** bezierList() { return (SkBezier**)fEdgeList; }
     55 
     56 private:
     57     enum Combine {
     58         kNo_Combine,
     59         kPartial_Combine,
     60         kTotal_Combine
     61     };
     62 
     63     Combine CombineVertical(const SkEdge* edge, SkEdge* last);
     64     Combine CombineVertical(const SkAnalyticEdge* edge, SkAnalyticEdge* last);
     65     Combine checkVertical(const SkEdge* edge, SkEdge** edgePtr);
     66     Combine checkVertical(const SkAnalyticEdge* edge, SkAnalyticEdge** edgePtr);
     67     bool vertical_line(const SkEdge* edge);
     68     bool vertical_line(const SkAnalyticEdge* edge);
     69 
     70     SkSTArenaAlloc<512> fAlloc;
     71     SkTDArray<void*>    fList;
     72 
     73     /*
     74      *  If we're in general mode, we allcoate the pointers in fList, and this
     75      *  will point at fList.begin(). If we're in polygon mode, fList will be
     76      *  empty, as we will have preallocated room for the pointers in fAlloc's
     77      *  block, and fEdgeList will point into that.
     78      */
     79     void**      fEdgeList;
     80 
     81     int         fShiftUp;
     82     EdgeType    fEdgeType;
     83 
     84 public:
     85     void addLine(const SkPoint pts[]);
     86     void addQuad(const SkPoint pts[]);
     87     void addCubic(const SkPoint pts[]);
     88     void addClipper(SkEdgeClipper*);
     89 
     90     EdgeType edgeType() const { return fEdgeType; }
     91 
     92     int buildPoly(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight);
     93 
     94     inline void addPolyLine(SkPoint pts[], char* &edge, size_t edgeSize, char** &edgePtr,
     95             int shiftUp) {
     96         if (fEdgeType == kBezier) {
     97             if (((SkLine*)edge)->set(pts)) {
     98                 *edgePtr++ = edge;
     99                 edge += edgeSize;
    100             }
    101             return;
    102         }
    103         bool analyticAA = fEdgeType == kAnalyticEdge;
    104         bool setLineResult = analyticAA ?
    105                 ((SkAnalyticEdge*)edge)->setLine(pts[0], pts[1]) :
    106                 ((SkEdge*)edge)->setLine(pts[0], pts[1], shiftUp);
    107         if (setLineResult) {
    108             Combine combine = analyticAA ?
    109                     checkVertical((SkAnalyticEdge*)edge, (SkAnalyticEdge**)edgePtr) :
    110                     checkVertical((SkEdge*)edge, (SkEdge**)edgePtr);
    111             if (kNo_Combine == combine) {
    112                 *edgePtr++ = edge;
    113                 edge += edgeSize;
    114             } else if (kTotal_Combine == combine) {
    115                 --edgePtr;
    116             }
    117         }
    118     }
    119 };
    120 
    121 #endif
    122