Skip to content

Commit 80555d0

Browse files
committed
[composer] Use the old line placement algorithm for arrows created in versions prior to 2.4 (fix #10457)
1 parent bff7882 commit 80555d0

File tree

2 files changed

+81
-17
lines changed

2 files changed

+81
-17
lines changed

src/core/composer/qgscomposerarrow.cpp

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ QgsComposerArrow::QgsComposerArrow( QgsComposition* c )
3131
, mStartYIdx( 0 )
3232
, mMarkerMode( DefaultMarker )
3333
, mArrowColor( QColor( 0, 0, 0 ) )
34+
, mBoundsBehaviour( 24 )
3435
{
3536
initGraphicsSettings();
3637
}
@@ -41,6 +42,7 @@ QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& st
4142
, mStopPoint( stopPoint )
4243
, mMarkerMode( DefaultMarker )
4344
, mArrowColor( QColor( 0, 0, 0 ) )
45+
, mBoundsBehaviour( 24 )
4446
{
4547
mStartXIdx = mStopPoint.x() < mStartPoint.x();
4648
mStartYIdx = mStopPoint.y() < mStartPoint.y();
@@ -77,6 +79,11 @@ void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem
7779

7880
//draw arrow
7981
QPen arrowPen = mPen;
82+
if ( mBoundsBehaviour == 22 )
83+
{
84+
//if arrow was created in versions prior to 2.4, use the old rendering style
85+
arrowPen.setCapStyle( Qt::FlatCap );
86+
}
8087
arrowPen.setColor( mArrowColor );
8188
painter->setPen( arrowPen );
8289
painter->setBrush( QBrush( mArrowColor ) );
@@ -134,9 +141,17 @@ void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
134141
QBrush arrowBrush = p->brush();
135142
arrowBrush.setColor( mArrowColor );
136143
p->setBrush( arrowBrush );
137-
QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
138-
QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
139-
drawArrowHead( p, stop.x() - pos().x(), stop.y() - pos().y(), angle( mStartPoint, stop ), mArrowHeadWidth );
144+
if ( mBoundsBehaviour == 22 )
145+
{
146+
//if arrow was created in versions prior to 2.4, use the old rendering style
147+
drawArrowHead( p, mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y(), angle( mStartPoint, mStopPoint ), mArrowHeadWidth );
148+
}
149+
else
150+
{
151+
QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
152+
QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
153+
drawArrowHead( p, stop.x() - pos().x(), stop.y() - pos().y(), angle( mStartPoint, stop ), mArrowHeadWidth );
154+
}
140155
}
141156

142157
void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QString &markerPath )
@@ -205,7 +220,30 @@ void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QStrin
205220
r.render( &imagePainter );
206221

207222
p->save();
208-
p->translate( canvasPoint.x() , canvasPoint.y() );
223+
if ( mBoundsBehaviour == 22 )
224+
{
225+
//if arrow was created in versions prior to 2.4, use the old rendering style
226+
//rotate image fix point for backtransform
227+
QPointF fixPoint;
228+
if ( type == StartMarker )
229+
{
230+
fixPoint.setX( 0 ); fixPoint.setY( arrowHeadHeight / 2.0 );
231+
}
232+
else
233+
{
234+
fixPoint.setX( 0 ); fixPoint.setY( -arrowHeadHeight / 2.0 );
235+
}
236+
QPointF rotatedFixPoint;
237+
double angleRad = ang / 180 * M_PI;
238+
rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
239+
rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );
240+
p->translate( canvasPoint.x() - rotatedFixPoint.x() , canvasPoint.y() - rotatedFixPoint.y() );
241+
}
242+
else
243+
{
244+
p->translate( canvasPoint.x() , canvasPoint.y() );
245+
}
246+
209247
p->rotate( ang );
210248
p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );
211249

@@ -264,20 +302,41 @@ void QgsComposerArrow::setArrowHeadWidth( double width )
264302
double QgsComposerArrow::computeMarkerMargin() const
265303
{
266304
double margin = 0;
267-
if ( mMarkerMode == DefaultMarker )
268-
{
269-
margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
270-
}
271-
else if ( mMarkerMode == NoMarker )
305+
306+
if ( mBoundsBehaviour == 22 )
272307
{
273-
margin = mPen.widthF() / std::sqrt( 2.0 );
308+
//if arrow was created in versions prior to 2.4, use the old rendering style
309+
if ( mMarkerMode == DefaultMarker )
310+
{
311+
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
312+
}
313+
else if ( mMarkerMode == NoMarker )
314+
{
315+
margin = mPen.widthF() / 2.0;
316+
}
317+
else if ( mMarkerMode == SVGMarker )
318+
{
319+
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
320+
margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
321+
}
274322
}
275-
else if ( mMarkerMode == SVGMarker )
323+
else
276324
{
277-
double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
278-
double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
279-
double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
280-
margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
325+
if ( mMarkerMode == DefaultMarker )
326+
{
327+
margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
328+
}
329+
else if ( mMarkerMode == NoMarker )
330+
{
331+
margin = mPen.widthF() / std::sqrt( 2.0 );
332+
}
333+
else if ( mMarkerMode == SVGMarker )
334+
{
335+
double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
336+
double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
337+
double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
338+
margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
339+
}
281340
}
282341
return margin;
283342
}
@@ -306,6 +365,7 @@ bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
306365
composerArrowElem.setAttribute( "markerMode", mMarkerMode );
307366
composerArrowElem.setAttribute( "startMarkerFile", mStartMarkerFile );
308367
composerArrowElem.setAttribute( "endMarkerFile", mEndMarkerFile );
368+
composerArrowElem.setAttribute( "boundsBehaviourVersion", QString::number( mBoundsBehaviour ) );
309369

310370
//arrow color
311371
QDomElement arrowColorElem = doc.createElement( "ArrowColor" );
@@ -338,6 +398,8 @@ bool QgsComposerArrow::readXML( const QDomElement& itemElem, const QDomDocument&
338398
setStartMarker( itemElem.attribute( "startMarkerFile", "" ) );
339399
setEndMarker( itemElem.attribute( "endMarkerFile", "" ) );
340400
mMarkerMode = QgsComposerArrow::MarkerMode( itemElem.attribute( "markerMode", "0" ).toInt() );
401+
//if bounds behaviour version is not set, default to 2.2 behaviour
402+
mBoundsBehaviour = itemElem.attribute( "boundsBehaviourVersion", "22" ).toInt();
341403

342404
//arrow color
343405
QDomNodeList arrowColorList = itemElem.elementsByTagName( "ArrowColor" );

src/core/composer/qgscomposerarrow.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,10 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
110110
/**Default marker, no marker or svg marker*/
111111
MarkerMode mMarkerMode;
112112
QColor mArrowColor;
113-
114-
113+
/**Indicates QGIS version to mimic bounding box behaviour for. The line placement changed in version 2.4, so a value
114+
* of 22 is used to indicate that the line should be drawn using the older placement routine.
115+
*/
116+
int mBoundsBehaviour;
115117

116118
/**Adapts the item scene rect to contain the start point, the stop point including the arrow marker and the outline.
117119
Needs to be called whenever the arrow width/height, the outline with or the endpoints are changed*/

0 commit comments

Comments
 (0)