Skip to content

Commit

Permalink
Fix grid annotations, port tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 7, 2017
1 parent b7e3526 commit 20b9d08
Show file tree
Hide file tree
Showing 20 changed files with 808 additions and 9 deletions.
98 changes: 98 additions & 0 deletions python/core/layout/qgslayoututils.sip
Expand Up @@ -9,6 +9,7 @@




class QgsLayoutUtils
{
%Docstring
Expand Down Expand Up @@ -87,6 +88,103 @@ class QgsLayoutUtils
:rtype: float
%End

static QFont scaledFontPixelSize( const QFont &font );
%Docstring
Returns a ``font`` where size is set in points and the size has been upscaled with FONT_WORKAROUND_SCALE
to workaround QT font rendering bugs.
Returns a font with size set in pixels.
:rtype: QFont
%End

static double fontAscentMM( const QFont &font );
%Docstring
Calculates a ``font`` ascent in millimeters, including workarounds for QT font rendering issues.
.. seealso:: fontDescentMM()
.. seealso:: fontHeightMM()
.. seealso:: fontHeightCharacterMM()
.. seealso:: textWidthMM()
:rtype: float
%End

static double fontDescentMM( const QFont &font );
%Docstring
Calculate a ``font`` descent in millimeters, including workarounds for QT font rendering issues.
.. seealso:: fontAscentMM()
.. seealso:: fontHeightMM()
.. seealso:: fontHeightCharacterMM()
.. seealso:: textWidthMM()
:rtype: float
%End

static double fontHeightMM( const QFont &font );
%Docstring
Calculate a ``font`` height in millimeters, including workarounds for QT font rendering issues.
The font height is the font ascent + descent + 1 (for the baseline).
.. seealso:: fontAscentMM()
.. seealso:: fontDescentMM()
.. seealso:: fontHeightCharacterMM()
.. seealso:: textWidthMM()
:rtype: float
%End

static double fontHeightCharacterMM( const QFont &font, QChar character );
%Docstring
Calculate a ``font`` height in millimeters of a single ``character``, including workarounds for QT font
rendering issues.
.. seealso:: fontAscentMM()
.. seealso:: fontDescentMM()
.. seealso:: fontHeightMM()
.. seealso:: textWidthMM()
:rtype: float
%End

static double textWidthMM( const QFont &font, const QString &text );
%Docstring
Calculate a ``font`` width in millimeters for a ``text`` string, including workarounds for QT font
rendering issues.
.. seealso:: fontAscentMM()
.. seealso:: fontDescentMM()
.. seealso:: fontHeightMM()
.. seealso:: fontHeightCharacterMM()
.. seealso:: textHeightMM()
:rtype: float
%End

static double textHeightMM( const QFont &font, const QString &text, double multiLineHeight = 1.0 );
%Docstring
Calculate a ``font`` height in millimeters for a ``text`` 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.

The ``multiLineHeight`` parameter specifies the line spacing factor.

.. seealso:: textWidthMM()
:rtype: float
%End

static void drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color = QColor() );
%Docstring
Draws ``text`` on a ``painter`` at a specific ``position``, taking care of layout specific issues (calculation to pixel,
scaling of font and painter to work around Qt font bugs).

If ``color`` is specified, text will be rendered in that color. If not specified, the current painter pen
color will be used instead.
%End

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 );
%Docstring
Draws ``text`` on a ``painter`` within a ``rectangle``, taking care of layout specific issues (calculation to pixel,
scaling of font and painter to work around Qt font bugs).

If ``color`` is specified, text will be rendered in that color. If not specified, the current painter pen
color will be used instead.

The text alignment within ``rectangle`` can be set via the ``halignment`` and ``valignment``
arguments.

The ``flags`` parameter allows for passing Qt.TextFlags to control appearance of rendered text.
%End

};

/************************************************************************
Expand Down
12 changes: 4 additions & 8 deletions src/core/layout/qgslayoutitemmapgrid.cpp
Expand Up @@ -1013,13 +1013,11 @@ void QgsLayoutItemMapGrid::drawCoordinateAnnotation( QPainter *p, QPointF pos, c
return;
}

QFontMetricsF fontMetrics( mGridAnnotationFont );

QgsLayoutItemMapGrid::BorderSide frameBorder = borderForLineCoord( pos, coordinateType );
double textWidth = fontMetrics.width( annotationString );
double textWidth = QgsLayoutUtils::textWidthMM( mGridAnnotationFont, annotationString );
//relevant for annotations is the height of digits
double textHeight = extension ? fontMetrics.ascent()
: fontMetrics.boundingRect( QChar( '0' ) ).height();
double textHeight = extension ? QgsLayoutUtils::fontAscentMM( mGridAnnotationFont )
: QgsLayoutUtils::fontHeightCharacterMM( mGridAnnotationFont, QChar( '0' ) );
double xpos = pos.x();
double ypos = pos.y();
int rotation = 0;
Expand Down Expand Up @@ -1339,9 +1337,7 @@ void QgsLayoutItemMapGrid::drawAnnotation( QPainter *p, QPointF pos, int rotatio
p->save();
p->translate( pos );
p->rotate( rotation );
p->setFont( mGridAnnotationFont );
p->setPen( mGridAnnotationFontColor );
p->drawText( QPointF( 0, 0 ), annotationText );
QgsLayoutUtils::drawText( p, QPointF( 0, 0 ), annotationText, mGridAnnotationFont, mGridAnnotationFontColor );
p->restore();
}

Expand Down
133 changes: 133 additions & 0 deletions src/core/layout/qgslayoututils.cpp
Expand Up @@ -159,3 +159,136 @@ double QgsLayoutUtils::relativePosition( const double position, const double bef
//return linearly scaled position
return m * position + c;
}
QFont QgsLayoutUtils::scaledFontPixelSize( const QFont &font )
{
//upscale using FONT_WORKAROUND_SCALE
//ref: http://osgeo-org.1560.x6.nabble.com/Multi-line-labels-and-font-bug-td4157152.html
QFont scaledFont = font;
double pixelSize = pointsToMM( scaledFont.pointSizeF() ) * FONT_WORKAROUND_SCALE + 0.5;
scaledFont.setPixelSize( pixelSize );
return scaledFont;
}

double QgsLayoutUtils::fontAscentMM( const QFont &font )
{
//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 );
return ( fontMetrics.ascent() / FONT_WORKAROUND_SCALE );
}

double QgsLayoutUtils::fontDescentMM( const QFont &font )
{
//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 );
return ( fontMetrics.descent() / FONT_WORKAROUND_SCALE );

}

double QgsLayoutUtils::fontHeightMM( const QFont &font )
{
//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 );
return ( fontMetrics.height() / FONT_WORKAROUND_SCALE );

}

double QgsLayoutUtils::fontHeightCharacterMM( const QFont &font, QChar character )
{
//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 );
return ( fontMetrics.boundingRect( character ).height() / FONT_WORKAROUND_SCALE );
}

double QgsLayoutUtils::textWidthMM( const QFont &font, const QString &text )
{
//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 );
return ( fontMetrics.width( text ) / FONT_WORKAROUND_SCALE );
}

double QgsLayoutUtils::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() + static_cast< double >( ( lines - 1 ) * fontHeight * multiLineHeight );

return textHeight / FONT_WORKAROUND_SCALE;
}

void QgsLayoutUtils::drawText( QPainter *painter, QPointF position, const QString &text, const QFont &font, const QColor &color )
{
if ( !painter )
{
return;
}

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

painter->save();
painter->setFont( textFont );
if ( color.isValid() )
{
painter->setPen( color );
}
double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
painter->scale( scaleFactor, scaleFactor );
painter->drawText( position * FONT_WORKAROUND_SCALE, text );
painter->restore();
}

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 )
{
if ( !painter )
{
return;
}

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

QRectF scaledRect( rect.x() * FONT_WORKAROUND_SCALE, rect.y() * FONT_WORKAROUND_SCALE,
rect.width() * FONT_WORKAROUND_SCALE, rect.height() * FONT_WORKAROUND_SCALE );

painter->save();
painter->setFont( textFont );
if ( color.isValid() )
{
painter->setPen( color );
}
double scaleFactor = 1.0 / FONT_WORKAROUND_SCALE;
painter->scale( scaleFactor, scaleFactor );
painter->drawText( scaledRect, halignment | valignment | flags, text );
painter->restore();
}

double QgsLayoutUtils::pointsToMM( const double pointSize )
{
//conversion to mm based on 1 point = 1/72 inch
return ( pointSize * 0.3527 );
}

double QgsLayoutUtils::mmToPoints( const double mmSize )
{
//conversion to points based on 1 point = 1/72 inch
return ( mmSize / 0.3527 );
}

0 comments on commit 20b9d08

Please sign in to comment.