| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef SkEdgeBuilder_DEFINED | |
| #define SkEdgeBuilder_DEFINED | |
| #include "SkArenaAlloc.h" | |
| #include "SkRect.h" | |
| #include "SkTDArray.h" | |
| #include "SkEdge.h" | |
| #include "SkAnalyticEdge.h" | |
| struct SkEdge; | |
| struct SkAnalyticEdge; | |
| class SkEdgeClipper; | |
| class SkPath; | |
| class SkEdgeBuilder { | |
| public: | |
| enum EdgeType { | |
| // Used in supersampling or non-AA scan coverter; it stores only integral y coordinates. | |
| kEdge, | |
| // Used in Analytic AA scan converter; it uses SkFixed to store fractional y. | |
| kAnalyticEdge, | |
| // Used in Delta AA scan converter; it's a super-light wrapper of SkPoint, which can then be | |
| // used to construct SkAnalyticEdge (kAnalyticEdge) later. We use kBezier to save the memory | |
| // allocation time (a SkBezier is much lighter than SkAnalyticEdge or SkEdge). Note that | |
| // Delta AA only has to deal with one SkAnalyticEdge at a time (whereas Analytic AA has to | |
| // deal with all SkAnalyticEdges at the same time). Thus for Delta AA, we only need to | |
| // allocate memory for n SkBeziers and 1 SkAnalyticEdge. (Analytic AA need to allocate | |
| // memory for n SkAnalyticEdges.) | |
| kBezier | |
| }; | |
| // static constexpr int kEdgeSizes[3] = {sizeof(SkEdge), sizeof(SkAnalyticEdge), sizeof(SkBezier)}; | |
| SkEdgeBuilder(); | |
| // returns the number of built edges. The array of those edge pointers | |
| // is returned from edgeList(). | |
| int build(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight, | |
| EdgeType edgeType = kEdge); | |
| int build_edges(const SkPath& path, const SkIRect* shiftedClip, | |
| int shiftEdgesUp, bool pathContainedInClip, EdgeType edgeType = kEdge); | |
| SkEdge** edgeList() { return (SkEdge**)fEdgeList; } | |
| SkAnalyticEdge** analyticEdgeList() { return (SkAnalyticEdge**)fEdgeList; } | |
| SkBezier** bezierList() { return (SkBezier**)fEdgeList; } | |
| bool isFinite() const { return fIsFinite; } | |
| private: | |
| enum Combine { | |
| kNo_Combine, | |
| kPartial_Combine, | |
| kTotal_Combine | |
| }; | |
| Combine CombineVertical(const SkEdge* edge, SkEdge* last); | |
| Combine CombineVertical(const SkAnalyticEdge* edge, SkAnalyticEdge* last); | |
| Combine checkVertical(const SkEdge* edge, SkEdge** edgePtr); | |
| Combine checkVertical(const SkAnalyticEdge* edge, SkAnalyticEdge** edgePtr); | |
| bool vertical_line(const SkEdge* edge); | |
| bool vertical_line(const SkAnalyticEdge* edge); | |
| SkSTArenaAlloc<512> fAlloc; | |
| SkTDArray<void*> fList; | |
| /* | |
| * If we're in general mode, we allcoate the pointers in fList, and this | |
| * will point at fList.begin(). If we're in polygon mode, fList will be | |
| * empty, as we will have preallocated room for the pointers in fAlloc's | |
| * block, and fEdgeList will point into that. | |
| */ | |
| void** fEdgeList; | |
| int fShiftUp; | |
| EdgeType fEdgeType; | |
| bool fIsFinite = true; | |
| public: | |
| void addLine(const SkPoint pts[]); | |
| void addQuad(const SkPoint pts[]); | |
| void addCubic(const SkPoint pts[]); | |
| void addClipper(SkEdgeClipper*); | |
| EdgeType edgeType() const { return fEdgeType; } | |
| int buildPoly(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight); | |
| inline void addPolyLine(SkPoint pts[], char* &edge, size_t edgeSize, char** &edgePtr, | |
| int shiftUp) { | |
| if (fEdgeType == kBezier) { | |
| if (((SkLine*)edge)->set(pts)) { | |
| *edgePtr++ = edge; | |
| edge += edgeSize; | |
| } | |
| return; | |
| } | |
| bool analyticAA = fEdgeType == kAnalyticEdge; | |
| bool setLineResult = analyticAA ? | |
| ((SkAnalyticEdge*)edge)->setLine(pts[0], pts[1]) : | |
| ((SkEdge*)edge)->setLine(pts[0], pts[1], shiftUp); | |
| if (setLineResult) { | |
| Combine combine = analyticAA ? | |
| checkVertical((SkAnalyticEdge*)edge, (SkAnalyticEdge**)edgePtr) : | |
| checkVertical((SkEdge*)edge, (SkEdge**)edgePtr); | |
| if (kNo_Combine == combine) { | |
| *edgePtr++ = edge; | |
| edge += edgeSize; | |
| } else if (kTotal_Combine == combine) { | |
| --edgePtr; | |
| } | |
| } | |
| } | |
| }; | |
| #endif |