File indexing completed on 2024-05-12 15:56:51

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2008 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "KoSnapStrategy.h"
0008 #include "KoSnapProxy.h"
0009 #include "KoSnapGuide.h"
0010 #include <KoPathShape.h>
0011 #include <KoPathPoint.h>
0012 #include <KoPathSegment.h>
0013 #include <KoCanvasBase.h>
0014 #include <KoViewConverter.h>
0015 
0016 #include <QPainter>
0017 #include <QPainterPath>
0018 
0019 #include <cmath>
0020 
0021 #if defined(_MSC_VER) && (_MSC_VER < 1800)
0022 #define isfinite(x) (double)(x)
0023 #endif
0024 
0025 KoSnapStrategy::KoSnapStrategy(KoSnapGuide::Strategy type)
0026     : m_snapType(type)
0027 {
0028 }
0029 
0030 QPointF KoSnapStrategy::snappedPosition() const
0031 {
0032     return m_snappedPosition;
0033 }
0034 
0035 void KoSnapStrategy::setSnappedPosition(const QPointF &position)
0036 {
0037     m_snappedPosition = position;
0038 }
0039 
0040 KoSnapGuide::Strategy KoSnapStrategy::type() const
0041 {
0042     return m_snapType;
0043 }
0044 
0045 qreal KoSnapStrategy::squareDistance(const QPointF &p1, const QPointF &p2)
0046 {
0047     const qreal dx = p1.x() - p2.x();
0048     const qreal dy = p1.y() - p2.y();
0049 
0050     return dx*dx + dy*dy;
0051 }
0052 
0053 qreal KoSnapStrategy::scalarProduct(const QPointF &p1, const QPointF &p2)
0054 {
0055     return p1.x() * p2.x() + p1.y() * p2.y();
0056 }
0057 
0058 OrthogonalSnapStrategy::OrthogonalSnapStrategy()
0059     : KoSnapStrategy(KoSnapGuide::OrthogonalSnapping)
0060 {
0061 }
0062 
0063 bool OrthogonalSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
0064 {
0065     Q_ASSERT(std::isfinite(maxSnapDistance));
0066     QPointF horzSnap, vertSnap;
0067     qreal minVertDist = HUGE_VAL;
0068     qreal minHorzDist = HUGE_VAL;
0069 
0070     QList<KoShape*> shapes = proxy->shapes(true);
0071     Q_FOREACH (KoShape * shape, shapes) {
0072         QList<QPointF> points = proxy->pointsFromShape(shape);
0073         foreach (const QPointF &point, points) {
0074             qreal dx = fabs(point.x() - mousePosition.x());
0075             if (dx < minHorzDist && dx < maxSnapDistance) {
0076                 minHorzDist = dx;
0077                 horzSnap = point;
0078             }
0079             qreal dy = fabs(point.y() - mousePosition.y());
0080             if (dy < minVertDist && dy < maxSnapDistance) {
0081                 minVertDist = dy;
0082                 vertSnap = point;
0083             }
0084         }
0085     }
0086 
0087     QPointF snappedPoint = mousePosition;
0088 
0089     if (minHorzDist < HUGE_VAL)
0090         snappedPoint.setX(horzSnap.x());
0091     if (minVertDist < HUGE_VAL)
0092         snappedPoint.setY(vertSnap.y());
0093 
0094     if (minHorzDist < HUGE_VAL)
0095         m_hLine = QLineF(horzSnap, snappedPoint);
0096     else
0097         m_hLine = QLineF();
0098 
0099     if (minVertDist < HUGE_VAL)
0100         m_vLine = QLineF(vertSnap, snappedPoint);
0101     else
0102         m_vLine = QLineF();
0103 
0104     setSnappedPosition(snappedPoint);
0105 
0106     return (minHorzDist < HUGE_VAL || minVertDist < HUGE_VAL);
0107 }
0108 
0109 QPainterPath OrthogonalSnapStrategy::decoration(const KoViewConverter &/*converter*/) const
0110 {
0111     QPainterPath decoration;
0112     if (! m_hLine.isNull()) {
0113         decoration.moveTo(m_hLine.p1());
0114         decoration.lineTo(m_hLine.p2());
0115     }
0116     if (! m_vLine.isNull()) {
0117         decoration.moveTo(m_vLine.p1());
0118         decoration.lineTo(m_vLine.p2());
0119     }
0120     return decoration;
0121 }
0122 
0123 NodeSnapStrategy::NodeSnapStrategy()
0124     : KoSnapStrategy(KoSnapGuide::NodeSnapping)
0125 {
0126 }
0127 
0128 bool NodeSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
0129 {
0130     Q_ASSERT(std::isfinite(maxSnapDistance));
0131     const qreal maxDistance = maxSnapDistance * maxSnapDistance;
0132     qreal minDistance = HUGE_VAL;
0133 
0134     QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
0135     rect.moveCenter(mousePosition);
0136     QList<QPointF> points = proxy->pointsInRect(rect, false);
0137     QPointF snappedPoint = mousePosition;
0138 
0139     foreach (const QPointF &point, points) {
0140         qreal distance = squareDistance(mousePosition, point);
0141         if (distance < maxDistance && distance < minDistance) {
0142             snappedPoint = point;
0143             minDistance = distance;
0144         }
0145     }
0146 
0147     setSnappedPosition(snappedPoint);
0148 
0149     return (minDistance < HUGE_VAL);
0150 }
0151 
0152 QPainterPath NodeSnapStrategy::decoration(const KoViewConverter &converter) const
0153 {
0154     QRectF unzoomedRect = converter.viewToDocument(QRectF(0, 0, 11, 11));
0155     unzoomedRect.moveCenter(snappedPosition());
0156     QPainterPath decoration;
0157     decoration.addEllipse(unzoomedRect);
0158     return decoration;
0159 }
0160 
0161 ExtensionSnapStrategy::ExtensionSnapStrategy()
0162     : KoSnapStrategy(KoSnapGuide::ExtensionSnapping)
0163 {
0164 }
0165 
0166 bool ExtensionSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
0167 {
0168     Q_ASSERT(std::isfinite(maxSnapDistance));
0169 
0170     const qreal maxDistance = maxSnapDistance * maxSnapDistance;
0171     qreal minDistances[2] = { HUGE_VAL, HUGE_VAL };
0172 
0173     QPointF snappedPoints[2] = { mousePosition, mousePosition };
0174     QPointF startPoints[2];
0175 
0176     QList<KoShape*> shapes = proxy->shapes(true);
0177 
0178     Q_FOREACH (KoShape * shape, shapes) {
0179         KoPathShape * path = dynamic_cast<KoPathShape*>(shape);
0180         if (! path) {
0181             continue;
0182         }
0183         QTransform matrix = path->absoluteTransformation();
0184 
0185         const int subpathCount = path->subpathCount();
0186         for (int subpathIndex = 0; subpathIndex < subpathCount; ++subpathIndex) {
0187             if (path->isClosedSubpath(subpathIndex))
0188                 continue;
0189 
0190             int pointCount = path->subpathPointCount(subpathIndex);
0191 
0192             // check the extension from the start point
0193             KoPathPoint * first = path->pointByIndex(KoPathPointIndex(subpathIndex, 0));
0194             QPointF firstSnapPosition = mousePosition;
0195             if (snapToExtension(firstSnapPosition, first, matrix)) {
0196                 qreal distance = squareDistance(firstSnapPosition, mousePosition);
0197                 if (distance < maxDistance) {
0198                     if (distance < minDistances[0]) {
0199                         minDistances[1] = minDistances[0];
0200                         snappedPoints[1] = snappedPoints[0];
0201                         startPoints[1] = startPoints[0];
0202 
0203                         minDistances[0] = distance;
0204                         snappedPoints[0] = firstSnapPosition;
0205                         startPoints[0] = matrix.map(first->point());
0206                     }
0207                     else if (distance < minDistances[1]) {
0208                         minDistances[1] = distance;
0209                         snappedPoints[1] = firstSnapPosition;
0210                         startPoints[1] = matrix.map(first->point());
0211                     }
0212                 }
0213             }
0214 
0215             // now check the extension from the last point
0216             KoPathPoint * last = path->pointByIndex(KoPathPointIndex(subpathIndex, pointCount - 1));
0217             QPointF lastSnapPosition = mousePosition;
0218             if (snapToExtension(lastSnapPosition, last, matrix)) {
0219                 qreal distance = squareDistance(lastSnapPosition, mousePosition);
0220                 if (distance < maxDistance) {
0221                     if (distance < minDistances[0]) {
0222                         minDistances[1] = minDistances[0];
0223                         snappedPoints[1] = snappedPoints[0];
0224                         startPoints[1] = startPoints[0];
0225 
0226                         minDistances[0] = distance;
0227                         snappedPoints[0] = lastSnapPosition;
0228                         startPoints[0] = matrix.map(last->point());
0229                     }
0230                     else if (distance < minDistances[1]) {
0231                         minDistances[1] = distance;
0232                         snappedPoints[1] = lastSnapPosition;
0233                         startPoints[1] = matrix.map(last->point());
0234                     }
0235                 }
0236             }
0237         }
0238     }
0239 
0240     m_lines.clear();
0241     // if we have to extension near our mouse position, they might have an intersection
0242     // near our mouse position which we want to use as the snapped position
0243     if (minDistances[0] < HUGE_VAL && minDistances[1] < HUGE_VAL) {
0244         // check if intersection of extension lines is near mouse position
0245         KoPathSegment s1(startPoints[0], snappedPoints[0] + snappedPoints[0]-startPoints[0]);
0246         KoPathSegment s2(startPoints[1], snappedPoints[1] + snappedPoints[1]-startPoints[1]);
0247         QList<QPointF> isects = s1.intersections(s2);
0248         if (isects.count() == 1 && squareDistance(isects[0], mousePosition) < maxDistance) {
0249             // add both extension lines
0250             m_lines.append(QLineF(startPoints[0], isects[0]));
0251             m_lines.append(QLineF(startPoints[1], isects[0]));
0252             setSnappedPosition(isects[0]);
0253         }
0254         else {
0255             // only add nearest extension line of both
0256             uint index = minDistances[0] < minDistances[1] ? 0 : 1;
0257             m_lines.append(QLineF(startPoints[index], snappedPoints[index]));
0258             setSnappedPosition(snappedPoints[index]);
0259         }
0260     }
0261     else  if (minDistances[0] < HUGE_VAL) {
0262         m_lines.append(QLineF(startPoints[0], snappedPoints[0]));
0263         setSnappedPosition(snappedPoints[0]);
0264     }
0265     else if (minDistances[1] < HUGE_VAL) {
0266         m_lines.append(QLineF(startPoints[1], snappedPoints[1]));
0267         setSnappedPosition(snappedPoints[1]);
0268     }
0269     else {
0270         // none of the extension lines is near our mouse position
0271         return false;
0272     }
0273     return true;
0274 }
0275 
0276 QPainterPath ExtensionSnapStrategy::decoration(const KoViewConverter &/*converter*/) const
0277 {
0278     QPainterPath decoration;
0279     foreach (const QLineF &line, m_lines) {
0280         decoration.moveTo(line.p1());
0281         decoration.lineTo(line.p2());
0282     }
0283     return decoration;
0284 }
0285 
0286 bool ExtensionSnapStrategy::snapToExtension(QPointF &position, KoPathPoint * point, const QTransform &matrix)
0287 {
0288     Q_ASSERT(point);
0289     QPointF direction = extensionDirection(point, matrix);
0290     if (direction.isNull())
0291         return false;
0292 
0293     QPointF extensionStart = matrix.map(point->point());
0294     QPointF extensionStop = matrix.map(point->point()) + direction;
0295     float posOnExtension = project(extensionStart, extensionStop, position);
0296     if (posOnExtension < 0.0)
0297         return false;
0298 
0299     position = extensionStart + posOnExtension * direction;
0300     return true;
0301 }
0302 
0303 qreal ExtensionSnapStrategy::project(const QPointF &lineStart, const QPointF &lineEnd, const QPointF &point)
0304 {
0305     // This is how the returned value should be used to get the
0306     // projectionPoint: ProjectionPoint = lineStart(1-resultingReal) + resultingReal*lineEnd;
0307 
0308     QPointF diff = lineEnd - lineStart;
0309     QPointF relPoint = point - lineStart;
0310     qreal diffLength = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
0311     if (diffLength == 0.0)
0312         return 0.0;
0313 
0314     diff /= diffLength;
0315     // project mouse position relative to stop position on extension line
0316     qreal scalar = relPoint.x() * diff.x() + relPoint.y() * diff.y();
0317     return scalar /= diffLength;
0318 }
0319 
0320 QPointF ExtensionSnapStrategy::extensionDirection(KoPathPoint * point, const QTransform &matrix)
0321 {
0322     Q_ASSERT(point);
0323 
0324     KoPathShape * path = point->parent();
0325     KoPathPointIndex index = path->pathPointIndex(point);
0326 
0327     // check if it is a start point
0328     if (point->properties() & KoPathPoint::StartSubpath) {
0329         if (point->activeControlPoint2()) {
0330             return matrix.map(point->point()) - matrix.map(point->controlPoint2());
0331         } else {
0332             KoPathPoint * next = path->pointByIndex(KoPathPointIndex(index.first, index.second + 1));
0333             if (! next){
0334                 return QPointF();
0335             }
0336             else if (next->activeControlPoint1()) {
0337                 return matrix.map(point->point()) - matrix.map(next->controlPoint1());
0338             }
0339             else {
0340                 return matrix.map(point->point()) - matrix.map(next->point());
0341             }
0342         }
0343     }
0344     else {
0345         if (point->activeControlPoint1()) {
0346             return matrix.map(point->point()) - matrix.map(point->controlPoint1());
0347         }
0348         else {
0349             KoPathPoint * prev = path->pointByIndex(KoPathPointIndex(index.first, index.second - 1));
0350             if (! prev){
0351                 return QPointF();
0352             }
0353             else if (prev->activeControlPoint2()) {
0354                 return matrix.map(point->point()) - matrix.map(prev->controlPoint2());
0355             }
0356             else {
0357                 return matrix.map(point->point()) - matrix.map(prev->point());
0358             }
0359         }
0360     }
0361 }
0362 
0363 IntersectionSnapStrategy::IntersectionSnapStrategy()
0364     : KoSnapStrategy(KoSnapGuide::IntersectionSnapping)
0365 {
0366 }
0367 
0368 bool IntersectionSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
0369 {
0370     Q_ASSERT(std::isfinite(maxSnapDistance));
0371     const qreal maxDistance = maxSnapDistance * maxSnapDistance;
0372     qreal minDistance = HUGE_VAL;
0373 
0374     QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
0375     rect.moveCenter(mousePosition);
0376     QPointF snappedPoint = mousePosition;
0377 
0378     QList<KoPathSegment> segments = proxy->segmentsInRect(rect, false);
0379     int segmentCount = segments.count();
0380     for (int i = 0; i < segmentCount; ++i) {
0381         const KoPathSegment &s1 = segments[i];
0382         for (int j = i + 1; j < segmentCount; ++j) {
0383             QList<QPointF> isects = s1.intersections(segments[j]);
0384             Q_FOREACH (const QPointF &point, isects) {
0385                 if (! rect.contains(point))
0386                     continue;
0387                 qreal distance = squareDistance(mousePosition, point);
0388                 if (distance < maxDistance && distance < minDistance) {
0389                     snappedPoint = point;
0390                     minDistance = distance;
0391                 }
0392             }
0393         }
0394     }
0395 
0396     setSnappedPosition(snappedPoint);
0397 
0398     return (minDistance < HUGE_VAL);
0399 }
0400 
0401 QPainterPath IntersectionSnapStrategy::decoration(const KoViewConverter &converter) const
0402 {
0403     QRectF unzoomedRect = converter.viewToDocument(QRectF(0, 0, 11, 11));
0404     unzoomedRect.moveCenter(snappedPosition());
0405     QPainterPath decoration;
0406     decoration.addRect(unzoomedRect);
0407     return decoration;
0408 }
0409 
0410 GridSnapStrategy::GridSnapStrategy()
0411     : KoSnapStrategy(KoSnapGuide::GridSnapping)
0412 {
0413 }
0414 
0415 bool GridSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
0416 {
0417     Q_ASSERT(std::isfinite(maxSnapDistance));
0418     if (! proxy->canvas()->snapToGrid())
0419         return false;
0420 
0421     // The 1e-10 here is a workaround for some weird division problem.
0422     // 360.00062366 / 2.83465058 gives 127 'exactly' when shown as a qreal,
0423     // but when casting into an int, we get 126. In fact it's 127 - 5.64e-15 !
0424     QPointF offset;
0425     QSizeF spacing;
0426     proxy->canvas()->gridSize(&offset, &spacing);
0427 
0428     // we want to snap to the nearest grid point, so calculate
0429     // the grid rows/columns before and after the points position
0430     int col = static_cast<int>((mousePosition.x() - offset.x()) / spacing.width() + 1e-10);
0431     int nextCol = col + 1;
0432     int row = static_cast<int>((mousePosition.y() - offset.y()) / spacing.height() + 1e-10);
0433     int nextRow = row + 1;
0434 
0435     // now check which grid line has less distance to the point
0436     qreal distToCol = qAbs(offset.x() + col * spacing.width() - mousePosition.x());
0437     qreal distToNextCol = qAbs(offset.x() + nextCol * spacing.width() - mousePosition.x());
0438 
0439     if (distToCol > distToNextCol) {
0440         col = nextCol;
0441         distToCol = distToNextCol;
0442     }
0443 
0444     qreal distToRow = qAbs(offset.y() + row * spacing.height() - mousePosition.y());
0445     qreal distToNextRow = qAbs(offset.y() + nextRow * spacing.height() - mousePosition.y());
0446     if (distToRow > distToNextRow) {
0447         row = nextRow;
0448         distToRow = distToNextRow;
0449     }
0450 
0451     QPointF snappedPoint = mousePosition;
0452 
0453     bool pointIsSnapped = false;
0454 
0455     const qreal sqDistance = distToCol * distToCol + distToRow * distToRow;
0456     const qreal maxSqDistance = maxSnapDistance * maxSnapDistance;
0457     // now check if we are inside the snap distance
0458     if (sqDistance < maxSqDistance) {
0459         snappedPoint = QPointF(offset.x() + col * spacing.width(), offset.y() + row * spacing.height());
0460         pointIsSnapped = true;
0461     } else if (distToRow < maxSnapDistance) {
0462         snappedPoint.ry() = offset.y() + row * spacing.height();
0463         pointIsSnapped = true;
0464     } else if (distToCol < maxSnapDistance) {
0465         snappedPoint.rx() = offset.x() + col * spacing.width();
0466         pointIsSnapped = true;
0467     }
0468 
0469     setSnappedPosition(snappedPoint);
0470 
0471     return pointIsSnapped;
0472 }
0473 
0474 QPainterPath GridSnapStrategy::decoration(const KoViewConverter &converter) const
0475 {
0476     QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
0477     QPainterPath decoration;
0478     decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0));
0479     decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0));
0480     decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height()));
0481     decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height()));
0482     return decoration;
0483 }
0484 
0485 BoundingBoxSnapStrategy::BoundingBoxSnapStrategy()
0486     : KoSnapStrategy(KoSnapGuide::BoundingBoxSnapping)
0487 {
0488 }
0489 
0490 bool BoundingBoxSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy *proxy, qreal maxSnapDistance)
0491 {
0492     Q_ASSERT(std::isfinite(maxSnapDistance));
0493     const qreal maxDistance = maxSnapDistance * maxSnapDistance;
0494     qreal minDistance = HUGE_VAL;
0495 
0496     QRectF rect(-maxSnapDistance, -maxSnapDistance, maxSnapDistance, maxSnapDistance);
0497 
0498     rect.moveCenter(mousePosition);
0499     QPointF snappedPoint = mousePosition;
0500 
0501     KoFlake::AnchorPosition pointId[5] = {
0502         KoFlake::TopLeft,
0503         KoFlake::TopRight,
0504         KoFlake::BottomRight,
0505         KoFlake::BottomLeft,
0506         KoFlake::Center
0507     };
0508 
0509     QList<KoShape*> shapes = proxy->shapesInRect(rect, true);
0510     Q_FOREACH (KoShape * shape, shapes) {
0511         qreal shapeMinDistance = HUGE_VAL;
0512         // first check the corner and center points
0513         for (int i = 0; i < 5; ++i) {
0514             m_boxPoints[i] = shape->absolutePosition(pointId[i]);
0515             qreal d = squareDistance(mousePosition, m_boxPoints[i]);
0516             if (d < minDistance && d < maxDistance) {
0517                 shapeMinDistance = d;
0518                 minDistance = d;
0519                 snappedPoint = m_boxPoints[i];
0520             }
0521         }
0522         // prioritize points over edges
0523         if (shapeMinDistance < maxDistance)
0524             continue;
0525 
0526         // now check distances to edges of bounding box
0527         for (int i = 0; i < 4; ++i) {
0528             QPointF pointOnLine;
0529             qreal d = squareDistanceToLine(m_boxPoints[i], m_boxPoints[(i+1)%4], mousePosition, pointOnLine);
0530             if (d < minDistance && d < maxDistance) {
0531                 minDistance = d;
0532                 snappedPoint = pointOnLine;
0533             }
0534         }
0535     }
0536     setSnappedPosition(snappedPoint);
0537 
0538     return (minDistance < maxDistance);
0539 }
0540 
0541 qreal BoundingBoxSnapStrategy::squareDistanceToLine(const QPointF &lineA, const QPointF &lineB, const QPointF &point, QPointF &pointOnLine)
0542 {
0543     QPointF diff = lineB - lineA;
0544     if(lineA == lineB)
0545         return HUGE_VAL;
0546     const qreal diffLength = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
0547 
0548     // project mouse position relative to start position on line
0549     const qreal scalar = KoSnapStrategy::scalarProduct(point - lineA, diff / diffLength);
0550 
0551     if (scalar < 0.0 || scalar > diffLength)
0552         return HUGE_VAL;
0553     // calculate vector between relative mouse position and projected mouse position
0554     pointOnLine = lineA + scalar / diffLength * diff;
0555     QPointF distVec = pointOnLine - point;
0556     return distVec.x()*distVec.x() + distVec.y()*distVec.y();
0557 }
0558 
0559 QPainterPath BoundingBoxSnapStrategy::decoration(const KoViewConverter &converter) const
0560 {
0561     QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
0562 
0563     QPainterPath decoration;
0564     decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), unzoomedSize.height()));
0565     decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), unzoomedSize.height()));
0566     decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), -unzoomedSize.height()));
0567     decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), -unzoomedSize.height()));
0568 
0569     return decoration;
0570 }
0571 
0572 // KoGuidesData has been moved into Krita. Please port this class!
0573 
0574 // LineGuideSnapStrategy::LineGuideSnapStrategy()
0575 //     : KoSnapStrategy(KoSnapGuide::GuideLineSnapping)
0576 // {
0577 // }
0578 
0579 // bool LineGuideSnapStrategy::snap(const QPointF &mousePosition, KoSnapProxy * proxy, qreal maxSnapDistance)
0580 // {
0581 //     Q_ASSERT(std::isfinite(maxSnapDistance));
0582 
0583 //     KoGuidesData * guidesData = proxy->canvas()->guidesData();
0584 
0585 //     if (!guidesData || !guidesData->showGuideLines())
0586 //         return false;
0587 
0588 //     QPointF snappedPoint = mousePosition;
0589 //     m_orientation = 0;
0590 
0591 //     qreal minHorzDistance = maxSnapDistance;
0592 //     Q_FOREACH (qreal guidePos, guidesData->horizontalGuideLines()) {
0593 //         qreal distance = qAbs(guidePos - mousePosition.y());
0594 //         if (distance < minHorzDistance) {
0595 //             snappedPoint.setY(guidePos);
0596 //             minHorzDistance = distance;
0597 //             m_orientation |= Qt::Horizontal;
0598 //         }
0599 //     }
0600 //     qreal minVertSnapDistance = maxSnapDistance;
0601 //     Q_FOREACH (qreal guidePos, guidesData->verticalGuideLines()) {
0602 //         qreal distance = qAbs(guidePos - mousePosition.x());
0603 //         if (distance < minVertSnapDistance) {
0604 //             snappedPoint.setX(guidePos);
0605 //             minVertSnapDistance = distance;
0606 //             m_orientation |= Qt::Vertical;
0607 //         }
0608 //     }
0609 //     setSnappedPosition(snappedPoint);
0610 //     return (minHorzDistance < maxSnapDistance || minVertSnapDistance < maxSnapDistance);
0611 // }
0612 
0613 // QPainterPath LineGuideSnapStrategy::decoration(const KoViewConverter &converter) const
0614 // {
0615 //     QSizeF unzoomedSize = converter.viewToDocument(QSizeF(5, 5));
0616 //     Q_ASSERT(unzoomedSize.isValid());
0617 
0618 //     QPainterPath decoration;
0619 //     if (m_orientation & Qt::Horizontal) {
0620 //         decoration.moveTo(snappedPosition() - QPointF(unzoomedSize.width(), 0));
0621 //         decoration.lineTo(snappedPosition() + QPointF(unzoomedSize.width(), 0));
0622 //     }
0623 //     if (m_orientation & Qt::Vertical) {
0624 //         decoration.moveTo(snappedPosition() - QPointF(0, unzoomedSize.height()));
0625 //         decoration.lineTo(snappedPosition() + QPointF(0, unzoomedSize.height()));
0626 //     }
0627 
0628 //     return decoration;
0629 // }