Skip to content

Commit 20b9d08

Browse files
committedNov 7, 2017
Fix grid annotations, port tests
1 parent b7e3526 commit 20b9d08

File tree

20 files changed

+808
-9
lines changed

20 files changed

+808
-9
lines changed
 

‎python/core/layout/qgslayoututils.sip

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111

12+
1213
class QgsLayoutUtils
1314
{
1415
%Docstring
@@ -87,6 +88,103 @@ class QgsLayoutUtils
8788
:rtype: float
8889
%End
8990

91+
static QFont scaledFontPixelSize( const QFont &font );
92+
%Docstring
93+
Returns a ``font`` where size is set in points and the size has been upscaled with FONT_WORKAROUND_SCALE
94+
to workaround QT font rendering bugs.
95+
Returns a font with size set in pixels.
96+
:rtype: QFont
97+
%End
98+
99+
static double fontAscentMM( const QFont &font );
100+
%Docstring
101+
Calculates a ``font`` ascent in millimeters, including workarounds for QT font rendering issues.
102+
.. seealso:: fontDescentMM()
103+
.. seealso:: fontHeightMM()
104+
.. seealso:: fontHeightCharacterMM()
105+
.. seealso:: textWidthMM()
106+
:rtype: float
107+
%End
108+
109+
static double fontDescentMM( const QFont &font );
110+
%Docstring
111+
Calculate a ``font`` descent in millimeters, including workarounds for QT font rendering issues.
112+
.. seealso:: fontAscentMM()
113+
.. seealso:: fontHeightMM()
114+
.. seealso:: fontHeightCharacterMM()
115+
.. seealso:: textWidthMM()
116+
:rtype: float
117+
%End
118+
119+
static double fontHeightMM( const QFont &font );
120+
%Docstring
121+
Calculate a ``font`` height in millimeters, including workarounds for QT font rendering issues.
122+
The font height is the font ascent + descent + 1 (for the baseline).
123+
.. seealso:: fontAscentMM()
124+
.. seealso:: fontDescentMM()
125+
.. seealso:: fontHeightCharacterMM()
126+
.. seealso:: textWidthMM()
127+
:rtype: float
128+
%End
129+
130+
static double fontHeightCharacterMM( const QFont &font, QChar character );
131+
%Docstring
132+
Calculate a ``font`` height in millimeters of a single ``character``, including workarounds for QT font
133+
rendering issues.
134+
.. seealso:: fontAscentMM()
135+
.. seealso:: fontDescentMM()
136+
.. seealso:: fontHeightMM()
137+
.. seealso:: textWidthMM()
138+
:rtype: float
139+
%End
140+
141+
static double textWidthMM( const QFont &font, const QString &text );
142+
%Docstring
143+
Calculate a ``font`` width in millimeters for a ``text`` string, including workarounds for QT font
144+
rendering issues.
145+
.. seealso:: fontAscentMM()
146+
.. seealso:: fontDescentMM()
147+
.. seealso:: fontHeightMM()
148+
.. seealso:: fontHeightCharacterMM()
149+
.. seealso:: textHeightMM()
150+
:rtype: float
151+
%End
152+
153+
static double textHeightMM( const QFont &font, const QString &text, double multiLineHeight = 1.0 );
154+
%Docstring
155+
Calculate a ``font`` height in millimeters for a ``text`` string, including workarounds for QT font
156+
rendering issues. Note that this method uses a non-standard measure of text height,
157+
where only the font ascent is considered for the first line of text.
158+
159+
The ``multiLineHeight`` parameter specifies the line spacing factor.
160+
161+
.. seealso:: textWidthMM()
162+
:rtype: float
163+
%End
164+
165+
static void drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color = QColor() );
166+
%Docstring
167+
Draws ``text`` on a ``painter`` at a specific ``position``, taking care of layout specific issues (calculation to pixel,
168+
scaling of font and painter to work around Qt font bugs).
169+
170+
If ``color`` is specified, text will be rendered in that color. If not specified, the current painter pen
171+
color will be used instead.
172+
%End
173+
174+
static void drawText( QPainter *painter, const QRectF &rectangle, const QString &text, const QFont &font, const QColor &color = QColor(), const Qt::AlignmentFlag halignment = Qt::AlignLeft, const Qt::AlignmentFlag valignment = Qt::AlignTop, const int flags = Qt::TextWordWrap );
175+
%Docstring
176+
Draws ``text`` on a ``painter`` within a ``rectangle``, taking care of layout specific issues (calculation to pixel,
177+
scaling of font and painter to work around Qt font bugs).
178+
179+
If ``color`` is specified, text will be rendered in that color. If not specified, the current painter pen
180+
color will be used instead.
181+
182+
The text alignment within ``rectangle`` can be set via the ``halignment`` and ``valignment``
183+
arguments.
184+
185+
The ``flags`` parameter allows for passing Qt.TextFlags to control appearance of rendered text.
186+
%End
187+
90188
};
91189

92190
/************************************************************************

‎src/core/layout/qgslayoutitemmapgrid.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,13 +1013,11 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos, c
10131013
return;
10141014
}
10151015

1016-
QFontMetricsF fontMetrics( mGridAnnotationFont );
1017-
10181016
QgsLayoutItemMapGrid::BorderSide frameBorder = borderForLineCoord( pos, coordinateType );
1019-
double textWidth = fontMetrics.width( annotationString );
1017+
double textWidth = QgsLayoutUtils::textWidthMM( mGridAnnotationFont, annotationString );
10201018
//relevant for annotations is the height of digits
1021-
double textHeight = extension ? fontMetrics.ascent()
1022-
: fontMetrics.boundingRect( QChar( '0' ) ).height();
1019+
double textHeight = extension ? QgsLayoutUtils::fontAscentMM( mGridAnnotationFont )
1020+
: QgsLayoutUtils::fontHeightCharacterMM( mGridAnnotationFont, QChar( '0' ) );
10231021
double xpos = pos.x();
10241022
double ypos = pos.y();
10251023
int rotation = 0;
@@ -1339,9 +1337,7 @@ void QgsLayoutItemMapGrid::drawAnnotation( QPainter *p, QPointF pos, int rotatio
13391337
p->save();
13401338
p->translate( pos );
13411339
p->rotate( rotation );
1342-
p->setFont( mGridAnnotationFont );
1343-
p->setPen( mGridAnnotationFontColor );
1344-
p->drawText( QPointF( 0, 0 ), annotationText );
1340+
QgsLayoutUtils::drawText( p, QPointF( 0, 0 ), annotationText, mGridAnnotationFont, mGridAnnotationFontColor );
13451341
p->restore();
13461342
}
13471343

‎src/core/layout/qgslayoututils.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,136 @@ double QgsLayoutUtils::relativePosition( const double position, const double bef
159159
//return linearly scaled position
160160
return m * position + c;
161161
}
162+
QFont QgsLayoutUtils::scaledFontPixelSize( const QFont &font )
163+
{
164+
//upscale using FONT_WORKAROUND_SCALE
165+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
166+
QFont scaledFont = font;
167+
double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
168+
scaledFont.setPixelSize( pixelSize );
169+
return scaledFont;
170+
}
171+
172+
double QgsLayoutUtils::fontAscentMM( const QFont &font )
173+
{
174+
//upscale using FONT_WORKAROUND_SCALE
175+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
176+
QFont metricsFont = scaledFontPixelSize( font );
177+
QFontMetricsF fontMetrics( metricsFont );
178+
return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
179+
}
180+
181+
double QgsLayoutUtils::fontDescentMM( const QFont &font )
182+
{
183+
//upscale using FONT_WORKAROUND_SCALE
184+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
185+
QFont metricsFont = scaledFontPixelSize( font );
186+
QFontMetricsF fontMetrics( metricsFont );
187+
return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );
188+
189+
}
190+
191+
double QgsLayoutUtils::fontHeightMM( const QFont &font )
192+
{
193+
//upscale using FONT_WORKAROUND_SCALE
194+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
195+
QFont metricsFont = scaledFontPixelSize( font );
196+
QFontMetricsF fontMetrics( metricsFont );
197+
return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );
198+
199+
}
200+
201+
double QgsLayoutUtils::fontHeightCharacterMM( const QFont &font, QChar character )
202+
{
203+
//upscale using FONT_WORKAROUND_SCALE
204+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
205+
QFont metricsFont = scaledFontPixelSize( font );
206+
QFontMetricsF fontMetrics( metricsFont );
207+
return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
208+
}
209+
210+
double QgsLayoutUtils::textWidthMM( const QFont &font, const QString &text )
211+
{
212+
//upscale using FONT_WORKAROUND_SCALE
213+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
214+
QFont metricsFont = scaledFontPixelSize( font );
215+
QFontMetricsF fontMetrics( metricsFont );
216+
return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
217+
}
218+
219+
double QgsLayoutUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
220+
{
221+
QStringList multiLineSplit = text.split( '\n' );
222+
int lines = multiLineSplit.size();
223+
224+
//upscale using FONT_WORKAROUND_SCALE
225+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
226+
QFont metricsFont = scaledFontPixelSize( font );
227+
QFontMetricsF fontMetrics( metricsFont );
228+
229+
double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
230+
double textHeight = fontMetrics.ascent() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );
231+
232+
return textHeight / FONT_WORKAROUND_SCALE;
233+
}
234+
235+
void QgsLayoutUtils::drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color )
236+
{
237+
if ( !painter )
238+
{
239+
return;
240+
}
241+
242+
//upscale using FONT_WORKAROUND_SCALE
243+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
244+
QFont textFont = scaledFontPixelSize( font );
245+
246+
painter->save();
247+
painter->setFont( textFont );
248+
if ( color.isValid() )
249+
{
250+
painter->setPen( color );
251+
}
252+
double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
253+
painter->scale( scaleFactor, scaleFactor );
254+
painter->drawText( position * FONT_WORKAROUND_SCALE, text );
255+
painter->restore();
256+
}
257+
258+
void QgsLayoutUtils::drawText( QPainter *painter, const QRectF &rect, const QString &text, const QFont &font, const QColor &color, const Qt::AlignmentFlag halignment, const Qt::AlignmentFlag valignment, const int flags )
259+
{
260+
if ( !painter )
261+
{
262+
return;
263+
}
264+
265+
//upscale using FONT_WORKAROUND_SCALE
266+
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
267+
QFont textFont = scaledFontPixelSize( font );
268+
269+
QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
270+
rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );
271+
272+
painter->save();
273+
painter->setFont( textFont );
274+
if ( color.isValid() )
275+
{
276+
painter->setPen( color );
277+
}
278+
double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
279+
painter->scale( scaleFactor, scaleFactor );
280+
painter->drawText( scaledRect, halignment | valignment | flags, text );
281+
painter->restore();
282+
}
283+
284+
double QgsLayoutUtils::pointsToMM( const double pointSize )
285+
{
286+
//conversion to mm based on 1 point = 1/72 inch
287+
return ( pointSize * 0.3527 );
288+
}
289+
290+
double QgsLayoutUtils::mmToPoints( const double mmSize )
291+
{
292+
//conversion to points based on 1 point = 1/72 inch
293+
return ( mmSize / 0.3527 );
294+
}

0 commit comments

Comments
 (0)
Please sign in to comment.