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