Skip to content

Commit

Permalink
Add pixel size limiting for labels defined in map units
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
dakcarto committed Nov 9, 2012
1 parent d49c7d7 commit e5f07ed
Show file tree
Hide file tree
Showing 6 changed files with 430 additions and 128 deletions.
3 changes: 3 additions & 0 deletions python/core/qgspallabeling.sip
Expand Up @@ -121,6 +121,9 @@ class QgsPalLayerSettings
bool addDirectionSymbol;
unsigned int upsidedownLabels; // whether, or how, to show upsidedown labels
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
bool fontLimitPixelSize; // true is label should be limited by fontMinPixelSize/fontMaxPixelSize
int fontMinPixelSize; // minimum pixel size for showing rendered map unit labels (1 - 1000)
int fontMaxPixelSize; // maximum pixel size for showing rendered map unit labels (1 - 10000)
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
bool distInMapUnits; //true if distance is in map units (otherwise in mm)
Expand Down
40 changes: 39 additions & 1 deletion src/app/qgslabelinggui.cpp
Expand Up @@ -239,6 +239,12 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
chkPlusSign->setChecked( plusSign );
}

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

void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
{
Q_UNUSED( index );
// disable pixel size limiting for labels defined in points
if ( index == 0 )
{
mFontLimitPixelGroupBox->setChecked( false );
}
else if ( index == 1 && mMinPixelLimit == 0 )
{
// initial minimum trigger value set, turn on pixel size limiting by default
// for labels defined in map units (ignored after first settings save)
mFontLimitPixelGroupBox->setChecked( true );
}
updateFont( mRefFont );
}

void QgsLabelingGui::on_mFontMinPixelSpinBox_valueChanged( int px )
{
// ensure max font pixel size for map unit labels can't be lower than min
mFontMaxPixelSpinBox->setMinimum( px );
mFontMaxPixelSpinBox->update();
}

void QgsLabelingGui::on_mFontMaxPixelSpinBox_valueChanged( int px )
{
// ensure max font pixel size for map unit labels can't be lower than min
if ( px < mFontMinPixelSpinBox->value() )
{
mFontMaxPixelSpinBox->blockSignals( true );
mFontMaxPixelSpinBox->setValue( mFontMinPixelSpinBox->value() );
mFontMaxPixelSpinBox->blockSignals( false );
}
mFontMaxPixelSpinBox->setMinimum( mFontMinPixelSpinBox->value() );
}

void QgsLabelingGui::on_mBufferUnitComboBox_currentIndexChanged( int index )
{
Q_UNUSED( index );
Expand Down
3 changes: 3 additions & 0 deletions src/app/qgslabelinggui.h
Expand Up @@ -61,6 +61,8 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void on_mFontWordSpacingSpinBox_valueChanged( double spacing );
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
void on_mFontMinPixelSpinBox_valueChanged( int px );
void on_mFontMaxPixelSpinBox_valueChanged( int px );
void on_mBufferUnitComboBox_currentIndexChanged( int index );
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );
Expand Down Expand Up @@ -95,6 +97,7 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase

int mXQuadOffset;
int mYQuadOffset;
int mMinPixelLimit;

void disableDataDefinedAlignment();
void enableDataDefinedAlignment();
Expand Down
62 changes: 41 additions & 21 deletions src/core/qgspallabeling.cpp
Expand Up @@ -215,6 +215,9 @@ QgsPalLayerSettings::QgsPalLayerSettings()
addDirectionSymbol = false;
upsidedownLabels = Upright;
fontSizeInMapUnits = false;
fontLimitPixelSize = false;
fontMinPixelSize = 0; //trigger to turn it on by default for map unit labels
fontMaxPixelSize = 10000;
bufferSizeInMapUnits = false;
labelOffsetInMapUnits = true;
distInMapUnits = false;
Expand Down Expand Up @@ -265,6 +268,9 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
addDirectionSymbol = s.addDirectionSymbol;
upsidedownLabels = s.upsidedownLabels;
fontSizeInMapUnits = s.fontSizeInMapUnits;
fontLimitPixelSize = s.fontLimitPixelSize;
fontMinPixelSize = s.fontMinPixelSize;
fontMaxPixelSize = s.fontMaxPixelSize;
bufferSizeInMapUnits = s.bufferSizeInMapUnits;
distInMapUnits = s.distInMapUnits;
labelOffsetInMapUnits = s.labelOffsetInMapUnits;
Expand Down Expand Up @@ -448,6 +454,9 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
upsidedownLabels = ( UpsideDownLabels ) layer->customProperty( "labeling/upsidedownLabels", QVariant( Upright ) ).toUInt();
minFeatureSize = layer->customProperty( "labeling/minFeatureSize" ).toDouble();
fontSizeInMapUnits = layer->customProperty( "labeling/fontSizeInMapUnits" ).toBool();
fontLimitPixelSize = layer->customProperty( "labeling/fontLimitPixelSize", QVariant( false ) ).toBool();
fontMinPixelSize = layer->customProperty( "labeling/fontMinPixelSize", QVariant( 0 ) ).toInt();
fontMaxPixelSize = layer->customProperty( "labeling/fontMaxPixelSize", QVariant( 10000 ) ).toInt();
bufferSizeInMapUnits = layer->customProperty( "labeling/bufferSizeInMapUnits" ).toBool();
distInMapUnits = layer->customProperty( "labeling/distInMapUnits" ).toBool();
labelOffsetInMapUnits = layer->customProperty( "labeling/labelOffsetInMapUnits", QVariant( true ) ).toBool();
Expand Down Expand Up @@ -509,6 +518,9 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
layer->setCustomProperty( "labeling/upsidedownLabels", ( unsigned int )upsidedownLabels );
layer->setCustomProperty( "labeling/minFeatureSize", minFeatureSize );
layer->setCustomProperty( "labeling/fontSizeInMapUnits", fontSizeInMapUnits );
layer->setCustomProperty( "labeling/fontLimitPixelSize", fontLimitPixelSize );
layer->setCustomProperty( "labeling/fontMinPixelSize", fontMinPixelSize );
layer->setCustomProperty( "labeling/fontMaxPixelSize", fontMaxPixelSize );
layer->setCustomProperty( "labeling/bufferSizeInMapUnits", bufferSizeInMapUnits );
layer->setCustomProperty( "labeling/distInMapUnits", distInMapUnits );
layer->setCustomProperty( "labeling/labelOffsetInMapUnits", labelOffsetInMapUnits );
Expand Down Expand Up @@ -658,6 +670,33 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
}
}

QFont labelFont = textFont;

//data defined label size?
QMap< DataDefinedProperties, int >::const_iterator it = dataDefinedProperties.find( QgsPalLayerSettings::Size );
if ( it != dataDefinedProperties.constEnd() )
{
//find out size
QVariant size = f.attributeMap().value( *it );
if ( size.isValid() )
{
double sizeDouble = size.toDouble();
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context ) < 1 )
{
return;
}
labelFont.setPixelSize( sizeToPixel( sizeDouble, context ) );
}
}

// defined 'minimum/maximum pixel font size' option
// TODO: add any data defined setting to override fontMinPixelSize/fontMaxPixelSize
if ( fontLimitPixelSize && fontSizeInMapUnits &&
( fontMinPixelSize > labelFont.pixelSize() || labelFont.pixelSize() > fontMaxPixelSize ) )
{
return;
}

QString labelText;

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

double labelX, labelY; // will receive label size
QFont labelFont = textFont;

//data defined label size?
QMap< DataDefinedProperties, int >::const_iterator it = dataDefinedProperties.find( QgsPalLayerSettings::Size );
if ( it != dataDefinedProperties.constEnd() )
{
//find out size
QVariant size = f.attributeMap().value( *it );
if ( size.isValid() )
{
double sizeDouble = size.toDouble();
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context ) < 1 )
{
return;
}
labelFont.setPixelSize( sizeToPixel( sizeDouble, context ) );
}
}

// this should come after any data defined option that affects font metrics
// this should come AFTER any data defined option that affects font metrics
QFontMetricsF* labelFontMetrics = new QFontMetricsF( labelFont );
double labelX, labelY; // will receive label size
calculateLabelSize( labelFontMetrics, labelText, labelX, labelY );

QgsGeometry* geom = f.geometry();
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgspallabeling.h
Expand Up @@ -175,6 +175,9 @@ class CORE_EXPORT QgsPalLayerSettings
bool addDirectionSymbol;
unsigned int upsidedownLabels; // whether, or how, to show upsidedown labels
bool fontSizeInMapUnits; //true if font size is in map units (otherwise in points)
bool fontLimitPixelSize; // true is label should be limited by fontMinPixelSize/fontMaxPixelSize
int fontMinPixelSize; // minimum pixel size for showing rendered map unit labels (1 - 1000)
int fontMaxPixelSize; // maximum pixel size for showing rendered map unit labels (1 - 10000)
bool bufferSizeInMapUnits; //true if buffer is in map units (otherwise in mm)
bool labelOffsetInMapUnits; //true if label offset is in map units (otherwise in mm)
bool distInMapUnits; //true if distance is in map units (otherwise in mm)
Expand Down

0 comments on commit e5f07ed

Please sign in to comment.