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