Skip to content

Commit 53c654f

Browse files
committed
[composer] Make sure ruler size is based off font size (fix #7476).
Only do ruler calculations once, not on every paint event.
1 parent d79b12b commit 53c654f

File tree

3 files changed

+58
-27
lines changed

3 files changed

+58
-27
lines changed

src/app/composer/qgscomposer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ void QgsComposer::zoomFull( void )
761761
}
762762
double height = mComposition->paperHeight() * nPages + mComposition->spaceBetweenPages() * ( nPages - 1 );
763763
mView->fitInView( 0, 0, mComposition->paperWidth() + 1, height + 1, Qt::KeepAspectRatio );
764+
mView->centerOn(( mComposition->paperWidth() + 1 ) / 2, ( height + 1 ) / 2 );
764765
}
765766
}
766767

src/gui/qgscomposerruler.cpp

+48-27
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,51 @@
66
#include <QPainter>
77
#include <cmath>
88

9-
const int RULER_MIN_SIZE = 20;
9+
const int RULER_FONT_SIZE = 8;
1010
const int COUNT_VALID_MULTIPLES = 3;
1111
const int COUNT_VALID_MAGNITUDES = 5;
1212
const int QgsComposerRuler::validScaleMultiples[] = {1, 2, 5};
1313
const int QgsComposerRuler::validScaleMagnitudes[] = {1, 10, 100, 1000, 10000};
1414

15-
QgsComposerRuler::QgsComposerRuler( QgsComposerRuler::Direction d ): QWidget( 0 ), mDirection( d ), mComposition( 0 ), mLineSnapItem( 0 )
15+
QgsComposerRuler::QgsComposerRuler( QgsComposerRuler::Direction d ) : QWidget( 0 ),
16+
mDirection( d ),
17+
mComposition( 0 ),
18+
mLineSnapItem( 0 ),
19+
mScaleMinPixelsWidth( 0 )
1620
{
1721
setMouseTracking( true );
22+
23+
//calculate minimum size required for ruler text
24+
mRulerFont = new QFont();
25+
mRulerFont->setPointSize( RULER_FONT_SIZE );
26+
mRulerFontMetrics = new QFontMetrics( *mRulerFont );
27+
28+
//calculate ruler sizes and marker seperations
29+
30+
//minimum gap required between major ticks is 3 digits * 250%, based on appearance
31+
mScaleMinPixelsWidth = mRulerFontMetrics->width( "000" ) * 2.5;
32+
//minimum ruler height is twice the font height in pixels
33+
mRulerMinSize = mRulerFontMetrics->height() * 1.5;
34+
35+
mMinPixelsPerDivision = mRulerMinSize / 4;
36+
//each small division must be at least 2 pixels apart
37+
if ( mMinPixelsPerDivision < 2 )
38+
mMinPixelsPerDivision = 2;
39+
40+
mPixelsBetweenLineAndText = mRulerMinSize / 10;
41+
mTextBaseline = mRulerMinSize / 1.667;
42+
mMinSpacingVerticalLabels = mRulerMinSize / 5;
1843
}
1944

2045
QgsComposerRuler::~QgsComposerRuler()
2146
{
47+
delete mRulerFontMetrics;
48+
delete mRulerFont;
2249
}
2350

2451
QSize QgsComposerRuler::minimumSizeHint() const
2552
{
26-
return QSize( RULER_MIN_SIZE, RULER_MIN_SIZE );
53+
return QSize( mRulerMinSize, mRulerMinSize );
2754
}
2855

2956
void QgsComposerRuler::paintEvent( QPaintEvent* event )
@@ -38,19 +65,13 @@ void QgsComposerRuler::paintEvent( QPaintEvent* event )
3865

3966
QTransform t = mTransform.inverted();
4067

41-
//calculate minimum size required for ruler text
42-
QFont rulerFont = p.font();
43-
rulerFont.setPointSize( 8 );
44-
QFontMetrics rulerFontMetrics( rulerFont );
45-
//minimum gap required between major ticks is 3 digits * 250%
46-
double minFontPixelsWidth = rulerFontMetrics.width( "000" ) * 2.5;
47-
p.setFont( rulerFont );
68+
p.setFont( *mRulerFont );
4869

4970
//find optimum scale for ruler (size of numbered divisions)
5071
int magnitude = 1;
5172
int multiple = 1;
5273
int mmDisplay;
53-
mmDisplay = optimumScale( minFontPixelsWidth, magnitude, multiple );
74+
mmDisplay = optimumScale( mScaleMinPixelsWidth, magnitude, multiple );
5475

5576
//find optimum number of small divisions
5677
int numSmallDivisions = optimumNumberDivisions( mmDisplay, multiple );
@@ -77,8 +98,8 @@ void QgsComposerRuler::paintEvent( QPaintEvent* event )
7798
double pixelCoord = mTransform.map( QPointF( markerPos, 0 ) ).x();
7899

79100
//draw large division and text
80-
p.drawLine( pixelCoord, 0, pixelCoord, RULER_MIN_SIZE );
81-
p.drawText( QPointF( pixelCoord + 2, RULER_MIN_SIZE / 2.0 + 2 ), QString::number( markerPos ) );
101+
p.drawLine( pixelCoord, 0, pixelCoord, mRulerMinSize );
102+
p.drawText( QPointF( pixelCoord + mPixelsBetweenLineAndText, mTextBaseline ), QString::number( markerPos ) );
82103

83104
//draw small divisions
84105
drawSmallDivisions( &p, markerPos, numSmallDivisions, mmDisplay, endX );
@@ -110,15 +131,15 @@ void QgsComposerRuler::paintEvent( QPaintEvent* event )
110131
while ( beforePageCoord > startY )
111132
{
112133
double pixelCoord = mTransform.map( QPointF( 0, beforePageCoord ) ).y();
113-
p.drawLine( 0, pixelCoord, RULER_MIN_SIZE, pixelCoord );
134+
p.drawLine( 0, pixelCoord, mRulerMinSize, pixelCoord );
114135
//calc size of label
115136
QString label = QString::number( beforePageCoord );
116-
int labelSize = rulerFontMetrics.width( label );
137+
int labelSize = mRulerFontMetrics->width( label );
117138

118139
//draw label only if it fits in before start of next page
119140
if ( pixelCoord + labelSize + 8 < firstPageY )
120141
{
121-
drawRotatedText( &p, QPointF( RULER_MIN_SIZE / 2.0 + 2.0, pixelCoord + 4.0 + labelSize ), label );
142+
drawRotatedText( &p, QPointF( mTextBaseline, pixelCoord + mMinSpacingVerticalLabels + labelSize ), label );
122143
}
123144

124145
//draw small divisions
@@ -163,16 +184,16 @@ void QgsComposerRuler::paintEvent( QPaintEvent* event )
163184
while (( totalCoord < nextPageStartPos ) || (( nextPageStartPos == 0 ) && ( totalCoord <= endY ) ) )
164185
{
165186
double pixelCoord = mTransform.map( QPointF( 0, totalCoord ) ).y();
166-
p.drawLine( 0, pixelCoord, RULER_MIN_SIZE, pixelCoord );
187+
p.drawLine( 0, pixelCoord, mRulerMinSize, pixelCoord );
167188
//calc size of label
168189
QString label = QString::number( pageCoord );
169-
int labelSize = rulerFontMetrics.width( label );
190+
int labelSize = mRulerFontMetrics->width( label );
170191

171192
//draw label only if it fits in before start of next page
172193
if (( pixelCoord + labelSize + 8 < nextPageStartPixel )
173194
|| ( nextPageStartPixel == 0 ) )
174195
{
175-
drawRotatedText( &p, QPointF( RULER_MIN_SIZE / 2.0 + 2.0, pixelCoord + 4.0 + labelSize ), label );
196+
drawRotatedText( &p, QPointF( mTextBaseline, pixelCoord + mMinSpacingVerticalLabels + labelSize ), label );
176197
}
177198

178199
//draw small divisions
@@ -194,11 +215,11 @@ void QgsComposerRuler::drawMarkerPos( QPainter *painter )
194215
painter->setPen( QColor( Qt::red ) );
195216
if ( mDirection == Horizontal )
196217
{
197-
painter->drawLine( mMarkerPos.x(), 0, mMarkerPos.x(), RULER_MIN_SIZE );
218+
painter->drawLine( mMarkerPos.x(), 0, mMarkerPos.x(), mRulerMinSize );
198219
}
199220
else
200221
{
201-
painter->drawLine( 0, mMarkerPos.y(), RULER_MIN_SIZE, mMarkerPos.y() );
222+
painter->drawLine( 0, mMarkerPos.y(), mRulerMinSize, mMarkerPos.y() );
202223
}
203224
}
204225

@@ -245,21 +266,21 @@ void QgsComposerRuler::drawSmallDivisions( QPainter *painter, double startPos, i
245266
if (( numDivisions == 10 && i == 4 ) || ( numDivisions == 4 && i == 1 ) )
246267
{
247268
//if drawing the 5th line of 10 or drawing the 2nd line of 4, then draw it slightly longer
248-
lineSize = RULER_MIN_SIZE / 1.5;
269+
lineSize = mRulerMinSize / 1.5;
249270
}
250271
else
251272
{
252-
lineSize = RULER_MIN_SIZE / 1.25;
273+
lineSize = mRulerMinSize / 1.25;
253274
}
254275

255276
//draw either horizontal or vertical line depending on ruler direction
256277
if ( mDirection == Horizontal )
257278
{
258-
painter->drawLine( pixelCoord, lineSize, pixelCoord, RULER_MIN_SIZE );
279+
painter->drawLine( pixelCoord, lineSize, pixelCoord, mRulerMinSize );
259280
}
260281
else
261282
{
262-
painter->drawLine( lineSize, pixelCoord, RULER_MIN_SIZE, pixelCoord );
283+
painter->drawLine( lineSize, pixelCoord, mRulerMinSize, pixelCoord );
263284
}
264285
}
265286
}
@@ -321,8 +342,8 @@ int QgsComposerRuler::optimumNumberDivisions( double rulerScale, int scaleMultip
321342
{
322343
//find pixel size for this small division
323344
double candidateSize = largeDivisionSize / ( *divisions_it );
324-
//small divisions must be seperated by at least 4 pixels
325-
if ( candidateSize >= 4 )
345+
//check if this seperation is more then allowed min seperation
346+
if ( candidateSize >= mMinPixelsPerDivision )
326347
{
327348
//found a good candidate, return it
328349
return ( *divisions_it );

src/gui/qgscomposerruler.h

+9
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ class GUI_EXPORT QgsComposerRuler: public QWidget
4747
//items snapped to the current snap line
4848
QList< QPair< QgsComposerItem*, QgsComposerItem::ItemPositionMode > > mSnappedItems;
4949

50+
QFont * mRulerFont;
51+
QFontMetrics * mRulerFontMetrics;
52+
double mScaleMinPixelsWidth;
53+
int mRulerMinSize;
54+
int mMinPixelsPerDivision;
55+
int mPixelsBetweenLineAndText;
56+
int mTextBaseline;
57+
int mMinSpacingVerticalLabels;
58+
5059
void setSnapLinePosition( const QPointF& pos );
5160

5261
//calculate optimum labeled units for ruler so that labels are a good distance apart

0 commit comments

Comments
 (0)