epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 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 | */ |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 7 | #ifndef SkEdgeBuilder_DEFINED |
| 8 | #define SkEdgeBuilder_DEFINED |
| 9 | |
Herb Derby | 4b1b04d | 2017-03-01 13:44:39 -0500 | [diff] [blame] | 10 | #include "SkArenaAlloc.h" |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 11 | #include "SkRect.h" |
| 12 | #include "SkTDArray.h" |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 13 | #include "SkEdge.h" |
| 14 | #include "SkAnalyticEdge.h" |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 15 | |
senorblanco@chromium.org | b1501a3 | 2009-12-04 19:53:28 +0000 | [diff] [blame] | 16 | struct SkEdge; |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 17 | struct SkAnalyticEdge; |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 18 | class SkEdgeClipper; |
| 19 | class SkPath; |
| 20 | |
| 21 | class SkEdgeBuilder { |
| 22 | public: |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 23 | enum EdgeType { |
Yuqian Li | 5eb8fc5 | 2017-08-08 14:00:52 -0400 | [diff] [blame] | 24 | // Used in supersampling or non-AA scan coverter; it stores only integral y coordinates. |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 25 | kEdge, |
Yuqian Li | 5eb8fc5 | 2017-08-08 14:00:52 -0400 | [diff] [blame] | 26 | |
| 27 | // Used in Analytic AA scan converter; it uses SkFixed to store fractional y. |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 28 | kAnalyticEdge, |
Yuqian Li | 5eb8fc5 | 2017-08-08 14:00:52 -0400 | [diff] [blame] | 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.) |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 37 | kBezier |
| 38 | }; |
| 39 | |
| 40 | // static constexpr int kEdgeSizes[3] = {sizeof(SkEdge), sizeof(SkAnalyticEdge), sizeof(SkBezier)}; |
| 41 | |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 42 | SkEdgeBuilder(); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 43 | |
reed@google.com | c8d640b | 2012-08-02 14:26:43 +0000 | [diff] [blame] | 44 | // returns the number of built edges. The array of those edge pointers |
| 45 | // is returned from edgeList(). |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 46 | int build(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight, |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 47 | EdgeType edgeType = kEdge); |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 48 | |
Yuqian Li | 1c84088 | 2017-05-26 14:50:35 -0400 | [diff] [blame] | 49 | int build_edges(const SkPath& path, const SkIRect* shiftedClip, |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 50 | int shiftEdgesUp, bool pathContainedInClip, EdgeType edgeType = kEdge); |
Yuqian Li | 1c84088 | 2017-05-26 14:50:35 -0400 | [diff] [blame] | 51 | |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 52 | SkEdge** edgeList() { return (SkEdge**)fEdgeList; } |
| 53 | SkAnalyticEdge** analyticEdgeList() { return (SkAnalyticEdge**)fEdgeList; } |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 54 | SkBezier** bezierList() { return (SkBezier**)fEdgeList; } |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 55 | |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 56 | private: |
caryclark | afd25f7 | 2016-01-30 14:07:20 -0800 | [diff] [blame] | 57 | enum Combine { |
| 58 | kNo_Combine, |
| 59 | kPartial_Combine, |
| 60 | kTotal_Combine |
| 61 | }; |
| 62 | |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 63 | Combine CombineVertical(const SkEdge* edge, SkEdge* last); |
| 64 | Combine CombineVertical(const SkAnalyticEdge* edge, SkAnalyticEdge* last); |
caryclark | afd25f7 | 2016-01-30 14:07:20 -0800 | [diff] [blame] | 65 | Combine checkVertical(const SkEdge* edge, SkEdge** edgePtr); |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 66 | Combine checkVertical(const SkAnalyticEdge* edge, SkAnalyticEdge** edgePtr); |
| 67 | bool vertical_line(const SkEdge* edge); |
| 68 | bool vertical_line(const SkAnalyticEdge* edge); |
caryclark | afd25f7 | 2016-01-30 14:07:20 -0800 | [diff] [blame] | 69 | |
Florin Malita | 14a6430 | 2017-05-24 14:53:44 -0400 | [diff] [blame] | 70 | SkSTArenaAlloc<512> fAlloc; |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 71 | SkTDArray<void*> fList; |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 72 | |
reed@google.com | c8d640b | 2012-08-02 14:26:43 +0000 | [diff] [blame] | 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 | */ |
liyuqian | 38911a7 | 2016-10-04 11:23:22 -0700 | [diff] [blame] | 79 | void** fEdgeList; |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 80 | |
reed | 01d3319 | 2015-02-07 12:18:41 -0800 | [diff] [blame] | 81 | int fShiftUp; |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 82 | EdgeType fEdgeType; |
rmistry@google.com | fbfcd56 | 2012-08-23 18:09:54 +0000 | [diff] [blame] | 83 | |
reed@google.com | 277c3f8 | 2013-05-31 15:17:50 +0000 | [diff] [blame] | 84 | public: |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 85 | void addLine(const SkPoint pts[]); |
| 86 | void addQuad(const SkPoint pts[]); |
| 87 | void addCubic(const SkPoint pts[]); |
| 88 | void addClipper(SkEdgeClipper*); |
reed@google.com | c8d640b | 2012-08-02 14:26:43 +0000 | [diff] [blame] | 89 | |
Yuqian Li | 5eb8fc5 | 2017-08-08 14:00:52 -0400 | [diff] [blame] | 90 | EdgeType edgeType() const { return fEdgeType; } |
| 91 | |
reed | 01d3319 | 2015-02-07 12:18:41 -0800 | [diff] [blame] | 92 | int buildPoly(const SkPath& path, const SkIRect* clip, int shiftUp, bool clipToTheRight); |
Yuqian Li | df60e36 | 2017-07-25 11:26:31 -0400 | [diff] [blame] | 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 | } |
reed@android.com | 909994f | 2009-11-18 16:09:51 +0000 | [diff] [blame] | 119 | }; |
| 120 | |
| 121 | #endif |