mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Adv labeling, add multi-line spacing and alignment
This commit is contained in:
parent
a22742d146
commit
e08833ac3b
@ -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
|
||||
{
|
||||
@ -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 );
|
||||
|
||||
|
@ -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 );
|
||||
@ -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;
|
||||
|
@ -187,6 +187,8 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
labelOffsetInMapUnits = true;
|
||||
distInMapUnits = false;
|
||||
wrapChar = "";
|
||||
multilineHeight = 1.0;
|
||||
multilineAlign = MultiLeft;
|
||||
preserveRotation = true;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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 );
|
||||
}
|
||||
@ -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 );
|
||||
}
|
||||
@ -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 )
|
||||
@ -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() ) );
|
||||
@ -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 )
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
@ -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 );
|
||||
|
||||
|
@ -449,7 +449,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<y>-162</y>
|
||||
<width>686</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
@ -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">
|
||||
@ -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">
|
||||
@ -1493,7 +1493,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>686</width>
|
||||
<width>636</width>
|
||||
<height>553</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -2355,7 +2355,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>686</width>
|
||||
<width>488</width>
|
||||
<height>951</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
Loading…
x
Reference in New Issue
Block a user