Skip to content

Commit e5f07ed

Browse files
committed
Add pixel size limiting for labels defined in map units
- Allows user to quickly set visibility thresholds based upon text legibility - By default initially on for map unit labels to skip rendering at sizes < 3 px
1 parent d49c7d7 commit e5f07ed

File tree

6 files changed

+430
-128
lines changed

6 files changed

+430
-128
lines changed

python/core/qgspallabeling.sip

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ class QgsPalLayerSettings
121121
bool addDirectionSymbol;
122122
unsigned int upsidedownLabels; // whether, or how, to show upsidedown labels
123123
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
124+
bool fontLimitPixelSize; // true is label should be limited by fontMinPixelSize/fontMaxPixelSize
125+
int fontMinPixelSize; // minimum pixel size for showing rendered map unit labels (1 - 1000)
126+
int fontMaxPixelSize; // maximum pixel size for showing rendered map unit labels (1 - 10000)
124127
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
125128
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
126129
bool distInMapUnits; //true if distance is in map units (otherwise in mm)

src/app/qgslabelinggui.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
239239
chkPlusSign->setChecked( plusSign );
240240
}
241241

242+
// set pixel size limiting checked state before unit choice so limiting can be
243+
// turned on as a default for map units, if minimum trigger value of 0 is used
244+
mFontLimitPixelGroupBox->setChecked( lyr.fontLimitPixelSize );
245+
mMinPixelLimit = lyr.fontMinPixelSize; // ignored after first settings save
246+
mFontMinPixelSpinBox->setValue( lyr.fontMinPixelSize == 0 ? 3 : lyr.fontMinPixelSize );
247+
mFontMaxPixelSpinBox->setValue( lyr.fontMaxPixelSize );
242248
if ( lyr.fontSizeInMapUnits )
243249
{
244250
mFontSizeUnitComboBox->setCurrentIndex( 1 );
@@ -465,6 +471,9 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
465471
}
466472
lyr.minFeatureSize = mMinSizeSpinBox->value();
467473
lyr.fontSizeInMapUnits = ( mFontSizeUnitComboBox->currentIndex() == 1 );
474+
lyr.fontLimitPixelSize = mFontLimitPixelGroupBox->isChecked();
475+
lyr.fontMinPixelSize = mFontMinPixelSpinBox->value();
476+
lyr.fontMaxPixelSize = mFontMaxPixelSpinBox->value();
468477
lyr.wrapChar = wrapCharacterEdit->text();
469478
lyr.multilineHeight = mFontLineHeightSpinBox->value();
470479
lyr.multilineAlign = ( QgsPalLayerSettings::MultiLineAlign ) mFontMultiLineComboBox->currentIndex();
@@ -1004,10 +1013,39 @@ void QgsLabelingGui::on_mFontLetterSpacingSpinBox_valueChanged( double spacing )
10041013

10051014
void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
10061015
{
1007-
Q_UNUSED( index );
1016+
// disable pixel size limiting for labels defined in points
1017+
if ( index == 0 )
1018+
{
1019+
mFontLimitPixelGroupBox->setChecked( false );
1020+
}
1021+
else if ( index == 1 && mMinPixelLimit == 0 )
1022+
{
1023+
// initial minimum trigger value set, turn on pixel size limiting by default
1024+
// for labels defined in map units (ignored after first settings save)
1025+
mFontLimitPixelGroupBox->setChecked( true );
1026+
}
10081027
updateFont( mRefFont );
10091028
}
10101029

1030+
void QgsLabelingGui::on_mFontMinPixelSpinBox_valueChanged( int px )
1031+
{
1032+
// ensure max font pixel size for map unit labels can't be lower than min
1033+
mFontMaxPixelSpinBox->setMinimum( px );
1034+
mFontMaxPixelSpinBox->update();
1035+
}
1036+
1037+
void QgsLabelingGui::on_mFontMaxPixelSpinBox_valueChanged( int px )
1038+
{
1039+
// ensure max font pixel size for map unit labels can't be lower than min
1040+
if ( px < mFontMinPixelSpinBox->value() )
1041+
{
1042+
mFontMaxPixelSpinBox->blockSignals( true );
1043+
mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
1044+
mFontMaxPixelSpinBox->blockSignals( false );
1045+
}
1046+
mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
1047+
}
1048+
10111049
void QgsLabelingGui::on_mBufferUnitComboBox_currentIndexChanged( int index )
10121050
{
10131051
Q_UNUSED( index );

src/app/qgslabelinggui.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
6161
void on_mFontWordSpacingSpinBox_valueChanged( double spacing );
6262
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
6363
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
64+
void on_mFontMinPixelSpinBox_valueChanged( int px );
65+
void on_mFontMaxPixelSpinBox_valueChanged( int px );
6466
void on_mBufferUnitComboBox_currentIndexChanged( int index );
6567
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
6668
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );
@@ -95,6 +97,7 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
9597

9698
int mXQuadOffset;
9799
int mYQuadOffset;
100+
int mMinPixelLimit;
98101

99102
void disableDataDefinedAlignment();
100103
void enableDataDefinedAlignment();

src/core/qgspallabeling.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ QgsPalLayerSettings::QgsPalLayerSettings()
215215
addDirectionSymbol = false;
216216
upsidedownLabels = Upright;
217217
fontSizeInMapUnits = false;
218+
fontLimitPixelSize = false;
219+
fontMinPixelSize = 0; //trigger to turn it on by default for map unit labels
220+
fontMaxPixelSize = 10000;
218221
bufferSizeInMapUnits = false;
219222
labelOffsetInMapUnits = true;
220223
distInMapUnits = false;
@@ -265,6 +268,9 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
265268
addDirectionSymbol = s.addDirectionSymbol;
266269
upsidedownLabels = s.upsidedownLabels;
267270
fontSizeInMapUnits = s.fontSizeInMapUnits;
271+
fontLimitPixelSize = s.fontLimitPixelSize;
272+
fontMinPixelSize = s.fontMinPixelSize;
273+
fontMaxPixelSize = s.fontMaxPixelSize;
268274
bufferSizeInMapUnits = s.bufferSizeInMapUnits;
269275
distInMapUnits = s.distInMapUnits;
270276
labelOffsetInMapUnits = s.labelOffsetInMapUnits;
@@ -448,6 +454,9 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
448454
upsidedownLabels = ( UpsideDownLabels ) layer->customProperty( "labeling/upsidedownLabels", QVariant( Upright ) ).toUInt();
449455
minFeatureSize = layer->customProperty( "labeling/minFeatureSize" ).toDouble();
450456
fontSizeInMapUnits = layer->customProperty( "labeling/fontSizeInMapUnits" ).toBool();
457+
fontLimitPixelSize = layer->customProperty( "labeling/fontLimitPixelSize", QVariant( false ) ).toBool();
458+
fontMinPixelSize = layer->customProperty( "labeling/fontMinPixelSize", QVariant( 0 ) ).toInt();
459+
fontMaxPixelSize = layer->customProperty( "labeling/fontMaxPixelSize", QVariant( 10000 ) ).toInt();
451460
bufferSizeInMapUnits = layer->customProperty( "labeling/bufferSizeInMapUnits" ).toBool();
452461
distInMapUnits = layer->customProperty( "labeling/distInMapUnits" ).toBool();
453462
labelOffsetInMapUnits = layer->customProperty( "labeling/labelOffsetInMapUnits", QVariant( true ) ).toBool();
@@ -509,6 +518,9 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
509518
layer->setCustomProperty( "labeling/upsidedownLabels", ( unsigned int )upsidedownLabels );
510519
layer->setCustomProperty( "labeling/minFeatureSize", minFeatureSize );
511520
layer->setCustomProperty( "labeling/fontSizeInMapUnits", fontSizeInMapUnits );
521+
layer->setCustomProperty( "labeling/fontLimitPixelSize", fontLimitPixelSize );
522+
layer->setCustomProperty( "labeling/fontMinPixelSize", fontMinPixelSize );
523+
layer->setCustomProperty( "labeling/fontMaxPixelSize", fontMaxPixelSize );
512524
layer->setCustomProperty( "labeling/bufferSizeInMapUnits", bufferSizeInMapUnits );
513525
layer->setCustomProperty( "labeling/distInMapUnits", distInMapUnits );
514526
layer->setCustomProperty( "labeling/labelOffsetInMapUnits", labelOffsetInMapUnits );
@@ -658,6 +670,33 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
658670
}
659671
}
660672

673+
QFont labelFont = textFont;
674+
675+
//data defined label size?
676+
QMap< DataDefinedProperties, int >::const_iterator it = dataDefinedProperties.find( QgsPalLayerSettings::Size );
677+
if ( it != dataDefinedProperties.constEnd() )
678+
{
679+
//find out size
680+
QVariant size = f.attributeMap().value( *it );
681+
if ( size.isValid() )
682+
{
683+
double sizeDouble = size.toDouble();
684+
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context ) < 1 )
685+
{
686+
return;
687+
}
688+
labelFont.setPixelSize( sizeToPixel( sizeDouble, context ) );
689+
}
690+
}
691+
692+
// defined 'minimum/maximum pixel font size' option
693+
// TODO: add any data defined setting to override fontMinPixelSize/fontMaxPixelSize
694+
if ( fontLimitPixelSize && fontSizeInMapUnits &&
695+
( fontMinPixelSize > labelFont.pixelSize() || labelFont.pixelSize() > fontMaxPixelSize ) )
696+
{
697+
return;
698+
}
699+
661700
QString labelText;
662701

663702
// Check to see if we are a expression string.
@@ -695,28 +734,9 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
695734
labelText = f.attributeMap()[fieldIndex].toString();
696735
}
697736

698-
double labelX, labelY; // will receive label size
699-
QFont labelFont = textFont;
700-
701-
//data defined label size?
702-
QMap< DataDefinedProperties, int >::const_iterator it = dataDefinedProperties.find( QgsPalLayerSettings::Size );
703-
if ( it != dataDefinedProperties.constEnd() )
704-
{
705-
//find out size
706-
QVariant size = f.attributeMap().value( *it );
707-
if ( size.isValid() )
708-
{
709-
double sizeDouble = size.toDouble();
710-
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context ) < 1 )
711-
{
712-
return;
713-
}
714-
labelFont.setPixelSize( sizeToPixel( sizeDouble, context ) );
715-
}
716-
}
717-
718-
// this should come after any data defined option that affects font metrics
737+
// this should come AFTER any data defined option that affects font metrics
719738
QFontMetricsF* labelFontMetrics = new QFontMetricsF( labelFont );
739+
double labelX, labelY; // will receive label size
720740
calculateLabelSize( labelFontMetrics, labelText, labelX, labelY );
721741

722742
QgsGeometry* geom = f.geometry();

src/core/qgspallabeling.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ class CORE_EXPORT QgsPalLayerSettings
175175
bool addDirectionSymbol;
176176
unsigned int upsidedownLabels; // whether, or how, to show upsidedown labels
177177
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
178+
bool fontLimitPixelSize; // true is label should be limited by fontMinPixelSize/fontMaxPixelSize
179+
int fontMinPixelSize; // minimum pixel size for showing rendered map unit labels (1 - 1000)
180+
int fontMaxPixelSize; // maximum pixel size for showing rendered map unit labels (1 - 10000)
178181
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
179182
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
180183
bool distInMapUnits; //true if distance is in map units (otherwise in mm)

0 commit comments

Comments
 (0)