QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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:280
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.
QFont definedFont()
Font to be used for rendering.
The QgsLabelFeature class describes a feature that should be used within the labeling engine...
QSizeF size(double angle=0.0) const
Size of the label (in map units)
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.