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