Qt 4.8
Classes | Enumerations | Functions
qpathclipper.cpp File Reference
#include "qpathclipper_p.h"
#include <private/qbezier_p.h>
#include <private/qdatabuffer_p.h>
#include <private/qnumeric_p.h>
#include <qmath.h>
#include <qdebug.h>

Go to the source code of this file.

Classes

struct  QCrossingEdge
 
struct  QIntersection
 
class  QIntersectionFinder
 
class  QKdPointFinder
 
class  QKdPointTree
 
struct  QKdPointTree::Node
 

Enumerations

enum  Edge
 

Functions

static void add (QPainterPath &path, const QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
 
static void addLineTo (QPainterPath &path, const QPointF &point)
 
static bool bool_op (bool a, bool b, QPathClipper::Operation op)
 
static void clear (QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
 
static int commonEdge (const QWingedEdge &list, int a, int b)
 
static bool comparePoints (const QPointF &a, const QPointF &b)
 
static qreal component (const QPointF &point, unsigned int i)
 
static double computeAngle (const QPointF &v)
 
static qreal dot (const QPointF &a, const QPointF &b)
 
static QVector< QCrossingEdgefindCrossings (const QWingedEdge &list, qreal y)
 
static bool fuzzyCompare (qreal a, qreal b)
 
static bool fuzzyIsNull (qreal d)
 
static bool isLine (const QBezier &bezier)
 
static QPointF midPoint (const QWingedEdge &list, int ei)
 
static void normalize (double &x, double &y)
 
template<typename InputIterator >
InputIterator qFuzzyFind (InputIterator first, InputIterator last, qreal val)
 
template<typename Iterator , typename Equality >
Iterator qRemoveDuplicates (Iterator begin, Iterator end, Equality eq)
 
template<typename T >
void qTraverseKdPointTree (QKdPointTree::Node &node, T &t, int depth=0)
 
static void traverse (QWingedEdge &list, int edge, QPathEdge::Traversal traversal)
 

Enumeration Type Documentation

◆ Edge

enum Edge

Definition at line 1949 of file qpathclipper.cpp.

Function Documentation

◆ add()

static void add ( QPainterPath path,
const QWingedEdge list,
int  edge,
QPathEdge::Traversal  traversal 
)
static

Definition at line 1329 of file qpathclipper.cpp.

Referenced by QPathClipper::handleCrossingEdges(), and QWingedEdge::toPath().

1330 {
1332  status.edge = edge;
1333  status.traversal = traversal;
1334  status.direction = QPathEdge::Forward;
1335 
1336  path.moveTo(*list.vertex(list.edge(edge)->first));
1337 
1338  do {
1339  const QPathEdge *ep = list.edge(status.edge);
1340 
1341  addLineTo(path, *list.vertex(ep->vertex(status.direction)));
1342 
1343  if (status.traversal == QPathEdge::LeftTraversal)
1344  ep->flag &= ~16;
1345  else
1346  ep->flag &= ~32;
1347 
1348  status = list.next(status);
1349  } while (status.edge != edge);
1350 }
QPathEdge::Traversal traversal
QPathVertex * vertex(int vertex)
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
int vertex(Direction direction) const
static void addLineTo(QPainterPath &path, const QPointF &point)
TraversalStatus next(const TraversalStatus &status) const
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
QPathEdge::Direction direction
QPathEdge * edge(int edge)

◆ addLineTo()

static void addLineTo ( QPainterPath path,
const QPointF point 
)
static

Definition at line 1307 of file qpathclipper.cpp.

Referenced by add().

1308 {
1309  const int elementCount = path.elementCount();
1310  if (elementCount >= 2) {
1311  const QPainterPath::Element &middle = path.elementAt(elementCount - 1);
1312  if (middle.type == QPainterPath::LineToElement) {
1313  const QPointF first = path.elementAt(elementCount - 2);
1314  const QPointF d1 = point - first;
1315  const QPointF d2 = middle - first;
1316 
1317  const QPointF p(-d1.y(), d1.x());
1318 
1319  if (qFuzzyIsNull(dot(p, d2))) {
1320  path.setElementPositionAt(elementCount - 1, point.x(), point.y());
1321  return;
1322  }
1323  }
1324  }
1325 
1326  path.lineTo(point);
1327 }
ElementType type
the type of element
Definition: qpainterpath.h:81
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
void setElementPositionAt(int i, qreal x, qreal y)
Sets the x and y coordinate of the element at index index to x and y.
Definition: qpainterpath.h:409
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
static qreal dot(const QPointF &a, const QPointF &b)

◆ bool_op()

static bool bool_op ( bool  a,
bool  b,
QPathClipper::Operation  op 
)
static

Definition at line 1779 of file qpathclipper.cpp.

Referenced by QPathClipper::handleCrossingEdges().

1780 {
1781  switch (op) {
1782  case QPathClipper::BoolAnd:
1783  return a && b;
1784  case QPathClipper::BoolOr: // fall-through
1786  return a || b;
1787  case QPathClipper::BoolSub:
1788  return a && !b;
1789  default:
1790  Q_ASSERT(false);
1791  return false;
1792  }
1793 }
long ASN1_INTEGER_get ASN1_INTEGER * a
#define Q_ASSERT(cond)
Definition: qglobal.h:1823

◆ clear()

static void clear ( QWingedEdge list,
int  edge,
QPathEdge::Traversal  traversal 
)
static

Definition at line 1501 of file qpathclipper.cpp.

Referenced by QPathClipper::handleCrossingEdges().

1502 {
1504  status.edge = edge;
1505  status.traversal = traversal;
1506  status.direction = QPathEdge::Forward;
1507 
1508  do {
1509  if (status.traversal == QPathEdge::LeftTraversal)
1510  list.edge(status.edge)->flag |= 1;
1511  else
1512  list.edge(status.edge)->flag |= 2;
1513 
1514  status = list.next(status);
1515  } while (status.edge != edge);
1516 }
QPathEdge::Traversal traversal
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
TraversalStatus next(const TraversalStatus &status) const
QPathEdge::Direction direction
QPathEdge * edge(int edge)

◆ commonEdge()

static int commonEdge ( const QWingedEdge list,
int  a,
int  b 
)
static

Definition at line 1146 of file qpathclipper.cpp.

Referenced by QWingedEdge::addEdge().

1147 {
1148  const QPathVertex *ap = list.vertex(a);
1149  Q_ASSERT(ap);
1150 
1151  const QPathVertex *bp = list.vertex(b);
1152  Q_ASSERT(bp);
1153 
1154  if (ap->edge < 0 || bp->edge < 0)
1155  return -1;
1156 
1158  status.edge = ap->edge;
1159  status.direction = list.edge(status.edge)->directionTo(a);
1161 
1162  do {
1163  const QPathEdge *ep = list.edge(status.edge);
1164 
1165  if ((ep->first == a && ep->second == b)
1166  || (ep->first == b && ep->second == a))
1167  return status.edge;
1168 
1169  status = list.next(status);
1170  status.flip();
1171  } while (status.edge != ap->edge);
1172 
1173  return -1;
1174 }
QPathEdge::Traversal traversal
QPathVertex * vertex(int vertex)
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
long ASN1_INTEGER_get ASN1_INTEGER * a
TraversalStatus next(const TraversalStatus &status) const
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QPathEdge::Direction direction
Direction directionTo(int vertex) const
QPathEdge * edge(int edge)

◆ comparePoints()

static bool comparePoints ( const QPointF a,
const QPointF b 
)
inlinestatic

Definition at line 77 of file qpathclipper.cpp.

Referenced by QPathSegments::addPath(), QIntersectionFinder::hasIntersections(), isLine(), and QIntersectionFinder::linesIntersect().

78 {
79  return fuzzyIsNull(a.x() - b.x())
80  && fuzzyIsNull(a.y() - b.y());
81 }
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
static bool fuzzyIsNull(qreal d)
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287

◆ component()

static qreal component ( const QPointF point,
unsigned int  i 
)
inlinestatic

◆ computeAngle()

static double computeAngle ( const QPointF v)
static

Definition at line 1176 of file qpathclipper.cpp.

Referenced by QWingedEdge::addEdge().

1177 {
1178 #if 1
1179  if (v.x() == 0) {
1180  return v.y() <= 0 ? 0 : 64.;
1181  } else if (v.y() == 0) {
1182  return v.x() <= 0 ? 32. : 96.;
1183  }
1184 
1185  double vx = v.x();
1186  double vy = v.y();
1187  normalize(vx, vy);
1188  if (vy < 0) {
1189  if (vx < 0) { // 0 - 32
1190  return -32. * vx;
1191  } else { // 96 - 128
1192  return 128. - 32. * vx;
1193  }
1194  } else { // 32 - 96
1195  return 64. + 32. * vx;
1196  }
1197 #else
1198  // doesn't seem to be robust enough
1199  return qAtan2(v.x(), v.y()) + Q_PI;
1200 #endif
1201 }
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
qreal qAtan2(qreal x, qreal y)
Definition: qmath.h:189
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
static void normalize(double &x, double &y)
static const qreal Q_PI
Definition: qmath_p.h:61

◆ dot()

static qreal dot ( const QPointF a,
const QPointF b 
)
static

◆ findCrossings()

static QVector<QCrossingEdge> findCrossings ( const QWingedEdge list,
qreal  y 
)
static

Definition at line 1821 of file qpathclipper.cpp.

Referenced by QPathClipper::handleCrossingEdges().

1822 {
1823  QVector<QCrossingEdge> crossings;
1824  for (int i = 0; i < list.edgeCount(); ++i) {
1825  const QPathEdge *edge = list.edge(i);
1826  QPointF a = *list.vertex(edge->first);
1827  QPointF b = *list.vertex(edge->second);
1828 
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());
1831  const QCrossingEdge edge = { i, intersection };
1832  crossings << edge;
1833  }
1834  }
1835  return crossings;
1836 }
double qreal
Definition: qglobal.h:1193
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QPathVertex * vertex(int vertex)
long ASN1_INTEGER_get ASN1_INTEGER * a
The QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QPathEdge * edge(int edge)
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
int edgeCount() const

◆ fuzzyCompare()

static bool fuzzyCompare ( qreal  a,
qreal  b 
)
static

Definition at line 1526 of file qpathclipper.cpp.

Referenced by QPathClipper::doClip().

1527 {
1528  return qFuzzyCompare(a, b);
1529 }
long ASN1_INTEGER_get ASN1_INTEGER * a
bool qFuzzyCompare(const QMatrix &m1, const QMatrix &m2)
The qFuzzyCompare function is for comparing two matrices using a fuzziness factor.
Definition: qmatrix.h:172

◆ fuzzyIsNull()

static bool fuzzyIsNull ( qreal  d)
inlinestatic

The algorithm is as follows:

  1. Find all intersections between the two paths (including self-intersections), and build a winged edge structure of non-intersecting parts.
  2. While there are more unhandled edges:
    1. Pick a y-coordinate from an unhandled edge.
    2. Intersect the horizontal line at y-coordinate with all edges.
    3. Traverse intersections left to right deciding whether each subpath should be added or not.
    4. If the subpath should be added, traverse the winged-edge structure and add the edges to a separate winged edge structure.
    5. Mark all edges in subpaths crossing the horizontal line as handled.

(Optional) Simplify the resulting winged edge structure by merging shared edges.

  1. Convert the resulting winged edge structure to a painter path.

Definition at line 69 of file qpathclipper.cpp.

Referenced by comparePoints(), and QKdPointFinder::operator()().

70 {
71  if (sizeof(qreal) == sizeof(double))
72  return qAbs(d) <= 1e-12;
73  else
74  return qAbs(d) <= 1e-5f;
75 }
double d
Definition: qnumeric_p.h:62
double qreal
Definition: qglobal.h:1193
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201

◆ isLine()

static bool isLine ( const QBezier bezier)
static

Definition at line 900 of file qpathclipper.cpp.

Referenced by QPathSegments::addPath().

901 {
902  const bool equal_1_2 = comparePoints(bezier.pt1(), bezier.pt2());
903  const bool equal_2_3 = comparePoints(bezier.pt2(), bezier.pt3());
904  const bool equal_3_4 = comparePoints(bezier.pt3(), bezier.pt4());
905 
906  // point?
907  if (equal_1_2 && equal_2_3 && equal_3_4)
908  return true;
909 
910  if (comparePoints(bezier.pt1(), bezier.pt4()))
911  return equal_1_2 || equal_3_4;
912 
913  return (equal_1_2 && equal_3_4) || (equal_1_2 && equal_2_3) || (equal_2_3 && equal_3_4);
914 }
QPointF pt4() const
Definition: qbezier_p.h:97
QPointF pt1() const
Definition: qbezier_p.h:94
QPointF pt2() const
Definition: qbezier_p.h:95
QPointF pt3() const
Definition: qbezier_p.h:96
static bool comparePoints(const QPointF &a, const QPointF &b)

◆ midPoint()

static QPointF midPoint ( const QWingedEdge list,
int  ei 
)
inlinestatic

Definition at line 1041 of file qpathclipper.cpp.

Referenced by QBezier::midTangent(), and QBezier::pt4().

1042 {
1043  const QPathEdge *ep = list.edge(ei);
1044  Q_ASSERT(ep);
1045 
1046  const QPointF a = *list.vertex(ep->first);
1047  const QPointF b = *list.vertex(ep->second);
1048  return a + 0.5 * (b - a);
1049 }
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
QPathVertex * vertex(int vertex)
long ASN1_INTEGER_get ASN1_INTEGER * a
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QPathEdge * edge(int edge)

◆ normalize()

static void normalize ( double &  x,
double &  y 
)
static

Definition at line 89 of file qpathclipper.cpp.

Referenced by ShaderEffectItem::bindGeometry(), computeAngle(), QXmlStreamReaderPrivate::parse(), QGridLayoutBox::QGridLayoutBox(), QRect::QRect(), and QDomNodePrivate::setNodeValue().

90 {
91  double reciprocal = 1 / qSqrt(x * x + y * y);
92  x *= reciprocal;
93  y *= reciprocal;
94 }
qreal qSqrt(qreal v)
Definition: qmath.h:205

◆ qFuzzyFind()

template<typename InputIterator >
InputIterator qFuzzyFind ( InputIterator  first,
InputIterator  last,
qreal  val 
)

Definition at line 1519 of file qpathclipper.cpp.

Referenced by QPathClipper::doClip().

1520 {
1521  while (first != last && !QT_PREPEND_NAMESPACE(qFuzzyCompare)(qreal(*first), qreal(val)))
1522  ++first;
1523  return first;
1524 }
double qreal
Definition: qglobal.h:1193
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
bool qFuzzyCompare(const QMatrix &m1, const QMatrix &m2)
The qFuzzyCompare function is for comparing two matrices using a fuzziness factor.
Definition: qmatrix.h:172

◆ qRemoveDuplicates()

template<typename Iterator , typename Equality >
Iterator qRemoveDuplicates ( Iterator  begin,
Iterator  end,
Equality  eq 
)

Definition at line 1483 of file qpathclipper.cpp.

Referenced by QPathClipper::doClip().

1484 {
1485  if (begin == end)
1486  return end;
1487 
1488  Iterator last = begin;
1489  ++begin;
1490  Iterator insert = begin;
1491  for (Iterator it = begin; it != end; ++it) {
1492  if (!eq(*it, *last)) {
1493  *insert++ = *it;
1494  last = it;
1495  }
1496  }
1497 
1498  return insert;
1499 }
#define it(className, varName)
Iterator
Synonym for QAbstractFileEngineIterator.
static const KeyPair *const end

◆ qTraverseKdPointTree()

template<typename T >
void qTraverseKdPointTree ( QKdPointTree::Node node,
T &  t,
int  depth = 0 
)

Definition at line 656 of file qpathclipper.cpp.

657 {
658  QKdPointTree::Traversal status = t(node, depth);
659 
660  const bool traverseRight = (status == QKdPointTree::TraverseBoth || status == QKdPointTree::TraverseRight);
661  const bool traverseLeft = (status == QKdPointTree::TraverseBoth || status == QKdPointTree::TraverseLeft);
662 
663  if (traverseLeft && node.left)
664  QT_PREPEND_NAMESPACE(qTraverseKdPointTree<T>)(*node.left, t, depth + 1);
665 
666  if (traverseRight && node.right)
667  QT_PREPEND_NAMESPACE(qTraverseKdPointTree<T>)(*node.right, t, depth + 1);
668 }
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87

◆ traverse()

static void traverse ( QWingedEdge list,
int  edge,
QPathEdge::Traversal  traversal 
)
static

Definition at line 1746 of file qpathclipper.cpp.

Referenced by QPathClipper::handleCrossingEdges().

1747 {
1749  status.edge = edge;
1750  status.traversal = traversal;
1751  status.direction = QPathEdge::Forward;
1752 
1753  do {
1754  int flag = status.traversal == QPathEdge::LeftTraversal ? 1 : 2;
1755 
1756  QPathEdge *ep = list.edge(status.edge);
1757 
1758  ep->flag |= (flag | (flag << 4));
1759 
1760 #ifdef QDEBUG_CLIPPER
1761  qDebug() << "traverse: adding edge " << status.edge << ", mask:" << (flag << 4) <<ep->flag;
1762 #endif
1763 
1764  status = list.next(status);
1765  } while (status.edge != edge);
1766 }
QPathEdge::Traversal traversal
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
TraversalStatus next(const TraversalStatus &status) const
QPathEdge::Direction direction
Q_CORE_EXPORT void qDebug(const char *,...)
QPathEdge * edge(int edge)