52static const int kPtCount[] = { 1, 1, 2, 2, 3, 0 };
53static const int kPtIndex[] = { 0, 1, 1, 1, 1, 0 };
62 bounds.setBounds(pts,
kPtCount[verb] + 1);
63 if (bounds.fTop > edge.
fY) {
66 if (bounds.fBottom <= edge.
fY) {
69 if (bounds.fLeft >= edge.
fX) {
79 for (
int index = 0; index <
count; ) {
81 if (intersectX < edge.
fX) {
85 if (intersectX > edge.
fX) {
86 tVals[index] = tVals[--
count];
97 tVals[index] = tVals[--
count];
100 for (
int index = 0; index <
count; ++index) {
103 for (
int index = 0; index <
count; ++index) {
108 winding += (
int) directions[index];
123 result = pts[0].
fX < pts[1].
fX ? pts[0] : pts[1];
133 result = pts[0].
fX < pts[2].
fX ? pts[0] : pts[2];
137 conic.set(pts, weight);
138 if (!conic.monotonicInX()) {
142 result = conic.ptAtT(t).asSkPoint();
144 result = pts[0].
fX < pts[2].
fX ? pts[0] : pts[2];
150 if (!cubic.monotonicInX()) {
154 for (
int index = 0; index < roots; ++index) {
155 SkPoint temp = cubic.ptAtT(tValues[index]).asSkPoint();
156 if (0 == index ||
result.fX > temp.
fX) {
162 result = cubic.ptAtT(t).asSkPoint();
164 result = pts[0].
fX < pts[3].
fX ? pts[0] : pts[3];
188 if (!bounds.isEmpty()) {
189 containers->emplace_back(bounds, lastStart, verbStart);
190 lastStart = verbStart;
197 bounds.joinPossiblyEmptyRect(verbBounds);
201 if (!bounds.isEmpty()) {
202 containers->emplace_back(bounds, lastStart, ++verbStart);
214 verb = iter.
next(pts);
215 if (++verbCount <
contour.fVerbStart) {
218 if (verbCount >=
contour.fVerbEnd) {
228 total_signed_area += (pts[0].
fY - pts[1].
fY) * (pts[0].fX + pts[1].fX);
232 total_signed_area += (pts[0].
fY - pts[2].
fY) * (pts[0].fX + pts[2].fX);
235 total_signed_area += (pts[0].
fY - pts[3].
fY) * (pts[0].fX + pts[3].fX);
252 verb = iter.
next(pts);
253 if (++verbCount <
contour.fVerbStart) {
256 if (verbCount >=
contour.fVerbEnd) {
262 bool horizontal =
true;
263 for (
int index = 1; index <=
kPtCount[verb]; ++index) {
264 if (pts[0].fY != pts[index].fY) {
272 if (edge == Edge::kCompare) {
297 this->
nextEdge(test, Edge::kInitial);
301 int winding = this->
nextEdge(contour, Edge::kCompare);
304 test.fContained = winding != 0;
305 return -1 <= winding && winding <= 1;
318 if (
contour.fBounds.contains((*iter)->fBounds)) {
319 contour.fChildren.push_back(*iter);
329 for (
auto grandChild : child->
fChildren) {
343 bool reversed =
false;
344 for (
auto grandChild : child->
fChildren) {
345 reversed |=
markReverse(grandChild->fContained ? child : parent, grandChild);
359 auto iter = iterate.
begin();
367 for (; iter != iterate.
end() && verbCount <
contour.fVerbEnd; ++iter, ++verbCount) {
368 auto [verb, pts,
w] = *iter;
377 temp->
quadTo(pts[1], pts[2]);
383 temp->
cubicTo(pts[1], pts[2], pts[3]);
404 result->setFillType(fillType);
409 if (!path.isFinite()) {
419 if (path.isEmpty() || path.isConvex()) {
423 vector<Contour> contours;
426 if (contours.size() <= 1) {
431 for (
auto&
contour : contours) {
436 [](
const Contour*
contour) ->
bool { return contour->fChildren.empty(); } )) {
448 bool reversed =
false;
static bool between(SkScalar a, SkScalar b, SkScalar c)
#define SK_INIT_TO_AVOID_WARNING
static bool set_result_path(SkPath *result, const SkPath &path, SkPathFillType fillType)
static Contour::Direction to_direction(SkScalar dy)
static SkPoint left_edge(SkPoint pts[4], SkPath::Verb verb, SkScalar weight)
static const int kPtIndex[]
static SkScalar conic_weight(const SkPath::Iter &iter, SkPath::Verb verb)
static int contains_edge(SkPoint pts[4], SkPath::Verb verb, SkScalar weight, const SkPoint &edge)
static const int kPtCount[]
bool AsWinding(const SkPath &path, SkPath *result)
static int(*const CurveIntercept[])(const SkPoint[], SkScalar, SkScalar, double *)
static SkPoint(*const CurvePointAtT[])(const SkPoint[], SkScalar, double)
static SkVector(*const CurveSlopeAtT[])(const SkPoint[], SkScalar, double)
bool zero_or_one(double x)
@ kClose
SkPath::RawIter returns 0 points.
@ kCubic
SkPath::RawIter returns 4 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
Type::kYUV Type::kRGBA() int(0.7 *637)
bool containerContains(Contour &contour, Contour &test)
int nextEdge(Contour &contour, Edge edge)
SkPath reverseMarkedContours(vector< Contour > &contours, SkPathFillType fillType)
void inParent(Contour &contour, Contour &parent)
Contour::Direction getDirection(Contour &contour)
bool markReverse(Contour *parent, Contour *child)
void contourBounds(vector< Contour > *containers)
bool checkContainerChildren(Contour *parent, Contour *child)
OpAsWinding(const SkPath &path)
SkPathBuilder & conicTo(SkPoint pt1, SkPoint pt2, SkScalar w)
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & setFillType(SkPathFillType ft)
SkPathBuilder & cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3)
SkPathBuilder & moveTo(SkPoint pt)
SkPathBuilder & quadTo(SkPoint pt1, SkPoint pt2)
static void ReverseAddPath(SkPathBuilder *builder, const SkPath &reverseMe)
Verb next(SkPoint pts[4])
SkScalar conicWeight() const
Contour(const SkRect &bounds, int lastStart, int verbStart)
vector< Contour * > fChildren
static int FindExtrema(const double src[], SkScalar weight, double tValue[1])
static int FindExtrema(const double src[], double tValue[2])
SkPoint asSkPoint() const
const SkDQuad & set(const SkPoint pts[kPointCount] SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
bool monotonicInX() const
static int FindExtrema(const double src[], double tValue[1])
SkDPoint ptAtT(double t) const
SkPath::RangeIter begin()
void setBounds(const SkPoint pts[], int count)