Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[labeling] Fix evalution of letter/word spacing when font size is map…
… units

Fixes #32825
  • Loading branch information
nyalldawson committed Nov 19, 2019
1 parent 19d0b11 commit 0d6599a
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 6 deletions.
10 changes: 5 additions & 5 deletions src/core/qgspallabeling.cpp
Expand Up @@ -1795,9 +1795,9 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
// this is done here for later use in making label backgrounds part of collision management (when implemented)
labelFont.setCapitalization( QFont::MixedCase ); // reset this - we don't use QFont's handling as it breaks with curved labels

parseTextStyle( labelFont, fontunits, context );
if ( mDataDefinedProperties.hasActiveProperties() )
{
parseTextStyle( labelFont, fontunits, context );
parseTextFormatting( context );
parseTextBuffer( context );
parseTextMask( context );
Expand Down Expand Up @@ -2933,22 +2933,22 @@ void QgsPalLayerSettings::parseTextStyle( QFont &labelFont,
}

// data defined word spacing?
double wordspace = labelFont.wordSpacing();
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::FontWordSpacing ) )
{
double wordspace = labelFont.wordSpacing();
context.expressionContext().setOriginalValueVariable( wordspace );
wordspace = mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::FontWordSpacing, context.expressionContext(), wordspace );
labelFont.setWordSpacing( context.convertToPainterUnits( wordspace, fontunits, mFormat.sizeMapUnitScale() ) );
}
labelFont.setWordSpacing( context.convertToPainterUnits( wordspace, fontunits, mFormat.sizeMapUnitScale() ) );

// data defined letter spacing?
double letterspace = labelFont.letterSpacing();
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::FontLetterSpacing ) )
{
double letterspace = labelFont.letterSpacing();
context.expressionContext().setOriginalValueVariable( letterspace );
letterspace = mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::FontLetterSpacing, context.expressionContext(), letterspace );
labelFont.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( letterspace, fontunits, mFormat.sizeMapUnitScale() ) );
}
labelFont.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( letterspace, fontunits, mFormat.sizeMapUnitScale() ) );

// data defined strikeout font style?
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Strikeout ) )
Expand Down
110 changes: 109 additions & 1 deletion tests/src/core/testqgslabelingengine.cpp
Expand Up @@ -77,6 +77,8 @@ class TestQgsLabelingEngine : public QObject
void testVerticalOrientationLetterLineSpacing();
void testRotationBasedOrientationPoint();
void testRotationBasedOrientationLine();
void testMapUnitLetterSpacing();
void testMapUnitWordSpacing();

private:
QgsVectorLayer *vl = nullptr;
Expand Down Expand Up @@ -2349,7 +2351,7 @@ void TestQgsLabelingEngine::testVerticalOrientationLetterLineSpacing()
format.setOrientation( QgsTextFormat::VerticalOrientation );
format.setLineHeight( 1.5 );
QFont font = format.font();
font.setLetterSpacing( QFont::AbsoluteSpacing, 5 );
font.setLetterSpacing( QFont::AbsoluteSpacing, 3.75 );
format.setFont( font );
settings.setFormat( format );

Expand Down Expand Up @@ -2467,5 +2469,111 @@ void TestQgsLabelingEngine::testRotationBasedOrientationLine()
QgsProject::instance()->removeMapLayer( vl2 );
}

void TestQgsLabelingEngine::testMapUnitLetterSpacing()
{
QgsPalLayerSettings settings;
setDefaultLabelParams( settings );

QgsTextFormat format = settings.format();
format.setSize( 50 );
format.setSizeUnit( QgsUnitTypes::RenderMapUnits );
format.setColor( QColor( 0, 0, 0 ) );
settings.setFormat( format );

settings.fieldName = QStringLiteral( "'XX'" );
settings.isExpression = true;
settings.placement = QgsPalLayerSettings::Line;
QFont font = format.font();
font.setLetterSpacing( QFont::AbsoluteSpacing, 30 );
format.setFont( font );
settings.setFormat( format );

std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
vl2->setRenderer( new QgsNullSymbolRenderer() );

QgsFeature f;
f.setAttributes( QgsAttributes() << 1 );
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString (190020 5000000, 190180 5000000)" ) ) );
QVERIFY( vl2->dataProvider()->addFeature( f ) );

vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
vl2->setLabelsEnabled( true );

// make a fake render context
QSize size( 640, 480 );
QgsMapSettings mapSettings;
mapSettings.setDestinationCrs( vl2->crs() );

mapSettings.setOutputSize( size );
mapSettings.setExtent( QgsRectangle( 190000, 5000000, 190200, 5000010 ) );
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
mapSettings.setOutputDpi( 96 );

QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
engineSettings.setFlag( QgsLabelingEngineSettings::UsePartialCandidates, false );
//engineSettings.setFlag( QgsLabelingEngineSettings::DrawCandidates, true );
mapSettings.setLabelingEngineSettings( engineSettings );

QgsMapRendererSequentialJob job( mapSettings );
job.start();
job.waitForFinished();

QImage img = job.renderedImage();
QVERIFY( imageCheck( QStringLiteral( "label_letter_spacing_map_units" ), img, 20 ) );
}

void TestQgsLabelingEngine::testMapUnitWordSpacing()
{
QgsPalLayerSettings settings;
setDefaultLabelParams( settings );

QgsTextFormat format = settings.format();
format.setSize( 50 );
format.setSizeUnit( QgsUnitTypes::RenderMapUnits );
format.setColor( QColor( 0, 0, 0 ) );
settings.setFormat( format );

settings.fieldName = QStringLiteral( "'X X'" );
settings.isExpression = true;
settings.placement = QgsPalLayerSettings::Line;
QFont font = format.font();
font.setWordSpacing( 30 );
format.setFont( font );
settings.setFormat( format );

std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
vl2->setRenderer( new QgsNullSymbolRenderer() );

QgsFeature f;
f.setAttributes( QgsAttributes() << 1 );
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString (190020 5000000, 190180 5000000)" ) ) );
QVERIFY( vl2->dataProvider()->addFeature( f ) );

vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
vl2->setLabelsEnabled( true );

// make a fake render context
QSize size( 640, 480 );
QgsMapSettings mapSettings;
mapSettings.setDestinationCrs( vl2->crs() );

mapSettings.setOutputSize( size );
mapSettings.setExtent( QgsRectangle( 190000, 5000000, 190200, 5000010 ) );
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
mapSettings.setOutputDpi( 96 );

QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
engineSettings.setFlag( QgsLabelingEngineSettings::UsePartialCandidates, false );
//engineSettings.setFlag( QgsLabelingEngineSettings::DrawCandidates, true );
mapSettings.setLabelingEngineSettings( engineSettings );

QgsMapRendererSequentialJob job( mapSettings );
job.start();
job.waitForFinished();

QImage img = job.renderedImage();
QVERIFY( imageCheck( QStringLiteral( "label_word_spacing_map_units" ), img, 20 ) );
}

QGSTEST_MAIN( TestQgsLabelingEngine )
#include "testqgslabelingengine.moc"
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0d6599a

Please sign in to comment.