Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[composer] Add method for calculating height of text
Sponsored by City of Uster
  • Loading branch information
nyalldawson committed Aug 18, 2015
1 parent dba794c commit 29cc064
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
13 changes: 13 additions & 0 deletions python/core/composer/qgscomposerutils.sip
Expand Up @@ -202,9 +202,22 @@ class QgsComposerUtils
* @see fontDescentMM
* @see fontHeightMM
* @see fontHeightCharacterMM
* @see textHeightMM
*/
static double textWidthMM( const QFont& font, const QString& text );

/** Calculate font height in millimeters for a string, including workarounds for QT font
* rendering issues. Note that this method uses a non-standard measure of text height,
* where only the font ascent is considered for the first line of text.
* @param font input font
* @param text string to calculate height of
* @param multiLineHeight line spacing factor
* @returns string height in millimeters
* @note added in version 2.12
* @see textWidthMM
*/
static double textHeightMM( const QFont& font, const QString& text, double multiLineHeight = 1.0 );

/** Draws text on a painter at a specific position, taking care of composer specific issues (calculation to pixel,
* scaling of font and painter to work around Qt font bugs)
* @param painter destination QPainter
Expand Down
16 changes: 16 additions & 0 deletions src/core/composer/qgscomposerutils.cpp
Expand Up @@ -481,6 +481,22 @@ double QgsComposerUtils::textWidthMM( const QFont &font, const QString &text )
return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
}

double QgsComposerUtils::textHeightMM( const QFont &font, const QString &text, double multiLineHeight )
{
QStringList multiLineSplit = text.split( "\n" );
int lines = multiLineSplit.size();

//upscale using FONT_WORKAROUND_SCALE
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
QFont metricsFont = scaledFontPixelSize( font );
QFontMetricsF fontMetrics( metricsFont );

double fontHeight = fontMetrics.ascent() + fontMetrics.descent(); // ignore +1 for baseline
double textHeight = fontMetrics.ascent() + ( double )(( lines - 1 ) * fontHeight * multiLineHeight );

return textHeight / FONT_WORKAROUND_SCALE;
}

void QgsComposerUtils::drawText( QPainter *painter, const QPointF &pos, const QString &text, const QFont &font, const QColor &color )
{
if ( !painter )
Expand Down
13 changes: 13 additions & 0 deletions src/core/composer/qgscomposerutils.h
Expand Up @@ -223,9 +223,22 @@ class CORE_EXPORT QgsComposerUtils
* @see fontDescentMM
* @see fontHeightMM
* @see fontHeightCharacterMM
* @see textHeightMM
*/
static double textWidthMM( const QFont& font, const QString& text );

/** Calculate font height in millimeters for a string, including workarounds for QT font
* rendering issues. Note that this method uses a non-standard measure of text height,
* where only the font ascent is considered for the first line of text.
* @param font input font
* @param text string to calculate height of
* @param multiLineHeight line spacing factor
* @returns string height in millimeters
* @note added in version 2.12
* @see textWidthMM
*/
static double textHeightMM( const QFont& font, const QString& text, double multiLineHeight = 1.0 );

/** Draws text on a painter at a specific position, taking care of composer specific issues (calculation to pixel,
* scaling of font and painter to work around Qt font bugs)
* @param painter destination QPainter
Expand Down
17 changes: 16 additions & 1 deletion tests/src/core/testqgscomposerutils.cpp
Expand Up @@ -56,7 +56,8 @@ class TestQgsComposerUtils : public QObject
void fontDescentMM(); //test calculating font descent in mm
void fontHeightMM(); //test calculating font height in mm
void fontHeightCharacterMM(); //test calculating font character height in mm
void textWidthMM(); //test calculting text width in mm
void textWidthMM(); //test calculating text width in mm
void textHeightMM(); //test calculating text height in mm
void drawTextPos(); //test drawing text at a pos
void drawTextRect(); //test drawing text in a rect

Expand Down Expand Up @@ -617,6 +618,20 @@ void TestQgsComposerUtils::textWidthMM()
QVERIFY( qgsDoubleNear( QgsComposerUtils::textWidthMM( mTestFont, QString( "test string" ) ), 20, 2 ) );
}

void TestQgsComposerUtils::textHeightMM()
{
//platform specific font rendering differences mean this test needs to be very leniant
mTestFont.setPointSize( 12 );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test string" ) ) ) );
QVERIFY( qgsDoubleNear( QgsComposerUtils::textHeightMM( mTestFont, QString( "test string" ) ), 3.9, 0.2 ) );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ) ) ) );
QVERIFY( qgsDoubleNear( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ) ), 8.7, 0.2 ) );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ), 2 ) ) );
QVERIFY( qgsDoubleNear( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ), 2 ), 13.5, 0.2 ) );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring\nstring" ) ) ) );
QVERIFY( qgsDoubleNear( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring\nstring" ) ), 13.5, 0.2 ) );
}

void TestQgsComposerUtils::drawTextPos()
{
//test drawing with no painter
Expand Down

0 comments on commit 29cc064

Please sign in to comment.