4
4
#include " qgsgeometry.h"
5
5
#include < pal/feature.h>
6
6
#include < pal/palgeometry.h>
7
+ #include < QTextBoundaryFinder>
7
8
8
9
using namespace pal ;
9
10
@@ -49,6 +50,19 @@ class QgsPalGeometry : public PalGeometry
49
50
const char * strId () { return mStrId .data (); }
50
51
QString text () { return mText ; }
51
52
53
+ /* * Returns the text component corresponding to a specified label part
54
+ * @param partId. Set to -1 for labels which are not broken into parts (eg, non-curved labels), or the required
55
+ * part index for labels which are broken into parts (curved labels)
56
+ * @note added in QGIS 2.10
57
+ */
58
+ QString text ( int partId ) const
59
+ {
60
+ if ( partId == -1 )
61
+ return mText ;
62
+ else
63
+ return mClusters .at ( partId );
64
+ }
65
+
52
66
pal::LabelInfo* info ( QFontMetricsF* fm, const QgsMapToPixel* xform, double fontScale, double maxinangle, double maxoutangle )
53
67
{
54
68
if ( mInfo )
@@ -74,29 +88,41 @@ class QgsPalGeometry : public PalGeometry
74
88
// (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
75
89
qreal charWidth;
76
90
qreal wordSpaceFix;
77
- mInfo = new pal::LabelInfo ( mText .count (), labelHeight, maxinangle, maxoutangle );
78
- for ( int i = 0 ; i < mText .count (); i++ )
91
+
92
+ // split string by valid grapheme boundaries - required for certain scripts (see #6883)
93
+ QTextBoundaryFinder boundaryFinder ( QTextBoundaryFinder::Grapheme, mText );
94
+ int currentBoundary = -1 ;
95
+ int previousBoundary = 0 ;
96
+ while (( currentBoundary = boundaryFinder.toNextBoundary () ) > 0 )
97
+ {
98
+ mClusters << mText .mid ( previousBoundary, currentBoundary - previousBoundary );
99
+ previousBoundary = currentBoundary;
100
+ }
101
+
102
+ mInfo = new pal::LabelInfo ( mClusters .count (), labelHeight, maxinangle, maxoutangle );
103
+ for ( int i = 0 ; i < mClusters .count (); i++ )
79
104
{
80
- mInfo ->char_info [i].chr = mText [i].unicode ();
105
+ // doesn't appear to be used anywhere:
106
+ // mInfo->char_info[i].chr = textClusters[i].unicode();
81
107
82
108
// reconstruct how Qt creates word spacing, then adjust per individual stored character
83
109
// this will allow PAL to create each candidate width = character width + correct spacing
84
- charWidth = fm->width ( mText [i] );
110
+ charWidth = fm->width ( mClusters [i] );
85
111
if ( mCurvedLabeling )
86
112
{
87
113
wordSpaceFix = qreal ( 0.0 );
88
- if ( mText [i] == QString ( " " )[ 0 ] )
114
+ if ( mClusters [i] == QString ( " " ) )
89
115
{
90
116
// word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
91
117
int nxt = i + 1 ;
92
- wordSpaceFix = ( nxt < mText .count () && mText [nxt] != QString ( " " )[ 0 ] ) ? mWordSpacing : qreal ( 0.0 );
118
+ wordSpaceFix = ( nxt < mClusters .count () && mClusters [nxt] != QString ( " " ) ) ? mWordSpacing : qreal ( 0.0 );
93
119
}
94
- if ( fm->width ( QString ( mText [i] ) ) - fm->width ( mText [i] ) - mLetterSpacing != qreal ( 0.0 ) )
120
+ if ( fm->width ( QString ( mClusters [i] ) ) - fm->width ( mClusters [i] ) - mLetterSpacing != qreal ( 0.0 ) )
95
121
{
96
122
// word spacing applied when it shouldn't be
97
123
wordSpaceFix -= mWordSpacing ;
98
124
}
99
- charWidth = fm->width ( QString ( mText [i] ) ) + wordSpaceFix;
125
+ charWidth = fm->width ( QString ( mClusters [i] ) ) + wordSpaceFix;
100
126
}
101
127
102
128
double labelWidth = mapScale * charWidth / fontScale;
@@ -135,6 +161,7 @@ class QgsPalGeometry : public PalGeometry
135
161
protected:
136
162
GEOSGeometry* mG ;
137
163
QString mText ;
164
+ QStringList mClusters ;
138
165
QByteArray mStrId ;
139
166
QgsFeatureId mId ;
140
167
LabelInfo* mInfo ;
0 commit comments