LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/ops - GrAAConvexTessellator.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 67 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 GrAAConvexTessellator_DEFINED
       9             : #define GrAAConvexTessellator_DEFINED
      10             : 
      11             : #include "SkColor.h"
      12             : #include "SkPaint.h"
      13             : #include "SkPoint.h"
      14             : #include "SkScalar.h"
      15             : #include "SkStrokeRec.h"
      16             : #include "SkTDArray.h"
      17             : 
      18             : class SkCanvas;
      19             : class SkMatrix;
      20             : class SkPath;
      21             : 
      22             : //#define GR_AA_CONVEX_TESSELLATOR_VIZ 1
      23             : 
      24             : // device space distance which we inset / outset points in order to create the soft antialiased edge
      25             : static const SkScalar kAntialiasingRadius = 0.5f;
      26             : 
      27             : class GrAAConvexTessellator;
      28             : 
      29             : // The AAConvexTessellator holds the global pool of points and the triangulation
      30             : // that connects them. It also drives the tessellation process.
      31             : // The outward facing normals of the original polygon are stored (in 'fNorms') to service
      32             : // computeDepthFromEdge requests.
      33           0 : class GrAAConvexTessellator {
      34             : public:
      35           0 :     GrAAConvexTessellator(SkStrokeRec::Style style = SkStrokeRec::kFill_Style,
      36             :                           SkScalar strokeWidth = -1.0f,
      37             :                           SkPaint::Join join = SkPaint::Join::kBevel_Join,
      38             :                           SkScalar miterLimit = 0.0f)
      39           0 :         : fSide(SkPoint::kOn_Side)
      40             :         , fStrokeWidth(strokeWidth)
      41             :         , fStyle(style)
      42             :         , fJoin(join)
      43           0 :         , fMiterLimit(miterLimit) {
      44           0 :     }
      45             : 
      46           0 :     SkPoint::Side side() const { return fSide; }
      47             : 
      48             :     bool tessellate(const SkMatrix& m, const SkPath& path);
      49             : 
      50             :     // The next five should only be called after tessellate to extract the result
      51           0 :     int numPts() const { return fPts.count(); }
      52           0 :     int numIndices() const { return fIndices.count(); }
      53             : 
      54           0 :     const SkPoint& lastPoint() const { return fPts.top(); }
      55           0 :     const SkPoint& point(int index) const { return fPts[index]; }
      56           0 :     int index(int index) const { return fIndices[index]; }
      57           0 :     SkScalar coverage(int index) const { return fCoverages[index]; }
      58             : 
      59             : #if GR_AA_CONVEX_TESSELLATOR_VIZ
      60             :     void draw(SkCanvas* canvas) const;
      61             : #endif
      62             : 
      63             :     // The tessellator can be reused for multiple paths by rewinding in between
      64             :     void rewind();
      65             : 
      66             : private:
      67             :     // CandidateVerts holds the vertices for the next ring while they are
      68             :     // being generated. Its main function is to de-dup the points.
      69           0 :     class CandidateVerts {
      70             :     public:
      71           0 :         void setReserve(int numPts) { fPts.setReserve(numPts); }
      72           0 :         void rewind() { fPts.rewind(); }
      73             : 
      74           0 :         int numPts() const { return fPts.count(); }
      75             : 
      76           0 :         const SkPoint& lastPoint() const { return fPts.top().fPt; }
      77           0 :         const SkPoint& firstPoint() const { return fPts[0].fPt; }
      78           0 :         const SkPoint& point(int index) const { return fPts[index].fPt; }
      79             : 
      80           0 :         int originatingIdx(int index) const { return fPts[index].fOriginatingIdx; }
      81           0 :         int origEdge(int index) const { return fPts[index].fOrigEdgeId; }
      82           0 :         bool needsToBeNew(int index) const { return fPts[index].fNeedsToBeNew; }
      83             : 
      84           0 :         int addNewPt(const SkPoint& newPt, int originatingIdx, int origEdge, bool needsToBeNew) {
      85           0 :             struct PointData* pt = fPts.push();
      86           0 :             pt->fPt = newPt;
      87           0 :             pt->fOrigEdgeId = origEdge;
      88           0 :             pt->fOriginatingIdx = originatingIdx;
      89           0 :             pt->fNeedsToBeNew = needsToBeNew;
      90           0 :             return fPts.count() - 1;
      91             :         }
      92             : 
      93           0 :         int fuseWithPrior(int origEdgeId) {
      94           0 :             fPts.top().fOrigEdgeId = origEdgeId;
      95           0 :             fPts.top().fOriginatingIdx = -1;
      96           0 :             fPts.top().fNeedsToBeNew = true;
      97           0 :             return fPts.count() - 1;
      98             :         }
      99             : 
     100           0 :         int fuseWithNext() {
     101           0 :             fPts[0].fOriginatingIdx = -1;
     102           0 :             fPts[0].fNeedsToBeNew = true;
     103           0 :             return 0;
     104             :         }
     105             : 
     106           0 :         int fuseWithBoth() {
     107           0 :             if (fPts.count() > 1) {
     108           0 :                 fPts.pop();
     109             :             }
     110             : 
     111           0 :             fPts[0].fOriginatingIdx = -1;
     112           0 :             fPts[0].fNeedsToBeNew = true;
     113           0 :             return 0;
     114             :         }
     115             : 
     116             :     private:
     117             :         struct PointData {
     118             :             SkPoint fPt;
     119             :             int     fOriginatingIdx;
     120             :             int     fOrigEdgeId;
     121             :             bool    fNeedsToBeNew;
     122             :         };
     123             : 
     124             :         SkTDArray<struct PointData> fPts;
     125             :     };
     126             : 
     127             :     // The Ring holds a set of indices into the global pool that together define
     128             :     // a single polygon inset.
     129           0 :     class Ring {
     130             :     public:
     131           0 :         void setReserve(int numPts) { fPts.setReserve(numPts); }
     132           0 :         void rewind() { fPts.rewind(); }
     133             : 
     134           0 :         int numPts() const { return fPts.count(); }
     135             : 
     136           0 :         void addIdx(int index, int origEdgeId) {
     137           0 :             struct PointData* pt = fPts.push();
     138           0 :             pt->fIndex = index;
     139           0 :             pt->fOrigEdgeId = origEdgeId;
     140           0 :         }
     141             : 
     142             :         // Upgrade this ring so that it can behave like an originating ring
     143           0 :         void makeOriginalRing() {
     144           0 :             for (int i = 0; i < fPts.count(); ++i) {
     145           0 :                 fPts[i].fOrigEdgeId = fPts[i].fIndex;
     146             :             }            
     147           0 :         }
     148             : 
     149             :         // init should be called after all the indices have been added (via addIdx)
     150             :         void init(const GrAAConvexTessellator& tess);
     151             :         void init(const SkTDArray<SkVector>& norms, const SkTDArray<SkVector>& bisectors);
     152             : 
     153           0 :         const SkPoint& norm(int index) const { return fPts[index].fNorm; }
     154           0 :         const SkPoint& bisector(int index) const { return fPts[index].fBisector; }
     155           0 :         int index(int index) const { return fPts[index].fIndex; }
     156           0 :         int origEdgeID(int index) const { return fPts[index].fOrigEdgeId; }
     157             :         void setOrigEdgeId(int index, int id) { fPts[index].fOrigEdgeId = id; }
     158             : 
     159             :     #if GR_AA_CONVEX_TESSELLATOR_VIZ
     160             :         void draw(SkCanvas* canvas, const GrAAConvexTessellator& tess) const;
     161             :     #endif
     162             : 
     163             :     private:
     164             :         void computeNormals(const GrAAConvexTessellator& result);
     165             :         void computeBisectors(const GrAAConvexTessellator& tess);
     166             : 
     167             :         SkDEBUGCODE(bool isConvex(const GrAAConvexTessellator& tess) const;)
     168             : 
     169             :         struct PointData {
     170             :             SkPoint fNorm;
     171             :             SkPoint fBisector;
     172             :             int     fIndex;
     173             :             int     fOrigEdgeId;
     174             :         };
     175             : 
     176             :         SkTDArray<PointData> fPts;
     177             :     };
     178             : 
     179             :     // Represents whether a given point is within a curve. A point is inside a curve only if it is
     180             :     // an interior point within a quad, cubic, or conic, or if it is the endpoint of a quad, cubic,
     181             :     // or conic with another curve meeting it at (more or less) the same angle.
     182             :     enum CurveState {
     183             :         // point is a sharp vertex
     184             :         kSharp_CurveState,
     185             :         // endpoint of a curve with the other side's curvature not yet determined
     186             :         kIndeterminate_CurveState,
     187             :         // point is in the interior of a curve
     188             :         kCurve_CurveState
     189             :     };
     190             : 
     191           0 :     bool movable(int index) const { return fMovable[index]; }
     192             : 
     193             :     // Movable points are those that can be slid along their bisector.
     194             :     // Basically, a point is immovable if it is part of the original
     195             :     // polygon or it results from the fusing of two bisectors.
     196             :     int addPt(const SkPoint& pt, SkScalar depth, SkScalar coverage, bool movable, CurveState curve);
     197             :     void popLastPt();
     198             :     void popFirstPtShuffle();
     199             : 
     200             :     void updatePt(int index, const SkPoint& pt, SkScalar depth, SkScalar coverage);
     201             : 
     202             :     void addTri(int i0, int i1, int i2);
     203             : 
     204           0 :     void reservePts(int count) {
     205           0 :         fPts.setReserve(count);
     206           0 :         fCoverages.setReserve(count);
     207           0 :         fMovable.setReserve(count);
     208           0 :     }
     209             : 
     210             :     SkScalar computeDepthFromEdge(int edgeIdx, const SkPoint& p) const;
     211             : 
     212             :     bool computePtAlongBisector(int startIdx, const SkPoint& bisector,
     213             :                                 int edgeIdx, SkScalar desiredDepth,
     214             :                                 SkPoint* result) const;
     215             : 
     216             :     void lineTo(const SkPoint& p, CurveState curve);
     217             : 
     218             :     void lineTo(const SkMatrix& m, SkPoint p, CurveState curve);
     219             : 
     220             :     void quadTo(const SkPoint pts[3]);
     221             : 
     222             :     void quadTo(const SkMatrix& m, SkPoint pts[3]);
     223             : 
     224             :     void cubicTo(const SkMatrix& m, SkPoint pts[4]);
     225             : 
     226             :     void conicTo(const SkMatrix& m, SkPoint pts[3], SkScalar w);
     227             : 
     228             :     void terminate(const Ring& lastRing);
     229             : 
     230             :     // return false on failure/degenerate path
     231             :     bool extractFromPath(const SkMatrix& m, const SkPath& path);
     232             :     void computeBisectors();
     233             : 
     234             :     void fanRing(const Ring& ring);
     235             : 
     236             :     Ring* getNextRing(Ring* lastRing);
     237             : 
     238             :     void createOuterRing(const Ring& previousRing, SkScalar outset, SkScalar coverage,
     239             :                          Ring* nextRing);
     240             : 
     241             :     bool createInsetRings(Ring& previousRing, SkScalar initialDepth, SkScalar initialCoverage,
     242             :                           SkScalar targetDepth, SkScalar targetCoverage, Ring** finalRing);
     243             : 
     244             :     bool createInsetRing(const Ring& lastRing, Ring* nextRing,
     245             :                          SkScalar initialDepth, SkScalar initialCoverage, SkScalar targetDepth,
     246             :                          SkScalar targetCoverage, bool forceNew);
     247             : 
     248             :     void validate() const;
     249             : 
     250             :     // fPts, fCoverages, fMovable & fCurveState should always have the same # of elements
     251             :     SkTDArray<SkPoint>    fPts;
     252             :     SkTDArray<SkScalar>   fCoverages;
     253             :     // movable points are those that can be slid further along their bisector
     254             :     SkTDArray<bool>       fMovable;
     255             :     // Tracks whether a given point is interior to a curve. Such points are
     256             :     // assumed to have shallow curvature.
     257             :     SkTDArray<CurveState> fCurveState;
     258             : 
     259             :     // The outward facing normals for the original polygon
     260             :     SkTDArray<SkVector>   fNorms;
     261             :     // The inward facing bisector at each point in the original polygon. Only
     262             :     // needed for exterior ring creation and then handed off to the initial ring.
     263             :     SkTDArray<SkVector>   fBisectors;
     264             : 
     265             :     SkPoint::Side         fSide;    // winding of the original polygon
     266             : 
     267             :     // The triangulation of the points
     268             :     SkTDArray<int>        fIndices;
     269             : 
     270             :     Ring                  fInitialRing;
     271             : #if GR_AA_CONVEX_TESSELLATOR_VIZ
     272             :     // When visualizing save all the rings
     273             :     SkTDArray<Ring*>      fRings;
     274             : #else
     275             :     Ring                  fRings[2];
     276             : #endif
     277             :     CandidateVerts        fCandidateVerts;
     278             : 
     279             :     // the stroke width is only used for stroke or stroke-and-fill styles
     280             :     SkScalar              fStrokeWidth;
     281             :     SkStrokeRec::Style    fStyle;
     282             : 
     283             :     SkPaint::Join         fJoin;
     284             : 
     285             :     SkScalar              fMiterLimit;
     286             : 
     287             :     SkTDArray<SkPoint>    fPointBuffer;
     288             : };
     289             : 
     290             : 
     291             : #endif

Generated by: LCOV version 1.13