Skip to content

Commit

Permalink
[composer] Use the old line placement algorithm for arrows created in…
Browse files Browse the repository at this point in the history
… versions prior to 2.4 (fix #10457)
  • Loading branch information
nyalldawson committed Jun 16, 2014
1 parent bff7882 commit 80555d0
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 17 deletions.
92 changes: 77 additions & 15 deletions src/core/composer/qgscomposerarrow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ QgsComposerArrow::QgsComposerArrow( QgsComposition* c )
, mStartYIdx( 0 )
, mMarkerMode( DefaultMarker )
, mArrowColor( QColor( 0, 0, 0 ) )
, mBoundsBehaviour( 24 )
{
initGraphicsSettings();
}
Expand All @@ -41,6 +42,7 @@ QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& st
, mStopPoint( stopPoint )
, mMarkerMode( DefaultMarker )
, mArrowColor( QColor( 0, 0, 0 ) )
, mBoundsBehaviour( 24 )
{
mStartXIdx = mStopPoint.x() < mStartPoint.x();
mStartYIdx = mStopPoint.y() < mStartPoint.y();
Expand Down Expand Up @@ -77,6 +79,11 @@ void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem

//draw arrow
QPen arrowPen = mPen;
if ( mBoundsBehaviour == 22 )
{
//if arrow was created in versions prior to 2.4, use the old rendering style
arrowPen.setCapStyle( Qt::FlatCap );
}
arrowPen.setColor( mArrowColor );
painter->setPen( arrowPen );
painter->setBrush( QBrush( mArrowColor ) );
Expand Down Expand Up @@ -134,9 +141,17 @@ void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
QBrush arrowBrush = p->brush();
arrowBrush.setColor( mArrowColor );
p->setBrush( arrowBrush );
QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
drawArrowHead( p, stop.x() - pos().x(), stop.y() - pos().y(), angle( mStartPoint, stop ), mArrowHeadWidth );
if ( mBoundsBehaviour == 22 )
{
//if arrow was created in versions prior to 2.4, use the old rendering style
drawArrowHead( p, mStopPoint.x() - pos().x(), mStopPoint.y() - pos().y(), angle( mStartPoint, mStopPoint ), mArrowHeadWidth );
}
else
{
QVector2D dir = QVector2D( mStopPoint - mStartPoint ).normalized();
QPointF stop = mStopPoint + ( dir * 0.5 * mArrowHeadWidth ).toPointF();
drawArrowHead( p, stop.x() - pos().x(), stop.y() - pos().y(), angle( mStartPoint, stop ), mArrowHeadWidth );
}
}

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

p->save();
p->translate( canvasPoint.x() , canvasPoint.y() );
if ( mBoundsBehaviour == 22 )
{
//if arrow was created in versions prior to 2.4, use the old rendering style
//rotate image fix point for backtransform
QPointF fixPoint;
if ( type == StartMarker )
{
fixPoint.setX( 0 ); fixPoint.setY( arrowHeadHeight / 2.0 );
}
else
{
fixPoint.setX( 0 ); fixPoint.setY( -arrowHeadHeight / 2.0 );
}
QPointF rotatedFixPoint;
double angleRad = ang / 180 * M_PI;
rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );
p->translate( canvasPoint.x() - rotatedFixPoint.x() , canvasPoint.y() - rotatedFixPoint.y() );
}
else
{
p->translate( canvasPoint.x() , canvasPoint.y() );
}

p->rotate( ang );
p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );

Expand Down Expand Up @@ -264,20 +302,41 @@ void QgsComposerArrow::setArrowHeadWidth( double width )
double QgsComposerArrow::computeMarkerMargin() const
{
double margin = 0;
if ( mMarkerMode == DefaultMarker )
{
margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
}
else if ( mMarkerMode == NoMarker )

if ( mBoundsBehaviour == 22 )
{
margin = mPen.widthF() / std::sqrt( 2.0 );
//if arrow was created in versions prior to 2.4, use the old rendering style
if ( mMarkerMode == DefaultMarker )
{
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
}
else if ( mMarkerMode == NoMarker )
{
margin = mPen.widthF() / 2.0;
}
else if ( mMarkerMode == SVGMarker )
{
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
}
}
else if ( mMarkerMode == SVGMarker )
else
{
double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
if ( mMarkerMode == DefaultMarker )
{
margin = mPen.widthF() / std::sqrt( 2.0 ) + mArrowHeadWidth / 2.0;
}
else if ( mMarkerMode == NoMarker )
{
margin = mPen.widthF() / std::sqrt( 2.0 );
}
else if ( mMarkerMode == SVGMarker )
{
double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
double stopMarkerMargin = std::sqrt( 0.25 * ( mStopArrowHeadHeight * mStopArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
double markerMargin = qMax( startMarkerMargin, stopMarkerMargin );
margin = qMax( mPen.widthF() / std::sqrt( 2.0 ), markerMargin );
}
}
return margin;
}
Expand Down Expand Up @@ -306,6 +365,7 @@ bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
composerArrowElem.setAttribute( "markerMode", mMarkerMode );
composerArrowElem.setAttribute( "startMarkerFile", mStartMarkerFile );
composerArrowElem.setAttribute( "endMarkerFile", mEndMarkerFile );
composerArrowElem.setAttribute( "boundsBehaviourVersion", QString::number( mBoundsBehaviour ) );

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

//arrow color
QDomNodeList arrowColorList = itemElem.elementsByTagName( "ArrowColor" );
Expand Down
6 changes: 4 additions & 2 deletions src/core/composer/qgscomposerarrow.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
/**Default marker, no marker or svg marker*/
MarkerMode mMarkerMode;
QColor mArrowColor;


/**Indicates QGIS version to mimic bounding box behaviour for. The line placement changed in version 2.4, so a value
* of 22 is used to indicate that the line should be drawn using the older placement routine.
*/
int mBoundsBehaviour;

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

0 comments on commit 80555d0

Please sign in to comment.