• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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