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