QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgstextlabelfeature.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstextlabelfeature.cpp
3  ---------------------
4  begin : December 2015
5  copyright : (C) 2015 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgstextlabelfeature.h"
17 
18 #include "qgsgeometry.h"
19 #include "qgspallabeling.h"
20 #include <pal/feature.h>
21 
22 
24  : QgsLabelFeature( id, geometry, size )
25  , mFontMetrics( NULL )
26 {
27  mDefinedFont = QFont();
28 }
29 
30 
32 {
33  delete mFontMetrics;
34 }
35 
36 
37 QString QgsTextLabelFeature::text( int partId ) const
38 {
39  if ( partId == -1 )
40  return mLabelText;
41  else
42  return mClusters.at( partId );
43 }
44 
45 
46 void QgsTextLabelFeature::calculateInfo( bool curvedLabeling, QFontMetricsF* fm, const QgsMapToPixel* xform, double fontScale, double maxinangle, double maxoutangle )
47 {
48  if ( mInfo )
49  return;
50 
51  mFontMetrics = new QFontMetricsF( *fm ); // duplicate metrics for when drawing label
52 
53  qreal letterSpacing = mDefinedFont.letterSpacing();
54  qreal wordSpacing = mDefinedFont.wordSpacing();
55 
56  // max angle between curved label characters (20.0/-20.0 was default in QGIS <= 1.8)
57  if ( maxinangle < 20.0 )
58  maxinangle = 20.0;
59  if ( 60.0 < maxinangle )
60  maxinangle = 60.0;
61  if ( maxoutangle > -20.0 )
62  maxoutangle = -20.0;
63  if ( -95.0 > maxoutangle )
64  maxoutangle = -95.0;
65 
66  // create label info!
67  double mapScale = xform->mapUnitsPerPixel();
68  double labelHeight = mapScale * fm->height() / fontScale;
69 
70  // mLetterSpacing/mWordSpacing = 0.0 is default for non-curved labels
71  // (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
72  qreal charWidth;
73  qreal wordSpaceFix;
74 
75  //split string by valid grapheme boundaries - required for certain scripts (see #6883)
77 
78  mInfo = new pal::LabelInfo( mClusters.count(), labelHeight, maxinangle, maxoutangle );
79  for ( int i = 0; i < mClusters.count(); i++ )
80  {
81  // reconstruct how Qt creates word spacing, then adjust per individual stored character
82  // this will allow PAL to create each candidate width = character width + correct spacing
83  charWidth = fm->width( mClusters[i] );
84  if ( curvedLabeling )
85  {
86  wordSpaceFix = qreal( 0.0 );
87  if ( mClusters[i] == QLatin1String( " " ) )
88  {
89  // word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
90  int nxt = i + 1;
91  wordSpaceFix = ( nxt < mClusters.count() && mClusters[nxt] != QLatin1String( " " ) ) ? wordSpacing : qreal( 0.0 );
92  }
93  // this workaround only works for clusters with a single character. Not sure how it should be handled
94  // with multi-character clusters.
95  if ( mClusters[i].length() == 1 &&
96  !qgsDoubleNear( fm->width( QString( mClusters[i].at( 0 ) ) ), fm->width( mClusters[i].at( 0 ) ) + letterSpacing ) )
97  {
98  // word spacing applied when it shouldn't be
99  wordSpaceFix -= wordSpacing;
100  }
101 
102  charWidth = fm->width( QString( mClusters[i] ) ) + wordSpaceFix;
103  }
104 
105  double labelWidth = mapScale * charWidth / fontScale;
106  mInfo->char_info[i].width = labelWidth;
107  }
108 }
QFontMetricsF * mFontMetrics
Metrics of the font for rendering.
QgsTextLabelFeature(QgsFeatureId id, GEOSGeometry *geometry, const QSizeF &size)
Construct text label feature.
QString mLabelText
text of the label
QStringList mClusters
List of graphemes (used for curved labels)
~QgsTextLabelFeature()
Clean up.
const T & at(int i) const
pal::LabelInfo * mInfo
extra information for curved labels (may be null)
qreal width(const QString &text) const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
CharacterInfo * char_info
Definition: feature.h:75
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
int count(const T &value) const
qreal letterSpacing() const
Optional additional info about label (for curved labels)
Definition: feature.h:52
void calculateInfo(bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, double fontScale, double maxinangle, double maxoutangle)
calculate data for info(). setDefinedFont() must have been called already.
QString text(int partId) const
Returns the text component corresponding to a specified label part.
double mapUnitsPerPixel() const
Return current map units per pixel.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
static QStringList splitToGraphemes(const QString &text)
Splits a text string to a list of graphemes, which are the smallest allowable character divisions in ...
qint64 QgsFeatureId
Definition: qgsfeature.h:31
QFont mDefinedFont
Font for rendering.
qreal height() const
qreal wordSpacing() const