QGIS API Documentation  3.24.2-Tisler (13c1a02865)
qgsvectorlayerlabeling.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerlabeling.cpp
3  ---------------------
4  begin : September 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 #include "qgsvectorlayerlabeling.h"
16 
17 #include "qgspallabeling.h"
18 #include "qgsrulebasedlabeling.h"
19 #include "qgsvectorlayer.h"
20 #include "qgssymbollayerutils.h"
21 #include "qgssymbollayer.h"
22 #include "qgsmarkersymbollayer.h"
23 #include "qgis.h"
24 #include "qgsstyleentityvisitor.h"
25 #include "qgsmarkersymbol.h"
26 
28 {
29  const QString type = element.attribute( QStringLiteral( "type" ) );
30  if ( type == QLatin1String( "rule-based" ) )
31  {
32  return QgsRuleBasedLabeling::create( element, context );
33  }
34  else if ( type == QLatin1String( "simple" ) )
35  {
36  return QgsVectorLayerSimpleLabeling::create( element, context );
37  }
38  else
39  {
40  return nullptr;
41  }
42 }
43 
45 {
46  return true;
47 }
48 
50 {
52  settings.fieldName = layer->displayField();
53 
54  switch ( layer->geometryType() )
55  {
59  break;
62  break;
65  break;
66 
69  break;
70  }
71  return settings;
72 }
73 
75 {
76  return new QgsVectorLayerLabelProvider( layer, QString(), false, mSettings.get() );
77 }
78 
80  : mSettings( new QgsPalLayerSettings( settings ) )
81 {
82 
83 }
84 
86 {
87  return QStringLiteral( "simple" );
88 }
89 
91 {
92  return new QgsVectorLayerSimpleLabeling( *mSettings );
93 }
94 
95 QDomElement QgsVectorLayerSimpleLabeling::save( QDomDocument &doc, const QgsReadWriteContext &context ) const
96 {
97  QDomElement elem = doc.createElement( QStringLiteral( "labeling" ) );
98  elem.setAttribute( QStringLiteral( "type" ), QStringLiteral( "simple" ) );
99  elem.appendChild( mSettings->writeXml( doc, context ) );
100  return elem;
101 }
102 
104 {
105  Q_UNUSED( providerId )
106  return *mSettings;
107 }
108 
110 {
111  if ( mSettings )
112  {
113  QgsStyleLabelSettingsEntity entity( *mSettings );
114  if ( !visitor->visit( &entity ) )
115  return false;
116  }
117  return true;
118 }
119 
121 {
122  return mSettings->containsAdvancedEffects();
123 }
124 
126 {
127  const QDomElement settingsElem = element.firstChildElement( QStringLiteral( "settings" ) );
128  if ( !settingsElem.isNull() )
129  {
131  settings.readXml( settingsElem, context );
133  }
134 
136 }
137 
139 {
140  double quadOffsetX = 0.5, quadOffsetY = 0.5;
141 
142  // adjust quadrant offset of labels
143  switch ( quadrantPosition )
144  {
146  quadOffsetX = 1;
147  quadOffsetY = 0;
148  break;
150  quadOffsetX = 0.5;
151  quadOffsetY = 0;
152  break;
154  quadOffsetX = 0;
155  quadOffsetY = 0;
156  break;
158  quadOffsetX = 1;
159  quadOffsetY = 0.5;
160  break;
162  quadOffsetX = 0;
163  quadOffsetY = 0.5;
164  break;
166  quadOffsetX = 1;
167  quadOffsetY = 1;
168  break;
170  quadOffsetX = 0.5;
171  quadOffsetY = 1;
172  break;
174  quadOffsetX = 0;
175  quadOffsetY = 1.0;
176  break;
178  break;
179  }
180 
181  return QPointF( quadOffsetX, quadOffsetY );
182 }
183 
184 /*
185  * This is not a generic function encoder, just enough to encode the label case control functions
186  */
187 void appendSimpleFunction( QDomDocument &doc, QDomElement &parent, const QString &name, const QString &attribute )
188 {
189  QDomElement function = doc.createElement( QStringLiteral( "ogc:Function" ) );
190  function.setAttribute( QStringLiteral( "name" ), name );
191  parent.appendChild( function );
192  QDomElement property = doc.createElement( QStringLiteral( "ogc:PropertyName" ) );
193  property.appendChild( doc.createTextNode( attribute ) );
194  function.appendChild( property );
195 }
196 
197 std::unique_ptr<QgsMarkerSymbolLayer> backgroundToMarkerLayer( const QgsTextBackgroundSettings &settings )
198 {
199  std::unique_ptr<QgsMarkerSymbolLayer> layer;
200  switch ( settings.type() )
201  {
203  {
205  svg->setStrokeWidth( settings.strokeWidth() );
206  svg->setStrokeWidthUnit( settings.strokeWidthUnit() );
207  layer.reset( svg );
208  break;
209  }
211  {
212  // just grab the first layer and hope for the best
213  if ( settings.markerSymbol() && settings.markerSymbol()->symbolLayerCount() > 0 )
214  {
215  layer.reset( static_cast< QgsMarkerSymbolLayer * >( settings.markerSymbol()->symbolLayer( 0 )->clone() ) );
216  break;
217  }
218  FALLTHROUGH // not set, just go with the default
219  }
224  {
226  // default value
228  switch ( settings.type() )
229  {
233  break;
237  break;
240  break;
241  }
242 
243  marker->setShape( shape );
244  marker->setStrokeWidth( settings.strokeWidth() );
245  marker->setStrokeWidthUnit( settings.strokeWidthUnit() );
246  layer.reset( marker );
247  }
248  }
249  layer->setEnabled( true );
250  // a marker does not have a size x and y, just a size (and it should be at least one)
251  const QSizeF size = settings.size();
252  layer->setSize( std::max( 1., std::max( size.width(), size.height() ) ) );
253  layer->setSizeUnit( settings.sizeUnit() );
254  // fill and stroke
255  QColor fillColor = settings.fillColor();
256  QColor strokeColor = settings.strokeColor();
257  if ( settings.opacity() < 1 )
258  {
259  const int alpha = std::round( settings.opacity() * 255 );
260  fillColor.setAlpha( alpha );
261  strokeColor.setAlpha( alpha );
262  }
263  layer->setFillColor( fillColor );
264  layer->setStrokeColor( strokeColor );
265  // rotation
267  {
268  layer->setAngle( settings.rotation() );
269  }
270  // offset
271  layer->setOffset( settings.offset() );
272  layer->setOffsetUnit( settings.offsetUnit() );
273 
274  return layer;
275 }
276 
277 void QgsAbstractVectorLayerLabeling::writeTextSymbolizer( QDomNode &parent, QgsPalLayerSettings &settings, const QVariantMap &props ) const
278 {
279  QDomDocument doc = parent.ownerDocument();
280 
281  // text symbolizer
282  QDomElement textSymbolizerElement = doc.createElement( QStringLiteral( "se:TextSymbolizer" ) );
283  parent.appendChild( textSymbolizerElement );
284 
285  // label
286  QgsTextFormat format = settings.format();
287  const QFont font = format.font();
288  QDomElement labelElement = doc.createElement( QStringLiteral( "se:Label" ) );
289  textSymbolizerElement.appendChild( labelElement );
290  if ( settings.isExpression )
291  {
292  labelElement.appendChild( doc.createComment( QStringLiteral( "SE Export for %1 not implemented yet" ).arg( settings.getLabelExpression()->dump() ) ) );
293  labelElement.appendChild( doc.createTextNode( "Placeholder" ) );
294  }
295  else
296  {
297  Qgis::Capitalization capitalization = format.capitalization();
298  if ( capitalization == Qgis::Capitalization::MixedCase && font.capitalization() != QFont::MixedCase )
299  capitalization = static_cast< Qgis::Capitalization >( font.capitalization() );
300  if ( capitalization == Qgis::Capitalization::AllUppercase )
301  {
302  appendSimpleFunction( doc, labelElement, QStringLiteral( "strToUpperCase" ), settings.fieldName );
303  }
304  else if ( capitalization == Qgis::Capitalization::AllLowercase )
305  {
306  appendSimpleFunction( doc, labelElement, QStringLiteral( "strToLowerCase" ), settings.fieldName );
307  }
308  else if ( capitalization == Qgis::Capitalization::ForceFirstLetterToCapital )
309  {
310  appendSimpleFunction( doc, labelElement, QStringLiteral( "strCapitalize" ), settings.fieldName );
311  }
312  else
313  {
314  QDomElement propertyNameElement = doc.createElement( QStringLiteral( "ogc:PropertyName" ) );
315  propertyNameElement.appendChild( doc.createTextNode( settings.fieldName ) );
316  labelElement.appendChild( propertyNameElement );
317  }
318  }
319 
320  // font
321  QDomElement fontElement = doc.createElement( QStringLiteral( "se:Font" ) );
322  textSymbolizerElement.appendChild( fontElement );
323  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-family" ), font.family() ) );
324  const double fontSize = QgsSymbolLayerUtils::rescaleUom( format.size(), format.sizeUnit(), props );
325  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-size" ), QString::number( fontSize ) ) );
326  if ( format.font().italic() )
327  {
328  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-style" ), QStringLiteral( "italic" ) ) );
329  }
330  if ( format.font().bold() )
331  {
332  fontElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "font-weight" ), QStringLiteral( "bold" ) ) );
333  }
334 
335  // label placement
336  QDomElement labelPlacement = doc.createElement( QStringLiteral( "se:LabelPlacement" ) );
337  textSymbolizerElement.appendChild( labelPlacement );
338  double maxDisplacement = 0;
339  double repeatDistance = 0;
340  switch ( settings.placement )
341  {
343  {
344  QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
345  labelPlacement.appendChild( pointPlacement );
346  // anchor point
347  const QPointF anchor = quadOffsetToSldAnchor( settings.quadOffset );
348  QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, anchor );
349  // displacement
350  if ( settings.xOffset > 0 || settings.yOffset > 0 )
351  {
352  const QgsUnitTypes::RenderUnit offsetUnit = settings.offsetUnits;
353  const double dx = QgsSymbolLayerUtils::rescaleUom( settings.xOffset, offsetUnit, props );
354  const double dy = QgsSymbolLayerUtils::rescaleUom( settings.yOffset, offsetUnit, props );
355  QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( dx, dy ) );
356  }
357  // rotation
358  if ( settings.angleOffset != 0 )
359  {
360  QDomElement rotation = doc.createElement( "se:Rotation" );
361  pointPlacement.appendChild( rotation );
362  rotation.appendChild( doc.createTextNode( QString::number( settings.angleOffset ) ) );
363  }
364  }
365  break;
368  {
369  QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
370  labelPlacement.appendChild( pointPlacement );
371 
372  // SLD cannot do either, but let's do a best effort setting the distance using
373  // anchor point and displacement
374  QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0, 0.5 ) );
376  const double radius = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
377  const double offset = std::sqrt( radius * radius / 2 ); // make it start top/right
378  maxDisplacement = radius + 1; // lock the distance
379  QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( offset, offset ) );
380  }
381  break;
385  {
386  // still a point placement (for "free" it's a fallback, there is no SLD equivalent)
387  QDomElement pointPlacement = doc.createElement( "se:PointPlacement" );
388  labelPlacement.appendChild( pointPlacement );
389  QgsSymbolLayerUtils::createAnchorPointElement( doc, pointPlacement, QPointF( 0.5, 0.5 ) );
391  const double dist = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
392  QgsSymbolLayerUtils::createDisplacementElement( doc, pointPlacement, QPointF( 0, dist ) );
393  break;
394  }
398  {
399  QDomElement linePlacement = doc.createElement( "se:LinePlacement" );
400  labelPlacement.appendChild( linePlacement );
401 
402  // perpendicular distance if required
403  if ( settings.dist > 0 )
404  {
406  const double dist = QgsSymbolLayerUtils::rescaleUom( settings.dist, distUnit, props );
407  QDomElement perpendicular = doc.createElement( "se:PerpendicularOffset" );
408  linePlacement.appendChild( perpendicular );
409  perpendicular.appendChild( doc.createTextNode( qgsDoubleToString( dist, 2 ) ) );
410  }
411 
412  // repeat distance if required
413  if ( settings.repeatDistance > 0 )
414  {
415  QDomElement repeat = doc.createElement( "se:Repeat" );
416  linePlacement.appendChild( repeat );
417  repeat.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
418  QDomElement gap = doc.createElement( "se:Gap" );
419  linePlacement.appendChild( gap );
421  gap.appendChild( doc.createTextNode( qgsDoubleToString( repeatDistance, 2 ) ) );
422  }
423 
424  // always generalized
425  QDomElement generalize = doc.createElement( "se:GeneralizeLine" );
426  linePlacement.appendChild( generalize );
427  generalize.appendChild( doc.createTextNode( QStringLiteral( "true" ) ) );
428  }
429  break;
430  }
431 
432  // halo
433  const QgsTextBufferSettings buffer = format.buffer();
434  if ( buffer.enabled() )
435  {
436  QDomElement haloElement = doc.createElement( QStringLiteral( "se:Halo" ) );
437  textSymbolizerElement.appendChild( haloElement );
438 
439  QDomElement radiusElement = doc.createElement( QStringLiteral( "se:Radius" ) );
440  haloElement.appendChild( radiusElement );
441  // the SLD uses a radius, which is actually half of the link thickness the buffer size specifies
442  const double radius = QgsSymbolLayerUtils::rescaleUom( buffer.size(), buffer.sizeUnit(), props ) / 2;
443  radiusElement.appendChild( doc.createTextNode( qgsDoubleToString( radius ) ) );
444 
445  QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
446  haloElement.appendChild( fillElement );
447  fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), buffer.color().name() ) );
448  if ( buffer.opacity() != 1 )
449  {
450  fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( buffer.opacity() ) ) );
451  }
452  }
453 
454  // fill
455  QDomElement fillElement = doc.createElement( QStringLiteral( "se:Fill" ) );
456  textSymbolizerElement.appendChild( fillElement );
457  fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill" ), format.color().name() ) );
458  if ( format.opacity() != 1 )
459  {
460  fillElement.appendChild( QgsSymbolLayerUtils::createSvgParameterElement( doc, QStringLiteral( "fill-opacity" ), QString::number( format.opacity() ) ) );
461  }
462 
463  // background graphic (not supported by SE 1.1, but supported by the GeoTools ecosystem as an extension)
464  const QgsTextBackgroundSettings background = format.background();
465  if ( background.enabled() )
466  {
467  std::unique_ptr<QgsMarkerSymbolLayer> layer = backgroundToMarkerLayer( background );
468  layer->writeSldMarker( doc, textSymbolizerElement, props );
469  }
470 
471  // priority and zIndex, the default values are 0 and 5 in qgis (and between 0 and 10),
472  // in the GeoTools ecosystem there is a single priority value set at 1000 by default
473  if ( settings.priority != 5 || settings.zIndex > 0 )
474  {
475  QDomElement priorityElement = doc.createElement( QStringLiteral( "se:Priority" ) );
476  textSymbolizerElement.appendChild( priorityElement );
477  int priority = 500 + 1000 * settings.zIndex + ( settings.priority - 5 ) * 100;
478  if ( settings.priority == 0 && settings.zIndex > 0 )
479  {
480  // small adjustment to make sure labels in z index n+1 are all above level n despite the priority value
481  priority += 1;
482  }
483  priorityElement.appendChild( doc.createTextNode( QString::number( priority ) ) );
484  }
485 
486  // vendor options for text appearance
487  if ( font.underline() )
488  {
489  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "underlineText" ), QStringLiteral( "true" ) );
490  textSymbolizerElement.appendChild( vo );
491  }
492  if ( font.strikeOut() )
493  {
494  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "strikethroughText" ), QStringLiteral( "true" ) );
495  textSymbolizerElement.appendChild( vo );
496  }
497  // vendor options for text positioning
498  if ( maxDisplacement > 0 )
499  {
500  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxDisplacement" ), qgsDoubleToString( maxDisplacement, 2 ) );
501  textSymbolizerElement.appendChild( vo );
502  }
504  {
505  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "followLine" ), QStringLiteral( "true" ) );
506  textSymbolizerElement.appendChild( vo );
508  {
509  // SLD has no notion for this, the GeoTools ecosystem can only do a single angle
510  const double angle = std::min( std::fabs( settings.maxCurvedCharAngleIn ), std::fabs( settings.maxCurvedCharAngleOut ) );
511  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "maxAngleDelta" ), qgsDoubleToString( angle ) );
512  textSymbolizerElement.appendChild( vo );
513  }
514  }
515  if ( repeatDistance > 0 )
516  {
517  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "repeat" ), qgsDoubleToString( repeatDistance, 2 ) );
518  textSymbolizerElement.appendChild( vo );
519  }
520  // miscellaneous options
521  if ( settings.displayAll )
522  {
523  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "conflictResolution" ), QStringLiteral( "false" ) );
524  textSymbolizerElement.appendChild( vo );
525  }
527  {
528  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "forceLeftToRight" ), QStringLiteral( "false" ) );
529  textSymbolizerElement.appendChild( vo );
530  }
531  if ( settings.lineSettings().mergeLines() )
532  {
533  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "group" ), QStringLiteral( "yes" ) );
534  textSymbolizerElement.appendChild( vo );
535  if ( settings.labelPerPart )
536  {
537  const QDomElement vo = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "labelAllGroup" ), QStringLiteral( "true" ) );
538  textSymbolizerElement.appendChild( vo );
539  }
540  }
541  // background symbol resize handling
542  if ( background.enabled() )
543  {
544  // enable resizing if needed
545  switch ( background.sizeType() )
546  {
548  {
549  QString resizeType;
551  {
552  resizeType = QStringLiteral( "stretch" );
553  }
554  else
555  {
556  resizeType = QStringLiteral( "proportional" );
557  }
558  const QDomElement voResize = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-resize" ), resizeType );
559  textSymbolizerElement.appendChild( voResize );
560 
561  // now hadle margin
562  const QSizeF size = background.size();
563  if ( size.width() > 0 || size.height() > 0 )
564  {
565  double x = QgsSymbolLayerUtils::rescaleUom( size.width(), background.sizeUnit(), props );
566  double y = QgsSymbolLayerUtils::rescaleUom( size.height(), background.sizeUnit(), props );
567  // in case of ellipse qgis pads the size generously to make sure the text is inside the ellipse
568  // the following seems to do the trick and keep visual output similar
569  if ( background.type() == QgsTextBackgroundSettings::ShapeEllipse )
570  {
571  x += fontSize / 2;
572  y += fontSize;
573  }
574  const QString resizeSpec = QString( "%1 %2" ).arg( qgsDoubleToString( x, 2 ), qgsDoubleToString( y, 2 ) );
575  const QDomElement voMargin = QgsSymbolLayerUtils::createVendorOptionElement( doc, QStringLiteral( "graphic-margin" ), resizeSpec );
576  textSymbolizerElement.appendChild( voMargin );
577  }
578  break;
579  }
582  // nothing to do here
583  break;
584  }
585  }
586 }
587 
588 
589 void QgsVectorLayerSimpleLabeling::toSld( QDomNode &parent, const QVariantMap &props ) const
590 {
591 
592  if ( mSettings->drawLabels )
593  {
594  QDomDocument doc = parent.ownerDocument();
595 
596  QDomElement ruleElement = doc.createElement( QStringLiteral( "se:Rule" ) );
597  parent.appendChild( ruleElement );
598 
599  // scale dependencies
600  if ( mSettings->scaleVisibility )
601  {
602  QVariantMap scaleProps = QVariantMap();
603  // tricky here, the max scale is expressed as its denominator, but it's still the max scale
604  // in other words, the smallest scale denominator....
605  scaleProps.insert( "scaleMinDenom", qgsDoubleToString( mSettings->maximumScale ) );
606  scaleProps.insert( "scaleMaxDenom", qgsDoubleToString( mSettings->minimumScale ) );
607  QgsSymbolLayerUtils::applyScaleDependency( doc, ruleElement, scaleProps );
608  }
609 
610  writeTextSymbolizer( ruleElement, *mSettings, props );
611  }
612 
613 
614 }
615 
616 void QgsVectorLayerSimpleLabeling::setSettings( QgsPalLayerSettings *settings, const QString &providerId )
617 {
618  Q_UNUSED( providerId )
619 
620  if ( mSettings.get() == settings )
621  return;
622 
623  mSettings.reset( settings );
624 }
MarkerShape
Marker shapes.
Definition: qgis.h:1042
Capitalization
String capitalization options.
Definition: qgis.h:1236
@ MixedCase
Mixed case, ie no change.
@ AllLowercase
Convert all characters to lowercase.
@ ForceFirstLetterToCapital
Convert just the first letter of each word to uppercase, leave the rest untouched.
@ AllUppercase
Convert all characters to uppercase.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
virtual void writeTextSymbolizer(QDomNode &parent, QgsPalLayerSettings &settings, const QVariantMap &props) const
Writes a TextSymbolizer element contents based on the provided labeling settings.
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Try to create instance of an implementation based on the XML data.
virtual QgsPalLayerSettings settings(const QString &providerId=QString()) const =0
Gets associated label settings.
static QgsPalLayerSettings defaultSettingsForLayer(const QgsVectorLayer *layer)
Returns the default layer settings to use for the specified vector layer.
virtual QString type() const =0
Unique type string of the labeling configuration implementation.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
bool mergeLines() const
Returns true if connected line features with identical label text should be merged prior to generatin...
Abstract base class for marker symbol layers.
Contains settings for how a map layer will be labeled.
double yOffset
Vertical offset of label.
double maxCurvedCharAngleIn
Maximum angle between inside curved label characters (valid range 20.0 to 60.0).
double zIndex
Z-Index of label, where labels with a higher z-index are rendered on top of labels with a lower z-ind...
bool displayAll
If true, all features will be labelled even when overlaps occur.
double xOffset
Horizontal offset of label.
QgsExpression * getLabelExpression()
Returns the QgsExpression for this label settings.
QuadrantPosition quadOffset
Sets the quadrant in which to offset labels from feature.
@ ShowAll
Show upside down for all labels, including dynamic ones.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
QgsUnitTypes::RenderUnit offsetUnits
Units for offsets of label.
double repeatDistance
Distance for repeating labels for a single feature.
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ Free
Arranges candidates scattered throughout a polygon feature. Candidates are rotated to respect the pol...
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
@ OrderedPositionsAroundPoint
Candidates are placed in predefined positions around a point. Preference is given to positions with g...
@ OutsidePolygons
Candidates are placed outside of polygon boundaries. Applies to polygon layers only....
int priority
Label priority.
bool labelPerPart
true if every part of a multi-part feature should be labeled.
QgsUnitTypes::RenderUnit distUnits
Units the distance from feature to the label.
QgsUnitTypes::RenderUnit repeatDistanceUnit
Units for repeating labels for a single feature.
OffsetType offsetType
Offset type for layer (only applies in certain placement modes)
double angleOffset
Label rotation, in degrees clockwise.
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0)
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
@ FromSymbolBounds
Offset distance applies from rendered symbol bounds.
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
double dist
Distance from feature to the label.
const QgsTextFormat & format() const
Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
UpsideDownLabels upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
QString fieldName
Name of field (or an expression) to use for label text.
The class is used as a container of context for various read/write operations on other objects.
static QgsRuleBasedLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Create the instance from a DOM element with saved configuration.
void setShape(Qgis::MarkerShape shape)
Sets the rendered marker shape.
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke.
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit u)
Sets the unit for the width of the marker's stroke.
void setStrokeWidth(double w)
Sets the width of the marker's stroke.
An interface for classes which can visit style entity (e.g.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A label settings entity for QgsStyle databases.
Definition: qgsstyle.h:1315
void setStrokeWidthUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the stroke width.
static void createAnchorPointElement(QDomDocument &doc, QDomElement &element, QPointF anchor)
Creates a SE 1.1 anchor point element as a child of the specified element.
static void applyScaleDependency(QDomDocument &doc, QDomElement &ruleElem, QVariantMap &props)
Checks if the properties contain scaleMinDenom and scaleMaxDenom, if available, they are added into t...
static double rescaleUom(double size, QgsUnitTypes::RenderUnit unit, const QVariantMap &props)
Rescales the given size based on the uomScale found in the props, if any is found,...
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
static void createDisplacementElement(QDomDocument &doc, QDomElement &element, QPointF offset)
static QDomElement createSvgParameterElement(QDomDocument &doc, const QString &name, const QString &value)
virtual QgsSymbolLayer * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:420
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:160
Container for settings relating to a text background object.
RotationType rotationType() const
Returns the method used for rotating the background shape.
QString svgFile() const
Returns the absolute path to the background SVG file, if set.
QSizeF size() const
Returns the size of the background shape.
QgsUnitTypes::RenderUnit strokeWidthUnit() const
Returns the units used for the shape's stroke width.
@ SizePercent
Shape size is determined by percent of text size.
@ SizeBuffer
Shape size is determined by adding a buffer margin around text.
bool enabled() const
Returns whether the background is enabled.
double opacity() const
Returns the background shape's opacity.
QgsUnitTypes::RenderUnit offsetUnit() const
Returns the units used for the shape's offset.
double rotation() const
Returns the rotation for the background shape, in degrees clockwise.
QColor fillColor() const
Returns the color used for filing the background shape.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
ShapeType type() const
Returns the type of background shape (e.g., square, ellipse, SVG).
double strokeWidth() const
Returns the width of the shape's stroke (stroke).
@ ShapeSquare
Square - buffered sizes only.
QColor strokeColor() const
Returns the color used for outlining the background shape.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
@ RotationFixed
Shape rotation is a fixed angle.
QgsMarkerSymbol * markerSymbol() const
Returns the marker symbol to be rendered in the background.
QPointF offset() const
Returns the offset used for drawing the background shape.
Container for settings relating to a text buffer.
double size() const
Returns the size of the buffer.
bool enabled() const
Returns whether the buffer is enabled.
double opacity() const
Returns the buffer opacity.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
QColor color() const
Returns the color of the buffer.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
Qgis::Capitalization capitalization() const
Returns the text capitalization style.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
double opacity() const
Returns the text's opacity.
double size() const
Returns the size for rendered text.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:168
The QgsVectorLayerLabelProvider class implements a label provider for vector layers.
Basic implementation of the labeling interface.
QString type() const override
Unique type string of the labeling configuration implementation.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
QgsPalLayerSettings settings(const QString &providerId=QString()) const override
Gets associated label settings.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Returns labeling configuration as XML element.
bool requiresAdvancedEffects() const override
Returns true if drawing labels requires advanced effects like composition modes, which could prevent ...
QgsVectorLayerSimpleLabeling(const QgsPalLayerSettings &settings)
Constructs simple labeling configuration with given initial settings.
void setSettings(QgsPalLayerSettings *settings, const QString &providerId=QString()) override
Set pal settings (takes ownership).
QgsVectorLayerLabelProvider * provider(QgsVectorLayer *layer) const override
static QgsVectorLayerSimpleLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Create the instance from a DOM element with saved configuration.
QgsAbstractVectorLayerLabeling * clone() const override
Returns a new copy of the object.
void toSld(QDomNode &parent, const QVariantMap &props) const override
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
#define FALLTHROUGH
Definition: qgis.h:2092
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:1530
void appendSimpleFunction(QDomDocument &doc, QDomElement &parent, const QString &name, const QString &attribute)
QPointF quadOffsetToSldAnchor(QgsPalLayerSettings::QuadrantPosition quadrantPosition)
std::unique_ptr< QgsMarkerSymbolLayer > backgroundToMarkerLayer(const QgsTextBackgroundSettings &settings)