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