Skip to content

Commit

Permalink
Adv labeling, add multi-line spacing and alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
dakcarto committed Oct 23, 2012
1 parent a22742d commit e08833a
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 14 deletions.
9 changes: 9 additions & 0 deletions python/core/qgspallabeling.sip
Expand Up @@ -34,6 +34,13 @@ class QgsPalLayerSettings
ShowAll // show upside down for all labels, including dynamic ones
};

enum MultiLineAlign
{
MultiLeft = 0,
MultiCenter,
MultiRight
};

// increment iterator in _writeDataDefinedPropertyMap() when adding more
enum DataDefinedProperties
{
Expand Down Expand Up @@ -118,6 +125,8 @@ class QgsPalLayerSettings
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)
QString wrapChar;
double multilineHeight; //0.0 to 10.0, leading between lines as multiplyer of line height
MultiLineAlign multilineAlign; // horizontal alignment of multi-line labels
// called from register feature hook
void calculateLabelSize( const QFontMetricsF* fm, QString text, double& labelX, double& labelY );

Expand Down
4 changes: 4 additions & 0 deletions src/app/qgslabelinggui.cpp
Expand Up @@ -192,6 +192,8 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
}

wrapCharacterEdit->setText( lyr.wrapChar );
mFontLineHeightSpinBox->setValue( lyr.multilineHeight );
mFontMultiLineComboBox->setCurrentIndex(( unsigned int ) lyr.multilineAlign );
chkPreserveRotation->setChecked( lyr.preserveRotation );

mPreviewBackgroundBtn->setColor( lyr.previewBkgrdColor );
Expand Down Expand Up @@ -461,6 +463,8 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
lyr.minFeatureSize = mMinSizeSpinBox->value();
lyr.fontSizeInMapUnits = ( mFontSizeUnitComboBox->currentIndex() == 1 );
lyr.wrapChar = wrapCharacterEdit->text();
lyr.multilineHeight = mFontLineHeightSpinBox->value();
lyr.multilineAlign = ( QgsPalLayerSettings::MultiLineAlign ) mFontMultiLineComboBox->currentIndex();
if ( chkPreserveRotation->isChecked() )
{
lyr.preserveRotation = true;
Expand Down
59 changes: 50 additions & 9 deletions src/core/qgspallabeling.cpp
Expand Up @@ -187,6 +187,8 @@ QgsPalLayerSettings::QgsPalLayerSettings()
labelOffsetInMapUnits = true;
distInMapUnits = false;
wrapChar = "";
multilineHeight = 1.0;
multilineAlign = MultiLeft;
preserveRotation = true;
}

Expand Down Expand Up @@ -235,6 +237,8 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
distInMapUnits = s.distInMapUnits;
labelOffsetInMapUnits = s.labelOffsetInMapUnits;
wrapChar = s.wrapChar;
multilineHeight = s.multilineHeight;
multilineAlign = s.multilineAlign;
preserveRotation = s.preserveRotation;

dataDefinedProperties = s.dataDefinedProperties;
Expand Down Expand Up @@ -416,6 +420,8 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
distInMapUnits = layer->customProperty( "labeling/distInMapUnits" ).toBool();
labelOffsetInMapUnits = layer->customProperty( "labeling/labelOffsetInMapUnits", QVariant( true ) ).toBool();
wrapChar = layer->customProperty( "labeling/wrapChar" ).toString();
multilineHeight = layer->customProperty( "labeling/multilineHeight", QVariant( 1.0 ) ).toDouble();
multilineAlign = ( MultiLineAlign ) layer->customProperty( "labeling/multilineAlign", QVariant( MultiLeft ) ).toUInt();
preserveRotation = layer->customProperty( "labeling/preserveRotation", QVariant( true ) ).toBool();
_readDataDefinedPropertyMap( layer, dataDefinedProperties );
}
Expand Down Expand Up @@ -475,6 +481,8 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
layer->setCustomProperty( "labeling/distInMapUnits", distInMapUnits );
layer->setCustomProperty( "labeling/labelOffsetInMapUnits", labelOffsetInMapUnits );
layer->setCustomProperty( "labeling/wrapChar", wrapChar );
layer->setCustomProperty( "labeling/multilineHeight", multilineHeight );
layer->setCustomProperty( "labeling/multilineAlign", ( unsigned int )multilineAlign );
layer->setCustomProperty( "labeling/preserveRotation", preserveRotation );
_writeDataDefinedPropertyMap( layer, dataDefinedProperties );
}
Expand Down Expand Up @@ -540,16 +548,20 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t
text.append( ">" );
}

double w, h;
double w = 0.0, h = 0.0;
QStringList multiLineSplit;
if ( !wrapChar.isEmpty() )
multiLineSplit = text.split( wrapChar );
else
multiLineSplit = text.split( "\n" );
int lines = multiLineSplit.size();

h = fm->height() * multiLineSplit.size() / rasterCompressFactor;
w = 0;
for ( int i = 0; i < multiLineSplit.size(); ++i )
double labelHeight = fm->ascent() + fm->descent(); // ignore +1 for baseline

h += fm->height() + ( double )(( lines - 1 ) * labelHeight * multilineHeight );
h /= rasterCompressFactor;

for ( int i = 0; i < lines; ++i )
{
double width = fm->width( multiLineSplit.at( i ) );
if ( width > w )
Expand Down Expand Up @@ -1661,7 +1673,24 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, co
else
multiLineList = txt.split( "\n" );

for ( int i = 0; i < multiLineList.size(); ++i )
int lines = multiLineList.size();

double labelWidest = 0.0;
for ( int i = 0; i < lines; ++i )
{
double labelWidth = labelfm->width( multiLineList.at( i ) );
if ( labelWidth > labelWidest )
{
labelWidest = labelWidth;
}
}

double labelHeight = labelfm->ascent() + labelfm->descent(); // ignore +1 for baseline

// needed to move bottom of text's descender to within bottom edge of label
double ascentOffset = 0.25 * labelfm->ascent(); // labelfm->descent() is not enough

for ( int i = 0; i < lines; ++i )
{
painter->save();
painter->translate( QPointF( outPt.x(), outPt.y() ) );
Expand All @@ -1671,10 +1700,22 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, co
// to workaround a Qt font scaling bug with small font sizes
painter->scale( 1.0 / lyr.rasterCompressFactor, 1.0 / lyr.rasterCompressFactor );

double yMultiLineOffset = ( multiLineList.size() - 1 - i ) * labelfm->height();
double ascentOffset = 0.0;
ascentOffset = labelfm->height() * 0.25 * labelfm->ascent() / labelfm->height();
painter->translate( QPointF( 0, - ascentOffset - yMultiLineOffset ) );
// figure x offset for horizontal alignment of multiple lines
double xMultiLineOffset = 0.0;
if ( lines > 1 && lyr.multilineAlign != QgsPalLayerSettings::MultiLeft )
{
double labelWidth = labelfm->width( multiLineList.at( i ) );
double labelWidthDiff = labelWidest - labelWidth;
if ( lyr.multilineAlign == QgsPalLayerSettings::MultiCenter )
{
labelWidthDiff /= 2;
}
xMultiLineOffset = labelWidthDiff * lyr.rasterCompressFactor;
QgsDebugMsg( QString( "xMultiLineOffset: %0" ).arg( xMultiLineOffset ) );
}

double yMultiLineOffset = ( lines - 1 - i ) * labelHeight * lyr.multilineHeight;
painter->translate( QPointF( xMultiLineOffset, - ascentOffset - yMultiLineOffset ) );

if ( drawBuffer )
{
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgspallabeling.h
Expand Up @@ -88,6 +88,13 @@ class CORE_EXPORT QgsPalLayerSettings
ShowAll // show upside down for all labels, including dynamic ones
};

enum MultiLineAlign
{
MultiLeft = 0,
MultiCenter,
MultiRight
};

// increment iterator in _writeDataDefinedPropertyMap() when adding more
enum DataDefinedProperties
{
Expand Down Expand Up @@ -172,6 +179,8 @@ class CORE_EXPORT QgsPalLayerSettings
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)
QString wrapChar;
double multilineHeight; //0.0 to 10.0, leading between lines as multiplyer of line height
MultiLineAlign multilineAlign; // horizontal alignment of multi-line labels
// called from register feature hook
void calculateLabelSize( const QFontMetricsF* fm, QString text, double& labelX, double& labelY );

Expand Down
10 changes: 5 additions & 5 deletions src/ui/qgslabelingguibase.ui
Expand Up @@ -449,7 +449,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-162</y>
<width>686</width>
<height>628</height>
</rect>
Expand Down Expand Up @@ -523,7 +523,7 @@
<item>
<widget class="QDoubleSpinBox" name="mFontLineHeightSpinBox">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand Down Expand Up @@ -576,7 +576,7 @@
<item>
<widget class="QComboBox" name="mFontMultiLineComboBox">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
Expand Down Expand Up @@ -1493,7 +1493,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>686</width>
<width>636</width>
<height>553</height>
</rect>
</property>
Expand Down Expand Up @@ -2355,7 +2355,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>686</width>
<width>488</width>
<height>951</height>
</rect>
</property>
Expand Down

0 comments on commit e08833a

Please sign in to comment.