6#include <private/qbezier_p.h>
7#include <private/qdatabuffer_p.h>
8#include <private/qnumeric_p.h>
34 if (
sizeof(
qreal) ==
sizeof(
double))
35 return qAbs(
d) <= 1e-12;
37 return qAbs(
d) <= 1e-5f;
49 return a.x() *
b.x() +
a.y() *
b.y();
54 double reciprocal = 1 /
qSqrt(
x *
x +
y *
y);
78bool QIntersectionFinder::linesIntersect(
const QLineF &
a,
const QLineF &
b)
const
92 if (p1_equals_q1 && p2_equals_q2)
98 if (p1_equals_q2 && p2_equals_q1)
102 const QPointF qDelta = q2 - q1;
104 const qreal par = pDelta.
x() * qDelta.y() - pDelta.y() * qDelta.x();
107 const QPointF normal(-pDelta.y(), pDelta.x());
111 const qreal dp =
dot(pDelta, pDelta);
116 if ((tq1 > 0 && tq1 < dp) || (tq2 > 0 && tq2 < dp))
119 const qreal dq =
dot(qDelta, qDelta);
124 if ((tp1 > 0 && tp1 < dq) || (tp2 > 0 && tp2 < dq))
131 const qreal invPar = 1 / par;
133 const qreal tp = (qDelta.y() * (q1.x() -
p1.x()) -
134 qDelta.x() * (q1.y() -
p1.y())) * invPar;
136 if (tp < 0 || tp > 1)
139 const qreal tq = (pDelta.y() * (q1.x() -
p1.x()) -
140 pDelta.x() * (q1.y() -
p1.y())) * invPar;
142 return tq >= 0 && tq <= 1;
147 if (
a.segments() == 0 ||
b.segments() == 0)
150 const QRectF &rb0 =
b.elementBounds(0);
157 for (
int i = 1;
i <
b.segments(); ++
i) {
159 minX =
qMin(minX,
r.left());
167 for (
int i = 0;
i <
a.segments(); ++
i) {
175 for (
int j = 0;
j <
b.segments(); ++
j) {
183 if (linesIntersect(
a.lineAt(
i),
b.lineAt(
j)))
199 int lowestRightIndex;
226 void produceIntersections(
int segment);
229 TreeNode buildTree(
int first,
int last,
int depth,
const RectF &bounds);
231 void produceIntersectionsLeaf(
const TreeNode &node,
int segment);
232 void produceIntersections(
const TreeNode &node,
int segment,
const RectF &segmentBounds,
const RectF &nodeBounds,
int axis);
233 void intersectLines(
const QLineF &
a,
const QLineF &
b, QDataBuffer<QIntersection> &intersections);
240 QList<TreeNode> m_tree;
241 QDataBuffer<QIntersection> m_intersections;
253 m_index.resize(m_segments.segments());
255 for (
int i = 0;
i < m_index.size(); ++
i) {
258 const QRectF &segmentBounds = m_segments.elementBounds(
i);
260 if (segmentBounds.left() < m_bounds.x1)
261 m_bounds.x1 = segmentBounds.
left();
262 if (segmentBounds.top() < m_bounds.y1)
263 m_bounds.y1 = segmentBounds.top();
264 if (segmentBounds.right() > m_bounds.x2)
265 m_bounds.x2 = segmentBounds.right();
266 if (segmentBounds.bottom() > m_bounds.y2)
267 m_bounds.y2 = segmentBounds.bottom();
272 TreeNode root = buildTree(0, m_index.size(), 0, m_bounds);
278 return axis == 0 ?
pos.x() :
pos.y();
281TreeNode SegmentTree::buildTree(
int first,
int last,
int depth,
const RectF &bounds)
286 node.index.interval.first =
first;
287 node.index.interval.last = last;
292 int splitAxis = (
depth & 1);
297 qreal split = 0.5f * ((&bounds.x1)[splitAxis] + (&bounds.x2)[splitAxis]);
299 node.splitLeft = (&bounds.x1)[splitAxis];
300 node.splitRight = (&bounds.x2)[splitAxis];
302 node.lowestLeftIndex = INT_MAX;
303 node.lowestRightIndex = INT_MAX;
305 const int treeSize = m_tree.size();
307 node.index.children.left = treeSize;
308 node.index.children.right = treeSize + 1;
310 m_tree.resize(treeSize + 2);
317 const int index = m_index.
at(l);
320 qreal lowCoordinate = coordinate(segmentBounds.topLeft(), splitAxis);
322 if (coordinate(segmentBounds.center(), splitAxis) <
split) {
323 qreal highCoordinate = coordinate(segmentBounds.bottomRight(), splitAxis);
324 if (highCoordinate > node.splitLeft)
325 node.splitLeft = highCoordinate;
326 if (
index < node.lowestLeftIndex)
327 node.lowestLeftIndex =
index;
330 if (lowCoordinate < node.splitRight)
331 node.splitRight = lowCoordinate;
332 if (
index < node.lowestRightIndex)
333 node.lowestRightIndex =
index;
334 qSwap(m_index[l], m_index[
r]);
339 RectF lbounds = bounds;
340 (&lbounds.x2)[splitAxis] = node.splitLeft;
342 RectF rbounds = bounds;
343 (&rbounds.x1)[splitAxis] = node.splitRight;
346 m_tree[node.index.children.left] =
left;
348 TreeNode
right = buildTree(l, last,
depth + 1, rbounds);
349 m_tree[node.index.children.right] =
right;
354void SegmentTree::intersectLines(
const QLineF &
a,
const QLineF &
b, QDataBuffer<QIntersection> &intersections)
368 if (p1_equals_q1 && p2_equals_q2)
374 if (p1_equals_q2 && p2_equals_q1)
378 const QPointF qDelta = q2 - q1;
380 const qreal par = pDelta.
x() * qDelta.y() - pDelta.y() * qDelta.x();
383 const QPointF normal(-pDelta.y(), pDelta.x());
387 const qreal invDp = 1 /
dot(pDelta, pDelta);
389 const qreal tq1 =
dot(pDelta, q1 -
p1) * invDp;
390 const qreal tq2 =
dot(pDelta, q2 -
p1) * invDp;
392 if (tq1 > 0 && tq1 < 1) {
394 intersection.
alphaA = tq1;
396 intersection.
pos = q1;
397 intersections.add(intersection);
400 if (tq2 > 0 && tq2 < 1) {
402 intersection.
alphaA = tq2;
404 intersection.
pos = q2;
405 intersections.add(intersection);
408 const qreal invDq = 1 /
dot(qDelta, qDelta);
410 const qreal tp1 =
dot(qDelta,
p1 - q1) * invDq;
411 const qreal tp2 =
dot(qDelta,
p2 - q1) * invDq;
413 if (tp1 > 0 && tp1 < 1) {
416 intersection.
alphaB = tp1;
417 intersection.
pos =
p1;
418 intersections.add(intersection);
421 if (tp2 > 0 && tp2 < 1) {
424 intersection.
alphaB = tp2;
425 intersection.
pos =
p2;
426 intersections.add(intersection);
435 if (p1_equals_q1 || p1_equals_q2 || p2_equals_q1 || p2_equals_q2)
439 const qreal tp = (qDelta.y() * (q1.x() -
p1.x()) -
440 qDelta.x() * (q1.y() -
p1.y())) / par;
441 const qreal tq = (pDelta.y() * (q1.x() -
p1.x()) -
442 pDelta.x() * (q1.y() -
p1.y())) / par;
444 if (tp<0 || tp>1 || tq<0 || tq>1)
453 if ((q_zero || q_one) && (p_zero || p_one))
466 pt = q1 + (q2 - q1) * tq;
472 intersection.
pos = pt;
473 intersections.add(intersection);
476void SegmentTree::produceIntersections(
int segment)
481 sbounds.x1 = segmentBounds.
left();
482 sbounds.y1 = segmentBounds.top();
483 sbounds.x2 = segmentBounds.right();
484 sbounds.y2 = segmentBounds.bottom();
486 produceIntersections(m_tree.at(0),
segment, sbounds, m_bounds, 0);
489void SegmentTree::produceIntersectionsLeaf(
const TreeNode &node,
int segment)
494 for (
int i = node.index.interval.first;
i < node.index.interval.last; ++
i) {
506 m_intersections.reset();
510 intersectLines(lineA, lineB, m_intersections);
512 for (
int k = 0; k < m_intersections.size(); ++k) {
514 i_isect.
t = m_intersections.at(k).alphaA;
515 j_isect.t = m_intersections.at(k).alphaB;
517 i_isect.vertex = j_isect.vertex = m_segments.
addPoint(m_intersections.at(k).pos);
528void SegmentTree::produceIntersections(
const TreeNode &node,
int segment,
const RectF &segmentBounds,
const RectF &nodeBounds,
int axis)
531 produceIntersectionsLeaf(node,
segment);
535 RectF lbounds = nodeBounds;
536 (&lbounds.x2)[axis] = node.splitLeft;
538 RectF rbounds = nodeBounds;
539 (&rbounds.x1)[axis] = node.splitRight;
541 if (
segment > node.lowestLeftIndex && (&segmentBounds.x1)[axis] <= node.splitLeft)
542 produceIntersections(m_tree.at(node.index.children.left),
segment, segmentBounds, lbounds, !axis);
544 if (
segment > node.lowestRightIndex && (&segmentBounds.x2)[axis] >= node.splitRight)
545 produceIntersections(m_tree.at(node.index.children.right),
segment, segmentBounds, rbounds, !axis);
555 tree.produceIntersections(
i);
578 , m_nodes(m_segments->
points())
581 m_nodes.resize(m_segments->points());
583 for (
int i = 0;
i < m_nodes.size(); ++
i) {
584 m_nodes.at(
i).point =
i;
585 m_nodes.at(
i).id = -1;
588 m_rootNode = build(0, m_nodes.size());
595 return &m_nodes.at(m_rootNode);
605 QDataBuffer<Node> m_nodes;
619 if (traverseLeft && node.
left)
620 QT_PREPEND_NAMESPACE(qTraverseKdPointTree<T>)(*node.
left,
t,
depth + 1);
622 if (traverseRight && node.
right)
623 QT_PREPEND_NAMESPACE(qTraverseKdPointTree<T>)(*node.
right,
t,
depth + 1);
642 while (
first <= last) {
657 m_nodes.at(last).left = &m_nodes.at(build(
begin, last,
depth + 1));
659 m_nodes.at(last).left =
nullptr;
662 m_nodes.at(last).right = &m_nodes.at(build(last + 1,
end,
depth + 1));
664 m_nodes.at(last).right =
nullptr;
677 pointComponents[0] =
segments.pointAt(point).x();
678 pointComponents[1] =
segments.pointAt(point).y();
686 const QPointF &nodePoint = m_segments->pointAt(node.
point);
688 const qreal pivotComponents[] = { nodePoint.
x(), nodePoint.y() };
690 const qreal pivot = pivotComponents[
depth & 1];
694 const qreal pivot2 = pivotComponents[(
depth + 1) & 1];
699 node.
id = m_tree->nextId();
705 }
else if (
value < pivot) {
718 qreal pointComponents[2];
730 QDataBuffer<QPointF> mergedPoints(
points());
731 QDataBuffer<int> pointIndices(
points());
735 QT_PREPEND_NAMESPACE(qTraverseKdPointTree<QKdPointFinder>)(*tree.
rootNode(), finder);
739 if (finder.result() >= mergedPoints.size())
740 mergedPoints << m_points.at(
i);
742 pointIndices << finder.result();
745 for (
int i = 0;
i < m_segments.size(); ++
i) {
746 m_segments.at(
i).va = pointIndices.at(m_segments.at(
i).va);
747 m_segments.at(
i).vb = pointIndices.at(m_segments.at(
i).vb);
750 for (
int i = 0;
i < m_intersections.size(); ++
i)
751 m_intersections.at(
i).vertex = pointIndices.at(m_intersections.at(
i).vertex);
753 m_points.swap(mergedPoints);
757void QWingedEdge::intersectAndAdd()
762 m_segments.mergePoints();
764 for (
int i = 0;
i < m_segments.points(); ++
i)
765 addVertex(m_segments.pointAt(
i));
767 QDataBuffer<QPathSegments::Intersection> intersections(m_segments.segments());
768 for (
int i = 0;
i < m_segments.segments(); ++
i) {
769 intersections.reset();
771 int pathId = m_segments.pathId(
i);
775 intersections << *isect;
778 isect += isect->next;
784 std::sort(intersections.data(), intersections.data() + intersections.size());
786 int first = m_segments.segmentAt(
i).va;
787 int second = m_segments.segmentAt(
i).vb;
790 for (
int j = 0;
j < intersections.size(); ++
j) {
793 QPathEdge *ep = edge(addEdge(last, isect.vertex));
796 const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.vertex).y() ? 1 : -1;
806 QPathEdge *ep = edge(addEdge(last, second));
809 const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
826 m_edges(subject.elementCount()),
827 m_vertices(subject.elementCount()),
828 m_segments(subject.elementCount())
862 if (equal_1_2 && equal_2_3 && equal_3_4)
866 return equal_1_2 || equal_3_4;
868 return (equal_1_2 && equal_3_4) || (equal_1_2 && equal_2_3) || (equal_2_3 && equal_3_4);
874 m_intersections.
reset();
884 int firstSegment = m_segments.size();
886 bool hasMoveTo =
false;
889 for (
int i = 0;
i <
path.elementCount(); ++
i) {
890 int current = m_points.
size();
894 currentPoint =
path.elementAt(
i+2);
896 currentPoint =
path.elementAt(
i);
899 current = lastMoveTo;
901 m_points << currentPoint;
903 switch (
path.elementAt(
i).type) {
905 if (hasMoveTo && last != lastMoveTo && !
comparePoints(m_points.
at(last), m_points.
at(lastMoveTo)))
906 m_segments <<
Segment(m_pathId, last, lastMoveTo);
908 last = lastMoveTo = current;
911 m_segments <<
Segment(m_pathId, last, current);
918 m_segments <<
Segment(m_pathId, last, current);
925 if (threshold < 3) threshold = 3;
926 qreal one_over_threshold_minus_1 =
qreal(1) / (threshold - 1);
928 for (
int t = 1;
t < threshold - 1; ++
t) {
929 currentPoint = bezier.
pointAt(
t * one_over_threshold_minus_1);
935 m_points << currentPoint;
938 m_segments <<
Segment(m_pathId, last, current);
950 if (hasMoveTo && last != lastMoveTo && !
comparePoints(m_points.
at(last), m_points.
at(lastMoveTo)))
951 m_segments <<
Segment(m_pathId, last, lastMoveTo);
953 for (
int i = firstSegment;
i < m_segments.size(); ++
i) {
972qreal QWingedEdge::delta(
int vertex,
int a,
int b)
const
977 double a_angle = ap->angle;
978 double b_angle = bp->angle;
981 a_angle = ap->invAngle;
984 b_angle = bp->invAngle;
986 double result = b_angle - a_angle;
1007 TraversalStatus status;
1010 status.edge = vp->
edge;
1012#ifdef QDEBUG_CLIPPER
1014 qDebug() <<
"Finding insert status for edge" << ei <<
"at vertex" <<
QPointF(*vp) <<
", angles: " << ep->
angle << ep->
invAngle;
1018 status =
next(status);
1022 qreal d2 = delta(vi, ei, status.edge);
1024#ifdef QDEBUG_CLIPPER
1033 }
while (status.edge != vp->
edge);
1039 if (
edge(status.edge)->
vertex(status.direction) != vi)
1042#ifdef QDEBUG_CLIPPER
1051void QWingedEdge::removeEdge(
int ei)
1055 TraversalStatus status;
1060 TraversalStatus forwardRight =
next(status);
1061 forwardRight.flipDirection();
1064 TraversalStatus forwardLeft =
next(status);
1065 forwardLeft.flipDirection();
1068 TraversalStatus backwardLeft =
next(status);
1069 backwardLeft.flipDirection();
1072 TraversalStatus backwardRight =
next(status);
1073 backwardRight.flipDirection();
1075 edge(forwardRight.edge)->
setNext(forwardRight.traversal, forwardRight.direction, forwardLeft.edge);
1076 edge(forwardLeft.edge)->
setNext(forwardLeft.traversal, forwardLeft.direction, forwardRight.edge);
1078 edge(backwardRight.edge)->
setNext(backwardRight.traversal, backwardRight.direction, backwardLeft.edge);
1079 edge(backwardLeft.edge)->
setNext(backwardLeft.traversal, backwardLeft.direction, backwardRight.edge);
1087 a->edge = backwardRight.edge;
1088 b->edge = forwardRight.edge;
1099 if (ap->edge < 0 || bp->edge < 0)
1103 status.
edge = ap->edge;
1114 status =
list.next(status);
1116 }
while (status.
edge != ap->edge);
1125 return v.y() <= 0 ? 0 : 64.;
1126 }
else if (
v.y() == 0) {
1127 return v.x() <= 0 ? 32. : 96.;
1137 return 128. - 32. * vx;
1140 return 64. + 32. * vx;
1167 int ei = m_edges.
size() - 1;
1183#ifdef QDEBUG_CLIPPER
1184 printf(
"** Adding edge %d / vertices: %.07f %.07f, %.07f %.07f\n", ei,
fp->x,
fp->y,
sp->x,
sp->y);
1187 for (
int i = 0;
i < 2; ++
i) {
1205 op->
setNext(os.traversal, os.direction, ei);
1206 np->setNext(
ns.traversal,
ns.direction, ei);
1220 ep->
setNext(os.traversal, os.direction, oe);
1238 return m_vertices.
size() - 1;
1240 for (
int i = 0;
i < m_vertices.
size(); ++
i) {
1249 return m_vertices.
size() - 1;
1254 const int elementCount =
path.elementCount();
1255 if (elementCount >= 2) {
1265 path.setElementPositionAt(elementCount - 1, point.
x(), point.
y());
1293 status =
list.next(status);
1294 }
while (status.
edge != edge);
1303 int flag = 0x3 << 4;
1304 if ((ep->
flag & flag) == flag) {
1319 if (ep->
flag & 16) {
1332 if (subjectPath == clipPath)
1343 bool subjectIsRect =
pathToRect(subjectPath);
1346 if (subjectIsRect && clipIsRect)
1348 else if (subjectIsRect)
1350 else if (clipIsRect)
1354 a.setPath(subjectPath);
1356 b.setPath(clipPath);
1359 if (finder.hasIntersections(
a,
b))
1383 if (subjectPath == clipPath)
1399 a.setPath(subjectPath);
1401 b.setPath(clipPath);
1404 if (finder.hasIntersections(
a,
b))
1420 : subjectPath(subject)
1440 status =
list.next(status);
1441 }
while (status.
edge != edge);
1444template <
typename InputIterator>
1459 if (
path.elementCount() != 5)
1462 const bool mightBeRect =
path.elementAt(0).isMoveTo()
1463 &&
path.elementAt(1).isLineTo()
1464 &&
path.elementAt(2).isLineTo()
1465 &&
path.elementAt(3).isLineTo()
1466 &&
path.elementAt(4).isLineTo();
1477 if (
path.elementAt(1).y !=
y1)
1480 if (
path.elementAt(2).x !=
x2)
1483 if (
path.elementAt(3).x !=
x1 ||
path.elementAt(3).y !=
y2)
1486 if (
path.elementAt(4).x !=
x1 ||
path.elementAt(4).y !=
y1)
1501 if (subjectPath == clipPath)
1504 bool subjectIsRect =
pathToRect(subjectPath,
nullptr);
1505 bool clipIsRect =
pathToRect(clipPath,
nullptr);
1510 if (!clipBounds.intersects(subjectBounds)) {
1522 result.addPath(clipPath);
1533 if (clipBounds.contains(subjectBounds)) {
1546 }
else if (subjectBounds.contains(clipBounds)) {
1547 if (subjectIsRect) {
1571 return intersect(clipPath, subjectBounds);
1572 else if (clipIsRect)
1573 return intersect(subjectPath, clipBounds);
1579 doClip(
list, ClipMode);
1587 QList<qreal> y_coords;
1588 y_coords.reserve(
list.vertexCount());
1589 for (
int i = 0;
i <
list.vertexCount(); ++
i)
1590 y_coords <<
list.vertex(
i)->y;
1592 std::sort(y_coords.begin(), y_coords.end());
1593 y_coords.erase(std::unique(y_coords.begin(), y_coords.end(),
fuzzyCompare), y_coords.end());
1595#ifdef QDEBUG_CLIPPER
1596 printf(
"sorted y coords:\n");
1597 for (
int i = 0;
i < y_coords.size(); ++
i) {
1598 printf(
"%.9f\n", y_coords.at(
i));
1606 qreal maxHeight = 0;
1607 for (
int i = 0;
i <
list.edgeCount(); ++
i) {
1611 if ((edge->
flag & 0x3) == 0x3)
1623 if (
height > maxHeight) {
1637 const int last =
qFuzzyFind(y_coords.cbegin() +
first, y_coords.cend(),
qMax(
a->y,
b->y)) - y_coords.cbegin();
1643 int bestIdx =
first;
1644 for (
int i =
first + 1;
i < last; ++
i) {
1645 qreal gap = y_coords.at(
i + 1) - y_coords.at(
i);
1647 if (gap > biggestGap) {
1652 const qreal bestY = 0.5 * (y_coords.at(bestIdx) + y_coords.at(bestIdx + 1));
1654#ifdef QDEBUG_CLIPPER
1655 printf(
"y: %.9f, gap: %.9f\n", bestY, biggestGap);
1658 if (handleCrossingEdges(
list, bestY,
mode) &&
mode == CheckMode)
1665 if (
mode == ClipMode)
1683 ep->
flag |= (flag | (flag << 4));
1685#ifdef QDEBUG_CLIPPER
1686 qDebug() <<
"traverse: adding edge " << status.
edge <<
", mask:" << (flag << 4) <<ep->
flag;
1689 status =
list.next(status);
1690 }
while (status.
edge != edge);
1728 int w = ((ep->
flag >> 4) ^ (ep->
flag >> 5)) & 1;
1736 if ((
a.y() <
y &&
b.y() >
y) || (
a.y() >
y &&
b.y() <
y)) {
1737 qreal intersectionX =
a.x() + (
b.x() -
a.x()) * (
y -
a.y()) / (
b.y() -
a.y());
1739 if (intersectionX >
x)
1749 QList<QCrossingEdge> crossings;
1750 for (
int i = 0;
i <
list.edgeCount(); ++
i) {
1755 if ((
a.y() <
y &&
b.y() >
y) || (
a.y() >
y &&
b.y() <
y)) {
1756 const qreal intersection =
a.x() + (
b.x() -
a.x()) * (
y -
a.y()) / (
b.y() -
a.y());
1769 std::sort(crossings.begin(), crossings.end());
1776#ifdef QDEBUG_CLIPPER
1777 qDebug() <<
"crossings:" << crossings.size();
1779 for (
int i = 0;
i < crossings.size() - 1; ++
i) {
1780 int ei = crossings.at(
i).edge;
1786 const bool hasLeft = (edge->
flag >> 4) & 1;
1787 const bool hasRight = (edge->
flag >> 4) & 2;
1789 windingD += hasLeft ^ hasRight;
1791 const bool inA = (windingA & aMask) != 0;
1792 const bool inB = (windingB & bMask) != 0;
1793 const bool inD = (windingD & 0x1) != 0;
1795 const bool inside =
bool_op(inA, inB, op);
1796 const bool add = inD ^ inside;
1798#ifdef QDEBUG_CLIPPER
1799 printf(
"y %f, x %f, inA: %d, inB: %d, inD: %d, inside: %d, flag: %x, bezier: %p, edge: %d\n",
y, crossings.at(
i).x, inA, inB, inD, inside, edge->
flag, edge->bezier, ei);
1803 if (
mode == CheckMode)
1810 if (!(edge->
flag & 1))
1813 if (!(edge->
flag & 2))
1816 if (!(edge->
flag & 1))
1819 if (!(edge->
flag & 2))
1825 if (!(edge->
flag & 1))
1828 if (!(edge->
flag & 2))
1841 QList<QPainterPath> subpaths;
1846 for (
int i = 0;
i <
path.elementCount(); ++
i) {
1851 subpaths += current;
1864 Q_ASSERT(!
"toSubpaths(), bad element type");
1870 subpaths << current;
1880static bool isVertical(Edge edge)
1908 return line.pointAt((
t -
a.x()) / (
b.x() -
a.x()));
1910 return line.pointAt((
t -
a.y()) / (
b.y() -
a.y()));
1916 if (
path.elementCount() > 0)
1927 bool outA = compare<edge>(
a,
t);
1928 bool outB = compare<edge>(
b,
t);
1942 if (
path.elementCount() > 0)
1955 bool outA = compare<edge>(
a,
t);
1956 bool outB = compare<edge>(
b,
t);
1957 bool outC = compare<edge>(
c,
t);
1958 bool outD = compare<edge>(
d,
t);
1960 int outCount = int(outA) + int(outB) + int(outC) + int(outD);
1965 if (outCount == 0) {
1966 addBezier(
result, bezier);
1979 points[0] = unflipped.pt1();
1983 if (stationary > 0) {
1988 if (stationary > 1) {
1997 qreal lastIntersection = 0;
1999 outA = compare<edge>(
points[
i],
t);
2000 outB = compare<edge>(
points[
i+1],
t);
2006 addBezier(
result, unflipped.getSubRange(lastIntersection, intersection));
2008 lastIntersection = intersection;
2013 addBezier(
result, unflipped.getSubRange(lastIntersection, 1));
2021 for (
int i = 1;
i <
path.elementCount(); ++
i) {
2032 int last =
path.elementCount() - 1;
2041 QList<QPainterPath> subpaths = toSubpaths(
path);
2045 for (
int i = 0;
i < subpaths.size(); ++
i) {
2054 bounds =
subPath.boundingRect();
2056 if (bounds.
top() <
rect.top())
2061 if (
subPath.elementCount() > 1)
2067 if (
result.boundingRect().isEmpty())
qreal tForY(qreal t0, qreal t1, qreal y) const
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
QPointF pointAt(qreal t) const
int stationaryYPoints(qreal &t0, qreal &t1) const
QBezier mapBy(const QTransform &transform) const
bool hasIntersections(const QPathSegments &a, const QPathSegments &b) const
void produceIntersections(QPathSegments &segments)
QKdPointFinder(int point, const QPathSegments &segments, QKdPointTree &tree)
QKdPointTree::Traversal operator()(QKdPointTree::Node &node, int depth)
QKdPointTree(const QPathSegments &segments)
int build(int begin, int end, int depth=0)
\inmodule QtCore\compares equality \compareswith equality QLine \endcompareswith
const_reference at(qsizetype i) const noexcept
const_iterator cbegin() const noexcept
bool isMoveTo() const
Returns true if the element is moving the current position, otherwise returns false.
bool isLineTo() const
Returns true if the element is a line, otherwise returns false.
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
QPainterPath::Element elementAt(int i) const
Returns the element at the given index in the painter path.
int elementCount() const
Returns the number of path elements in the painter path.
QPainterPath simplified() const
void addPath(const QPainterPath &path)
Adds the given path to this path as a closed subpath.
QRectF controlPointRect() const
Returns the rectangle containing all the points and control points in this path.
bool intersects(const QRectF &rect) const
Returns true if any point in the given rectangle intersects the path; otherwise returns false.
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision.
bool contains(const QPointF &pt) const
Returns true if the given point is inside the path, otherwise returns false.
Qt::FillRule fillRule() const
Returns the painter path's currently set fill rule.
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
void cubicTo(const QPointF &ctrlPt1, const QPointF &ctrlPt2, const QPointF &endPt)
Adds a cubic Bezier curve between the current position and the given endPoint using the control point...
QPathClipper(const QPainterPath &subject, const QPainterPath &clip)
static bool pathToRect(const QPainterPath &path, QRectF *rect=nullptr)
QPainterPath clip(Operation op=BoolAnd)
void setNext(Traversal traversal, Direction direction, int next)
Direction directionTo(int vertex) const
int next(Traversal traversal, Direction direction) const
int vertex(Direction direction) const
void setPath(const QPainterPath &path)
void addPath(const QPainterPath &path)
void addIntersection(int index, const Intersection &intersection)
int addPoint(const QPointF &point)
const QRectF & elementBounds(int index) const
const QLineF lineAt(int index) const
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr qreal height() const noexcept
Returns the height of the rectangle.
constexpr qreal width() const noexcept
Returns the width of the rectangle.
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
bool intersects(const QRectF &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e.
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
int addEdge(const QPointF &a, const QPointF &b)
bool isInside(qreal x, qreal y) const
TraversalStatus next(const TraversalStatus &status) const
QPathEdge * edge(int edge)
QPainterPath toPath() const
QPathVertex * vertex(int vertex)
void flip(QMatrix4x4 &matrix)
Combined button and popup list for selecting options.
static const QPainterPath::ElementType * subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end, const qreal *points, bool *closed)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
bool qFuzzyIsNull(qfloat16 f) noexcept
qfloat16 qSqrt(qfloat16 f)
void uint64_t uint64_t uint64_t value2
static QT_BEGIN_NAMESPACE const qreal Q_PI
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
constexpr T qAbs(const T &t)
constexpr static Q_DECL_CONST_FUNCTION double qt_inf() noexcept
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLfloat GLfloat GLfloat GLfloat GLfloat maxY
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLenum GLint components
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLuint GLfloat GLfloat y0
GLfloat GLfloat GLfloat GLfloat maxX
GLfixed GLfixed GLint GLint GLfixed points
GLfixed GLfixed GLfixed y2
GLsizei const GLchar *const * path
static bool clipLine(QLineF *line, const QRect &rect)
static qreal dot(const QPointF &a, const QPointF &b)
static QList< QCrossingEdge > findCrossings(const QWingedEdge &list, qreal y)
static bool bool_op(bool a, bool b, QPathClipper::Operation op)
static void normalize(double &x, double &y)
static QT_BEGIN_NAMESPACE bool fuzzyIsNull(qreal d)
static bool fuzzyCompare(qreal a, qreal b)
static bool comparePoints(const QPointF &a, const QPointF &b)
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
void qTraverseKdPointTree(QKdPointTree::Node &node, T &t, int depth=0)
static qreal component(const QPointF &point, unsigned int i)
static void addLineTo(QPainterPath &path, const QPointF &point)
static int commonEdge(const QWingedEdge &list, int a, int b)
static bool isLine(const QBezier &bezier)
InputIterator qFuzzyFind(InputIterator first, InputIterator last, qreal val)
static double computeAngle(const QPointF &v)
static void traverse(QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static int segmentCount(const QPainterPath &path, qreal pathLength)
static void split(QT_FT_Vector *b)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
static int compare(quint64 a, quint64 b)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
bool operator<(const QCrossingEdge &edge) const
QPathEdge::Traversal traversal
QPathEdge::Direction direction