44 #include <private/qbezier_p.h> 45 #include <private/qdatabuffer_p.h> 46 #include <private/qnumeric_p.h> 71 if (
sizeof(
qreal) ==
sizeof(
double))
72 return qAbs(d) <= 1e-12;
74 return qAbs(d) <= 1e-5f;
86 return a.
x() * b.
x() + a.
y() * b.
y();
91 double reciprocal = 1 /
qSqrt(x * x + y * y);
111 bool linesIntersect(
const QLineF &a,
const QLineF &b)
const;
128 if (p1_equals_q1 && p2_equals_q2)
134 if (p1_equals_q2 && p2_equals_q1)
137 const QPointF pDelta = p2 - p1;
138 const QPointF qDelta = q2 - q1;
140 const qreal par = pDelta.
x() * qDelta.
y() - pDelta.
y() * qDelta.
x();
143 const QPointF normal(-pDelta.
y(), pDelta.
x());
147 const qreal dp =
dot(pDelta, pDelta);
149 const qreal tq1 =
dot(pDelta, q1 - p1);
150 const qreal tq2 =
dot(pDelta, q2 - p1);
152 if ((tq1 > 0 && tq1 < dp) || (tq2 > 0 && tq2 < dp))
155 const qreal dq =
dot(qDelta, qDelta);
157 const qreal tp1 =
dot(qDelta, p1 - q1);
158 const qreal tp2 =
dot(qDelta, p2 - q1);
160 if ((tp1 > 0 && tp1 < dq) || (tp2 > 0 && tp2 < dq))
167 const qreal invPar = 1 / par;
169 const qreal tp = (qDelta.
y() * (q1.x() - p1.x()) -
170 qDelta.
x() * (q1.y() - p1.y())) * invPar;
172 if (tp < 0 || tp > 1)
175 const qreal tq = (pDelta.
y() * (q1.x() - p1.x()) -
176 pDelta.
x() * (q1.y() - p1.y())) * invPar;
178 return tq >= 0 && tq <= 1;
193 for (
int i = 1; i < b.
segments(); ++i) {
201 QRectF rb(minX, minY, maxX - minX, maxY - minY);
203 for (
int i = 0; i < a.
segments(); ++i) {
206 if (r1.
left() > rb.right() || rb.left() > r1.
right())
208 if (r1.
top() > rb.bottom() || rb.top() > r1.
bottom())
211 for (
int j = 0; j < b.
segments(); ++j) {
235 int lowestRightIndex;
264 void produceIntersections(
int segment);
267 TreeNode buildTree(
int first,
int last,
int depth,
const RectF &bounds);
269 void produceIntersectionsLeaf(
const TreeNode &node,
int segment);
270 void produceIntersections(
const TreeNode &node,
int segment,
const RectF &segmentBounds,
const RectF &nodeBounds,
int axis);
283 : m_segments(segments),
291 m_index.resize(m_segments.segments());
293 for (
int i = 0; i < m_index.size(); ++i) {
296 const QRectF &segmentBounds = m_segments.elementBounds(i);
298 if (segmentBounds.
left() < m_bounds.x1)
299 m_bounds.x1 = segmentBounds.
left();
300 if (segmentBounds.
top() < m_bounds.y1)
301 m_bounds.y1 = segmentBounds.
top();
302 if (segmentBounds.
right() > m_bounds.x2)
303 m_bounds.x2 = segmentBounds.
right();
304 if (segmentBounds.
bottom() > m_bounds.y2)
305 m_bounds.y2 = segmentBounds.
bottom();
310 TreeNode root = buildTree(0, m_index.size(), 0, m_bounds);
317 QPointF(m_bounds.x2, m_bounds.y2));
322 return axis == 0 ? pos.
x() : pos.
y();
325 TreeNode SegmentTree::buildTree(
int first,
int last,
int depth,
const RectF &bounds)
327 if (depth >= 24 || (last - first) <= 10) {
330 node.index.interval.first = first;
331 node.index.interval.last = last;
336 int splitAxis = (depth & 1);
341 qreal split = 0.5f * ((&bounds.x1)[splitAxis] + (&bounds.x2)[splitAxis]);
343 node.splitLeft = (&bounds.x1)[splitAxis];
344 node.splitRight = (&bounds.x2)[splitAxis];
346 node.lowestLeftIndex =
INT_MAX;
347 node.lowestRightIndex =
INT_MAX;
349 const int treeSize = m_tree.size();
351 node.index.children.left = treeSize;
352 node.index.children.right = treeSize + 1;
354 m_tree.resize(treeSize + 2);
361 const int index = m_index.at(l);
362 const QRectF &segmentBounds = m_segments.elementBounds(index);
364 qreal lowCoordinate = coordinate(segmentBounds.
topLeft(), splitAxis);
366 if (coordinate(segmentBounds.
center(), splitAxis) < split) {
368 if (highCoordinate > node.splitLeft)
369 node.splitLeft = highCoordinate;
370 if (index < node.lowestLeftIndex)
371 node.lowestLeftIndex =
index;
374 if (lowCoordinate < node.splitRight)
375 node.splitRight = lowCoordinate;
376 if (index < node.lowestRightIndex)
377 node.lowestRightIndex =
index;
378 qSwap(m_index[l], m_index[r]);
383 RectF lbounds = bounds;
384 (&lbounds.x2)[splitAxis] = node.splitLeft;
386 RectF rbounds = bounds;
387 (&rbounds.x1)[splitAxis] = node.splitRight;
389 TreeNode
left = buildTree(first, l, depth + 1, lbounds);
390 m_tree[node.index.children.left] =
left;
392 TreeNode
right = buildTree(l, last, depth + 1, rbounds);
393 m_tree[node.index.children.right] =
right;
412 if (p1_equals_q1 && p2_equals_q2)
418 if (p1_equals_q2 && p2_equals_q1)
421 const QPointF pDelta = p2 - p1;
422 const QPointF qDelta = q2 - q1;
424 const qreal par = pDelta.
x() * qDelta.
y() - pDelta.
y() * qDelta.
x();
427 const QPointF normal(-pDelta.
y(), pDelta.
x());
431 const qreal invDp = 1 /
dot(pDelta, pDelta);
433 const qreal tq1 =
dot(pDelta, q1 - p1) * invDp;
434 const qreal tq2 =
dot(pDelta, q2 - p1) * invDp;
436 if (tq1 > 0 && tq1 < 1) {
438 intersection.
alphaA = tq1;
440 intersection.
pos = q1;
441 intersections.
add(intersection);
444 if (tq2 > 0 && tq2 < 1) {
446 intersection.
alphaA = tq2;
448 intersection.
pos = q2;
449 intersections.
add(intersection);
452 const qreal invDq = 1 /
dot(qDelta, qDelta);
454 const qreal tp1 =
dot(qDelta, p1 - q1) * invDq;
455 const qreal tp2 =
dot(qDelta, p2 - q1) * invDq;
457 if (tp1 > 0 && tp1 < 1) {
460 intersection.
alphaB = tp1;
461 intersection.
pos = p1;
462 intersections.
add(intersection);
465 if (tp2 > 0 && tp2 < 1) {
468 intersection.
alphaB = tp2;
469 intersection.
pos = p2;
470 intersections.
add(intersection);
479 if (p1_equals_q1 || p1_equals_q2 || p2_equals_q1 || p2_equals_q2)
483 const qreal tp = (qDelta.
y() * (q1.x() - p1.x()) -
484 qDelta.
x() * (q1.y() - p1.y())) / par;
485 const qreal tq = (pDelta.
y() * (q1.x() - p1.x()) -
486 pDelta.
x() * (q1.y() - p1.y())) / par;
488 if (tp<0 || tp>1 || tq<0 || tq>1)
497 if ((q_zero || q_one) && (p_zero || p_one))
510 pt = q1 + (q2 - q1) * tq;
515 intersection.alphaB = tq;
516 intersection.pos = pt;
517 intersections.
add(intersection);
520 void SegmentTree::produceIntersections(
int segment)
522 const QRectF &segmentBounds = m_segments.elementBounds(segment);
525 sbounds.x1 = segmentBounds.
left();
526 sbounds.y1 = segmentBounds.
top();
527 sbounds.x2 = segmentBounds.
right();
528 sbounds.y2 = segmentBounds.
bottom();
530 produceIntersections(m_tree.at(0), segment, sbounds, m_bounds, 0);
533 void SegmentTree::produceIntersectionsLeaf(
const TreeNode &node,
int segment)
535 const QRectF &r1 = m_segments.elementBounds(segment);
536 const QLineF lineA = m_segments.lineAt(segment);
538 for (
int i = node.index.interval.first; i < node.index.interval.last; ++i) {
539 const int other = m_index.at(i);
540 if (other >= segment)
543 const QRectF &r2 = m_segments.elementBounds(other);
550 m_intersections.reset();
552 const QLineF lineB = m_segments.lineAt(other);
554 intersectLines(lineA, lineB, m_intersections);
556 for (
int k = 0; k < m_intersections.size(); ++k) {
558 i_isect.
vertex = j_isect.
vertex = m_segments.addPoint(m_intersections.at(k).pos);
560 i_isect.
t = m_intersections.at(k).alphaA;
561 j_isect.
t = m_intersections.at(k).alphaB;
566 m_segments.addIntersection(segment, i_isect);
567 m_segments.addIntersection(other, j_isect);
572 void SegmentTree::produceIntersections(
const TreeNode &node,
int segment,
const RectF &segmentBounds,
const RectF &nodeBounds,
int axis)
575 produceIntersectionsLeaf(node, segment);
579 RectF lbounds = nodeBounds;
580 (&lbounds.x2)[axis] = node.splitLeft;
582 RectF rbounds = nodeBounds;
583 (&rbounds.x1)[axis] = node.splitRight;
585 if (segment > node.lowestLeftIndex && (&segmentBounds.x1)[axis] <= node.splitLeft)
586 produceIntersections(m_tree.at(node.index.children.left), segment, segmentBounds, lbounds, !axis);
588 if (segment > node.lowestRightIndex && (&segmentBounds.x2)[axis] >= node.splitRight)
589 produceIntersections(m_tree.at(node.index.children.right), segment, segmentBounds, rbounds, !axis);
596 SegmentTree tree(segments);
598 for (
int i = 0; i < segments.
segments(); ++i)
599 tree.produceIntersections(i);
621 : m_segments(&segments)
622 , m_nodes(m_segments->points())
625 m_nodes.resize(m_segments->points());
627 for (
int i = 0; i < m_nodes.size(); ++i) {
628 m_nodes.at(i).point = i;
629 m_nodes.at(i).id = -1;
632 m_rootNode = build(0, m_nodes.size());
635 int build(
int begin,
int end,
int depth = 0);
639 return &m_nodes.at(m_rootNode);
655 template <
typename T>
663 if (traverseLeft && node.
left)
666 if (traverseRight && node.
right)
673 const qreal components[] = { point.
x(), point.
y() };
674 return components[i];
681 const qreal pivot =
component(m_segments->pointAt(m_nodes.at(begin).point), depth & 1);
683 int first = begin + 1;
686 while (first <= last) {
687 const qreal value =
component(m_segments->pointAt(m_nodes.at(first).point), depth & 1);
692 qSwap(m_nodes.at(first), m_nodes.at(last));
697 qSwap(m_nodes.at(last), m_nodes.at(begin));
700 m_nodes.at(last).left = &m_nodes.at(build(begin, last, depth + 1));
702 m_nodes.at(last).left = 0;
705 m_nodes.at(last).right = &m_nodes.at(build(last + 1, end, depth + 1));
707 m_nodes.at(last).right = 0;
718 , m_segments(&segments)
721 pointComponents[0] = segments.
pointAt(point).
x();
722 pointComponents[1] = segments.
pointAt(point).
y();
730 const QPointF &nodePoint = m_segments->pointAt(node.
point);
732 const qreal pivotComponents[] = { nodePoint.
x(), nodePoint.
y() };
734 const qreal pivot = pivotComponents[depth & 1];
735 const qreal value = pointComponents[depth & 1];
738 const qreal pivot2 = pivotComponents[(depth + 1) & 1];
739 const qreal value2 = pointComponents[(depth + 1) & 1];
743 node.
id = m_tree->nextId();
749 }
else if (value < pivot) {
778 for (
int i = 0; i < points(); ++i) {
785 mergedPoints << m_points.
at(i);
787 pointIndices << finder.
result();
790 for (
int i = 0; i < m_segments.size(); ++i) {
791 m_segments.at(i).va = pointIndices.
at(m_segments.at(i).va);
792 m_segments.at(i).vb = pointIndices.
at(m_segments.at(i).vb);
795 for (
int i = 0; i < m_intersections.size(); ++i)
796 m_intersections.at(i).vertex = pointIndices.
at(m_intersections.at(i).vertex);
798 m_points.swap(mergedPoints);
807 m_segments.mergePoints();
809 for (
int i = 0; i < m_segments.points(); ++i)
810 addVertex(m_segments.pointAt(i));
813 for (
int i = 0; i < m_segments.segments(); ++i) {
814 intersections.
reset();
816 int pathId = m_segments.pathId(i);
820 intersections << *isect;
823 isect += isect->
next;
829 qSort(intersections.data(), intersections.data() + intersections.size());
831 int first = m_segments.segmentAt(i).va;
832 int second = m_segments.segmentAt(i).vb;
835 for (
int j = 0; j < intersections.size(); ++j) {
841 const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(isect.
vertex).y() ? 1 : -1;
851 QPathEdge *ep = edge(addEdge(last, second));
854 const int dir = m_segments.pointAt(last).y() < m_segments.pointAt(second).y() ? 1 : -1;
871 m_edges(subject.elementCount()),
907 if (equal_1_2 && equal_2_3 && equal_3_4)
911 return equal_1_2 || equal_3_4;
913 return (equal_1_2 && equal_3_4) || (equal_1_2 && equal_2_3) || (equal_2_3 && equal_3_4);
919 m_intersections.reset();
931 bool hasMoveTo =
false;
935 int current = m_points.size();
943 if (i > 0 &&
comparePoints(m_points.at(lastMoveTo), currentPoint))
944 current = lastMoveTo;
946 m_points << currentPoint;
950 if (hasMoveTo && last != lastMoveTo && !
comparePoints(m_points.at(last), m_points.at(lastMoveTo)))
953 last = lastMoveTo = current;
956 m_segments << Segment(m_pathId, last, current);
963 m_segments << Segment(m_pathId, last, current);
970 if (threshold < 3) threshold = 3;
971 qreal one_over_threshold_minus_1 =
qreal(1) / (threshold - 1);
973 for (
int t = 1; t < threshold - 1; ++t) {
974 currentPoint = bezier.
pointAt(t * one_over_threshold_minus_1);
976 int index = m_points.size();
980 m_points << currentPoint;
983 m_segments << Segment(m_pathId, last, current);
995 if (hasMoveTo && last != lastMoveTo && !
comparePoints(m_points.at(last), m_points.at(lastMoveTo)))
998 for (
int i = firstSegment; i <
m_segments.size(); ++i) {
999 const QLineF line = lineAt(i);
1022 double a_angle = ap->
angle;
1023 double b_angle = bp->
angle;
1025 if (vertex == ap->
second)
1028 if (vertex == bp->
second)
1031 double result = b_angle - a_angle;
1034 return result - 128.;
1035 else if (result < 0)
1036 return result + 128.;
1048 return a + 0.5 * (b -
a);
1067 #ifdef QDEBUG_CLIPPER 1069 qDebug() <<
"Finding insert status for edge" << ei <<
"at vertex" <<
QPointF(*vp) <<
", angles: " << ep->
angle << ep->
invAngle;
1073 status =
next(status);
1079 #ifdef QDEBUG_CLIPPER 1085 position = status.
edge;
1097 #ifdef QDEBUG_CLIPPER 1169 status = list.
next(status);
1180 return v.
y() <= 0 ? 0 : 64.;
1181 }
else if (v.
y() == 0) {
1182 return v.
x() <= 0 ? 32. : 96.;
1192 return 128. - 32. * vx;
1195 return 64. + 32. * vx;
1227 QPathEdge *ep =
edge(ei);
1238 #ifdef QDEBUG_CLIPPER 1239 printf(
"** Adding edge %d / vertices: %.07f %.07f, %.07f %.07f\n", ei, fp->
x, fp->
y, sp->x, sp->y);
1242 for (
int i = 0; i < 2; ++i) {
1248 int vi = ep->
vertex(dirs[i]);
1292 if (vertex.
x == last.
x && vertex.
y == last.
y)
1310 if (elementCount >= 2) {
1314 const QPointF d1 = point - first;
1315 const QPointF d2 = middle - first;
1348 status = list.
next(status);
1349 }
while (status.
edge != edge);
1358 int flag = 0x3 << 4;
1359 if ((ep->
flag & flag) == flag) {
1374 if (ep->
flag & 16) {
1387 if (subjectPath == clipPath)
1390 QRectF r1 = subjectPath.controlPointRect();
1391 QRectF r2 = clipPath.controlPointRect();
1398 bool subjectIsRect = pathToRect(subjectPath);
1399 bool clipIsRect = pathToRect(clipPath);
1401 if (subjectIsRect && clipIsRect)
1403 else if (subjectIsRect)
1404 return clipPath.intersects(r1);
1405 else if (clipIsRect)
1406 return subjectPath.intersects(r2);
1409 a.setPath(subjectPath);
1417 for (
int i = 0; i < clipPath.elementCount(); ++i) {
1419 const QPointF point = clipPath.elementAt(i);
1420 if (r1.
contains(point) && subjectPath.contains(point))
1425 for (
int i = 0; i < subjectPath.elementCount(); ++i) {
1427 const QPointF point = subjectPath.elementAt(i);
1428 if (r2.
contains(point) && clipPath.contains(point))
1438 if (subjectPath == clipPath)
1441 QRectF r1 = subjectPath.controlPointRect();
1442 QRectF r2 = clipPath.controlPointRect();
1449 bool clipIsRect = pathToRect(clipPath);
1451 return subjectPath.contains(r2);
1454 a.setPath(subjectPath);
1462 for (
int i = 0; i < clipPath.elementCount(); ++i) {
1464 const QPointF point = clipPath.elementAt(i);
1465 if (!r1.
contains(point) || !subjectPath.contains(point))
1475 : subjectPath(subject)
1482 template <
typename Iterator,
typename Equality>
1488 Iterator last = begin;
1490 Iterator insert = begin;
1491 for (Iterator
it = begin;
it !=
end; ++
it) {
1492 if (!eq(*
it, *last)) {
1514 status = list.
next(status);
1515 }
while (status.
edge != edge);
1518 template <
typename InputIterator>
1589 return QPainterPath();
1607 if (clipBounds.
contains(subjectBounds)) {
1611 return QPainterPath();
1620 }
else if (subjectBounds.
contains(clipBounds)) {
1621 if (subjectIsRect) {
1626 result.
addRect(subjectBounds);
1630 result.
addRect(subjectBounds);
1647 else if (clipIsRect)
1665 y_coords << list.
vertex(i)->
y;
1670 #ifdef QDEBUG_CLIPPER 1671 printf(
"sorted y coords:\n");
1672 for (
int i = 0; i < y_coords.
size(); ++i) {
1673 printf(
"%.9f\n", y_coords[i]);
1681 qreal maxHeight = 0;
1682 for (
int i = 0; i < list.
edgeCount(); ++i) {
1686 if ((edge->
flag & 0x3) == 0x3)
1698 if (height > maxHeight) {
1717 qreal bestY = 0.5 * (y_coords[first] + y_coords[first+1]);
1718 qreal biggestGap = y_coords[first+1] - y_coords[first];
1720 for (
int i = first + 1; i < last; ++i) {
1721 qreal gap = y_coords[i+1] - y_coords[i];
1723 if (gap > biggestGap) {
1724 bestY = 0.5 * (y_coords[i] + y_coords[i+1]);
1729 #ifdef QDEBUG_CLIPPER 1730 printf(
"y: %.9f, gap: %.9f\n", bestY, biggestGap);
1758 ep->
flag |= (flag | (flag << 4));
1760 #ifdef QDEBUG_CLIPPER 1761 qDebug() <<
"traverse: adding edge " << status.
edge <<
", mask:" << (flag << 4) <<ep->
flag;
1764 status = list.
next(status);
1765 }
while (status.
edge != edge);
1798 for (
int i = 0; i < edgeCount(); ++i) {
1802 int w = ((ep->
flag >> 4) ^ (ep->
flag >> 5)) & 1;
1810 if ((a.
y() < y && b.
y() > y) || (a.
y() > y && b.
y() < y)) {
1811 qreal intersectionX = a.
x() + (b.
x() - a.
x()) * (y - a.
y()) / (b.
y() - a.
y());
1813 if (intersectionX > x)
1824 for (
int i = 0; i < list.
edgeCount(); ++i) {
1829 if ((a.
y() < y && b.
y() > y) || (a.
y() > y && b.
y() < y)) {
1830 const qreal intersection = a.
x() + (b.
x() - a.
x()) * (y - a.
y()) / (b.
y() - a.
y());
1850 #ifdef QDEBUG_CLIPPER 1851 qDebug() <<
"crossings:" << crossings.
size();
1853 for (
int i = 0; i < crossings.
size() - 1; ++i) {
1854 int ei = crossings.
at(i).
edge;
1860 const bool hasLeft = (edge->
flag >> 4) & 1;
1861 const bool hasRight = (edge->
flag >> 4) & 2;
1863 windingD += hasLeft ^ hasRight;
1865 const bool inA = (windingA &
aMask) != 0;
1866 const bool inB = (windingB &
bMask) != 0;
1867 const bool inD = (windingD & 0x1) != 0;
1869 const bool inside =
bool_op(inA, inB,
op);
1870 const bool add = inD ^ inside;
1872 #ifdef QDEBUG_CLIPPER 1873 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);
1884 if (!(edge->
flag & 1))
1887 if (!(edge->
flag & 2))
1890 if (!(edge->
flag & 1))
1893 if (!(edge->
flag & 2))
1899 if (!(edge->
flag & 1))
1902 if (!(edge->
flag & 2))
1925 subpaths += current;
1938 Q_ASSERT(!
"toSubpaths(), bad element type");
1944 subpaths << current;
1954 static bool isVertical(
Edge edge)
1959 template <Edge edge>
1975 template <Edge edge>
1982 return line.
pointAt((t - a.
x()) / (b.
x() - a.
x()));
1984 return line.
pointAt((t - a.
y()) / (b.
y() - a.
y()));
1998 template <Edge edge>
2001 bool outA = compare<edge>(
a, t);
2002 bool outB = compare<edge>(b, t);
2007 addLine(result,
QLineF(intersectLine<edge>(a, b, t), b));
2009 addLine(result,
QLineF(a, intersectLine<edge>(a, b, t)));
2011 addLine(result,
QLineF(a, b));
2024 template <Edge edge>
2029 bool outA = compare<edge>(
a, t);
2030 bool outB = compare<edge>(b, t);
2031 bool outC = compare<edge>(
c, t);
2032 bool outD = compare<edge>(
d, t);
2034 int outCount = int(outA) + int(outB) + int(outC) + int(outD);
2039 if (outCount == 0) {
2040 addBezier(result, bezier);
2048 qreal t0 = 0, t1 = 1;
2053 points[0] = unflipped.
pt1();
2056 int segmentCount = 0;
2057 if (stationary > 0) {
2059 segments[segmentCount] = t0;
2060 points[segmentCount] = unflipped.
pointAt(t0);
2062 if (stationary > 1) {
2064 segments[segmentCount] = t1;
2065 points[segmentCount] = unflipped.
pointAt(t1);
2068 segments[segmentCount] = 1;
2069 points[segmentCount] = unflipped.
pt4();
2071 qreal lastIntersection = 0;
2072 for (
int i = 0; i < segmentCount; ++i) {
2073 outA = compare<edge>(points[i], t);
2074 outB = compare<edge>(points[i+1], t);
2077 qreal intersection = flipped.
tForY(segments[i], segments[i+1], t);
2080 addBezier(result, unflipped.
getSubRange(lastIntersection, intersection));
2082 lastIntersection = intersection;
2087 addBezier(result, unflipped.
getSubRange(lastIntersection, 1));
2091 template <Edge edge>
2119 for (
int i = 0; i < subpaths.
size(); ++i) {
2124 subPath = clip<Left>(subPath, rect.
left());
2126 subPath = clip<Right>(subPath, rect.
right());
2130 if (bounds.
top() < rect.
top())
2131 subPath = clip<Top>(subPath, rect.
top());
2133 subPath = clip<Bottom>(subPath, rect.
bottom());
2146 return intersectPath(path, rect);
ElementType type
the type of element
QPointF bottomRight() const
Returns the position of the rectangle's bottom-right corner.
void produceIntersections(QPathSegments &segments)
The QPainterPath::Element class specifies the position and type of a subpath.
static bool fuzzyCompare(qreal a, qreal b)
QPathEdge::Traversal traversal
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
qreal y() const
Returns the y-coordinate of the rectangle's top edge.
qreal right() const
Returns the x-coordinate of the rectangle's right edge.
void addPath(const QPainterPath &path)
Adds the given path to this path as a closed subpath.
static void clear(QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QDataBuffer< Node > m_nodes
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
#define QT_END_NAMESPACE
This macro expands to.
TraversalStatus findInsertStatus(int vertex, int edge) const
const QPathSegments * m_segments
const QLineF lineAt(int index) const
#define it(className, varName)
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
QPathClipper(const QPainterPath &subject, const QPainterPath &clip)
int build(int begin, int end, int depth=0)
QPointF p1() const
Returns the line's start point.
InputIterator qFuzzyFind(InputIterator first, InputIterator last, qreal val)
const QPathSegments * m_segments
QKdPointTree::Traversal operator()(QKdPointTree::Node &node, int depth)
The QPointF class defines a point in the plane using floating point precision.
bool linesIntersect(const QLineF &a, const QLineF &b) const
qreal left() const
Returns the x-coordinate of the rectangle's left edge.
static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
QPathVertex * vertex(int vertex)
QPointF topLeft() const
Returns the position of the rectangle's top-left corner.
QPainterPath toPath() const
bool isLineTo() const
Returns true if the element is a line, otherwise returns false.
static bool clipLine(QLineF *line, const QRect &rect)
static LibLoadStatus status
static Q_DECL_CONSTEXPR bool qFuzzyCompare(double p1, double p2)
long ASN1_INTEGER_get ASN1_INTEGER * a
int vertex(Direction direction) const
QPointF pointAt(qreal t) const
static void addLineTo(QPainterPath &path, const QPointF &point)
bool intersects(const QRectF &r) const
Returns true if this rectangle intersects with the given rectangle (i.
qreal y
the y coordinate of the element's position.
int stationaryYPoints(qreal &t0, qreal &t1) const
TraversalStatus next(const TraversalStatus &status) const
Q_DECL_CONSTEXPR T qAbs(const T &t)
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
static void traverse(QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QPathEdge::Direction direction
qreal x() const
Returns the x-coordinate of this point.
void resize(int size)
Sets the size of the vector to size.
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the vector...
QRectF boundingRect() const
Returns the bounding rectangle of this painter path as a rectangle with floating point precision...
The QLineF class provides a two-dimensional vector using floating point precision.
static const QRectF boundingRect(const QPointF *points, int pointCount)
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
Q_CORE_EXPORT void qDebug(const char *,...)
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
bool contains(const QPointF &p) const
Returns true if the given point is inside or on the edge of the rectangle; otherwise returns false...
int insert(const QPathVertex &vertex)
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
static double computeAngle(const QPointF &v)
qreal tForY(qreal t0, qreal t1, qreal y) const
void setElementPositionAt(int i, qreal x, qreal y)
Sets the x and y coordinate of the element at index index to x and y.
#define QT_BEGIN_NAMESPACE
This macro expands to.
static bool compare(const QVariant::Private *a, const QVariant::Private *b)
Compares a to b.
The QRectF class defines a rectangle in the plane using floating point precision. ...
void setPath(const QPainterPath &path)
Direction directionTo(int vertex) const
QKdPointTree(const QPathSegments &segments)
qreal height() const
Returns the height of the rectangle.
const T & at(int i) const
Returns the item at index position i in the list.
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
qreal qAtan2(qreal x, qreal y)
qreal width() const
Returns the width of the rectangle.
static void split(QT_FT_Vector *b)
Qt::FillRule fillRule() const
Returns the painter path's currently set fill rule.
static qreal component(const QPointF &point, unsigned int i)
bool isInside(qreal x, qreal y) const
QBezier mapBy(const QTransform &transform) const
void qSort(RandomAccessIterator start, RandomAccessIterator end)
QDataBuffer< QPathEdge > m_edges
static QVector< QCrossingEdge > findCrossings(const QWingedEdge &list, qreal y)
QPainterPath simplified() const
Returns a simplified version of this path.
void qSwap(T &value1, T &value2)
const T & at(int i) const
Returns the item at index position i in the vector.
const QPointF & pointAt(int vertex) const
int next(Traversal traversal, Direction direction) const
static void add(QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
QPathEdge * edge(int edge)
void setNext(Traversal traversal, Direction direction, int next)
iterator begin()
Returns an STL-style iterator pointing to the first item in the vector.
int addEdge(const QPointF &a, const QPointF &b)
qreal x() const
Returns the x-coordinate of the rectangle's left edge.
static bool fuzzyIsNull(qreal d)
void setCoords(qreal x1, qreal y1, qreal x2, qreal y2)
Sets the coordinates of the rectangle's top-left corner to (x1, y1), and the coordinates of its botto...
bool hasIntersections(const QPathSegments &a, const QPathSegments &b) const
static bool isLine(const QBezier &bezier)
int size() const
Returns the number of items in the list.
static bool pathToRect(const QPainterPath &path, QRectF *rect=0)
QPointF p2() const
Returns the line's end point.
bool isMoveTo() const
Returns true if the element is moving the current position, otherwise returns false.
static QPointF midPoint(const QWingedEdge &list, int ei)
qreal x
the x coordinate of the element's position.
qreal y() const
Returns the y-coordinate of this point.
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...
qreal top() const
Returns the y-coordinate of the rectangle's top edge.
QBezier getSubRange(qreal t0, qreal t1) const
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
int elementCount() const
Returns the number of path elements in the painter path.
static bool comparePoints(const QPointF &a, const QPointF &b)
void reserve(int size)
Attempts to allocate memory for at least size elements.
qreal bottom() const
Returns the y-coordinate of the rectangle's bottom edge.
static bool bool_op(bool a, bool b, QPathClipper::Operation op)
QKdPointFinder(int point, const QPathSegments &segments, QKdPointTree &tree)
static const KeyPair *const end
void qTraverseKdPointTree(QKdPointTree::Node &node, T &t, int depth=0)
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
static qreal dot(const QPointF &a, const QPointF &b)
QPointF center() const
Returns the center point of the rectangle.
static void normalize(double &x, double &y)
int size() const
Returns the number of items in the vector.
static const QPainterPath::ElementType * subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end, const qreal *points, bool *closed)
bool doClip(QWingedEdge &list, ClipperMode mode)
bool operator<(const QCrossingEdge &edge) const
QPainterPath clip(Operation op=BoolAnd)
QDataBuffer< QPathVertex > m_vertices
static int commonEdge(const QWingedEdge &list, int a, int b)
const QRectF & elementBounds(int index) const
bool handleCrossingEdges(QWingedEdge &list, qreal y, ClipperMode mode)
Iterator qRemoveDuplicates(Iterator begin, Iterator end, Equality eq)
void addPath(const QPainterPath &path)
qreal delta(int vertex, int a, int b) const
QPointF pointAt(qreal t) const
Returns the point at the parameterized position specified by t.