Skip to content

Commit 241e2f7

Browse files
committedApr 13, 2014
Merge pull request #1300 from manisandro/fix_composer_arrow_bbox
Improve print composer arrow bounding box logic
2 parents e87a7b8 + e214741 commit 241e2f7

File tree

2 files changed

+62
-19
lines changed

2 files changed

+62
-19
lines changed
 

‎src/core/composer/qgscomposerarrow.cpp

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ QgsComposerArrow::QgsComposerArrow( QgsComposition* c )
2626
: QgsComposerItem( c )
2727
, mStartPoint( 0, 0 )
2828
, mStopPoint( 0, 0 )
29+
, mStartXIdx( 0 )
30+
, mStartYIdx( 0 )
2931
, mMarkerMode( DefaultMarker )
3032
, mArrowColor( QColor( 0, 0, 0 ) )
3133
{
@@ -39,6 +41,8 @@ QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& st
3941
, mMarkerMode( DefaultMarker )
4042
, mArrowColor( QColor( 0, 0, 0 ) )
4143
{
44+
mStartXIdx = mStopPoint.x() < mStartPoint.x();
45+
mStartYIdx = mStopPoint.y() < mStartPoint.y();
4246
initGraphicsSettings();
4347
adaptItemSceneRect();
4448
}
@@ -97,18 +101,31 @@ void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem
97101

98102
void QgsComposerArrow::setSceneRect( const QRectF& rectangle )
99103
{
100-
//maintain the relative position of start and stop point in the rectangle
101-
double startPointXPos = ( mStartPoint.x() - pos().x() ) / rect().width();
102-
double startPointYPos = ( mStartPoint.y() - pos().y() ) / rect().height();
103-
double stopPointXPos = ( mStopPoint.x() - pos().x() ) / rect().width();
104-
double stopPointYPos = ( mStopPoint.y() - pos().y() ) / rect().height();
104+
if ( rectangle.width() < 0 )
105+
{
106+
mStartXIdx = 1 - mStartXIdx;
107+
}
108+
if ( rectangle.height() < 0 )
109+
{
110+
mStartYIdx = 1 - mStartYIdx;
111+
}
105112

106-
mStartPoint.setX( rectangle.left() + startPointXPos * rectangle.width() );
107-
mStartPoint.setY( rectangle.top() + startPointYPos * rectangle.height() );
108-
mStopPoint.setX( rectangle.left() + stopPointXPos * rectangle.width() );
109-
mStopPoint.setY( rectangle.top() + stopPointYPos * rectangle.height() );
113+
double margin = computeMarkerMargin();
110114

111-
adaptItemSceneRect();
115+
// Ensure the rectangle is at least as large as needed to include the markers
116+
QRectF rect = rectangle.unite( QRectF( rectangle.x(), rectangle.y(), 2. * margin, 2. * margin ) );
117+
118+
// Compute new start and stop positions
119+
double x[2] = {rect.x(), rect.x() + rect.width()};
120+
double y[2] = {rect.y(), rect.y() + rect.height()};
121+
122+
double xsign = x[mStartXIdx] < x[1 - mStartXIdx] ? 1.0 : -1.0;
123+
double ysign = y[mStartYIdx] < y[1 - mStartYIdx] ? 1.0 : -1.0;
124+
125+
mStartPoint = QPointF( x[mStartXIdx] + xsign * margin, y[mStartYIdx] + ysign * margin );
126+
mStopPoint = QPointF( x[1 - mStartXIdx] - xsign * margin, y[1 - mStartYIdx] - ysign * margin );
127+
128+
QgsComposerItem::setSceneRect( rect );
112129
}
113130

114131
void QgsComposerArrow::drawHardcodedMarker( QPainter *p, MarkerType type )
@@ -258,30 +275,41 @@ void QgsComposerArrow::setArrowHeadWidth( double width )
258275
adaptItemSceneRect();
259276
}
260277

261-
void QgsComposerArrow::adaptItemSceneRect()
278+
double QgsComposerArrow::computeMarkerMargin() const
262279
{
263-
//rectangle containing start and end point
264-
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
265-
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
266-
double enlarge = 0;
280+
double margin = 0;
267281
if ( mMarkerMode == DefaultMarker )
268282
{
269-
enlarge = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
283+
margin = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
270284
}
271285
else if ( mMarkerMode == NoMarker )
272286
{
273-
enlarge = mPen.widthF() / 2.0;
287+
margin = mPen.widthF() / 2.0;
274288
}
275289
else if ( mMarkerMode == SVGMarker )
276290
{
277291
double maxArrowHeight = qMax( mStartArrowHeadHeight, mStopArrowHeadHeight );
278-
enlarge = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
292+
margin = mPen.widthF() / 2 + qMax( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
279293
}
294+
return margin;
295+
}
280296

297+
void QgsComposerArrow::adaptItemSceneRect()
298+
{
299+
//rectangle containing start and end point
300+
QRectF rect = QRectF( qMin( mStartPoint.x(), mStopPoint.x() ), qMin( mStartPoint.y(), mStopPoint.y() ),
301+
qAbs( mStopPoint.x() - mStartPoint.x() ), qAbs( mStopPoint.y() - mStartPoint.y() ) );
302+
double enlarge = computeMarkerMargin();
281303
rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
282304
QgsComposerItem::setSceneRect( rect );
283305
}
284306

307+
void QgsComposerArrow::setMarkerMode( MarkerMode mode )
308+
{
309+
mMarkerMode = mode;
310+
adaptItemSceneRect();
311+
}
312+
285313
bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
286314
{
287315
QDomElement composerArrowElem = doc.createElement( "ComposerArrow" );
@@ -362,7 +390,12 @@ bool QgsComposerArrow::readXML( const QDomElement& itemElem, const QDomDocument&
362390
mStopPoint.setY( stopPointElem.attribute( "y", "0.0" ).toDouble() );
363391
}
364392

393+
mStartXIdx = mStopPoint.x() < mStartPoint.x();
394+
mStartYIdx = mStopPoint.y() < mStartPoint.y();
395+
365396
adaptItemSceneRect();
366397
emit itemChanged();
367398
return true;
368399
}
400+
401+

‎src/core/composer/qgscomposerarrow.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
6363
void setArrowColor( const QColor& c ) { mArrowColor = c; }
6464

6565
MarkerMode markerMode() const { return mMarkerMode;}
66-
void setMarkerMode( MarkerMode mode ) {mMarkerMode = mode;}
66+
void setMarkerMode( MarkerMode mode );
6767

6868
/** stores state in Dom element
6969
* @param elem is Dom element corresponding to 'Composer' tag
@@ -88,6 +88,12 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
8888
QPointF mStartPoint;
8989
QPointF mStopPoint;
9090

91+
/**Considering the rectangle as spanning [x[0], x[1]] x [y[0], y[1]], these
92+
* indices specify which index {0, 1} corresponds to the start point
93+
* coordinate of the respective dimension*/
94+
int mStartXIdx;
95+
int mStartYIdx;
96+
9197
QPen mPen;
9298
QBrush mBrush;
9399

@@ -110,6 +116,8 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
110116
/**Adapts the item scene rect to contain the start point, the stop point including the arrow marker and the outline.
111117
Needs to be called whenever the arrow width/height, the outline with or the endpoints are changed*/
112118
void adaptItemSceneRect();
119+
/**Computes the margin around the line necessary to include the markers */
120+
double computeMarkerMargin() const;
113121
/**Draws the default marker at the line end*/
114122
void drawHardcodedMarker( QPainter* p, MarkerType type );
115123
/**Draws a user-defined marker (must be an svg file)*/
@@ -119,3 +127,5 @@ class CORE_EXPORT QgsComposerArrow: public QgsComposerItem
119127
};
120128

121129
#endif // QGSCOMPOSERARROW_H
130+
131+

0 commit comments

Comments
 (0)
Please sign in to comment.