OLD | NEW |
| (Empty) |
1 /* libs/graphics/effects/SkCornerPathEffect.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkCornerPathEffect.h" | |
19 #include "SkPath.h" | |
20 #include "SkPoint.h" | |
21 #include "SkBuffer.h" | |
22 | |
23 SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) : fRadius(radius) | |
24 { | |
25 } | |
26 | |
27 SkCornerPathEffect::~SkCornerPathEffect() | |
28 { | |
29 } | |
30 | |
31 static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, SkP
oint* step) | |
32 { | |
33 SkScalar dist = SkPoint::Distance(a, b); | |
34 | |
35 step->set(b.fX - a.fX, b.fY - a.fY); | |
36 | |
37 if (dist <= radius * 2) { | |
38 step->scale(SK_ScalarHalf); | |
39 return false; | |
40 } | |
41 else { | |
42 step->scale(SkScalarDiv(radius, dist)); | |
43 return true; | |
44 } | |
45 } | |
46 | |
47 bool SkCornerPathEffect::filterPath(SkPath* dst, const SkPath& src, SkScalar* wi
dth) | |
48 { | |
49 if (fRadius == 0) | |
50 return false; | |
51 | |
52 SkPath::Iter iter(src, false); | |
53 SkPath::Verb verb, prevVerb = (SkPath::Verb)-1; | |
54 SkPoint pts[4]; | |
55 | |
56 bool closed; | |
57 SkPoint moveTo, lastCorner; | |
58 SkVector firstStep, step; | |
59 bool prevIsValid = true; | |
60 | |
61 // to avoid warnings | |
62 moveTo.set(0, 0); | |
63 firstStep.set(0, 0); | |
64 lastCorner.set(0, 0); | |
65 | |
66 for (;;) { | |
67 switch (verb = iter.next(pts)) { | |
68 case SkPath::kMove_Verb: | |
69 closed = iter.isClosedContour(); | |
70 if (closed) { | |
71 moveTo = pts[0]; | |
72 prevIsValid = false; | |
73 } | |
74 else { | |
75 dst->moveTo(pts[0]); | |
76 prevIsValid = true; | |
77 } | |
78 break; | |
79 case SkPath::kLine_Verb: | |
80 { | |
81 bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); | |
82 // prev corner | |
83 if (!prevIsValid) { | |
84 dst->moveTo(moveTo + step); | |
85 prevIsValid = true; | |
86 } | |
87 else { | |
88 dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, pts[0
].fY + step.fY); | |
89 } | |
90 if (drawSegment) { | |
91 dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); | |
92 } | |
93 lastCorner = pts[1]; | |
94 prevIsValid = true; | |
95 } | |
96 break; | |
97 case SkPath::kQuad_Verb: | |
98 // TBD - just replicate the curve for now | |
99 if (!prevIsValid) | |
100 { | |
101 dst->moveTo(pts[0]); | |
102 prevIsValid = true; | |
103 } | |
104 dst->quadTo(pts[1], pts[2]); | |
105 lastCorner = pts[2]; | |
106 firstStep.set(0, 0); | |
107 break; | |
108 case SkPath::kCubic_Verb: | |
109 if (!prevIsValid) | |
110 { | |
111 dst->moveTo(pts[0]); | |
112 prevIsValid = true; | |
113 } | |
114 // TBD - just replicate the curve for now | |
115 dst->cubicTo(pts[1], pts[2], pts[3]); | |
116 lastCorner = pts[3]; | |
117 firstStep.set(0, 0); | |
118 break; | |
119 case SkPath::kClose_Verb: | |
120 if (firstStep.fX || firstStep.fY) | |
121 dst->quadTo(lastCorner.fX, lastCorner.fY, | |
122 lastCorner.fX + firstStep.fX, | |
123 lastCorner.fY + firstStep.fY); | |
124 dst->close(); | |
125 break; | |
126 case SkPath::kDone_Verb: | |
127 goto DONE; | |
128 } | |
129 | |
130 if (SkPath::kMove_Verb == prevVerb) | |
131 firstStep = step; | |
132 prevVerb = verb; | |
133 } | |
134 DONE: | |
135 return true; | |
136 } | |
137 | |
138 SkFlattenable::Factory SkCornerPathEffect::getFactory() | |
139 { | |
140 return CreateProc; | |
141 } | |
142 | |
143 void SkCornerPathEffect::flatten(SkFlattenableWriteBuffer& buffer) | |
144 { | |
145 buffer.writeScalar(fRadius); | |
146 } | |
147 | |
148 SkFlattenable* SkCornerPathEffect::CreateProc(SkFlattenableReadBuffer& buffer) | |
149 { | |
150 return SkNEW_ARGS(SkCornerPathEffect, (buffer)); | |
151 } | |
152 | |
153 SkCornerPathEffect::SkCornerPathEffect(SkFlattenableReadBuffer& buffer) | |
154 { | |
155 fRadius = buffer.readScalar(); | |
156 } | |
157 | |
OLD | NEW |