Flutter Engine
The Flutter Engine
SkStrokerPriv.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8
10#include "include/core/SkPath.h"
12#include "src/core/SkGeometry.h"
14
15#include <utility>
16
17static void ButtCapper(SkPath* path, const SkPoint& pivot, const SkVector& normal,
18 const SkPoint& stop, SkPath*) {
19 path->lineTo(stop.fX, stop.fY);
20}
21
22static void RoundCapper(SkPath* path, const SkPoint& pivot, const SkVector& normal,
23 const SkPoint& stop, SkPath*) {
24 SkVector parallel;
25 SkPointPriv::RotateCW(normal, &parallel);
26
27 SkPoint projectedCenter = pivot + parallel;
28
29 path->conicTo(projectedCenter + normal, projectedCenter, SK_ScalarRoot2Over2);
30 path->conicTo(projectedCenter - normal, stop, SK_ScalarRoot2Over2);
31}
32
33static void SquareCapper(SkPath* path, const SkPoint& pivot, const SkVector& normal,
34 const SkPoint& stop, SkPath* otherPath) {
35 SkVector parallel;
36 SkPointPriv::RotateCW(normal, &parallel);
37
38 if (otherPath) {
39 path->setLastPt(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY);
40 path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY);
41 } else {
42 path->lineTo(pivot.fX + normal.fX + parallel.fX, pivot.fY + normal.fY + parallel.fY);
43 path->lineTo(pivot.fX - normal.fX + parallel.fX, pivot.fY - normal.fY + parallel.fY);
44 path->lineTo(stop.fX, stop.fY);
45 }
46}
47
48/////////////////////////////////////////////////////////////////////////////
49
50static bool is_clockwise(const SkVector& before, const SkVector& after) {
51 return before.fX * after.fY > before.fY * after.fX;
52}
53
59};
60
62// need more precise fixed normalization
63// SkASSERT(SkScalarAbs(dot) <= SK_Scalar1 + SK_ScalarNearlyZero);
64
65 if (dot >= 0) { // shallow or line
67 } else { // sharp or 180
69 }
70}
71
72static void HandleInnerJoin(SkPath* inner, const SkPoint& pivot, const SkVector& after) {
73#if 1
74 /* In the degenerate case that the stroke radius is larger than our segments
75 just connecting the two inner segments may "show through" as a funny
76 diagonal. To pseudo-fix this, we go through the pivot point. This adds
77 an extra point/edge, but I can't see a cheap way to know when this is
78 not needed :(
79 */
80 inner->lineTo(pivot.fX, pivot.fY);
81#endif
82
83 inner->lineTo(pivot.fX - after.fX, pivot.fY - after.fY);
84}
85
86static void BluntJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal,
87 const SkPoint& pivot, const SkVector& afterUnitNormal,
88 SkScalar radius, SkScalar invMiterLimit, bool, bool) {
89 SkVector after;
90 afterUnitNormal.scale(radius, &after);
91
92 if (!is_clockwise(beforeUnitNormal, afterUnitNormal)) {
93 using std::swap;
94 swap(outer, inner);
95 after.negate();
96 }
97
98 outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY);
99 HandleInnerJoin(inner, pivot, after);
100}
101
102static void RoundJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal,
103 const SkPoint& pivot, const SkVector& afterUnitNormal,
104 SkScalar radius, SkScalar invMiterLimit, bool, bool) {
105 SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal);
106 AngleType angleType = Dot2AngleType(dotProd);
107
108 if (angleType == kNearlyLine_AngleType)
109 return;
110
111 SkVector before = beforeUnitNormal;
112 SkVector after = afterUnitNormal;
114
115 if (!is_clockwise(before, after)) {
116 using std::swap;
117 swap(outer, inner);
118 before.negate();
119 after.negate();
121 }
122
124 matrix.setScale(radius, radius);
125 matrix.postTranslate(pivot.fX, pivot.fY);
127 int count = SkConic::BuildUnitArc(before, after, dir, &matrix, conics);
128 if (count > 0) {
129 for (int i = 0; i < count; ++i) {
130 outer->conicTo(conics[i].fPts[1], conics[i].fPts[2], conics[i].fW);
131 }
132 after.scale(radius);
133 HandleInnerJoin(inner, pivot, after);
134 }
135}
136
137#define kOneOverSqrt2 (0.707106781f)
138
139static void MiterJoiner(SkPath* outer, SkPath* inner, const SkVector& beforeUnitNormal,
140 const SkPoint& pivot, const SkVector& afterUnitNormal,
141 SkScalar radius, SkScalar invMiterLimit,
142 bool prevIsLine, bool currIsLine) {
143 // negate the dot since we're using normals instead of tangents
144 SkScalar dotProd = SkPoint::DotProduct(beforeUnitNormal, afterUnitNormal);
145 AngleType angleType = Dot2AngleType(dotProd);
146 SkVector before = beforeUnitNormal;
147 SkVector after = afterUnitNormal;
148 SkVector mid;
149 SkScalar sinHalfAngle;
150 bool ccw;
151
152 if (angleType == kNearlyLine_AngleType) {
153 return;
154 }
155 if (angleType == kNearly180_AngleType) {
156 currIsLine = false;
157 goto DO_BLUNT;
158 }
159
160 ccw = !is_clockwise(before, after);
161 if (ccw) {
162 using std::swap;
163 swap(outer, inner);
164 before.negate();
165 after.negate();
166 }
167
168 /* Before we enter the world of square-roots and divides,
169 check if we're trying to join an upright right angle
170 (common case for stroking rectangles). If so, special case
171 that (for speed an accuracy).
172 Note: we only need to check one normal if dot==0
173 */
174 if (0 == dotProd && invMiterLimit <= kOneOverSqrt2) {
175 mid = (before + after) * radius;
176 goto DO_MITER;
177 }
178
179 /* midLength = radius / sinHalfAngle
180 if (midLength > miterLimit * radius) abort
181 if (radius / sinHalf > miterLimit * radius) abort
182 if (1 / sinHalf > miterLimit) abort
183 if (1 / miterLimit > sinHalf) abort
184 My dotProd is opposite sign, since it is built from normals and not tangents
185 hence 1 + dot instead of 1 - dot in the formula
186 */
187 sinHalfAngle = SkScalarSqrt(SkScalarHalf(SK_Scalar1 + dotProd));
188 if (sinHalfAngle < invMiterLimit) {
189 currIsLine = false;
190 goto DO_BLUNT;
191 }
192
193 // choose the most accurate way to form the initial mid-vector
194 if (angleType == kSharp_AngleType) {
195 mid.set(after.fY - before.fY, before.fX - after.fX);
196 if (ccw) {
197 mid.negate();
198 }
199 } else {
200 mid.set(before.fX + after.fX, before.fY + after.fY);
201 }
202
203 mid.setLength(radius / sinHalfAngle);
204DO_MITER:
205 if (prevIsLine) {
206 outer->setLastPt(pivot.fX + mid.fX, pivot.fY + mid.fY);
207 } else {
208 outer->lineTo(pivot.fX + mid.fX, pivot.fY + mid.fY);
209 }
210
211DO_BLUNT:
212 after.scale(radius);
213 if (!currIsLine) {
214 outer->lineTo(pivot.fX + after.fX, pivot.fY + after.fY);
215 }
216 HandleInnerJoin(inner, pivot, after);
217}
218
219/////////////////////////////////////////////////////////////////////////////
220
222 const SkStrokerPriv::CapProc gCappers[] = {
224 };
225
226 SkASSERT((unsigned)cap < SkPaint::kCapCount);
227 return gCappers[cap];
228}
229
231 const SkStrokerPriv::JoinProc gJoiners[] = {
233 };
234
235 SkASSERT((unsigned)join < SkPaint::kJoinCount);
236 return gJoiners[join];
237}
SkPoint fPts[2]
int count
Definition: FontMgrTest.cpp:50
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkRotationDirection
Definition: SkGeometry.h:321
@ kCW_SkRotationDirection
Definition: SkGeometry.h:322
@ kCCW_SkRotationDirection
Definition: SkGeometry.h:323
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
#define SK_Scalar1
Definition: SkScalar.h:18
#define SkScalarHalf(a)
Definition: SkScalar.h:75
#define SkScalarSqrt(x)
Definition: SkScalar.h:42
#define SK_ScalarRoot2Over2
Definition: SkScalar.h:23
static void MiterJoiner(SkPath *outer, SkPath *inner, const SkVector &beforeUnitNormal, const SkPoint &pivot, const SkVector &afterUnitNormal, SkScalar radius, SkScalar invMiterLimit, bool prevIsLine, bool currIsLine)
static AngleType Dot2AngleType(SkScalar dot)
static bool is_clockwise(const SkVector &before, const SkVector &after)
#define kOneOverSqrt2
static void RoundCapper(SkPath *path, const SkPoint &pivot, const SkVector &normal, const SkPoint &stop, SkPath *)
static void HandleInnerJoin(SkPath *inner, const SkPoint &pivot, const SkVector &after)
AngleType
@ kNearly180_AngleType
@ kSharp_AngleType
@ kNearlyLine_AngleType
@ kShallow_AngleType
static void BluntJoiner(SkPath *outer, SkPath *inner, const SkVector &beforeUnitNormal, const SkPoint &pivot, const SkVector &afterUnitNormal, SkScalar radius, SkScalar invMiterLimit, bool, bool)
static void RoundJoiner(SkPath *outer, SkPath *inner, const SkVector &beforeUnitNormal, const SkPoint &pivot, const SkVector &afterUnitNormal, SkScalar radius, SkScalar invMiterLimit, bool, bool)
static void ButtCapper(SkPath *path, const SkPoint &pivot, const SkVector &normal, const SkPoint &stop, SkPath *)
static void SquareCapper(SkPath *path, const SkPoint &pivot, const SkVector &normal, const SkPoint &stop, SkPath *otherPath)
static constexpr int kCapCount
Definition: SkPaint.h:343
static constexpr int kJoinCount
Definition: SkPaint.h:368
Definition: SkPath.h:59
void setLastPt(SkScalar x, SkScalar y)
Definition: SkPath.cpp:608
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
SkPath & conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar w)
Definition: SkPath.cpp:766
static void RotateCW(const SkPoint &src, SkPoint *dst)
Definition: SkPointPriv.h:83
void(* JoinProc)(SkPath *outer, SkPath *inner, const SkVector &beforeUnitNormal, const SkPoint &pivot, const SkVector &afterUnitNormal, SkScalar radius, SkScalar invMiterLimit, bool prevIsLine, bool currIsLine)
Definition: SkStrokerPriv.h:36
static CapProc CapFactory(SkPaint::Cap)
static JoinProc JoinFactory(SkPaint::Join)
void(* CapProc)(SkPath *path, const SkPoint &pivot, const SkVector &normal, const SkPoint &stop, SkPath *otherPath)
Definition: SkStrokerPriv.h:30
float SkScalar
Definition: extension.cpp:12
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
Definition: switches.h:145
SINT T dot(const Vec< N, T > &a, const Vec< N, T > &b)
Definition: SkVx.h:964
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
@ kMaxConicsForArc
Definition: SkGeometry.h:411
static int BuildUnitArc(const SkVector &start, const SkVector &stop, SkRotationDirection, const SkMatrix *, SkConic conics[kMaxConicsForArc])
void negate()
Definition: SkPoint_impl.h:357
bool setLength(float length)
Definition: SkPoint.cpp:30
float fX
x-axis value
Definition: SkPoint_impl.h:164
static float DotProduct(const SkVector &a, const SkVector &b)
Definition: SkPoint_impl.h:518
void set(float x, float y)
Definition: SkPoint_impl.h:200
void scale(float scale, SkPoint *dst) const
Definition: SkPoint.cpp:17
float fY
y-axis value
Definition: SkPoint_impl.h:165