Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(566)

Side by Side Diff: skia/sgl/SkStrokerPriv.cpp

Issue 113827: Remove the remainder of the skia source code from the Chromium repo.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « skia/sgl/SkStrokerPriv.h ('k') | skia/sgl/SkTSearch.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* libs/graphics/sgl/SkStrokerPriv.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 "SkStrokerPriv.h"
19 #include "SkGeometry.h"
20 #include "SkPath.h"
21
22 static void ButtCapper(SkPath* path, const SkPoint& pivot,
23 const SkVector& normal, const SkPoint& stop,
24 SkPath*)
25 {
26 path->lineTo(stop.fX, stop.fY);
27 }
28
29 static void RoundCapper(SkPath* path, const SkPoint& pivot,
30 const SkVector& normal, const SkPoint& stop,
31 SkPath*)
32 {
33 SkScalar px = pivot.fX;
34 SkScalar py = pivot.fY;
35 SkScalar nx = normal.fX;
36 SkScalar ny = normal.fY;
37 SkScalar sx = SkScalarMul(nx, CUBIC_ARC_FACTOR);
38 SkScalar sy = SkScalarMul(ny, CUBIC_ARC_FACTOR);
39
40 path->cubicTo(px + nx + CWX(sx, sy), py + ny + CWY(sx, sy),
41 px + CWX(nx, ny) + sx, py + CWY(nx, ny) + sy,
42 px + CWX(nx, ny), py + CWY(nx, ny));
43 path->cubicTo(px + CWX(nx, ny) - sx, py + CWY(nx, ny) - sy,
44 px - nx + CWX(sx, sy), py - ny + CWY(sx, sy),
45 stop.fX, stop.fY);
46 }
47
48 static void SquareCapper(SkPath* path, const SkPoint& pivot,
49 const SkVector& normal, const SkPoint& stop,
50 SkPath* otherPath)
51 {
52 SkVector parallel;
53 normal.rotateCW(&parallel);
54
55 if (otherPath)
56 {
57 path->setLastPt(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY);
58 path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY);
59 }
60 else
61 {
62 path->lineTo(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY);
63 path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY);
64 path->lineTo(stop.fX, stop.fY);
65 }
66 }
67
68 /////////////////////////////////////////////////////////////////////////////
69
70 static bool is_clockwise(const SkVector& before, const SkVector& after)
71 {
72 return SkScalarMul(before.fX, after.fY) - SkScalarMul(before.fY, after.fX) > 0;
73 }
74
75 enum AngleType {
76 kNearly180_AngleType,
77 kSharp_AngleType,
78 kShallow_AngleType,
79 kNearlyLine_AngleType
80 };
81
82 static AngleType Dot2AngleType(SkScalar dot)
83 {
84 // need more precise fixed normalization
85 // SkASSERT(SkScalarAbs(dot) <= SK_Scalar1 + SK_ScalarNearlyZero);
86
87 if (dot >= 0) // shallow or line
88 return SkScalarNearlyZero(SK_Scalar1 - dot) ? kNearlyLine_AngleType : kS hallow_AngleType;
89 else // sharp or 180
90 return SkScalarNearlyZero(SK_Scalar1 + dot) ? kNearly180_AngleType : kSh arp_AngleType;
91 }
92
93 static void HandleInnerJoin(SkPath* inner, const SkPoint& pivot, const SkVector& after)
94 {
95 #if 1
96 /* In the degenerate case that the stroke radius is larger than our segment s
97 just connecting the two inner segments may "show through" as a funny
98 diagonal. To pseudo-fix this, we go through the pivot point. This adds
99 an extra point/edge, but I can't see a cheap way to know when this is
100 not needed :(
101 */
102 inner->lineTo(pivot.fX, pivot.fY);
103 #endif
104
105 inner->lineTo(pivot.fX - after.fX, pivot.fY - after.fY);
106 }
107
108 static void BluntJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnit Normal,
109 const SkPoint& pivot, const SkVector& afterUnitNormal,
110 SkScalar radius, SkScalar invMiterLimit, bool, bool)
111 {
112 SkVector after;
113 afterUnitNormal.scale(radius, &after);
114
115 if (!is_clockwise(beforeUnitNormal, afterUnitNormal))
116 {
117 SkTSwap<SkPath*>(outer, inner);
118 after.negate();
119 }
120
121 outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY);
122 HandleInnerJoin(inner, pivot, after);
123 }
124
125 static void RoundJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnit Normal,
126 const SkPoint& pivot, const SkVector& afterUnitNormal,
127 SkScalar radius, SkScalar invMiterLimit, bool, bool)
128 {
129 SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal) ;
130 AngleType angleType = Dot2AngleType(dotProd);
131
132 if (angleType == kNearlyLine_AngleType)
133 return;
134
135 SkVector before = beforeUnitNormal;
136 SkVector after = afterUnitNormal;
137 SkRotationDirection dir = kCW_SkRotationDirection;
138
139 if (!is_clockwise(before, after))
140 {
141 SkTSwap<SkPath*>(outer, inner);
142 before.negate();
143 after.negate();
144 dir = kCCW_SkRotationDirection;
145 }
146
147 SkPoint pts[kSkBuildQuadArcStorage];
148 SkMatrix matrix;
149 matrix.setScale(radius, radius);
150 matrix.postTranslate(pivot.fX, pivot.fY);
151 int count = SkBuildQuadArc(before, after, dir, &matrix, pts);
152 SkASSERT((count & 1) == 1);
153
154 if (count > 1)
155 {
156 for (int i = 1; i < count; i += 2)
157 outer->quadTo(pts[i].fX, pts[i].fY, pts[i+1].fX, pts[i+1].fY);
158
159 after.scale(radius);
160 HandleInnerJoin(inner, pivot, after);
161 }
162 }
163
164 #ifdef SK_SCALAR_IS_FLOAT
165 #define kOneOverSqrt2 (0.707106781f)
166 #else
167 #define kOneOverSqrt2 (46341)
168 #endif
169
170 static void MiterJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnit Normal,
171 const SkPoint& pivot, const SkVector& afterUnitNormal,
172 SkScalar radius, SkScalar invMiterLimit,
173 bool prevIsLine, bool currIsLine)
174 {
175 // negate the dot since we're using normals instead of tangents
176 SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal) ;
177 AngleType angleType = Dot2AngleType(dotProd);
178 SkVector before = beforeUnitNormal;
179 SkVector after = afterUnitNormal;
180 SkVector mid;
181 SkScalar sinHalfAngle;
182 bool ccw;
183
184 if (angleType == kNearlyLine_AngleType)
185 return;
186 if (angleType == kNearly180_AngleType)
187 {
188 currIsLine = false;
189 goto DO_BLUNT;
190 }
191
192 ccw = !is_clockwise(before, after);
193 if (ccw)
194 {
195 SkTSwap<SkPath*>(outer, inner);
196 before.negate();
197 after.negate();
198 }
199
200 /* Before we enter the world of square-roots and divides,
201 check if we're trying to join an upright right angle
202 (common case for stroking rectangles). If so, special case
203 that (for speed an accuracy).
204 Note: we only need to check one normal if dot==0
205 */
206 if (0 == dotProd && invMiterLimit <= kOneOverSqrt2)
207 {
208 mid.set(SkScalarMul(before.fX + after.fX, radius),
209 SkScalarMul(before.fY + after.fY, radius));
210 goto DO_MITER;
211 }
212
213 /* midLength = radius / sinHalfAngle
214 if (midLength > miterLimit * radius) abort
215 if (radius / sinHalf > miterLimit * radius) abort
216 if (1 / sinHalf > miterLimit) abort
217 if (1 / miterLimit > sinHalf) abort
218 My dotProd is opposite sign, since it is built from normals and not tang ents
219 hence 1 + dot instead of 1 - dot in the formula
220 */
221 sinHalfAngle = SkScalarSqrt(SkScalarHalf(SK_Scalar1 + dotProd));
222 if (sinHalfAngle < invMiterLimit)
223 {
224 currIsLine = false;
225 goto DO_BLUNT;
226 }
227
228 // choose the most accurate way to form the initial mid-vector
229 if (angleType == kSharp_AngleType)
230 {
231 mid.set(after.fY - before.fY, before.fX - after.fX);
232 if (ccw)
233 mid.negate();
234 }
235 else
236 mid.set(before.fX + after.fX, before.fY + after.fY);
237
238 mid.setLength(SkScalarDiv(radius, sinHalfAngle));
239 DO_MITER:
240 if (prevIsLine)
241 outer->setLastPt(pivot.fX + mid.fX, pivot.fY + mid.fY);
242 else
243 outer->lineTo(pivot.fX + mid.fX, pivot.fY + mid.fY);
244
245 DO_BLUNT:
246 after.scale(radius);
247 if (!currIsLine)
248 outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY);
249 HandleInnerJoin(inner, pivot, after);
250 }
251
252 /////////////////////////////////////////////////////////////////////////////
253
254 SkStrokerPriv::CapProc SkStrokerPriv::CapFactory(SkPaint::Cap cap)
255 {
256 static const SkStrokerPriv::CapProc gCappers[] = {
257 ButtCapper, RoundCapper, SquareCapper
258 };
259
260 SkASSERT((unsigned)cap < SkPaint::kCapCount);
261 return gCappers[cap];
262 }
263
264 SkStrokerPriv::JoinProc SkStrokerPriv::JoinFactory(SkPaint::Join join)
265 {
266 static const SkStrokerPriv::JoinProc gJoiners[] = {
267 MiterJoiner, RoundJoiner, BluntJoiner
268 };
269
270 SkASSERT((unsigned)join < SkPaint::kJoinCount);
271 return gJoiners[join];
272 }
273
274
275
OLDNEW
« no previous file with comments | « skia/sgl/SkStrokerPriv.h ('k') | skia/sgl/SkTSearch.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698