File indexing completed on 2024-04-14 03:47:41

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2006-2009 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 //
0006 
0007 
0008 #include "ClipPainter.h"
0009 
0010 #include <cmath>
0011 
0012 #include "MarbleDebug.h"
0013 
0014 
0015 namespace Marble
0016 {
0017 
0018 class ClipPainterPrivate
0019 {
0020  public:
0021     explicit ClipPainterPrivate( ClipPainter * parent );
0022 
0023     ClipPainter * q;
0024 
0025     // true if clipping is on.
0026     bool    m_doClip;
0027 
0028     // The limits
0029     qreal  m_left;
0030     qreal  m_right;
0031     qreal  m_top;
0032     qreal  m_bottom;
0033 
0034     // Used in the paint process of vectors..
0035     int     m_currentSector;
0036     int     m_previousSector;
0037 
0038     //  int m_debugNodeCount;
0039 
0040     QPointF    m_currentPoint;
0041     QPointF    m_previousPoint; 
0042 
0043     inline int sector( const QPointF & point ) const;
0044 
0045     inline QPointF clipTop( qreal m, const QPointF & point ) const;
0046     inline QPointF clipLeft( qreal m, const QPointF & point ) const;
0047     inline QPointF clipBottom( qreal m, const QPointF & point ) const;
0048     inline QPointF clipRight( qreal m, const QPointF & point ) const;
0049 
0050     inline void initClipRect();
0051 
0052     inline void clipPolyObject ( const QPolygonF & sourcePolygon, 
0053                                  QVector<QPolygonF> & clippedPolyObjects,
0054                                  bool isClosed );
0055 
0056     inline void clipMultiple( QPolygonF & clippedPolyObject,
0057                               QVector<QPolygonF> & clippedPolyObjects,
0058                               bool isClosed );
0059     inline void clipOnce( QPolygonF & clippedPolyObject,
0060                               QVector<QPolygonF> & clippedPolyObjects,
0061                               bool isClosed );
0062     inline void clipOnceCorner( QPolygonF & clippedPolyObject,
0063                                 QVector<QPolygonF> & clippedPolyObjects,
0064                                 const QPointF& corner,
0065                                 const QPointF& point,
0066                                 bool isClosed ) const;
0067     inline void clipOnceEdge(   QPolygonF & clippedPolyObject,
0068                                 QVector<QPolygonF> & clippedPolyObjects,
0069                                 const QPointF& point,
0070                                 bool isClosed ) const;
0071 
0072 
0073     void labelPosition(const QPolygonF &polygon, QVector<QPointF> &labelNodes,
0074                                 LabelPositionFlags labelPositionFlags) const;
0075 
0076     bool pointAllowsLabel(const QPointF &point) const;
0077     QPointF interpolateLabelPoint(const QPointF &previousPoint,
0078                                   const QPointF &currentPoint,
0079                                   LabelPositionFlags labelPositionFlags) const;
0080 
0081     static inline qreal _m( const QPointF & start, const QPointF & end );
0082 
0083     void debugDrawNodes( const QPolygonF & );
0084 
0085     qreal m_labelAreaMargin;
0086 
0087     int m_debugPenBatchColor;
0088     int m_debugBrushBatchColor;
0089     int m_debugPolygonsLevel;
0090     bool m_debugBatchRender;
0091 };
0092 
0093 }
0094 
0095 using namespace Marble;
0096 
0097 // #define MARBLE_DEBUG
0098 
0099 ClipPainter::ClipPainter(QPaintDevice * pd, bool clip)
0100     : QPainter( pd ), d( new ClipPainterPrivate( this ) )
0101 {
0102     d->initClipRect();
0103 
0104     // m_debugNodeCount = 0;
0105     d->m_doClip = clip;
0106 }
0107 
0108 
0109 ClipPainter::ClipPainter()
0110     : d( new ClipPainterPrivate( this ) )
0111 {
0112 }
0113 
0114 
0115 ClipPainter::~ClipPainter()
0116 {
0117     delete d;
0118 }
0119 
0120 
0121 void ClipPainter::setScreenClip(bool enable)
0122 {
0123     d->m_doClip = enable;
0124 }
0125 
0126 
0127 bool ClipPainter::hasScreenClip() const
0128 {
0129     return d->m_doClip;
0130 }
0131 
0132 
0133 void ClipPainter::drawPolygon ( const QPolygonF & polygon,
0134                                 Qt::FillRule fillRule )
0135 {
0136     if ( d->m_doClip ) {    
0137         d->initClipRect();
0138         QVector<QPolygonF> clippedPolyObjects;
0139 
0140         d->clipPolyObject( polygon, clippedPolyObjects, true );
0141 
0142         for( const QPolygonF & clippedPolyObject: clippedPolyObjects ) { 
0143             if ( clippedPolyObject.size() > 2 ) {
0144                 // mDebug() << "Size: " << clippedPolyObject.size();
0145                 if (d->m_debugPolygonsLevel) {
0146                     QBrush brush = QPainter::brush();
0147                     QBrush originalBrush = brush;
0148                     QColor color = brush.color();
0149                     color.setAlpha(color.alpha()*0.75);
0150                     brush.setColor(color);
0151                     QPainter::setBrush(brush);
0152 
0153                     QPainter::drawPolygon ( clippedPolyObject, fillRule );
0154 
0155                     QPainter::setBrush(originalBrush);
0156 
0157                     d->debugDrawNodes( clippedPolyObject );
0158                 }
0159                 else {
0160                     QPainter::drawPolygon ( clippedPolyObject, fillRule );
0161                 }
0162             }
0163         }
0164     }
0165     else {
0166         if (d->m_debugPolygonsLevel) {
0167             QBrush brush = QPainter::brush();
0168             QBrush originalBrush = brush;
0169             QColor color = brush.color();
0170             color.setAlpha(color.alpha()*0.75);
0171             brush.setColor(color);
0172             QPainter::setBrush(brush);
0173 
0174             QPainter::drawPolygon ( polygon, fillRule );
0175 
0176             QPainter::setBrush(originalBrush);
0177 
0178             d->debugDrawNodes( polygon );
0179         }
0180         else {
0181             QPainter::drawPolygon ( polygon, fillRule );
0182         }
0183     }
0184 }
0185 
0186 void ClipPainter::drawPolyline( const QPolygonF & polygon )
0187 {
0188     if ( d->m_doClip ) {
0189         d->initClipRect();
0190         QVector<QPolygonF> clippedPolyObjects;
0191 
0192         d->clipPolyObject( polygon, clippedPolyObjects, false );
0193 
0194         for( const QPolygonF & clippedPolyObject: clippedPolyObjects ) { 
0195             if ( clippedPolyObject.size() > 1 ) {
0196                 if (d->m_debugPolygonsLevel) {
0197                     QPen pen = QPainter::pen();
0198                     QPen originalPen = pen;
0199                     QColor color = pen.color();
0200                     color.setAlpha(color.alpha()*0.75);
0201                     pen.setColor(color);
0202                     QPainter::setPen(pen);
0203 
0204                     QPainter::drawPolyline ( clippedPolyObject );
0205 
0206                     QPainter::setPen(originalPen);
0207 
0208                     d->debugDrawNodes( clippedPolyObject );
0209                 }
0210                 else {
0211                     QPainter::drawPolyline ( clippedPolyObject );
0212                 }
0213             }
0214         }
0215     }
0216     else {
0217         if (d->m_debugPolygonsLevel) {
0218             QPen pen = QPainter::pen();
0219             QPen originalPen = pen;
0220             QColor color = pen.color();
0221             color.setAlpha(color.alpha()*0.75);
0222             pen.setColor(color);
0223             QPainter::setPen(pen);
0224 
0225             QPainter::drawPolyline ( polygon );
0226 
0227             QPainter::setPen(originalPen);
0228 
0229             d->debugDrawNodes( polygon );
0230         }
0231         else {
0232             QPainter::drawPolyline ( polygon );
0233         }
0234     }
0235 }
0236 
0237 void ClipPainter::drawPolyline(const QPolygonF & polygon, QVector<QPointF>& labelNodes,
0238                                LabelPositionFlags positionFlags)
0239 {
0240     if ( d->m_doClip ) {
0241         d->initClipRect();
0242         QVector<QPolygonF> clippedPolyObjects;
0243 
0244         d->clipPolyObject( polygon, clippedPolyObjects, false );
0245 
0246         for( const QPolygonF & clippedPolyObject: clippedPolyObjects ) { 
0247             if (d->m_debugPolygonsLevel) {
0248                 QPen pen = QPainter::pen();
0249                 QPen originalPen = pen;
0250                 QColor color = pen.color();
0251                 color.setAlpha(color.alpha()*0.75);
0252                 pen.setColor(color);
0253                 QPainter::setPen(pen);
0254 
0255                 QPainter::drawPolyline ( clippedPolyObject );
0256 
0257                 QPainter::setPen(originalPen);
0258 
0259                 d->debugDrawNodes( clippedPolyObject );
0260             }
0261             else {
0262                 QPainter::drawPolyline ( clippedPolyObject );
0263             }
0264         }
0265     }
0266     else {
0267         if (d->m_debugPolygonsLevel) {
0268             QPen pen = QPainter::pen();
0269             QPen originalPen = pen;
0270             QColor color = pen.color();
0271             color.setAlpha(color.alpha()*0.75);
0272             pen.setColor(color);
0273             QPainter::setPen(pen);
0274 
0275             QPainter::drawPolyline ( polygon );
0276 
0277             QPainter::setPen(originalPen);
0278 
0279             d->debugDrawNodes( polygon );
0280         }
0281         else {
0282             QPainter::drawPolyline ( polygon );
0283         }
0284 
0285         d->labelPosition( polygon, labelNodes, positionFlags );
0286     }
0287 }
0288 
0289 void ClipPainter::labelPosition(const QPolygonF &polygon, QVector<QPointF> &labelNodes,
0290                                        LabelPositionFlags labelPositionFlags) const
0291 {
0292     d->labelPosition(polygon, labelNodes, labelPositionFlags);
0293 }
0294 
0295 void ClipPainter::setPen(const QColor &color) {
0296     if (d->m_debugBatchRender) {
0297         qDebug();
0298     }
0299     setPen(QPen(color));
0300 }
0301 
0302 void ClipPainter::setPen(Qt::PenStyle style) {
0303     if (d->m_debugBatchRender) {
0304         qDebug();
0305     }
0306     setPen(QPen(style));
0307 }
0308 
0309 void ClipPainter::setPen(const QPen & pen) {
0310     if (d->m_debugBatchRender) {
0311         qDebug();
0312         if (pen != QPainter::pen()) {
0313             qDebug() << "--" << pen.color()  << QPainter::pen().color() ;
0314             QPen newPen = pen;
0315             newPen.setColor((Qt::GlobalColor)(d->m_debugPenBatchColor+4));
0316             QPainter::setPen(newPen);
0317             d->m_debugPenBatchColor++;
0318             d->m_debugPenBatchColor %= 14;
0319         }
0320         else {
0321             qDebug() << "++";
0322             QPainter::setPen(pen);
0323         }
0324     }
0325     else {
0326         QPainter::setPen(pen);
0327     }
0328 }
0329 
0330 void ClipPainter::setBrush(const QBrush & brush) {
0331     if (d->m_debugBatchRender) {
0332         qDebug();
0333         if (brush != QPainter::brush()) {
0334             qDebug() << "--" << brush.color()  << QPainter::brush().color() ;
0335             QBrush batchColor(QColor((Qt::GlobalColor)(d->m_debugBrushBatchColor)));
0336             QPainter::setBrush(batchColor);
0337             d->m_debugBrushBatchColor++;
0338             d->m_debugBrushBatchColor %= 20;
0339         }
0340         else {
0341             qDebug() << "++";
0342             QPainter::setBrush(brush);
0343         }
0344     }
0345     else {
0346         QPainter::setBrush(brush);
0347     }
0348 }
0349 
0350 void ClipPainterPrivate::labelPosition(const QPolygonF &polygon, QVector<QPointF> &labelNodes,
0351                                        LabelPositionFlags labelPositionFlags) const
0352 {
0353     if ( labelPositionFlags.testFlag( LineCenter ) ) {
0354         // The Label at the center of the polyline:
0355         if ( polygon.size() > 0 ) {
0356             const int labelPosition = polygon.size() / 2; // implied: 0 <= labelPosition < polygon.size()
0357             labelNodes << polygon.at( labelPosition );
0358         }
0359     }
0360 
0361     if ( polygon.size() > 0 && labelPositionFlags.testFlag( LineStart ) ) {
0362         if ( pointAllowsLabel( polygon.first() ) ) {
0363             labelNodes << polygon.first();
0364         }
0365 
0366         // The Label at the start of the polyline:
0367         for ( int it = 1; it < polygon.size(); ++it ) {
0368             const bool currentAllowsLabel = pointAllowsLabel(polygon.at(it));
0369 
0370             if ( currentAllowsLabel ) {
0371                 // As polygon.size() > 0 it's ensured that it-1 exists.
0372                 QPointF node = interpolateLabelPoint( polygon.at( it -1 ), polygon.at( it ),
0373                                                     labelPositionFlags );
0374                 if ( node != QPointF( -1.0, -1.0 ) ) {
0375                     labelNodes << node;
0376                 }
0377                 break;
0378             }
0379         }
0380     }
0381 
0382     if ( polygon.size() > 1 && labelPositionFlags.testFlag( LineEnd ) ) {
0383         if ( pointAllowsLabel( polygon.at( polygon.size() - 1 ) ) ) {
0384             labelNodes << polygon.at( polygon.size() - 1 );
0385         }
0386 
0387         // The Label at the end of the polyline:
0388         for ( int it = polygon.size() - 2; it > 0; --it ) {
0389             const bool currentAllowsLabel = pointAllowsLabel(polygon.at(it));
0390 
0391             if ( currentAllowsLabel ) {
0392                 QPointF node = interpolateLabelPoint( polygon.at( it + 1 ), polygon.at( it ),
0393                                                     labelPositionFlags );
0394                 if ( node != QPointF( -1.0, -1.0 ) ) {
0395                     labelNodes << node;
0396                 }
0397                 break;
0398             }
0399         }
0400     }
0401 }
0402 
0403 bool ClipPainterPrivate::pointAllowsLabel(const QPointF &point) const
0404 {
0405     return point.x() > m_labelAreaMargin && point.x() < q->viewport().width() - m_labelAreaMargin 
0406          && point.y() > m_labelAreaMargin && point.y() < q->viewport().height() - m_labelAreaMargin;
0407 }
0408 
0409 QPointF ClipPainterPrivate::interpolateLabelPoint(const QPointF &previousPoint,
0410                                                   const QPointF &currentPoint,
0411                                                   LabelPositionFlags labelPositionFlags) const
0412 {
0413     qreal m = _m( previousPoint, currentPoint );
0414     if ( previousPoint.x() <= m_labelAreaMargin ) {
0415         if ( labelPositionFlags.testFlag( IgnoreXMargin ) ) {
0416             return QPointF( -1.0, -1.0 );
0417         }
0418         return QPointF( m_labelAreaMargin, 
0419                         previousPoint.y() + ( m_labelAreaMargin - previousPoint.x() ) * m );
0420     }
0421     else if ( previousPoint.x() >= q->viewport().width() - m_labelAreaMargin  ) {
0422         if ( labelPositionFlags.testFlag( IgnoreXMargin ) ) {
0423             return QPointF( -1.0, -1.0 );
0424         }
0425         return QPointF( q->viewport().width() - m_labelAreaMargin,
0426                         previousPoint.y() - 
0427                         ( previousPoint.x() - q->viewport().width() + m_labelAreaMargin ) * m );        
0428     }
0429 
0430     if ( previousPoint.y() <= m_labelAreaMargin ) {
0431         if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) {
0432             return QPointF( -1.0, -1.0 );
0433         }
0434         return QPointF( previousPoint.x() + ( m_labelAreaMargin - previousPoint.y() ) / m, 
0435                         m_labelAreaMargin );
0436     } 
0437     else if ( previousPoint.y() >= q->viewport().height() - m_labelAreaMargin  ) {
0438         if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) {
0439             return QPointF( -1.0, -1.0 );
0440         }
0441         return QPointF(   previousPoint.x() - 
0442                         ( previousPoint.y() - q->viewport().height() + m_labelAreaMargin ) / m,
0443                           q->viewport().height() - m_labelAreaMargin );        
0444     }
0445 
0446 //    mDebug() << "Previous and current node position are allowed!";
0447 
0448     return QPointF( -1.0, -1.0 );
0449 }
0450 
0451 ClipPainterPrivate::ClipPainterPrivate( ClipPainter * parent )
0452     : m_doClip( true ),
0453       m_left(0.0),
0454       m_right(0.0),
0455       m_top(0.0),
0456       m_bottom(0.0),
0457       m_currentSector(4),
0458       m_previousSector(4),
0459       m_currentPoint(QPointF()),
0460       m_previousPoint(QPointF()), 
0461       m_labelAreaMargin(10.0),
0462       m_debugPenBatchColor(0),
0463       m_debugBrushBatchColor(0),
0464       m_debugPolygonsLevel(0),
0465       m_debugBatchRender(false)
0466 {
0467     q = parent;
0468 }
0469 
0470 void ClipPainterPrivate::initClipRect ()
0471 {
0472     qreal penHalfWidth = q->pen().widthF() / 2.0 + 1.0;
0473 
0474     m_left   = -penHalfWidth; 
0475     m_right  = (qreal)(q->device()->width()) + penHalfWidth;
0476     m_top    = -penHalfWidth; 
0477     m_bottom = (qreal)(q->device()->height()) + penHalfWidth;
0478 }
0479 
0480 qreal ClipPainterPrivate::_m( const QPointF & start, const QPointF & end )
0481 {
0482     qreal  divisor = end.x() - start.x();
0483     if ( std::fabs( divisor ) < 0.000001 ) {
0484         // this is in screencoordinates so the difference
0485         // between 0, 0.000001 and -0.000001 isn't visible at all 
0486         divisor = 0.000001;
0487     }
0488 
0489     return ( end.y() - start.y() ) 
0490          / divisor;
0491 }
0492 
0493 
0494 QPointF ClipPainterPrivate::clipTop( qreal m, const QPointF & point ) const
0495 {
0496     return QPointF( ( m_top - point.y() ) / m + point.x(), m_top );
0497 }
0498 
0499 QPointF ClipPainterPrivate::clipLeft( qreal m, const QPointF & point ) const
0500 {
0501     return QPointF( m_left, ( m_left - point.x() ) * m + point.y() );
0502 }
0503 
0504 QPointF ClipPainterPrivate::clipBottom( qreal m, const QPointF & point ) const
0505 {
0506     return QPointF( ( m_bottom - point.y() ) / m + point.x(), m_bottom );
0507 }
0508 
0509 QPointF ClipPainterPrivate::clipRight( qreal m, const QPointF & point ) const
0510 {
0511     return QPointF( m_right, ( m_right - point.x() ) * m + point.y() );
0512 }
0513 
0514 int ClipPainterPrivate::sector( const QPointF & point ) const
0515 {
0516     // If we think of the image borders as (infinitely long) parallel
0517     // lines then the plane is divided into 9 sectors.  Each of these
0518     // sections is identified by a unique keynumber (currentSector):
0519     //
0520     //  0 | 1 | 2
0521     //  --+---+--
0522     //  3 | 4 | 5 <- sector number "4" represents the onscreen sector / viewport
0523     //  --+---+--
0524     //  6 | 7 | 8
0525     //
0526 
0527     // Figure out the section of the current point.
0528     int xSector = 1;
0529     if ( point.x() < m_left )
0530         xSector = 0;
0531     else if ( point.x() > m_right )
0532         xSector = 2;
0533 
0534     int ySector = 3;
0535     if ( point.y() < m_top )
0536         ySector = 0;
0537     else if ( point.y() > m_bottom )
0538         ySector = 6;
0539 
0540     // By adding xSector and ySector we get a
0541     // sector number of the values shown in the ASCII-art graph above.
0542     return ySector + xSector;
0543 
0544 }
0545 
0546 void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon, 
0547                                           QVector<QPolygonF> & clippedPolyObjects,
0548                                           bool isClosed )
0549 {
0550     //  mDebug() << "ClipPainter enabled." ;
0551 
0552     // Only create a new polyObject as soon as we know for sure that 
0553     // the current point is on the screen. 
0554     QPolygonF clippedPolyObject = QPolygonF();
0555 
0556     const QVector<QPointF>::const_iterator  itStartPoint = polygon.constBegin();
0557     const QVector<QPointF>::const_iterator  itEndPoint   = polygon.constEnd();
0558     QVector<QPointF>::const_iterator        itPoint      = itStartPoint;
0559 
0560     // We use a while loop to be able to cover linestrings as well as linear rings:
0561     // Linear rings require to tessellate the path from the last node to the first node
0562     // which isn't really convenient to achieve with a for loop ...
0563 
0564     bool processingLastNode = false;
0565 
0566     while ( itPoint != itEndPoint ) {
0567         m_currentPoint = (*itPoint);
0568         // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y();
0569 
0570         // Figure out the sector of the current point.
0571         m_currentSector = sector( m_currentPoint );
0572 
0573         // Initialize the variables related to the previous point.
0574         if ( itPoint == itStartPoint && processingLastNode == false ) {
0575             if ( isClosed ) {
0576                 m_previousPoint = polygon.last();
0577 
0578                 // Figure out the sector of the previous point.
0579                 m_previousSector = sector( m_previousPoint );
0580             }
0581             else {
0582                 m_previousSector = m_currentSector;
0583             }
0584         }
0585 
0586         // If the current point reaches a new sector, take care of clipping.
0587         if ( m_currentSector != m_previousSector ) {
0588             if ( m_currentSector == 4 || m_previousSector == 4 ) {
0589                 // In this case the current or the previous point is visible on the
0590                 // screen but not both. Hence we only need to clip once and require
0591                 // only one interpolation for both cases.
0592 
0593                 clipOnce( clippedPolyObject, clippedPolyObjects, isClosed );
0594             }
0595             else {
0596                 // This case mostly deals with lines that reach from one
0597                 // sector that is located off screen to another one that
0598                 // is located off screen. In this situation the line 
0599                 // can get clipped once, twice, or not at all.
0600                 clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed );
0601             }
0602 
0603             m_previousSector = m_currentSector;
0604         }
0605 
0606         // If the current point is onscreen, just add it to our final polygon.
0607         if ( m_currentSector == 4 ) {
0608 
0609             clippedPolyObject << m_currentPoint;
0610 #ifdef MARBLE_DEBUG
0611             ++(m_debugNodeCount);
0612 #endif
0613         }
0614 
0615         m_previousPoint = m_currentPoint;
0616 
0617         // Now let's handle the case where we have a (closed) polygon and where the
0618         // last point of the polyline is outside the viewport and the start point
0619         // is inside the viewport. This needs special treatment
0620         if ( processingLastNode ) {
0621             break;
0622         }
0623         ++itPoint;
0624 
0625         if ( itPoint == itEndPoint  && isClosed ) {
0626             itPoint = itStartPoint;
0627             processingLastNode = true;
0628         }
0629     }
0630 
0631     // Only add the pointer if there's node data available.
0632     if ( !clippedPolyObject.isEmpty() ) {
0633         clippedPolyObjects << clippedPolyObject;
0634     }
0635 }
0636 
0637 
0638 void ClipPainterPrivate::clipMultiple( QPolygonF & clippedPolyObject,
0639                                        QVector<QPolygonF> & clippedPolyObjects,
0640                                        bool isClosed )
0641 {
0642     Q_UNUSED( clippedPolyObjects )
0643     Q_UNUSED( isClosed )
0644 
0645     // Take care of adding nodes in the image corners if the iterator 
0646     // traverses off screen sections.
0647 
0648     qreal  m = _m( m_previousPoint, m_currentPoint );
0649 
0650     switch ( m_currentSector ) {
0651     case 0:
0652         if ( m_previousSector == 5 ) {
0653             QPointF pointRight = clipRight( m, m_previousPoint );
0654             QPointF pointTop = clipTop( m, m_currentPoint );
0655             QPointF pointLeft = clipLeft( m, m_currentPoint );
0656 
0657             if ( pointRight.y() > m_top ) {
0658                 clippedPolyObject << pointRight;
0659             } else {
0660                 clippedPolyObject << QPointF( m_right, m_top );
0661             }
0662             if ( pointTop.x() >= m_left && pointTop.x() < m_right )
0663                 clippedPolyObject << pointTop;
0664             if ( pointLeft.y() > m_top ) 
0665                 clippedPolyObject << pointLeft;
0666         }
0667         else if ( m_previousSector == 7 ) {
0668             QPointF pointBottom = clipBottom( m, m_previousPoint );
0669             QPointF pointTop = clipTop( m, m_currentPoint );
0670             QPointF pointLeft = clipLeft( m, m_currentPoint );
0671 
0672             if ( pointBottom.x() > m_left ) {
0673                 clippedPolyObject << pointBottom;
0674             } else {
0675                 clippedPolyObject << QPointF( m_left, m_bottom );
0676             }
0677             if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) 
0678                 clippedPolyObject << pointLeft;
0679             if ( pointTop.x() > m_left )
0680                 clippedPolyObject << pointTop;
0681         }
0682         else if ( m_previousSector == 8 ) {
0683             QPointF pointBottom = clipBottom( m, m_previousPoint );
0684             QPointF pointRight = clipRight( m, m_previousPoint );
0685             QPointF pointTop = clipTop( m, m_currentPoint );
0686             QPointF pointLeft = clipLeft( m, m_currentPoint );
0687 
0688             if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
0689                 clippedPolyObject << pointBottom;
0690             if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) 
0691                 clippedPolyObject << pointRight;
0692             if ( pointTop.x() > m_left && pointTop.x() < m_right ) 
0693                 clippedPolyObject << pointTop;
0694             if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) 
0695                 clippedPolyObject << pointLeft;
0696    
0697             if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom )
0698                 clippedPolyObject << QPointF( m_left, m_bottom );
0699             if ( pointTop.x() >= m_right && pointRight.y() <= m_top )
0700                 clippedPolyObject << QPointF( m_right, m_top );
0701         }
0702 
0703         clippedPolyObject << QPointF( m_left, m_top );
0704         break;
0705 
0706     case 1:
0707         if ( m_previousSector == 3 ) {
0708             QPointF pointLeft = clipLeft( m, m_previousPoint );
0709             QPointF pointTop = clipTop( m, m_currentPoint );
0710 
0711             if ( pointLeft.y() > m_top ) {
0712                 clippedPolyObject << pointLeft;
0713             } else {
0714                 clippedPolyObject << QPointF( m_left, m_top );
0715             }
0716             if ( pointTop.x() > m_left )
0717                 clippedPolyObject << pointTop;
0718         }
0719         else if ( m_previousSector == 5 ) {
0720             QPointF pointRight = clipRight( m, m_previousPoint );
0721             QPointF pointTop = clipTop( m, m_currentPoint );
0722 
0723             if ( pointRight.y() > m_top ) {
0724                 clippedPolyObject << pointRight;
0725             } else {
0726                 clippedPolyObject << QPointF( m_right, m_top );
0727             }
0728             if ( pointTop.x() < m_right )
0729                 clippedPolyObject << pointTop;
0730         }
0731         else if ( m_previousSector == 6 ) {
0732             QPointF pointBottom = clipBottom( m, m_previousPoint );
0733             QPointF pointLeft = clipLeft( m, m_previousPoint );
0734             QPointF pointTop = clipTop( m, m_currentPoint );
0735 
0736             if ( pointBottom.x() > m_left )
0737                 clippedPolyObject << pointBottom;
0738             if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) 
0739                 clippedPolyObject << pointLeft;
0740             if ( pointTop.x() > m_left ) {
0741                 clippedPolyObject << pointTop;
0742             } else {
0743                 clippedPolyObject << QPointF( m_left, m_top );
0744             }
0745         }
0746         else if ( m_previousSector == 7 ) {
0747             clippedPolyObject << clipBottom( m, m_previousPoint );
0748             clippedPolyObject << clipTop( m, m_currentPoint );
0749         }
0750         else if ( m_previousSector == 8 ) {
0751             QPointF pointBottom = clipBottom( m, m_previousPoint );
0752             QPointF pointRight = clipRight( m, m_previousPoint );
0753             QPointF pointTop = clipTop( m, m_currentPoint );
0754 
0755             if ( pointBottom.x() < m_right )
0756                 clippedPolyObject << pointBottom;
0757             if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) 
0758                 clippedPolyObject << pointRight;
0759             if ( pointTop.x() < m_right ) {
0760                 clippedPolyObject << pointTop;
0761             } else {
0762                 clippedPolyObject << QPointF( m_right, m_top );
0763             }
0764         }
0765         break;
0766 
0767     case 2:
0768         if ( m_previousSector == 3 ) {
0769             QPointF pointLeft = clipLeft( m, m_previousPoint );
0770             QPointF pointTop = clipTop( m, m_currentPoint );
0771             QPointF pointRight = clipRight( m, m_currentPoint );
0772 
0773             if ( pointLeft.y() > m_top ) {
0774                 clippedPolyObject << pointLeft;
0775             } else {
0776                 clippedPolyObject << QPointF( m_left, m_top );
0777             }
0778             if ( pointTop.x() > m_left && pointTop.x() <= m_right )
0779                 clippedPolyObject << pointTop;
0780             if ( pointRight.y() > m_top ) 
0781                 clippedPolyObject << pointRight;
0782         }
0783         else if ( m_previousSector == 7 ) {
0784             QPointF pointBottom = clipBottom( m, m_previousPoint );
0785             QPointF pointTop = clipTop( m, m_currentPoint );
0786             QPointF pointRight = clipRight( m, m_currentPoint );
0787 
0788             if ( pointBottom.x() < m_right ) {
0789                 clippedPolyObject << pointBottom;
0790             } else {
0791                 clippedPolyObject << QPointF( m_right, m_bottom );
0792             }
0793             if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) 
0794                 clippedPolyObject << pointRight;
0795             if ( pointTop.x() < m_right )
0796                 clippedPolyObject << pointTop;
0797         }
0798         else if ( m_previousSector == 6 ) {
0799             QPointF pointBottom = clipBottom( m, m_previousPoint );
0800             QPointF pointLeft = clipLeft( m, m_currentPoint );
0801             QPointF pointTop = clipTop( m, m_currentPoint );
0802             QPointF pointRight = clipRight( m, m_previousPoint );
0803 
0804             if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
0805                 clippedPolyObject << pointBottom;
0806             if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) 
0807                 clippedPolyObject << pointLeft;
0808             if ( pointTop.x() > m_left && pointTop.x() < m_right ) 
0809                 clippedPolyObject << pointTop;
0810             if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) 
0811                 clippedPolyObject << pointRight;
0812    
0813             if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom )
0814                 clippedPolyObject << QPointF( m_right, m_bottom );
0815             if ( pointTop.x() <= m_left && pointLeft.y() <= m_top )
0816                 clippedPolyObject << QPointF( m_left, m_top );
0817         }
0818 
0819         clippedPolyObject << QPointF( m_right, m_top );
0820         break;
0821 
0822     case 3:
0823         if ( m_previousSector == 7 ) {
0824             QPointF pointBottom = clipBottom( m, m_previousPoint );
0825             QPointF pointLeft = clipLeft( m, m_currentPoint );
0826 
0827             if ( pointBottom.x() > m_left )
0828                 clippedPolyObject << pointBottom;
0829             if ( pointLeft.y() < m_bottom ) {
0830                 clippedPolyObject << pointLeft;
0831             } else {
0832                 clippedPolyObject << QPointF( m_left, m_bottom );
0833             }
0834         }
0835         else if ( m_previousSector == 1 ) {
0836             QPointF pointTop = clipTop( m, m_previousPoint );
0837             QPointF pointLeft = clipLeft( m, m_currentPoint );
0838 
0839             if ( pointTop.x() > m_left )
0840                 clippedPolyObject << pointTop;
0841             if ( pointLeft.y() > m_top ) {
0842                 clippedPolyObject << pointLeft;
0843             } else {
0844                 clippedPolyObject << QPointF( m_left, m_top );
0845             }
0846         }
0847         else if ( m_previousSector == 8 ) {
0848             QPointF pointRight = clipRight( m, m_previousPoint );
0849             QPointF pointBottom = clipBottom( m, m_previousPoint );
0850             QPointF pointLeft = clipLeft( m, m_currentPoint );
0851 
0852             if ( pointRight.y() < m_bottom ) 
0853                 clippedPolyObject << pointRight;
0854             if ( pointBottom.x() > m_left && pointBottom.x() <= m_right )
0855                 clippedPolyObject << pointBottom;
0856             if ( pointLeft.y() < m_bottom ) {
0857                 clippedPolyObject << pointLeft;
0858             } else {
0859                 clippedPolyObject << QPointF( m_left, m_bottom );
0860             }
0861         }
0862         else if ( m_previousSector == 5 ) {
0863             clippedPolyObject << clipRight( m, m_previousPoint );
0864             clippedPolyObject << clipLeft( m, m_currentPoint );
0865         }
0866         else if ( m_previousSector == 2 ) {
0867             QPointF pointRight = clipRight( m, m_previousPoint );
0868             QPointF pointTop = clipTop( m, m_previousPoint );
0869             QPointF pointLeft = clipLeft( m, m_currentPoint );
0870 
0871             if ( pointRight.y() > m_top ) 
0872                 clippedPolyObject << pointRight;
0873             if ( pointTop.x() > m_left && pointTop.x() <= m_right )
0874                 clippedPolyObject << pointTop;
0875             if ( pointLeft.y() > m_top ) {
0876                 clippedPolyObject << pointLeft;
0877             } else {
0878                 clippedPolyObject << QPointF( m_left, m_top );
0879             }
0880         }
0881         break;
0882 
0883     case 5:
0884         if ( m_previousSector == 7 ) {
0885             QPointF pointBottom = clipBottom( m, m_previousPoint );
0886             QPointF pointRight = clipRight( m, m_currentPoint );
0887 
0888             if ( pointBottom.x() < m_right )
0889                 clippedPolyObject << pointBottom;
0890             if ( pointRight.y() < m_bottom ) {
0891                 clippedPolyObject << pointRight;
0892             } else {
0893                 clippedPolyObject << QPointF( m_right, m_bottom );
0894             }
0895         }
0896         else if ( m_previousSector == 1 ) {
0897             QPointF pointTop = clipTop( m, m_previousPoint );
0898             QPointF pointRight = clipRight( m, m_currentPoint );
0899 
0900             if ( pointTop.x() < m_right )
0901                 clippedPolyObject << pointTop;
0902             if ( pointRight.y() > m_top ) {
0903                 clippedPolyObject << pointRight;
0904             } else {
0905                 clippedPolyObject << QPointF( m_right, m_top );
0906             }
0907         }
0908         else if ( m_previousSector == 6 ) {
0909             QPointF pointLeft = clipLeft( m, m_previousPoint );
0910             QPointF pointBottom = clipBottom( m, m_previousPoint );
0911             QPointF pointRight = clipRight( m, m_currentPoint );
0912 
0913             if ( pointLeft.y() < m_bottom ) 
0914                 clippedPolyObject << pointLeft;
0915             if ( pointBottom.x() >= m_left && pointBottom.x() < m_right )
0916                 clippedPolyObject << pointBottom;
0917             if ( pointRight.y() < m_bottom ) {
0918                 clippedPolyObject << pointRight;
0919             } else {
0920                 clippedPolyObject << QPointF( m_right, m_bottom );
0921             }
0922         }
0923         else if ( m_previousSector == 3 ) {
0924             clippedPolyObject << clipLeft( m, m_previousPoint );
0925             clippedPolyObject << clipRight( m, m_currentPoint );
0926         }
0927         else if ( m_previousSector == 0 ) {
0928             QPointF pointLeft = clipLeft( m, m_previousPoint );
0929             QPointF pointTop = clipTop( m, m_previousPoint );
0930             QPointF pointRight = clipRight( m, m_currentPoint );
0931 
0932             if ( pointLeft.y() > m_top ) 
0933                 clippedPolyObject << pointLeft;
0934             if ( pointTop.x() >= m_left && pointTop.x() < m_right )
0935                 clippedPolyObject << pointTop;
0936             if ( pointRight.y() > m_top ) {
0937                 clippedPolyObject << pointRight;
0938             } else {
0939                 clippedPolyObject << QPointF( m_right, m_top );
0940             }
0941         }
0942         break;
0943 
0944     case 6:
0945         if ( m_previousSector == 5 ) {
0946             QPointF pointRight = clipRight( m, m_previousPoint );
0947             QPointF pointBottom = clipBottom( m, m_currentPoint );
0948             QPointF pointLeft = clipLeft( m, m_currentPoint );
0949 
0950             if ( pointRight.y() < m_bottom ) {
0951                 clippedPolyObject << pointRight;
0952             } else {
0953                 clippedPolyObject << QPointF( m_right, m_bottom );
0954             }
0955             if ( pointBottom.x() >= m_left && pointBottom.x() < m_right )
0956                 clippedPolyObject << pointBottom;
0957             if ( pointLeft.y() < m_bottom ) 
0958                 clippedPolyObject << pointLeft;
0959         }
0960         else if ( m_previousSector == 1 ) {
0961             QPointF pointTop = clipTop( m, m_previousPoint );
0962             QPointF pointLeft = clipLeft( m, m_currentPoint );
0963             QPointF pointBottom = clipBottom( m, m_currentPoint );
0964 
0965             if ( pointTop.x() > m_left ) {
0966                 clippedPolyObject << pointTop;
0967             } else {
0968                 clippedPolyObject << QPointF( m_left, m_top );
0969             }
0970             if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom ) 
0971                 clippedPolyObject << pointLeft;
0972             if ( pointBottom.x() > m_left )
0973                 clippedPolyObject << pointBottom;
0974         }
0975         else if ( m_previousSector == 2 ) {
0976             QPointF pointTop = clipTop( m, m_currentPoint );
0977             QPointF pointRight = clipRight( m, m_previousPoint );
0978             QPointF pointBottom = clipBottom( m, m_previousPoint );
0979             QPointF pointLeft = clipLeft( m, m_currentPoint );
0980 
0981             if ( pointTop.x() > m_left && pointTop.x() < m_right ) 
0982                 clippedPolyObject << pointTop;
0983             if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) 
0984                 clippedPolyObject << pointRight;
0985             if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
0986                 clippedPolyObject << pointBottom;
0987             if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) 
0988                 clippedPolyObject << pointLeft;
0989    
0990             if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom )
0991                 clippedPolyObject << QPointF( m_right, m_bottom );
0992             if ( pointTop.x() <= m_left && pointLeft.y() <= m_top )
0993                 clippedPolyObject << QPointF( m_left, m_top );
0994         }
0995 
0996         clippedPolyObject << QPointF( m_left, m_bottom );
0997         break;
0998 
0999     case 7:
1000         if ( m_previousSector == 3 ) {
1001             QPointF pointLeft = clipLeft( m, m_previousPoint );
1002             QPointF pointBottom = clipBottom( m, m_currentPoint );
1003 
1004             if ( pointLeft.y() < m_bottom ) {
1005                 clippedPolyObject << pointLeft;
1006             } else {
1007                 clippedPolyObject << QPointF( m_left, m_bottom );
1008             }
1009             if ( pointBottom.x() > m_left )
1010                 clippedPolyObject << pointBottom;
1011         }
1012         else if ( m_previousSector == 5 ) {
1013             QPointF pointRight = clipRight( m, m_previousPoint );
1014             QPointF pointBottom = clipBottom( m, m_currentPoint );
1015 
1016             if ( pointRight.y() < m_bottom ) {
1017                 clippedPolyObject << pointRight;
1018             } else {
1019                 clippedPolyObject << QPointF( m_right, m_bottom );
1020             }
1021             if ( pointBottom.x() < m_right )
1022                 clippedPolyObject << pointBottom;
1023         }
1024         else if ( m_previousSector == 0 ) {
1025             QPointF pointTop = clipTop( m, m_previousPoint );
1026             QPointF pointLeft = clipLeft( m, m_previousPoint );
1027             QPointF pointBottom = clipBottom( m, m_currentPoint );
1028 
1029             if ( pointTop.x() > m_left )
1030                 clippedPolyObject << pointTop;
1031             if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom ) 
1032                 clippedPolyObject << pointLeft;
1033             if ( pointBottom.x() > m_left ) {
1034                 clippedPolyObject << pointBottom;
1035             } else {
1036                 clippedPolyObject << QPointF( m_left, m_bottom );
1037             }
1038         }
1039         else if ( m_previousSector == 1 ) {
1040             clippedPolyObject << clipTop( m, m_previousPoint );
1041             clippedPolyObject << clipBottom( m, m_currentPoint );
1042         }
1043         else if ( m_previousSector == 2 ) {
1044             QPointF pointTop = clipTop( m, m_previousPoint );
1045             QPointF pointRight = clipRight( m, m_previousPoint );
1046             QPointF pointBottom = clipBottom( m, m_currentPoint );
1047 
1048             if ( pointTop.x() < m_right )
1049                 clippedPolyObject << pointTop;
1050             if ( pointRight.y() >= m_top && pointRight.y() < m_bottom ) 
1051                 clippedPolyObject << pointRight;
1052             if ( pointBottom.x() < m_right ) {
1053                 clippedPolyObject << pointBottom;
1054             } else {
1055                 clippedPolyObject << QPointF( m_right, m_bottom );
1056             }
1057         }
1058         break;
1059 
1060     case 8:
1061         if ( m_previousSector == 3 ) {
1062             QPointF pointLeft = clipLeft( m, m_previousPoint );
1063             QPointF pointBottom = clipBottom( m, m_currentPoint );
1064             QPointF pointRight = clipRight( m, m_currentPoint );
1065 
1066             if ( pointLeft.y() < m_bottom ) {
1067                 clippedPolyObject << pointLeft;
1068             } else {
1069                 clippedPolyObject << QPointF( m_left, m_bottom );
1070             }
1071             if ( pointBottom.x() > m_left && pointBottom.x() <= m_right )
1072                 clippedPolyObject << pointBottom;
1073             if ( pointRight.y() < m_bottom ) 
1074                 clippedPolyObject << pointRight;
1075         }
1076         else if ( m_previousSector == 1 ) {
1077             QPointF pointTop = clipTop( m, m_previousPoint );
1078             QPointF pointRight = clipRight( m, m_currentPoint );
1079             QPointF pointBottom = clipBottom( m, m_currentPoint );
1080 
1081             if ( pointTop.x() < m_right ) {
1082                 clippedPolyObject << pointTop;
1083             } else {
1084                 clippedPolyObject << QPointF( m_right, m_top );
1085             }
1086             if ( pointRight.y() > m_top && pointRight.y() <= m_bottom ) 
1087                 clippedPolyObject << pointRight;
1088             if ( pointBottom.x() < m_right )
1089                 clippedPolyObject << pointBottom;
1090         }
1091         else if ( m_previousSector == 0 ) {
1092             QPointF pointTop = clipTop( m, m_currentPoint );
1093             QPointF pointLeft = clipLeft( m, m_currentPoint );
1094             QPointF pointBottom = clipBottom( m, m_previousPoint );
1095             QPointF pointRight = clipRight( m, m_previousPoint );
1096 
1097             if ( pointTop.x() > m_left && pointTop.x() < m_right ) 
1098                 clippedPolyObject << pointTop;
1099             if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom ) 
1100                 clippedPolyObject << pointLeft;
1101             if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
1102                 clippedPolyObject << pointBottom;
1103             if ( pointRight.y() > m_top && pointRight.y() < m_bottom ) 
1104                 clippedPolyObject << pointRight;
1105    
1106             if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom )
1107                 clippedPolyObject << QPointF( m_left, m_bottom );
1108             if ( pointTop.x() >= m_right && pointRight.y() <= m_top )
1109                 clippedPolyObject << QPointF( m_right, m_top );
1110         }
1111 
1112         clippedPolyObject << QPointF( m_right, m_bottom );
1113         break;
1114 
1115     default:
1116         break;              
1117     }
1118 }
1119 
1120 void ClipPainterPrivate::clipOnceCorner( QPolygonF & clippedPolyObject,
1121                                          QVector<QPolygonF> & clippedPolyObjects,
1122                                          const QPointF& corner,
1123                                          const QPointF& point, 
1124                                          bool isClosed ) const
1125 {
1126     Q_UNUSED( clippedPolyObjects )
1127     Q_UNUSED( isClosed )
1128 
1129     if ( m_currentSector == 4) {
1130         // Appearing
1131         clippedPolyObject << corner;
1132         clippedPolyObject << point;
1133     } else {
1134         // Disappearing
1135         clippedPolyObject << point;
1136         clippedPolyObject << corner;
1137     }
1138 }
1139 
1140 void ClipPainterPrivate::clipOnceEdge( QPolygonF & clippedPolyObject,
1141                                        QVector<QPolygonF> & clippedPolyObjects,
1142                                        const QPointF& point,
1143                                        bool isClosed ) const
1144 {
1145     if ( m_currentSector == 4) {
1146         // Appearing
1147         if ( !isClosed ) {
1148             clippedPolyObject = QPolygonF();
1149         }
1150         clippedPolyObject << point;
1151     }
1152     else {
1153         // Disappearing
1154         clippedPolyObject << point;
1155         if ( !isClosed ) {
1156             clippedPolyObjects << clippedPolyObject;           
1157         }
1158     }
1159 }
1160 
1161 void ClipPainterPrivate::clipOnce( QPolygonF & clippedPolyObject,
1162                                    QVector<QPolygonF> & clippedPolyObjects,
1163                                    bool isClosed )
1164 {
1165     //  Interpolate border points (linear interpolation)
1166     QPointF point;
1167 
1168     // Calculating the slope.
1169     qreal m = _m( m_previousPoint, m_currentPoint );
1170 
1171     // Calculate in which sector the end of the line is located that is off screen 
1172     int offscreenpos = ( m_currentSector == 4 ) ? m_previousSector : m_currentSector;
1173 
1174     // "Rise over run" for all possible situations .
1175     switch ( offscreenpos ) {
1176     case 0: // topleft
1177         point = clipTop( m, m_previousPoint );
1178         if ( point.x() < m_left ) {
1179             point = clipLeft( m, point );
1180         }
1181         clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_left, m_top ), point, isClosed );
1182         break;
1183     case 1: // top
1184         point = clipTop( m, m_previousPoint );
1185         clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1186         break;
1187     case 2: // topright
1188         point = clipTop( m, m_previousPoint );
1189         if ( point.x() > m_right ) {
1190             point = clipRight( m, point );
1191         }
1192         clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_right, m_top ), point, isClosed );
1193         break;
1194     case 3: // left
1195         point = clipLeft( m, m_previousPoint );
1196         clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1197         break;
1198     case 5: // right
1199         point = clipRight( m, m_previousPoint );
1200         clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1201         break;
1202     case 6: // bottomleft
1203         point = clipBottom( m, m_previousPoint );
1204         if ( point.x() < m_left ) {
1205             point = clipLeft( m, point );
1206         }
1207         clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_left, m_bottom ), point, isClosed );
1208         break;
1209     case 7: // bottom
1210         point = clipBottom( m, m_previousPoint );
1211         clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1212         break;
1213     case 8: // bottomright
1214         point = clipBottom( m, m_previousPoint );
1215         if ( point.x() > m_right ) {
1216             point = clipRight( m, point );
1217         }
1218         clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_right, m_bottom ), point, isClosed );
1219         break;
1220     default:
1221         break;          
1222     }
1223 
1224 }
1225 
1226 void ClipPainter::setDebugPolygonsLevel( int level ) {
1227     d->m_debugPolygonsLevel = level;
1228 }
1229 
1230 void ClipPainter::setDebugBatchRender( bool enabled ) {
1231     d->m_debugBatchRender = enabled;
1232 }
1233 
1234 
1235 void ClipPainterPrivate::debugDrawNodes( const QPolygonF & polygon )
1236 {
1237 
1238     q->save();
1239     q->setRenderHint( QPainter::Antialiasing, false );
1240 
1241     q->setPen( Qt::red );
1242     q->setBrush(QBrush("#40FF0000"));
1243 
1244     const QVector<QPointF>::const_iterator  itStartPoint = polygon.constBegin();
1245     const QVector<QPointF>::const_iterator  itEndPoint   = polygon.constEnd();
1246     QVector<QPointF>::const_iterator        itPoint      = itStartPoint;
1247 
1248     int i = 0;
1249 
1250     for (; itPoint != itEndPoint; ++itPoint ) {
1251 
1252         ++i;
1253         
1254         if ( itPoint == itStartPoint || itPoint == itStartPoint + 1 || itPoint == itStartPoint + 2 ) {
1255             q->setPen( Qt::darkGreen );
1256             q->setBrush(QBrush("#4000FF00"));
1257             if ( itPoint == itStartPoint ) {
1258                 q->drawRect( itPoint->x() - 6.0, itPoint->y() - 6.0 , 12.0, 12.0 );
1259             }
1260             else if ( itPoint == itStartPoint + 1 ) {
1261                 q->drawRect( itPoint->x() - 4.0, itPoint->y() - 4.0 , 8.0, 8.0 );
1262             }
1263             else {
1264                 q->drawRect( itPoint->x() - 2.0, itPoint->y() - 2.0 , 4.0, 4.0 );
1265             }
1266             q->setPen( Qt::red );
1267             q->setBrush(QBrush("#40FF0000"));
1268         }
1269         else if ( itPoint == itEndPoint - 1 || itPoint == itEndPoint - 2 || itPoint == itEndPoint - 3 ) {
1270             q->setPen( Qt::blue );
1271             q->setBrush(QBrush("#400000FF"));
1272             if ( itPoint == itEndPoint - 3 ) {
1273                 q->drawRect( itPoint->x() - 6.0, itPoint->y() - 6.0 , 12.0, 12.0 );
1274             }
1275             else if ( itPoint == itEndPoint - 2 ) {
1276                 q->drawRect( itPoint->x() - 4.0, itPoint->y() - 4.0 , 8.0, 8.0 );
1277             }
1278             else {
1279                 q->drawRect( itPoint->x() - 2.0, itPoint->y() - 2.0 , 4.0, 4.0 );
1280             }
1281             q->setPen( Qt::red );
1282             q->setBrush(QBrush("#400000FF"));
1283         }
1284         else {
1285             q->drawRect( itPoint->x() - 4, itPoint->y() - 4 , 8.0, 8.0 );
1286         }
1287         if (m_debugPolygonsLevel == 2) {
1288             q->setFont(QFont(QStringLiteral("Sans Serif"), 7));
1289             q->setPen("black");
1290             q->setBrush(Qt::transparent);
1291             q->drawText(itPoint->x() + 6.0, itPoint->y() + (15 - (i * 5) % 30) , QString::number(i));
1292         }
1293     }
1294     q->restore();
1295 }