Skip to content

Commit

Permalink
Add letter and word spacing to curved labels for line layers
Browse files Browse the repository at this point in the history
- 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)
  • Loading branch information
dakcarto committed Nov 8, 2012
1 parent b5a12d3 commit 59fe8fd
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
20 changes: 5 additions & 15 deletions src/app/qgslabelinggui.cpp
Expand Up @@ -253,6 +253,9 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
btnTextColor->setColor( lyr.textColor );
mFontTranspSpinBox->setValue( lyr.textTransp );

mFontWordSpacingSpinBox->setValue( lyr.textFont.wordSpacing() );
mFontLetterSpacingSpinBox->setValue( lyr.textFont.letterSpacing() );

updateFontViaStyle( lyr.textNamedStyle );
updateFont( mRefFont );

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

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

void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
{
double singleStep = ( index == 1 ) ? 10.0 : 1.0 ; //10 for map units, 1 for mm
mFontSizeSpinBox->setSingleStep( singleStep );
mFontWordSpacingSpinBox->setSingleStep( singleStep );
mFontLetterSpacingSpinBox->setSingleStep( singleStep / 10 );
Q_UNUSED( index );
updateFont( mRefFont );
}

void QgsLabelingGui::on_mBufferUnitComboBox_currentIndexChanged( int index )
{
double singleStep = ( index == 1 ) ? 1.0 : 0.1 ; //1.0 for map units, 0.1 for mm
spinBufferSize->setSingleStep( singleStep );
Q_UNUSED( index );
updateFont( mRefFont );
}

void QgsLabelingGui::on_mPointOffsetUnitsComboBox_currentIndexChanged( int index )
{
double singleStep = ( index == 1 ) ? 1.0 : 0.1 ; //1.0 for map units, 0.1 for mm
mPointOffsetXOffsetSpinBox->setSingleStep( singleStep );
mPointOffsetYOffsetSpinBox->setSingleStep( singleStep );
}

void QgsLabelingGui::on_mXCoordinateComboBox_currentIndexChanged( const QString & text )
{
if ( text.isEmpty() ) //no data defined alignment without data defined position
Expand Down
1 change: 0 additions & 1 deletion src/app/qgslabelinggui.h
Expand Up @@ -62,7 +62,6 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
void on_mBufferUnitComboBox_currentIndexChanged( int index );
void on_mPointOffsetUnitsComboBox_currentIndexChanged( int index );
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );

Expand Down
44 changes: 41 additions & 3 deletions src/core/qgspallabeling.cpp
Expand Up @@ -57,14 +57,18 @@ using namespace pal;
class QgsPalGeometry : public PalGeometry
{
public:
QgsPalGeometry( QgsFeatureId id, QString text, GEOSGeometry* g )
QgsPalGeometry( QgsFeatureId id, QString text, GEOSGeometry* g,
qreal ltrSpacing = 0.0, qreal wordSpacing = 0.0, bool curvedLabeling = false )
: mG( g )
, mText( text )
, mId( id )
, mInfo( NULL )
, mIsDiagram( false )
, mIsPinned( false )
, mFontMetrics( NULL )
, mLetterSpacing( ltrSpacing )
, mWordSpacing( wordSpacing )
, mCurvedLabeling( curvedLabeling )
{
mStrId = FID_TO_STRING( id ).toAscii();
}
Expand Down Expand Up @@ -102,11 +106,36 @@ class QgsPalGeometry : public PalGeometry
QgsPoint ptZero = xform->toMapCoordinates( 0, 0 );
QgsPoint ptSize = xform->toMapCoordinatesF( 0.0, -fm->height() / fontScale );

// mLetterSpacing/mWordSpacing = 0.0 is default for non-curved labels
// (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
qreal charWidth;
qreal wordSpaceFix;
mInfo = new pal::LabelInfo( mText.count(), ptSize.y() - ptZero.y() );
for ( int i = 0; i < mText.count(); i++ )
{
mInfo->char_info[i].chr = mText[i].unicode();
ptSize = xform->toMapCoordinatesF( fm->width( mText[i] ) / fontScale , 0.0 );

// reconstruct how Qt creates word spacing, then adjust per individual stored character
// this will allow PAL to create each candidate width = character width + correct spacing
charWidth = fm->width( mText[i] );
if ( mCurvedLabeling )
{
wordSpaceFix = qreal( 0.0 );
if ( mText[i] == QString( " " )[0] )
{
// word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
int nxt = i + 1;
wordSpaceFix = ( nxt < mText.count() && mText[nxt] != QString( " " )[0] ) ? mWordSpacing : qreal( 0.0 );
}
if ( fm->width( QString( mText[i] ) ) - fm->width( mText[i] ) - mLetterSpacing != qreal( 0.0 ) )
{
// word spacing applied when it shouldn't be
wordSpaceFix -= mWordSpacing;
}
charWidth = fm->width( QString( mText[i] ) ) + wordSpaceFix;
}

ptSize = xform->toMapCoordinatesF((( double ) charWidth ) / fontScale , 0.0 );
mInfo->char_info[i].width = ptSize.x() - ptZero.x();
}
return mInfo;
Expand Down Expand Up @@ -135,6 +164,9 @@ class QgsPalGeometry : public PalGeometry
bool mIsDiagram;
bool mIsPinned;
QFontMetricsF* mFontMetrics;
qreal mLetterSpacing; // for use with curved labels
qreal mWordSpacing; // for use with curved labels
bool mCurvedLabeling; // whether the geometry is to be used for curved labeling placement
/**Stores attribute values for data defined properties*/
QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;

Expand Down Expand Up @@ -881,7 +913,13 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
}
}

QgsPalGeometry* lbl = new QgsPalGeometry( f.id(), labelText, geos_geom_clone );
QgsPalGeometry* lbl = new QgsPalGeometry(
f.id(),
labelText,
geos_geom_clone,
labelFont.letterSpacing(),
labelFont.wordSpacing(),
placement == QgsPalLayerSettings::Curved );

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

0 comments on commit 59fe8fd

Please sign in to comment.