QGIS API Documentation  2.8.6-Wien
qgspalgeometry.h
Go to the documentation of this file.
1 #ifndef QGSPALGEOMETRY_H
2 #define QGSPALGEOMETRY_H
3 
4 #include "qgsgeometry.h"
5 #include <pal/feature.h>
6 #include <pal/palgeometry.h>
7 #include <QTextBoundaryFinder>
8 
9 using namespace pal;
10 
12 {
13  public:
14  QgsPalGeometry( QgsFeatureId id, QString text, GEOSGeometry* g,
15  qreal ltrSpacing = 0.0, qreal wordSpacing = 0.0, bool curvedLabeling = false )
16  : mG( g )
17  , mText( text )
18  , mId( id )
19  , mInfo( NULL )
20  , mIsDiagram( false )
21  , mIsPinned( false )
22  , mFontMetrics( NULL )
23  , mLetterSpacing( ltrSpacing )
24  , mWordSpacing( wordSpacing )
25  , mCurvedLabeling( curvedLabeling )
26  {
27  mStrId = FID_TO_STRING( mId ).toAscii();
28  mDefinedFont = QFont();
29  }
30 
32  {
33  if ( mG )
34  GEOSGeom_destroy_r( QgsGeometry::getGEOSHandler(), mG );
35  delete mInfo;
36  delete mFontMetrics;
37  }
38 
39  // getGeosGeometry + releaseGeosGeometry is called twice: once when adding, second time when labeling
40 
41  const GEOSGeometry* getGeosGeometry() override
42  {
43  return mG;
44  }
45  void releaseGeosGeometry( const GEOSGeometry* /*geom*/ ) override
46  {
47  // nothing here - we'll delete the geometry in destructor
48  }
49 
50  const char* strId() { return mStrId.data(); }
51  QString text() { return mText; }
52 
58  QString text( int partId ) const
59  {
60  if ( partId == -1 )
61  return mText;
62  else
63  return mClusters.at( partId );
64  }
65 
66  pal::LabelInfo* info( QFontMetricsF* fm, const QgsMapToPixel* xform, double fontScale, double maxinangle, double maxoutangle )
67  {
68  if ( mInfo )
69  return mInfo;
70 
71  mFontMetrics = new QFontMetricsF( *fm ); // duplicate metrics for when drawing label
72 
73  // max angle between curved label characters (20.0/-20.0 was default in QGIS <= 1.8)
74  if ( maxinangle < 20.0 )
75  maxinangle = 20.0;
76  if ( 60.0 < maxinangle )
77  maxinangle = 60.0;
78  if ( maxoutangle > -20.0 )
79  maxoutangle = -20.0;
80  if ( -95.0 > maxoutangle )
81  maxoutangle = -95.0;
82 
83  // create label info!
84  double mapScale = xform->mapUnitsPerPixel();
85  double labelHeight = mapScale * fm->height() / fontScale;
86 
87  // mLetterSpacing/mWordSpacing = 0.0 is default for non-curved labels
88  // (non-curved spacings handled by Qt in QgsPalLayerSettings/QgsPalLabeling)
89  qreal charWidth;
90  qreal wordSpaceFix;
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++ )
104  {
105  //doesn't appear to be used anywhere:
106  //mInfo->char_info[i].chr = textClusters[i].unicode();
107 
108  // reconstruct how Qt creates word spacing, then adjust per individual stored character
109  // this will allow PAL to create each candidate width = character width + correct spacing
110  charWidth = fm->width( mClusters[i] );
111  if ( mCurvedLabeling )
112  {
113  wordSpaceFix = qreal( 0.0 );
114  if ( mClusters[i] == QString( " " ) )
115  {
116  // word spacing only gets added once at end of consecutive run of spaces, see QTextEngine::shapeText()
117  int nxt = i + 1;
118  wordSpaceFix = ( nxt < mClusters.count() && mClusters[nxt] != QString( " " ) ) ? mWordSpacing : qreal( 0.0 );
119  }
120  // this workaround only works for clusters with a single character. Not sure how it should be handled
121  // with multi-character clusters.
122  if ( mClusters[i].length() == 1 &&
123  !qgsDoubleNear( fm->width( QString( mClusters[i].at( 0 ) ) ), fm->width( mClusters[i].at( 0 ) ) + mLetterSpacing ) )
124  {
125  // word spacing applied when it shouldn't be
126  wordSpaceFix -= mWordSpacing;
127  }
128 
129  charWidth = fm->width( QString( mClusters[i] ) ) + wordSpaceFix;
130  }
131 
132  double labelWidth = mapScale * charWidth / fontScale;
133  mInfo->char_info[i].width = labelWidth;
134  }
135  return mInfo;
136  }
137 
138  const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& dataDefinedValues() const { return mDataDefinedValues; }
139  void addDataDefinedValue( QgsPalLayerSettings::DataDefinedProperties p, QVariant v ) { mDataDefinedValues.insert( p, v ); }
140 
141  void setIsDiagram( bool d ) { mIsDiagram = d; }
142  bool isDiagram() const { return mIsDiagram; }
143 
144  void setIsPinned( bool f ) { mIsPinned = f; }
145  bool isPinned() const { return mIsPinned; }
146 
147  void setDefinedFont( QFont f ) { mDefinedFont = QFont( f ); }
148  QFont definedFont() { return mDefinedFont; }
149 
150  QFontMetricsF* getLabelFontMetrics() { return mFontMetrics; }
151 
152  void setDiagramAttributes( const QgsAttributes& attrs ) { mDiagramAttributes = attrs; }
153  const QgsAttributes& diagramAttributes() { return mDiagramAttributes; }
154 
155  void feature( QgsFeature& feature )
156  {
157  feature.setFeatureId( mId );
158  feature.setAttributes( mDiagramAttributes );
159  feature.setValid( true );
160  }
161 
162  void setDxfLayer( QString dxfLayer ) { mDxfLayer = dxfLayer; }
163  QString dxfLayer() const { return mDxfLayer; }
164 
165  protected:
166  GEOSGeometry* mG;
167  QString mText;
168  QStringList mClusters;
169  QByteArray mStrId;
173  bool mIsPinned;
175  QFontMetricsF* mFontMetrics;
176  qreal mLetterSpacing; // for use with curved labels
177  qreal mWordSpacing; // for use with curved labels
178  bool mCurvedLabeling; // whether the geometry is to be used for curved labeling placement
180  QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;
181 
184 
185  QString mDxfLayer;
186 };
187 
188 #endif //QGSPALGEOMETRY_H
const GEOSGeometry * getGeosGeometry() override
get the GEOSGeometry of the feature This method is called by Pal each time it needs a geom&#39;s coordina...
void addDataDefinedValue(QgsPalLayerSettings::DataDefinedProperties p, QVariant v)
void setDxfLayer(QString dxfLayer)
const QgsAttributes & diagramAttributes()
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:83
void setAttributes(const QgsAttributes &attrs)
Definition: qgsfeature.h:187
QString text(int partId) const
Returns the text component corresponding to a specified label part.
void setIsDiagram(bool d)
QFontMetricsF * getLabelFontMetrics()
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:156
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:330
QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues
Stores attribute values for data defined properties.
QByteArray mStrId
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > & dataDefinedValues() const
void setFeatureId(QgsFeatureId id)
Set the feature id for this feature.
Definition: qgsfeature.cpp:128
QString dxfLayer() const
optional additional info about label (for curved labels)
Definition: feature.h:52
GEOSGeometry * mG
double mapUnitsPerPixel() const
Return current map units per pixel.
QgsPalGeometry(QgsFeatureId id, QString text, GEOSGeometry *g, qreal ltrSpacing=0.0, qreal wordSpacing=0.0, bool curvedLabeling=false)
void setDiagramAttributes(const QgsAttributes &attrs)
const char * strId()
void releaseGeosGeometry(const GEOSGeometry *) override
Called by Pal when it doesn&#39;t need the coordinates anymore.
void setValid(bool validity)
Set the validity of the feature.
Definition: qgsfeature.cpp:176
void setIsPinned(bool f)
bool isPinned() const
void setDefinedFont(QFont f)
static GEOSContextHandle_t getGEOSHandler()
return GEOS context handle
QgsAttributes mDiagramAttributes
Stores attribute values for diagram rendering.
QString text()
qint64 QgsFeatureId
Definition: qgsfeature.h:30
bool isDiagram() const
Interface that allows Pal to access user&#39;s geometries.
Definition: palgeometry.h:42
LabelInfo * mInfo
QgsFeatureId mId
A vector of attributes.
Definition: qgsfeature.h:103
void feature(QgsFeature &feature)
QFontMetricsF * mFontMetrics
QStringList mClusters
pal::LabelInfo * info(QFontMetricsF *fm, const QgsMapToPixel *xform, double fontScale, double maxinangle, double maxoutangle)