Skip to content

Commit 59fe8fd

Browse files
committed
Add letter and word spacing to curved labels for line layers
- Curved spacings match Qt-produced spacings for parallel (and other) labels - Remove redundant letter/word resetting in options gui - Remove on-fly adjustments to spinbox steps (only made sense with UTM, not LatLong)
1 parent b5a12d3 commit 59fe8fd

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

src/app/qgslabelinggui.cpp

+5-15
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
253253
btnTextColor->setColor( lyr.textColor );
254254
mFontTranspSpinBox->setValue( lyr.textTransp );
255255

256+
mFontWordSpacingSpinBox->setValue( lyr.textFont.wordSpacing() );
257+
mFontLetterSpacingSpinBox->setValue( lyr.textFont.letterSpacing() );
258+
256259
updateFontViaStyle( lyr.textNamedStyle );
257260
updateFont( mRefFont );
258261

@@ -728,8 +731,6 @@ void QgsLabelingGui::updateFont( QFont font )
728731
mFontCapitalsComboBox->setCurrentIndex( idx == -1 ? 0 : idx );
729732
mFontUnderlineBtn->setChecked( mRefFont.underline() );
730733
mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
731-
mFontWordSpacingSpinBox->setValue( mRefFont.wordSpacing() );
732-
mFontLetterSpacingSpinBox->setValue( mRefFont.letterSpacing() );
733734
blockFontChangeSignals( false );
734735

735736
// update font name with font face
@@ -1003,27 +1004,16 @@ void QgsLabelingGui::on_mFontLetterSpacingSpinBox_valueChanged( double spacing )
10031004

10041005
void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
10051006
{
1006-
double singleStep = ( index == 1 ) ? 10.0 : 1.0 ; //10 for map units, 1 for mm
1007-
mFontSizeSpinBox->setSingleStep( singleStep );
1008-
mFontWordSpacingSpinBox->setSingleStep( singleStep );
1009-
mFontLetterSpacingSpinBox->setSingleStep( singleStep / 10 );
1007+
Q_UNUSED( index );
10101008
updateFont( mRefFont );
10111009
}
10121010

10131011
void QgsLabelingGui::on_mBufferUnitComboBox_currentIndexChanged( int index )
10141012
{
1015-
double singleStep = ( index == 1 ) ? 1.0 : 0.1 ; //1.0 for map units, 0.1 for mm
1016-
spinBufferSize->setSingleStep( singleStep );
1013+
Q_UNUSED( index );
10171014
updateFont( mRefFont );
10181015
}
10191016

1020-
void QgsLabelingGui::on_mPointOffsetUnitsComboBox_currentIndexChanged( int index )
1021-
{
1022-
double singleStep = ( index == 1 ) ? 1.0 : 0.1 ; //1.0 for map units, 0.1 for mm
1023-
mPointOffsetXOffsetSpinBox->setSingleStep( singleStep );
1024-
mPointOffsetYOffsetSpinBox->setSingleStep( singleStep );
1025-
}
1026-
10271017
void QgsLabelingGui::on_mXCoordinateComboBox_currentIndexChanged( const QString & text )
10281018
{
10291019
if ( text.isEmpty() ) //no data defined alignment without data defined position

src/app/qgslabelinggui.h

-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
6262
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
6363
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
6464
void on_mBufferUnitComboBox_currentIndexChanged( int index );
65-
void on_mPointOffsetUnitsComboBox_currentIndexChanged( int index );
6665
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
6766
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );
6867

src/core/qgspallabeling.cpp

+41-3
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,18 @@ using namespace pal;
5757
class QgsPalGeometry : public PalGeometry
5858
{
5959
public:
60-
QgsPalGeometry( QgsFeatureId id, QString text, GEOSGeometry* g )
60+
QgsPalGeometry( QgsFeatureId id, QString text, GEOSGeometry* g,
61+
qreal ltrSpacing = 0.0, qreal wordSpacing = 0.0, bool curvedLabeling = false )
6162
: mG( g )
6263
, mText( text )
6364
, mId( id )
6465
, mInfo( NULL )
6566
, mIsDiagram( false )
6667
, mIsPinned( false )
6768
, mFontMetrics( NULL )
69+
, mLetterSpacing( ltrSpacing )
70+
, mWordSpacing( wordSpacing )
71+
, mCurvedLabeling( curvedLabeling )
6872
{
6973
mStrId = FID_TO_STRING( id ).toAscii();
7074
}
@@ -102,11 +106,36 @@ class QgsPalGeometry : public PalGeometry
102106
QgsPoint ptZero = xform->toMapCoordinates( 0, 0 );
103107
QgsPoint ptSize = xform->toMapCoordinatesF( 0.0, -fm->height() / fontScale );
104108

109+
// mLetterSpacing/mWordSpacing = 0.0 is default for non-curved labels
110+
// (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
111+
qreal charWidth;
112+
qreal wordSpaceFix;
105113
mInfo = new pal::LabelInfo( mText.count(), ptSize.y() - ptZero.y() );
106114
for ( int i = 0; i < mText.count(); i++ )
107115
{
108116
mInfo->char_info[i].chr = mText[i].unicode();
109-
ptSize = xform->toMapCoordinatesF( fm->width( mText[i] ) / fontScale , 0.0 );
117+
118+
// reconstruct how Qt creates word spacing, then adjust per individual stored character
119+
// this will allow PAL to create each candidate width = character width + correct spacing
120+
charWidth = fm->width( mText[i] );
121+
if ( mCurvedLabeling )
122+
{
123+
wordSpaceFix = qreal( 0.0 );
124+
if ( mText[i] == QString( " " )[0] )
125+
{
126+
// word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
127+
int nxt = i + 1;
128+
wordSpaceFix = ( nxt < mText.count() && mText[nxt] != QString( " " )[0] ) ? mWordSpacing : qreal( 0.0 );
129+
}
130+
if ( fm->width( QString( mText[i] ) ) - fm->width( mText[i] ) - mLetterSpacing != qreal( 0.0 ) )
131+
{
132+
// word spacing applied when it shouldn't be
133+
wordSpaceFix -= mWordSpacing;
134+
}
135+
charWidth = fm->width( QString( mText[i] ) ) + wordSpaceFix;
136+
}
137+
138+
ptSize = xform->toMapCoordinatesF((( double ) charWidth ) / fontScale , 0.0 );
110139
mInfo->char_info[i].width = ptSize.x() - ptZero.x();
111140
}
112141
return mInfo;
@@ -135,6 +164,9 @@ class QgsPalGeometry : public PalGeometry
135164
bool mIsDiagram;
136165
bool mIsPinned;
137166
QFontMetricsF* mFontMetrics;
167+
qreal mLetterSpacing; // for use with curved labels
168+
qreal mWordSpacing; // for use with curved labels
169+
bool mCurvedLabeling; // whether the geometry is to be used for curved labeling placement
138170
/**Stores attribute values for data defined properties*/
139171
QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;
140172

@@ -881,7 +913,13 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
881913
}
882914
}
883915

884-
QgsPalGeometry* lbl = new QgsPalGeometry( f.id(), labelText, geos_geom_clone );
916+
QgsPalGeometry* lbl = new QgsPalGeometry(
917+
f.id(),
918+
labelText,
919+
geos_geom_clone,
920+
labelFont.letterSpacing(),
921+
labelFont.wordSpacing(),
922+
placement == QgsPalLayerSettings::Curved );
885923

886924
// record the created geometry - it will be deleted at the end.
887925
geometries.append( lbl );

0 commit comments

Comments
 (0)