Skip to content

Commit

Permalink
Fix broken rendering of curved labels for scripts which use >1 char
Browse files Browse the repository at this point in the history
graphemes (fix #6883)

Cherry-picked from 2dc5d95
  • Loading branch information
nyalldawson committed Jun 24, 2015
1 parent 174943e commit 71b5a99
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 12 deletions.
3 changes: 1 addition & 2 deletions src/core/dxf/qgsdxfpallabeling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ void QgsDxfPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext&
return;

//label text
QString text = g->text();
QString txt = label->getPartId() == -1 ? text : QString( text[ label->getPartId()] );
QString txt = g->text( label->getPartId() );

//angle
double angle = label->getAlpha() * 180 / M_PI;
Expand Down
43 changes: 35 additions & 8 deletions src/core/qgspalgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "qgsgeometry.h"
#include <pal/feature.h>
#include <pal/palgeometry.h>
#include <QTextBoundaryFinder>

using namespace pal;

Expand Down Expand Up @@ -49,6 +50,19 @@ class QgsPalGeometry : public PalGeometry
const char* strId() { return mStrId.data(); }
QString text() { return mText; }

/** Returns the text component corresponding to a specified label part
* @param partId. Set to -1 for labels which are not broken into parts (eg, non-curved labels), or the required
* part index for labels which are broken into parts (curved labels)
* @note added in QGIS 2.10
*/
QString text( int partId ) const
{
if ( partId == -1 )
return mText;
else
return mClusters.at( partId );
}

pal::LabelInfo* info( QFontMetricsF* fm, const QgsMapToPixel* xform, double fontScale, double maxinangle, double maxoutangle )
{
if ( mInfo )
Expand All @@ -74,29 +88,41 @@ class QgsPalGeometry : public PalGeometry
// (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
qreal charWidth;
qreal wordSpaceFix;
mInfo = new pal::LabelInfo( mText.count(), labelHeight, maxinangle, maxoutangle );
for ( int i = 0; i < mText.count(); i++ )

//split string by valid grapheme boundaries - required for certain scripts (see #6883)
QTextBoundaryFinder boundaryFinder( QTextBoundaryFinder::Grapheme, mText );
int currentBoundary = -1;
int previousBoundary = 0;
while (( currentBoundary = boundaryFinder.toNextBoundary() ) > 0 )
{
mClusters << mText.mid( previousBoundary, currentBoundary - previousBoundary );
previousBoundary = currentBoundary;
}

mInfo = new pal::LabelInfo( mClusters.count(), labelHeight, maxinangle, maxoutangle );
for ( int i = 0; i < mClusters.count(); i++ )
{
mInfo->char_info[i].chr = mText[i].unicode();
//doesn't appear to be used anywhere:
//mInfo->char_info[i].chr = textClusters[i].unicode();

// 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] );
charWidth = fm->width( mClusters[i] );
if ( mCurvedLabeling )
{
wordSpaceFix = qreal( 0.0 );
if ( mText[i] == QString( " " )[0] )
if ( mClusters[i] == QString( " " ) )
{
// 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 );
wordSpaceFix = ( nxt < mClusters.count() && mClusters[nxt] != QString( " " ) ) ? mWordSpacing : qreal( 0.0 );
}
if ( fm->width( QString( mText[i] ) ) - fm->width( mText[i] ) - mLetterSpacing != qreal( 0.0 ) )
if ( fm->width( QString( mClusters[i] ) ) - fm->width( mClusters[i] ) - mLetterSpacing != qreal( 0.0 ) )
{
// word spacing applied when it shouldn't be
wordSpaceFix -= mWordSpacing;
}
charWidth = fm->width( QString( mText[i] ) ) + wordSpaceFix;
charWidth = fm->width( QString( mClusters[i] ) ) + wordSpaceFix;
}

double labelWidth = mapScale * charWidth / fontScale;
Expand Down Expand Up @@ -135,6 +161,7 @@ class QgsPalGeometry : public PalGeometry
protected:
GEOSGeometry* mG;
QString mText;
QStringList mClusters;
QByteArray mStrId;
QgsFeatureId mId;
LabelInfo* mInfo;
Expand Down
3 changes: 1 addition & 2 deletions src/core/qgspallabeling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4324,8 +4324,7 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& con
{

// TODO: optimize access :)
QString text = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->text();
QString txt = ( label->getPartId() == -1 ? text : QString( text[label->getPartId()] ) );
QString txt = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->text( label->getPartId() );
QFontMetricsF* labelfm = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->getLabelFontMetrics();

//add the direction symbol if needed
Expand Down

0 comments on commit 71b5a99

Please sign in to comment.