QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgspalgeometry.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgspalgeometry.h
3  ---------------------
4  begin : May 2009
5  copyright : (C) 2009 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
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 #ifndef QGSPALGEOMETRY_H
16 #define QGSPALGEOMETRY_H
17 
18 #include "qgsgeometry.h"
19 #include "qgspallabeling.h"
20 #include "pal/feature.h"
21 
22 #include "qgslabelingengine.h"
23 
31 {
32  public:
34  QgsTextLabelFeature( QgsFeatureId id, GEOSGeometry *geometry, const QSizeF &size )
35  : QgsLabelFeature( id, geometry, size )
36  , mFontMetrics( nullptr )
37  {
38  mDefinedFont = QFont();
39  }
40 
43  {
44  delete mFontMetrics;
45  }
46 
53  QString text( int partId ) const
54  {
55  if ( partId == -1 )
56  return mLabelText;
57  else
58  return mClusters.at( partId );
59  }
60 
62  void calculateInfo( bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, double fontScale, double maxinangle, double maxoutangle )
63  {
64  if ( mInfo )
65  return;
66 
67  mFontMetrics = new QFontMetricsF( *fm ); // duplicate metrics for when drawing label
68 
69  qreal letterSpacing = mDefinedFont.letterSpacing();
70  qreal wordSpacing = mDefinedFont.wordSpacing();
71 
72  // max angle between curved label characters (20.0/-20.0 was default in QGIS <= 1.8)
73  if ( maxinangle < 20.0 )
74  maxinangle = 20.0;
75  if ( 60.0 < maxinangle )
76  maxinangle = 60.0;
77  if ( maxoutangle > -20.0 )
78  maxoutangle = -20.0;
79  if ( -95.0 > maxoutangle )
80  maxoutangle = -95.0;
81 
82  // create label info!
83  double mapScale = xform->mapUnitsPerPixel();
84  double labelHeight = mapScale * fm->height() / fontScale;
85 
86  // mLetterSpacing/mWordSpacing = 0.0 is default for non-curved labels
87  // (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
88  qreal charWidth;
89  qreal wordSpaceFix;
90 
91  //split string by valid grapheme boundaries - required for certain scripts (see #6883)
93 
94  mInfo = new pal::LabelInfo( mClusters.count(), labelHeight, maxinangle, maxoutangle );
95  for ( int i = 0; i < mClusters.count(); i++ )
96  {
97  // reconstruct how Qt creates word spacing, then adjust per individual stored character
98  // this will allow PAL to create each candidate width = character width + correct spacing
99  charWidth = fm->width( mClusters[i] );
100  if ( curvedLabeling )
101  {
102  wordSpaceFix = qreal( 0.0 );
103  if ( mClusters[i] == QLatin1String( " " ) )
104  {
105  // word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
106  int nxt = i + 1;
107  wordSpaceFix = ( nxt < mClusters.count() && mClusters[nxt] != QLatin1String( " " ) ) ? wordSpacing : qreal( 0.0 );
108  }
109  // this workaround only works for clusters with a single character. Not sure how it should be handled
110  // with multi-character clusters.
111  if ( mClusters[i].length() == 1 &&
112  !qgsDoubleNear( fm->width( QString( mClusters[i].at( 0 ) ) ), fm->width( mClusters[i].at( 0 ) ) + letterSpacing ) )
113  {
114  // word spacing applied when it shouldn't be
115  wordSpaceFix -= wordSpacing;
116  }
117 
118  charWidth = fm->width( QString( mClusters[i] ) ) + wordSpaceFix;
119  }
120 
121  double labelWidth = mapScale * charWidth / fontScale;
122  mInfo->char_info[i].width = labelWidth;
123  }
124  }
125 
127  const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > &dataDefinedValues() const { return mDataDefinedValues; }
129  void setDataDefinedValues( const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > &values ) { mDataDefinedValues = values; }
130 
132  void setDefinedFont( const QFont &f ) { mDefinedFont = f; }
134  QFont definedFont() { return mDefinedFont; }
135 
137  QFontMetricsF *labelFontMetrics() { return mFontMetrics; }
138 
139  protected:
141  QStringList mClusters;
145  QFontMetricsF *mFontMetrics = nullptr;
147  QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;
148 
149 };
150 
151 #endif //QGSPALGEOMETRY_H
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > & dataDefinedValues() const
Gets data-defined values.
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
pal::LabelInfo * mInfo
extra information for curved labels (may be nullptr)
Class that adds extra information to QgsLabelFeature for text labels.
GEOSGeometry * geometry() const
Gets access to the associated geometry.
void setDefinedFont(const QFont &f)
Sets font to be used for rendering.
CharacterInfo * char_info
Definition: feature.h:83
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues
Stores attribute values for data defined properties.
void setDataDefinedValues(const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > &values)
Sets data-defined values.
Optional additional info about label (for curved labels)
Definition: feature.h:55
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
Returns current map units per pixel.
QSizeF size() const
Size of the label (in map units)
QFont definedFont()
Font to be used for rendering.
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 ...
QFont mDefinedFont
Font for rendering.
QFontMetricsF * labelFontMetrics()
Metrics of the font for rendering.