File indexing completed on 2024-05-12 16:33:20
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2011 Jan Hambrecht <jaham@gmx.net> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Library General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2 of the License, or (at your option) any later version. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Library General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Library General Public License 0015 * along with this library; see the file COPYING.LIB. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "MoveStartOffsetStrategy.h" 0021 #include "ChangeTextOffsetCommand.h" 0022 #include "ArtisticTextShape.h" 0023 #include <KoPathShape.h> 0024 #include <KoPathSegment.h> 0025 #include <KoToolBase.h> 0026 #include <math.h> 0027 0028 // helper function to calculate the squared distance between two points 0029 qreal squaredDistance(const QPointF &p1, const QPointF &p2) 0030 { 0031 qreal dx = p1.x()-p2.x(); 0032 qreal dy = p1.y()-p2.y(); 0033 return dx*dx + dy*dy; 0034 } 0035 0036 MoveStartOffsetStrategy::MoveStartOffsetStrategy(KoToolBase *tool, ArtisticTextShape *text) 0037 : KoInteractionStrategy(tool), m_text(text) 0038 { 0039 m_oldStartOffset = m_text->startOffset(); 0040 m_baselineShape = KoPathShape::createShapeFromPainterPath(m_text->baseline()); 0041 // cache number of segments and their length 0042 const int subpathCount = m_baselineShape->subpathCount(); 0043 for (int i = 0; i < subpathCount; ++i) { 0044 const int subpathPointCount = m_baselineShape->subpathPointCount(i); 0045 for (int j = 0; j < subpathPointCount; ++j) { 0046 KoPathSegment s = m_baselineShape->segmentByIndex(KoPathPointIndex(i, j)); 0047 if(s.isValid()) { 0048 const qreal length = s.length(); 0049 m_segmentLengths.append(length); 0050 m_totalLength += length; 0051 } 0052 } 0053 } 0054 } 0055 0056 MoveStartOffsetStrategy::~MoveStartOffsetStrategy() 0057 { 0058 delete m_baselineShape; 0059 } 0060 0061 void MoveStartOffsetStrategy::handleMouseMove(const QPointF &mouseLocation, Qt::KeyboardModifiers /*modifiers*/) 0062 { 0063 // map the global mouse position to local coordinates of our baseline path 0064 const QPointF localMousePoint = m_baselineShape->transformation().inverted().map(mouseLocation); 0065 0066 // create a roi to check segments at 0067 QRectF grabRect; 0068 grabRect.setHeight(2*grabSensitivity()); 0069 grabRect.setWidth(2*grabSensitivity()); 0070 grabRect.moveCenter(localMousePoint); 0071 0072 // get all segments intersecting our roi 0073 QList<KoPathSegment> segments = m_baselineShape->segmentsAt(grabRect); 0074 0075 // now find the nearest point of all picked segments 0076 KoPathSegment nearestSegment; 0077 qreal nearestPointParam = 0.0; 0078 KoPathPointIndex nearestPathPoint; 0079 qreal minDistance = HUGE_VAL; 0080 foreach(const KoPathSegment &s, segments) { 0081 qreal t = s.nearestPoint(localMousePoint); 0082 qreal distance = squaredDistance(localMousePoint, s.pointAt(t)); 0083 if ( distance < minDistance) { 0084 nearestPointParam = t; 0085 nearestSegment = s; 0086 nearestPathPoint = m_baselineShape->pathPointIndex(s.first()); 0087 minDistance = distance; 0088 } 0089 } 0090 0091 // now we need to map back to the length of the baseline path 0092 if (nearestSegment.isValid()) { 0093 // count number of path segments 0094 int segmentCount = 0; 0095 int nearestSegment = 0; 0096 const int subpathCount = m_baselineShape->subpathCount(); 0097 for (int i = 0; i < subpathCount; ++i) { 0098 const int subpathPointCount = m_baselineShape->subpathPointCount(i); 0099 if (i == nearestPathPoint.first) { 0100 nearestSegment = segmentCount + nearestPathPoint.second; 0101 } 0102 segmentCount += m_baselineShape->isClosedSubpath(i) ? subpathPointCount : subpathPointCount-1; 0103 } 0104 qreal length = 0.0; 0105 for (int i = 0; i < nearestSegment; ++i) { 0106 length += m_segmentLengths[i]; 0107 } 0108 length += nearestPointParam * m_segmentLengths[nearestSegment]; 0109 tool()->repaintDecorations(); 0110 m_text->setStartOffset(length / m_totalLength); 0111 tool()->repaintDecorations(); 0112 } 0113 } 0114 0115 KUndo2Command *MoveStartOffsetStrategy::createCommand() 0116 { 0117 return new ChangeTextOffsetCommand(m_text, m_oldStartOffset, m_text->startOffset()); 0118 } 0119 0120 void MoveStartOffsetStrategy::finishInteraction(Qt::KeyboardModifiers /*modifiers*/) 0121 { 0122 0123 }