1 #include "SkEdgeBuilder.h"
2 #include "SkPath.h"
3 #include "SkEdge.h"
4 #include "SkEdgeClipper.h"
5 #include "SkLineClipper.h"
6 #include "SkGeometry.h"
7
SkEdgeBuilder()8 SkEdgeBuilder::SkEdgeBuilder() : fAlloc(16*1024) {}
9
typedAllocThrow(SkChunkAlloc & alloc)10 template <typename T> static T* typedAllocThrow(SkChunkAlloc& alloc) {
11 return static_cast<T*>(alloc.allocThrow(sizeof(T)));
12 }
13
14 ///////////////////////////////////////////////////////////////////////////////
15
addLine(const SkPoint pts[])16 void SkEdgeBuilder::addLine(const SkPoint pts[]) {
17 SkEdge* edge = typedAllocThrow<SkEdge>(fAlloc);
18 if (edge->setLine(pts[0], pts[1], NULL, fShiftUp)) {
19 fList.push(edge);
20 } else {
21 // TODO: unallocate edge from storage...
22 }
23 }
24
addQuad(const SkPoint pts[])25 void SkEdgeBuilder::addQuad(const SkPoint pts[]) {
26 SkQuadraticEdge* edge = typedAllocThrow<SkQuadraticEdge>(fAlloc);
27 if (edge->setQuadratic(pts, fShiftUp)) {
28 fList.push(edge);
29 } else {
30 // TODO: unallocate edge from storage...
31 }
32 }
33
addCubic(const SkPoint pts[])34 void SkEdgeBuilder::addCubic(const SkPoint pts[]) {
35 SkCubicEdge* edge = typedAllocThrow<SkCubicEdge>(fAlloc);
36 if (edge->setCubic(pts, NULL, fShiftUp)) {
37 fList.push(edge);
38 } else {
39 // TODO: unallocate edge from storage...
40 }
41 }
42
addClipper(SkEdgeClipper * clipper)43 void SkEdgeBuilder::addClipper(SkEdgeClipper* clipper) {
44 SkPoint pts[4];
45 SkPath::Verb verb;
46
47 while ((verb = clipper->next(pts)) != SkPath::kDone_Verb) {
48 switch (verb) {
49 case SkPath::kLine_Verb:
50 this->addLine(pts);
51 break;
52 case SkPath::kQuad_Verb:
53 this->addQuad(pts);
54 break;
55 case SkPath::kCubic_Verb:
56 this->addCubic(pts);
57 break;
58 default:
59 break;
60 }
61 }
62 }
63
64 ///////////////////////////////////////////////////////////////////////////////
65
setShiftedClip(SkRect * dst,const SkIRect & src,int shift)66 static void setShiftedClip(SkRect* dst, const SkIRect& src, int shift) {
67 dst->set(SkIntToScalar(src.fLeft >> shift),
68 SkIntToScalar(src.fTop >> shift),
69 SkIntToScalar(src.fRight >> shift),
70 SkIntToScalar(src.fBottom >> shift));
71 }
72
build(const SkPath & path,const SkIRect * iclip,int shiftUp)73 int SkEdgeBuilder::build(const SkPath& path, const SkIRect* iclip,
74 int shiftUp) {
75 fAlloc.reset();
76 fList.reset();
77 fShiftUp = shiftUp;
78
79 SkPath::Iter iter(path, true);
80 SkPoint pts[4];
81 SkPath::Verb verb;
82
83 if (iclip) {
84 SkRect clip;
85 setShiftedClip(&clip, *iclip, shiftUp);
86 SkEdgeClipper clipper;
87
88 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
89 switch (verb) {
90 case SkPath::kMove_Verb:
91 case SkPath::kClose_Verb:
92 // we ignore these, and just get the whole segment from
93 // the corresponding line/quad/cubic verbs
94 break;
95 case SkPath::kLine_Verb: {
96 SkPoint lines[SkLineClipper::kMaxPoints];
97 int lineCount = SkLineClipper::ClipLine(pts, clip, lines);
98 for (int i = 0; i < lineCount; i++) {
99 this->addLine(&lines[i]);
100 }
101 break;
102 }
103 case SkPath::kQuad_Verb:
104 if (clipper.clipQuad(pts, clip)) {
105 this->addClipper(&clipper);
106 }
107 break;
108 case SkPath::kCubic_Verb:
109 if (clipper.clipCubic(pts, clip)) {
110 this->addClipper(&clipper);
111 }
112 break;
113 default:
114 SkASSERT(!"unexpected verb");
115 break;
116 }
117 }
118 } else {
119 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
120 switch (verb) {
121 case SkPath::kMove_Verb:
122 case SkPath::kClose_Verb:
123 // we ignore these, and just get the whole segment from
124 // the corresponding line/quad/cubic verbs
125 break;
126 case SkPath::kLine_Verb:
127 this->addLine(pts);
128 break;
129 case SkPath::kQuad_Verb: {
130 SkPoint monoX[5];
131 int n = SkChopQuadAtYExtrema(pts, monoX);
132 for (int i = 0; i <= n; i++) {
133 this->addQuad(&monoX[i * 2]);
134 }
135 break;
136 }
137 case SkPath::kCubic_Verb: {
138 SkPoint monoY[10];
139 int n = SkChopCubicAtYExtrema(pts, monoY);
140 for (int i = 0; i <= n; i++) {
141 this->addCubic(&monoY[i * 3]);
142 }
143 break;
144 }
145 default:
146 SkASSERT(!"unexpected verb");
147 break;
148 }
149 }
150 }
151 return fList.count();
152 }
153
154
155