QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgslabel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslabel.cpp - render vector labels
3  -------------------
4  begin : August 2004
5  copyright : (C) 2004 by Radim Blazek
6  email : [email protected]
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include <cmath>
18 #include <limits>
19 
20 #include <QString>
21 #include <QFont>
22 #include <QFontMetrics>
23 
24 #include <QPainter>
25 #include <QDomNode>
26 #include <QDomElement>
27 
28 #include "qgis.h"
29 #include "qgsfeature.h"
30 #include "qgsgeometry.h"
31 #include "qgsfield.h"
32 #include "qgslogger.h"
33 #include "qgsrectangle.h"
34 #include "qgsmaptopixel.h"
35 #include "qgscoordinatetransform.h"
36 #include "qgsrendercontext.h"
37 
38 #include "qgslabelattributes.h"
39 #include "qgslabel.h"
40 
41 // use M_PI define PI 3.141592654
42 #ifdef Q_OS_WIN
43 #undef M_PI
44 #define M_PI 4*atan(1.0)
45 #endif
46 
47 QgsLabel::QgsLabel( const QgsFields & fields )
48  : mMinScale( 0 )
49  , mMaxScale( 100000000 )
50  , mScaleBasedVisibility( false )
51 {
52  mFields = fields;
53  mLabelFieldIdx.resize( LabelFieldCount );
54  for ( int i = 0; i < LabelFieldCount; i++ )
55  {
56  mLabelFieldIdx[i] = -1;
57  }
58  mLabelAttributes = new QgsLabelAttributes( true );
59 }
60 
62 {
63  delete mLabelAttributes;
64 }
65 
67 {
68  int idx = mLabelFieldIdx[attr];
69  return idx < 0 ? QString() : feature.attribute( idx ).toString();
70 }
71 
73  QgsFeature &feature, bool selected,
74  QgsLabelAttributes *classAttributes )
75 {
76  Q_UNUSED( classAttributes );
77 
78  if ( mLabelAttributes->selectedOnly() && !selected )
79  return;
80 
81  QPen pen;
82  QFont font;
83  QString value;
84  QString text;
85 
86  /* Calc scale (not nice) */
87  QgsPoint point;
88  point = renderContext.mapToPixel().transform( 0, 0 );
89  double x1 = point.x();
90  point = renderContext.mapToPixel().transform( 1000, 0 );
91  double x2 = point.x();
92  double scale = ( x2 - x1 ) * 0.001;
93 
94  /* Text */
95  value = fieldValue( Text, feature );
96  if ( value.isEmpty() )
97  {
98  text = mLabelAttributes->text();
99  }
100  else
101  {
102  text = value;
103  }
104 
105  /* Font */
106  value = fieldValue( Family, feature );
107  if ( value.isEmpty() )
108  {
109  font.setFamily( mLabelAttributes->family() );
110  }
111  else
112  {
113  font.setFamily( value );
114  }
115 
116  double size;
117  value = fieldValue( Size, feature );
118  if ( value.isEmpty() )
119  {
120  size = mLabelAttributes->size();
121  }
122  else
123  {
124  size = value.toDouble();
125  }
126  int sizeType;
127  value = fieldValue( SizeType, feature );
128  if ( value.isEmpty() )
129  sizeType = mLabelAttributes->sizeType();
130  else
131  {
132  value = value.toLower();
133  if ( value.compare( "mapunits" ) == 0 )
134  sizeType = QgsLabelAttributes::MapUnits;
135  else
137  }
138  if ( sizeType == QgsLabelAttributes::MapUnits )
139  {
140  size *= scale;
141  }
142  else //point units
143  {
144  double sizeMM = size * 0.3527;
145  size = sizeMM * renderContext.scaleFactor();
146  }
147 
148  //Request font larger (multiplied by rasterScaleFactor) as a workaround for the Qt font bug
149  //and scale the painter down by rasterScaleFactor when drawing the label
150  size *= renderContext.rasterScaleFactor();
151 
152  if ( static_cast< int >( size ) <= 0 )
153  // skip too small labels
154  return;
155 
156  font.setPixelSize( size );
157 
158  value = fieldValue( Color, feature );
159  if ( value.isEmpty() )
160  {
161  pen.setColor( mLabelAttributes->color() );
162  }
163  else
164  {
165  pen.setColor( QColor( value ) );
166  }
167 
168  value = fieldValue( Bold, feature );
169  if ( value.isEmpty() )
170  {
171  font.setBold( mLabelAttributes->bold() );
172  }
173  else
174  {
175  font.setBold( static_cast< bool >( value.toInt() ) );
176  }
177 
178  value = fieldValue( Italic, feature );
179  if ( value.isEmpty() )
180  {
181  font.setItalic( mLabelAttributes->italic() );
182  }
183  else
184  {
185  font.setItalic( static_cast< bool >( value.toInt() ) );
186  }
187 
188  value = fieldValue( Underline, feature );
189  if ( value.isEmpty() )
190  {
191  font.setUnderline( mLabelAttributes->underline() );
192  }
193  else
194  {
195  font.setUnderline( static_cast< bool >( value.toInt() ) );
196  }
197 
198  value = fieldValue( StrikeOut, feature );
199  if ( value.isEmpty() )
200  {
201  font.setStrikeOut( mLabelAttributes->strikeOut() );
202  }
203  else
204  {
205  font.setStrikeOut( static_cast< bool >( value.toInt() ) );
206  }
207 
208  //
209  QgsPoint overridePoint;
210  bool useOverridePoint = false;
211  value = fieldValue( XCoordinate, feature );
212  if ( !value.isEmpty() )
213  {
214  overridePoint.setX( value.toDouble() );
215  useOverridePoint = true;
216  }
217  value = fieldValue( YCoordinate, feature );
218  if ( !value.isEmpty() )
219  {
220  overridePoint.setY( value.toDouble() );
221  useOverridePoint = true;
222  }
223 
224  /* Alignment */
225  int alignment;
226  QFontMetrics fm( font );
227  int width, height;
228 
229  if ( mLabelAttributes->multilineEnabled() )
230  {
231  QStringList texts = text.split( '\n' );
232 
233  width = 0;
234  for ( int i = 0; i < texts.size(); i++ )
235  {
236  int w = fm.width( texts[i] );
237  if ( w > width )
238  width = w;
239  }
240 
241  height = fm.height() * texts.size();
242  }
243  else
244  {
245  width = fm.width( text );
246  height = fm.height();
247  }
248 
249  int dx = 0;
250  int dy = 0;
251 
252  value = fieldValue( Alignment, feature );
253  if ( value.isEmpty() )
254  {
255  alignment = mLabelAttributes->alignment();
256  }
257  else
258  {
259  value = value.toLower();
260 
261  alignment = 0;
262 
263  if ( value.contains( "left" ) )
264  alignment |= Qt::AlignLeft;
265  else if ( value.contains( "right" ) )
266  alignment |= Qt::AlignRight;
267  else
268  alignment |= Qt::AlignHCenter;
269 
270  if ( value.contains( "bottom" ) )
271  alignment |= Qt::AlignBottom;
272  else if ( value.contains( "top" ) )
273  alignment |= Qt::AlignTop;
274  else
275  alignment |= Qt::AlignVCenter;
276  }
277 
278  if ( alignment & Qt::AlignLeft )
279  {
280  dx = 0;
281  }
282  else if ( alignment & Qt::AlignHCenter )
283  {
284  dx = -width / 2;
285  }
286  else if ( alignment & Qt::AlignRight )
287  {
288  dx = -width;
289  }
290 
291  if ( alignment & Qt::AlignBottom )
292  {
293  dy = 0;
294  }
295  else if ( alignment & Qt::AlignVCenter )
296  {
297  dy = height / 2;
298  }
299  else if ( alignment & Qt::AlignTop )
300  {
301  dy = height;
302  }
303 
304  // Offset
305  double xoffset, yoffset;
306  value = fieldValue( XOffset, feature );
307  if ( value.isEmpty() )
308  {
309  xoffset = mLabelAttributes->xOffset();
310  }
311  else
312  {
313  xoffset = value.toDouble();
314  }
315  value = fieldValue( YOffset, feature );
316  if ( value.isEmpty() )
317  {
318  yoffset = mLabelAttributes->yOffset();
319  }
320  else
321  {
322  yoffset = value.toDouble();
323  }
324 
325  // recalc offset to pixels
326  if ( mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits )
327  {
328  xoffset *= scale;
329  yoffset *= scale;
330  }
331  else
332  {
333  xoffset = xoffset * 0.3527 * renderContext.scaleFactor();
334  yoffset = yoffset * 0.3527 * renderContext.scaleFactor();
335  }
336 
337  // Angle
338  double ang;
339  value = fieldValue( Angle, feature );
340  if ( value.isEmpty() )
341  {
342  ang = mLabelAttributes->angle();
343  }
344  else
345  {
346  ang = value.toDouble();
347  }
348 
349 
350  // Work out a suitable position to put the label for the
351  // feature. For multi-geometries, put the same label on each
352  // part.
353  if ( useOverridePoint )
354  {
355  renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
356  xoffset, yoffset, ang, width, height, alignment );
357  }
358  else
359  {
360  std::vector<labelpoint> points;
361  labelPoint( points, feature );
362  for ( uint i = 0; i < points.size(); ++i )
363  {
364  renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
365  xoffset, yoffset, mLabelAttributes->angleIsAuto() ? points[i].angle : ang, width, height, alignment );
366  }
367  }
368 }
369 
370 void QgsLabel::renderLabel( QgsRenderContext &renderContext,
371  QgsPoint point,
372  const QString& text, const QFont& font, const QPen& pen,
373  int dx, int dy,
374  double xoffset, double yoffset,
375  double ang,
376  int width, int height, int alignment )
377 {
378  QPainter *painter = renderContext.painter();
379 
380  // Convert point to projected units
381  if ( renderContext.coordinateTransform() )
382  {
383  try
384  {
385  point = renderContext.coordinateTransform()->transform( point );
386  }
387  catch ( QgsCsException &cse )
388  {
389  Q_UNUSED( cse ); // unused otherwise
390  QgsDebugMsg( "Caught transform error. Skipping rendering this label" );
391  return;
392  }
393  }
394 
395  // and then to canvas units
396  renderContext.mapToPixel().transform( &point );
397  double x = point.x();
398  double y = point.y();
399 
400  double rad = ang * M_PI / 180;
401 
402  x = x + xoffset * cos( rad ) - yoffset * sin( rad );
403  y = y - xoffset * sin( rad ) - yoffset * cos( rad );
404 
405  painter->save();
406  painter->setFont( font );
407  painter->translate( x, y );
408  //correct oversampled font size back by scaling painter down
409  painter->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
410  painter->rotate( -ang );
411 
412  //
413  // Draw a buffer behind the text if one is desired
414  //
415  if ( mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled() )
416  {
417  double myBufferSize = mLabelAttributes->bufferSize() * 0.3527 * renderContext.scaleFactor() * renderContext.rasterScaleFactor();
418  QPen bufferPen;
419  if ( mLabelAttributes->bufferColorIsSet() )
420  {
421  bufferPen.setColor( mLabelAttributes->bufferColor() );
422  }
423  else //default to a white buffer
424  {
425  bufferPen.setColor( Qt::white );
426  }
427  painter->setPen( bufferPen );
428 
429  double bufferStepSize; //hack to distinguish pixel devices from logical devices
430  if (( renderContext.scaleFactor() - 1 ) > 1.5 )
431  {
432  bufferStepSize = 1;
433  }
434  else //draw more dense in case of logical devices
435  {
436  bufferStepSize = 1 / renderContext.rasterScaleFactor();
437  }
438 
439  for ( double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize )
440  {
441  for ( double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize )
442  {
443  if ( mLabelAttributes->multilineEnabled() )
444  painter->drawText( QRectF( i, j - height, width, height ), alignment, text );
445  else
446  painter->drawText( QPointF( i, j ), text );
447  }
448  }
449  }
450 
451  painter->setPen( pen );
452  if ( mLabelAttributes->multilineEnabled() )
453  painter->drawText( dx, dy - height, width, height, alignment, text );
454  else
455  painter->drawText( dx, dy, text );
456  painter->restore();
457 }
458 
460 {
461  for ( uint i = 0; i < LabelFieldCount; i++ )
462  {
463  if ( mLabelFieldIdx[i] == -1 )
464  continue;
465  bool found = false;
466  for ( QgsAttributeList::iterator it = fields.begin(); it != fields.end(); ++it )
467  {
468  if ( *it == mLabelFieldIdx[i] )
469  {
470  found = true;
471  break;
472  }
473  }
474  if ( !found )
475  {
476  fields.append( mLabelFieldIdx[i] );
477  }
478  }
479 }
480 
482 {
483  mFields = fields;
484 }
485 
487 {
488  return mFields;
489 }
490 
491 void QgsLabel::setLabelField( int attr, int fieldIndex )
492 {
493  if ( attr >= LabelFieldCount )
494  return;
495 
496  mLabelFieldIdx[attr] = fieldIndex;
497 }
498 
499 QString QgsLabel::labelField( int attr ) const
500 {
501  if ( attr >= LabelFieldCount )
502  return QString();
503 
504  int fieldIndex = mLabelFieldIdx[attr];
505  if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
506  return QString();
507  return mFields.at( fieldIndex ).name();
508 }
509 
511 {
512  return mLabelAttributes;
513 }
514 
515 void QgsLabel::labelPoint( std::vector<labelpoint>& points, QgsFeature & feature )
516 {
517  const QgsGeometry *geometry = feature.constGeometry();
518  const unsigned char *geom = geometry->asWkb();
519  size_t geomlen = geometry->wkbSize();
520  QGis::WkbType wkbType = geometry->wkbType();
521  labelpoint point;
522 
523  switch ( wkbType )
524  {
525  case QGis::WKBPoint25D:
526  case QGis::WKBPoint:
528  case QGis::WKBLineString:
529  case QGis::WKBPolygon25D:
530  case QGis::WKBPolygon:
531  {
532  labelPoint( point, geom, geomlen );
533  points.push_back( point );
534  }
535  break;
536 
538  case QGis::WKBMultiPoint:
543  // Return a position for each individual in the multi-feature
544  {
545  Q_ASSERT( 1 + sizeof( wkbType ) + sizeof( int ) <= geomlen );
546  geom += 1 + sizeof( wkbType );
547  int nFeatures = *( reinterpret_cast< const unsigned int * >( geom ) );
548  geom += sizeof( int );
549 
550  const unsigned char *feature = geom;
551  for ( int i = 0; i < nFeatures && feature; ++i )
552  {
553  feature = labelPoint( point, feature, geom + geomlen - feature );
554  points.push_back( point );
555  }
556  }
557  break;
558  default:
559  QgsDebugMsg( "Unknown geometry type of " + QString::number( wkbType ) );
560  }
561 }
562 
563 const unsigned char* QgsLabel::labelPoint( labelpoint& point, const unsigned char *geom, size_t geomlen )
564 {
565  // verify that local types match sizes as WKB spec
566  Q_ASSERT( sizeof( int ) == 4 );
567  Q_ASSERT( sizeof( QGis::WkbType ) == 4 );
568  Q_ASSERT( sizeof( double ) == 8 );
569 
570  if ( !geom )
571  {
572  QgsDebugMsg( "empty wkb" );
573  return nullptr;
574  }
575 
576  QGis::WkbType wkbType;
577 #ifndef QT_NO_DEBUG
578  const unsigned char *geomend = geom + geomlen;
579  Q_ASSERT( geom + 1 + sizeof( wkbType ) <= geomend );
580 #else
581  Q_UNUSED( geomlen );
582 #endif
583 
584  geom++; // skip endianness
585  memcpy( &wkbType, geom, sizeof( wkbType ) );
586  geom += sizeof( wkbType );
587 
588  int dims = 2;
589 
590  switch ( wkbType )
591  {
592  case QGis::WKBPoint25D:
593  case QGis::WKBPoint:
594  {
595 #ifndef QT_NO_DEBUG
596  Q_ASSERT( geom + 2*sizeof( double ) <= geomend );
597 #endif
598  const double *pts = reinterpret_cast< const double * >( geom );
599  point.p.set( pts[0], pts[1] );
600  point.angle = 0.0;
601  geom += 2 * sizeof( double );
602  }
603  break;
604 
606  dims = 3;
607  //intentional fall-through
608  FALLTHROUGH;
609  case QGis::WKBLineString: // Line center
610  {
611 #ifndef QT_NO_DEBUG
612  Q_ASSERT( geom + sizeof( int ) <= geomend );
613 #endif
614  int nPoints = *( reinterpret_cast< const unsigned int * >( geom ) );
615  geom += sizeof( int );
616 
617 #ifndef QT_NO_DEBUG
618  Q_ASSERT( geom + nPoints*sizeof( double )*dims <= geomend );
619 #endif
620 
621  // get line center
622  const double *pts = reinterpret_cast< const double * >( geom );
623  double tl = 0.0;
624  for ( int i = 1; i < nPoints; i++ )
625  {
626  double dx = pts[dims*i] - pts[dims*( i-1 )];
627  double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
628  tl += sqrt( dx * dx + dy * dy );
629  }
630  tl /= 2.0;
631 
632  // find line center
633  double l = 0.0;
634  for ( int i = 1; i < nPoints; i++ )
635  {
636  double dx = pts[dims*i] - pts[dims*( i-1 )];
637  double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
638  double dl = sqrt( dx * dx + dy * dy );
639 
640  if ( l + dl > tl )
641  {
642  double k = ( tl - l ) / dl;
643 
644  point.p.set( pts[dims*( i-1 )] + k * dx,
645  pts[dims*( i-1 )+1] + k * dy );
646  point.angle = atan2( dy, dx ) * 180.0 * M_1_PI;
647  break;
648  }
649 
650  l += dl;
651  }
652 
653  geom += nPoints * sizeof( double ) * dims;
654  }
655  break;
656 
657  case QGis::WKBPolygon25D:
658  dims = 3;
659  //intentional fall-through
660  FALLTHROUGH;
661  case QGis::WKBPolygon: // centroid of outer ring
662  {
663 #ifndef QT_NO_DEBUG
664  Q_ASSERT( geom + sizeof( int ) <= geomend );
665 #endif
666  int nRings = *( reinterpret_cast< const unsigned int * >( geom ) );
667  geom += sizeof( int );
668 
669  for ( int i = 0; i < nRings; ++i )
670  {
671 #ifndef QT_NO_DEBUG
672  Q_ASSERT( geom + sizeof( int ) <= geomend );
673 #endif
674  int nPoints = *( reinterpret_cast< const unsigned int * >( geom ) );
675  geom += sizeof( int );
676 
677 #ifndef QT_NO_DEBUG
678  Q_ASSERT( geom + nPoints*sizeof( double )*dims <= geomend );
679 #endif
680 
681  if ( i == 0 )
682  {
683  double sx = 0.0, sy = 0.0;
684  const double *pts = reinterpret_cast< const double* >( geom );
685  for ( int j = 0; j < nPoints - 1; j++ )
686  {
687  sx += pts[dims*j];
688  sy += pts[dims*j+1];
689  }
690  point.p.set( sx / ( nPoints - 1 ),
691  sy / ( nPoints - 1 ) );
692  point.angle = 0.0;
693  }
694 
695  geom += nPoints * sizeof( double ) * dims;
696  }
697  }
698  break;
699 
700  default:
701  // To get here is a bug because our caller should be filtering
702  // on wkb type.
703  QgsDebugMsg( "unsupported wkb type" );
704  return nullptr;
705  }
706 
707  return geom;
708 }
709 
710 bool QgsLabel::readLabelField( QDomElement &el, int attr, const QString& prefix = "field" )
711 {
712  QString name = prefix + "name";
713 
714  if ( el.hasAttribute( name ) )
715  {
716  name = el.attribute( name );
717 
718  int idx = 0;
719  for ( ; idx < mFields.count(); ++idx )
720  {
721  if ( mFields.at( idx ).name() == name )
722  {
723  break;
724  }
725  }
726 
727  if ( idx != mFields.count() )
728  {
729  mLabelFieldIdx[attr] = idx;
730  return true;
731  }
732  }
733  else if ( el.hasAttribute( prefix ) )
734  {
735  QString value = el.attribute( prefix );
736  mLabelFieldIdx[attr] = value.isEmpty() ? -1 : value.toInt();
737  return true;
738  }
739 
740  mLabelFieldIdx[attr] = -1;
741  return false;
742 }
743 
744 
745 void QgsLabel::readXML( const QDomNode& node )
746 {
747  QgsDebugMsg( " called for layer label properties, got node " + node.nodeName() );
748 
749  QDomNode scratchNode; // Dom node re-used to get current QgsLabel attribute
750  QDomElement el;
751 
752  int red, green, blue;
753  int type;
754 
755  /* Text */
756  scratchNode = node.namedItem( "label" );
757 
758  if ( scratchNode.isNull() )
759  {
760  QgsDebugMsg( "couldn't find QgsLabel ``label'' attribute" );
761  }
762  else
763  {
764  el = scratchNode.toElement();
765  mLabelAttributes->setText( el.attribute( "text", "" ) );
766  readLabelField( el, Text );
767  }
768 
769  /* Family */
770  scratchNode = node.namedItem( "family" );
771 
772  if ( scratchNode.isNull() )
773  {
774  QgsDebugMsg( "couldn't find QgsLabel ``family'' attribute" );
775  }
776  else
777  {
778  el = scratchNode.toElement();
779  mLabelAttributes->setFamily( el.attribute( "name", "" ) );
780  readLabelField( el, Family );
781  }
782 
783  /* Size */
784  scratchNode = node.namedItem( "size" );
785 
786  if ( scratchNode.isNull() )
787  {
788  QgsDebugMsg( "couldn't find QgsLabel ``size'' attribute" );
789  }
790  else
791  {
792  el = scratchNode.toElement();
793  if ( !el.hasAttribute( "unitfield" ) && !el.hasAttribute( "unitfieldname" ) )
794  {
795  type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
796  mLabelAttributes->setSize( el.attribute( "value", "0.0" ).toDouble(), type );
797  }
798  else
799  {
800  readLabelField( el, SizeType, "unitfield" );
801  }
802  readLabelField( el, Size );
803  }
804 
805  /* Bold */
806  scratchNode = node.namedItem( "bold" );
807 
808  if ( scratchNode.isNull() )
809  {
810  QgsDebugMsg( "couldn't find QgsLabel ``bold'' attribute" );
811  }
812  else
813  {
814  el = scratchNode.toElement();
815  mLabelAttributes->setBold( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
816  readLabelField( el, Bold );
817  }
818 
819  /* Italic */
820  scratchNode = node.namedItem( "italic" );
821 
822  if ( scratchNode.isNull() )
823  {
824  QgsDebugMsg( "couldn't find QgsLabel ``italic'' attribute" );
825  }
826  else
827  {
828  el = scratchNode.toElement();
829  mLabelAttributes->setItalic( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
830  readLabelField( el, Italic );
831  }
832 
833  /* Underline */
834  scratchNode = node.namedItem( "underline" );
835 
836  if ( scratchNode.isNull() )
837  {
838  QgsDebugMsg( "couldn't find QgsLabel ``underline'' attribute" );
839  }
840  else
841  {
842  el = scratchNode.toElement();
843  mLabelAttributes->setUnderline( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
844  readLabelField( el, Underline );
845  }
846 
847  /* Strikeout */
848  scratchNode = node.namedItem( "strikeout" );
849 
850  if ( scratchNode.isNull() )
851  {
852  QgsDebugMsg( "couldn't find QgsLabel ``strikeout'' attribute" );
853  }
854  else
855  {
856  el = scratchNode.toElement();
857  mLabelAttributes->setStrikeOut( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
858  readLabelField( el, StrikeOut );
859  }
860 
861  /* Color */
862  scratchNode = node.namedItem( "color" );
863 
864  if ( scratchNode.isNull() )
865  {
866  QgsDebugMsg( "couldn't find QgsLabel ``color'' attribute" );
867  }
868  else
869  {
870  el = scratchNode.toElement();
871 
872  red = el.attribute( "red", "0" ).toInt();
873  green = el.attribute( "green", "0" ).toInt();
874  blue = el.attribute( "blue", "0" ).toInt();
875 
876  mLabelAttributes->setColor( QColor( red, green, blue ) );
877 
878  readLabelField( el, Color );
879  }
880 
881  /* X */
882  scratchNode = node.namedItem( "x" );
883 
884  if ( scratchNode.isNull() )
885  {
886  QgsDebugMsg( "couldn't find QgsLabel ``x'' attribute" );
887  }
888  else
889  {
890  el = scratchNode.toElement();
891  readLabelField( el, XCoordinate );
892  }
893 
894  /* Y */
895  scratchNode = node.namedItem( "y" );
896 
897  if ( scratchNode.isNull() )
898  {
899  QgsDebugMsg( "couldn't find QgsLabel ``y'' attribute" );
900  }
901  else
902  {
903  el = scratchNode.toElement();
904  readLabelField( el, YCoordinate );
905  }
906 
907 
908  /* X,Y offset */
909  scratchNode = node.namedItem( "offset" );
910 
911  if ( scratchNode.isNull() )
912  {
913  QgsDebugMsg( "couldn't find QgsLabel ``offset'' attribute" );
914  }
915  else
916  {
917  double xoffset, yoffset;
918 
919  el = scratchNode.toElement();
920 
921  type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
922  xoffset = el.attribute( "x", "0.0" ).toDouble();
923  yoffset = el.attribute( "y", "0.0" ).toDouble();
924 
925  mLabelAttributes->setOffset( xoffset, yoffset, type );
926  readLabelField( el, XOffset, "xfield" );
927  readLabelField( el, YOffset, "yfield" );
928  }
929 
930  /* Angle */
931  scratchNode = node.namedItem( "angle" );
932 
933  if ( scratchNode.isNull() )
934  {
935  QgsDebugMsg( "couldn't find QgsLabel ``angle'' attribute" );
936  }
937  else
938  {
939  el = scratchNode.toElement();
940  mLabelAttributes->setAngle( el.attribute( "value", "0.0" ).toDouble() );
941  readLabelField( el, Angle );
942  mLabelAttributes->setAutoAngle( el.attribute( "auto", "0" ) == "1" );
943  }
944 
945  /* Alignment */
946  scratchNode = node.namedItem( "alignment" );
947 
948  if ( scratchNode.isNull() )
949  {
950  QgsDebugMsg( "couldn't find QgsLabel ``alignment'' attribute" );
951  }
952  else
953  {
954  el = scratchNode.toElement();
955  mLabelAttributes->setAlignment( QgsLabelAttributes::alignmentCode( el.attribute( "value", "" ) ) );
956  readLabelField( el, Alignment );
957  }
958 
959 
960  // Buffer
961  scratchNode = node.namedItem( "buffercolor" );
962 
963  if ( scratchNode.isNull() )
964  {
965  QgsDebugMsg( "couldn't find QgsLabel ``buffercolor'' attribute" );
966  }
967  else
968  {
969  el = scratchNode.toElement();
970 
971  red = el.attribute( "red", "0" ).toInt();
972  green = el.attribute( "green", "0" ).toInt();
973  blue = el.attribute( "blue", "0" ).toInt();
974 
975  mLabelAttributes->setBufferColor( QColor( red, green, blue ) );
976  readLabelField( el, BufferColor );
977  }
978 
979  scratchNode = node.namedItem( "buffersize" );
980 
981  if ( scratchNode.isNull() )
982  {
983  QgsDebugMsg( "couldn't find QgsLabel ``bffersize'' attribute" );
984  }
985  else
986  {
987  el = scratchNode.toElement();
988 
989  type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
990  mLabelAttributes->setBufferSize( el.attribute( "value", "0.0" ).toDouble(), type );
991  readLabelField( el, BufferSize );
992  }
993 
994  scratchNode = node.namedItem( "bufferenabled" );
995 
996  if ( scratchNode.isNull() )
997  {
998  QgsDebugMsg( "couldn't find QgsLabel ``bufferenabled'' attribute" );
999  }
1000  else
1001  {
1002  el = scratchNode.toElement();
1003 
1004  mLabelAttributes->setBufferEnabled( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
1005  readLabelField( el, BufferEnabled );
1006  }
1007 
1008  scratchNode = node.namedItem( "multilineenabled" );
1009 
1010  if ( scratchNode.isNull() )
1011  {
1012  QgsDebugMsg( "couldn't find QgsLabel ``multilineenabled'' attribute" );
1013  }
1014  else
1015  {
1016  el = scratchNode.toElement();
1017 
1018  mLabelAttributes->setMultilineEnabled( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
1019  readLabelField( el, MultilineEnabled );
1020  }
1021 
1022  scratchNode = node.namedItem( "selectedonly" );
1023 
1024  if ( scratchNode.isNull() )
1025  {
1026  QgsDebugMsg( "couldn't find QgsLabel ``selectedonly'' attribute" );
1027  }
1028  else
1029  {
1030  el = scratchNode.toElement();
1031  mLabelAttributes->setSelectedOnly( static_cast< bool >( el.attribute( "on", "0" ).toInt() ) );
1032  }
1033 
1034 } // QgsLabel::readXML()
1035 
1036 
1037 
1038 void QgsLabel::writeXML( QDomNode & layer_node, QDomDocument & document ) const
1039 {
1040  QDomElement labelattributes = document.createElement( "labelattributes" );
1041 
1042  // Text
1043  QDomElement label = document.createElement( "label" );
1044  label.setAttribute( "text", mLabelAttributes->text() );
1045  if ( mLabelAttributes->textIsSet() && mLabelFieldIdx[Text] != -1 )
1046  {
1047  label.setAttribute( "fieldname", labelField( Text ) );
1048  }
1049  else
1050  {
1051  label.setAttribute( "fieldname", "" );
1052  }
1053  labelattributes.appendChild( label );
1054 
1055  // Family
1056  QDomElement family = document.createElement( "family" );
1057  if ( mLabelAttributes->familyIsSet() && !mLabelAttributes->family().isNull() )
1058  {
1059  if ( mLabelFieldIdx[Family] != -1 )
1060  {
1061  family.setAttribute( "name", mLabelAttributes->family() );
1062  family.setAttribute( "fieldname", labelField( Family ) );
1063  }
1064  else
1065  {
1066  family.setAttribute( "name", mLabelAttributes->family() );
1067  family.setAttribute( "fieldname", "" );
1068  }
1069  }
1070  else
1071  {
1072  family.setAttribute( "name", "Arial" );
1073  family.setAttribute( "fieldname", "" );
1074  }
1075  labelattributes.appendChild( family );
1076 
1077  // size and units
1078  QDomElement size = document.createElement( "size" );
1079  size.setAttribute( "value", QString::number( mLabelAttributes->size() ) );
1080  if ( mLabelAttributes->sizeIsSet() )
1081  {
1082  if ( mLabelFieldIdx[Size] != -1 )
1083  {
1084  if ( mLabelFieldIdx[SizeType] != -1 )
1085  {
1086  size.setAttribute( "unitfieldname", labelField( SizeType ) );
1087  }
1088  else
1089  {
1090  size.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->sizeType() ) );
1091  }
1092  size.setAttribute( "fieldname", labelField( Size ) );
1093  }
1094  else
1095  {
1096  size.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->sizeType() ) );
1097  size.setAttribute( "fieldname", "" );
1098  }
1099  }
1100  else
1101  {
1102  size.setAttribute( "value", "12" );
1103  size.setAttribute( "units", "Points" );
1104  size.setAttribute( "fieldname", "" );
1105  }
1106  labelattributes.appendChild( size );
1107 
1108  // bold
1109  QDomElement bold = document.createElement( "bold" );
1110  if ( mLabelAttributes->boldIsSet() )
1111  {
1112  bold.setAttribute( "on", mLabelAttributes->bold() );
1113  if ( mLabelFieldIdx[Bold] != -1 )
1114  {
1115  bold.setAttribute( "fieldname", labelField( Bold ) );
1116  }
1117  else
1118  {
1119  bold.setAttribute( "fieldname", "" );
1120  }
1121  }
1122  else
1123  {
1124  bold.setAttribute( "on", 0 );
1125  bold.setAttribute( "fieldname", 0 );
1126  }
1127  labelattributes.appendChild( bold );
1128 
1129  // italics
1130  QDomElement italic = document.createElement( "italic" );
1131  if ( mLabelAttributes->italicIsSet() )
1132  {
1133  italic.setAttribute( "on", mLabelAttributes->italic() );
1134  if ( mLabelFieldIdx[Italic] != -1 )
1135  {
1136  italic.setAttribute( "fieldname", labelField( Italic ) );
1137  }
1138  else
1139  {
1140  italic.setAttribute( "fieldname", "" );
1141  }
1142  }
1143  else
1144  {
1145  italic.setAttribute( "on", "0" );
1146  italic.setAttribute( "fieldname", "" );
1147  }
1148  labelattributes.appendChild( italic );
1149 
1150  // underline
1151  QDomElement underline = document.createElement( "underline" );
1152  if ( mLabelAttributes->underlineIsSet() )
1153  {
1154  underline.setAttribute( "on", mLabelAttributes->underline() );
1155  if ( mLabelFieldIdx[Underline] != -1 )
1156  {
1157  underline.setAttribute( "fieldname", labelField( Underline ) );
1158  }
1159  else
1160  {
1161  underline.setAttribute( "fieldname", "" );
1162  }
1163  }
1164  else
1165  {
1166  underline.setAttribute( "on", 0 );
1167  underline.setAttribute( "fieldname", "" );
1168  }
1169  labelattributes.appendChild( underline );
1170 
1171  // strikeout
1172  QDomElement strikeOut = document.createElement( "strikeout" );
1173  if ( mLabelAttributes->strikeOutIsSet() )
1174  {
1175  strikeOut.setAttribute( "on", mLabelAttributes->strikeOut() );
1176  if ( mLabelFieldIdx[StrikeOut] != -1 )
1177  {
1178  strikeOut.setAttribute( "fieldname", labelField( StrikeOut ) );
1179  }
1180  else
1181  {
1182  strikeOut.setAttribute( "fieldname", "" );
1183  }
1184  }
1185  else
1186  {
1187  strikeOut.setAttribute( "on", 0 );
1188  strikeOut.setAttribute( "fieldname", "" );
1189  }
1190  labelattributes.appendChild( strikeOut );
1191 
1192  // color
1193  QDomElement color = document.createElement( "color" );
1194  if ( mLabelAttributes->colorIsSet() )
1195  {
1196  color.setAttribute( "red", mLabelAttributes->color().red() );
1197  color.setAttribute( "green", mLabelAttributes->color().green() );
1198  color.setAttribute( "blue", mLabelAttributes->color().blue() );
1199  if ( mLabelFieldIdx[Color] != -1 )
1200  {
1201  color.setAttribute( "fieldname", labelField( Color ) );
1202  }
1203  else
1204  {
1205  color.setAttribute( "fieldname", "" );
1206  }
1207  }
1208  else
1209  {
1210  color.setAttribute( "red", 0 );
1211  color.setAttribute( "green", 0 );
1212  color.setAttribute( "blue", 0 );
1213  color.setAttribute( "fieldname", "" );
1214  }
1215  labelattributes.appendChild( color );
1216 
1217  /* X */
1218  QDomElement x = document.createElement( "x" );
1219  if ( mLabelFieldIdx[XCoordinate] != -1 )
1220  {
1221  x.setAttribute( "fieldname", labelField( XCoordinate ) );
1222  }
1223  else
1224  {
1225  x.setAttribute( "fieldname", "" );
1226  }
1227  labelattributes.appendChild( x );
1228 
1229  /* Y */
1230  QDomElement y = document.createElement( "y" );
1231  if ( mLabelFieldIdx[YCoordinate] != -1 )
1232  {
1233  y.setAttribute( "fieldname", labelField( YCoordinate ) );
1234  }
1235  else
1236  {
1237  y.setAttribute( "fieldname", "" );
1238  }
1239  labelattributes.appendChild( y );
1240 
1241  // offset
1242  if ( mLabelAttributes->offsetIsSet() )
1243  {
1244  QDomElement offset = document.createElement( "offset" );
1245  offset.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->offsetType() ) );
1246  offset.setAttribute( "x", QString::number( mLabelAttributes->xOffset() ) );
1247  offset.setAttribute( "xfieldname", labelField( XOffset ) );
1248  offset.setAttribute( "y", QString::number( mLabelAttributes->yOffset() ) );
1249  offset.setAttribute( "yfieldname", labelField( YOffset ) );
1250  labelattributes.appendChild( offset );
1251  }
1252 
1253  // Angle
1254  QDomElement angle = document.createElement( "angle" );
1255  if ( mLabelAttributes->angleIsSet() )
1256  {
1257  angle.setAttribute( "value", QString::number( mLabelAttributes->angle() ) );
1258  if ( mLabelFieldIdx[Angle] != -1 )
1259  {
1260  angle.setAttribute( "fieldname", labelField( Angle ) );
1261  }
1262  else
1263  {
1264  angle.setAttribute( "fieldname", "" );
1265  }
1266  }
1267  else
1268  {
1269  angle.setAttribute( "value", "" );
1270  angle.setAttribute( "fieldname", "" );
1271  }
1272  angle.setAttribute( "auto", mLabelAttributes->angleIsAuto() ? "1" : "0" );
1273  labelattributes.appendChild( angle );
1274 
1275  // alignment
1276  if ( mLabelAttributes->alignmentIsSet() )
1277  {
1278  QDomElement alignment = document.createElement( "alignment" );
1279  alignment.setAttribute( "value", QgsLabelAttributes::alignmentName( mLabelAttributes->alignment() ) );
1280  alignment.setAttribute( "fieldname", labelField( Alignment ) );
1281  labelattributes.appendChild( alignment );
1282  }
1283 
1284  // buffer color
1285  QDomElement buffercolor = document.createElement( "buffercolor" );
1286  if ( mLabelAttributes->bufferColorIsSet() )
1287  {
1288  buffercolor.setAttribute( "red", mLabelAttributes->bufferColor().red() );
1289  buffercolor.setAttribute( "green", mLabelAttributes->bufferColor().green() );
1290  buffercolor.setAttribute( "blue", mLabelAttributes->bufferColor().blue() );
1291  if ( mLabelFieldIdx[BufferColor] != -1 )
1292  {
1293  buffercolor.setAttribute( "fieldname", labelField( BufferColor ) );
1294  }
1295  else
1296  {
1297  buffercolor.setAttribute( "fieldname", "" );
1298  }
1299  }
1300  else
1301  {
1302  buffercolor.setAttribute( "red", "" );
1303  buffercolor.setAttribute( "green", "" );
1304  buffercolor.setAttribute( "blue", "" );
1305  buffercolor.setAttribute( "fieldname", "" );
1306  }
1307  labelattributes.appendChild( buffercolor );
1308 
1309  // buffer size
1310  QDomElement buffersize = document.createElement( "buffersize" );
1311  if ( mLabelAttributes->bufferSizeIsSet() )
1312  {
1313  buffersize.setAttribute( "value", QString::number( mLabelAttributes->bufferSize() ) );
1314  buffersize.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->bufferSizeType() ) );
1315  if ( mLabelFieldIdx[BufferSize] != -1 )
1316  {
1317  buffersize.setAttribute( "fieldname", labelField( BufferSize ) );
1318  }
1319  else
1320  {
1321  buffersize.setAttribute( "fieldname", "" );
1322  }
1323  }
1324  else
1325  {
1326  buffersize.setAttribute( "value", "" );
1327  buffersize.setAttribute( "units", "" );
1328  buffersize.setAttribute( "fieldname", "" );
1329  }
1330  labelattributes.appendChild( buffersize );
1331 
1332  // buffer enabled
1333  QDomElement bufferenabled = document.createElement( "bufferenabled" );
1334  if ( mLabelAttributes->bufferEnabled() )
1335  {
1336  bufferenabled.setAttribute( "on", mLabelAttributes->bufferEnabled() );
1337  if ( mLabelFieldIdx[BufferEnabled] != -1 )
1338  {
1339  bufferenabled.setAttribute( "fieldname", labelField( BufferEnabled ) );
1340  }
1341  else
1342  {
1343  bufferenabled.setAttribute( "fieldname", "" );
1344  }
1345  }
1346  else
1347  {
1348  bufferenabled.setAttribute( "on", "" );
1349  bufferenabled.setAttribute( "fieldname", "" );
1350  }
1351  labelattributes.appendChild( bufferenabled );
1352 
1353  // multiline enabled
1354  QDomElement multilineenabled = document.createElement( "multilineenabled" );
1355  if ( mLabelAttributes->multilineEnabled() )
1356  {
1357  multilineenabled.setAttribute( "on", mLabelAttributes->multilineEnabled() );
1358  if ( mLabelFieldIdx[MultilineEnabled] != -1 )
1359  {
1360  multilineenabled.setAttribute( "fieldname", labelField( MultilineEnabled ) );
1361  }
1362  else
1363  {
1364  multilineenabled.setAttribute( "fieldname", "" );
1365  }
1366  }
1367  else
1368  {
1369  multilineenabled.setAttribute( "on", "" );
1370  multilineenabled.setAttribute( "fieldname", "" );
1371  }
1372  labelattributes.appendChild( multilineenabled );
1373 
1374  QDomElement selectedonly = document.createElement( "selectedonly" );
1375  if ( mLabelAttributes->selectedOnly() )
1376  {
1377  selectedonly.setAttribute( "on", mLabelAttributes->selectedOnly() );
1378  }
1379  else
1380  {
1381  selectedonly.setAttribute( "on", "" );
1382  }
1383  labelattributes.appendChild( selectedonly );
1384 
1385  layer_node.appendChild( labelattributes );
1386 }
1387 
1388 void QgsLabel::setScaleBasedVisibility( bool theVisibilityFlag )
1389 {
1390  mScaleBasedVisibility = theVisibilityFlag;
1391 }
1392 
1394 {
1395  return mScaleBasedVisibility;
1396 }
1397 
1398 void QgsLabel::setMinScale( float theMinScale )
1399 {
1400  mMinScale = theMinScale;
1401 }
1402 
1403 float QgsLabel::minScale() const
1404 {
1405  return mMinScale;
1406 }
1407 
1408 void QgsLabel::setMaxScale( float theMaxScale )
1409 {
1410  mMaxScale = theMaxScale;
1411 }
1412 
1413 float QgsLabel::maxScale() const
1414 {
1415  return mMaxScale;
1416 }
1417 
1418 bool QgsLabel::isInScaleRange( double scale ) const
1419 {
1420  return !mScaleBasedVisibility ||
1421  ( mMinScale * QGis::SCALE_PRECISION < scale && scale * QGis::SCALE_PRECISION < mMaxScale );
1422 }
QgsPoint transform(const QgsPoint &p, TransformDirection direction=ForwardTransform) const
Transform the point from Source Coordinate System to Destination Coordinate System If the direction i...
void setBufferColor(const QColor &color)
void setMultilineEnabled(bool useMultiline)
void setBold(bool enable)
void setLabelField(int attr, int fieldIndex)
Set label field.
Definition: qgslabel.cpp:491
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
void setSize(double size, int type)
void setUnderline(bool enable)
QString name
Definition: qgsfield.h:52
void setSelectedOnly(bool selectedonly)
static int unitsCode(const QString &name)
QDomNode appendChild(const QDomNode &newChild)
void setFamily(const QString &family)
QString attribute(const QString &name, const QString &defValue) const
QString labelField(int attr) const
label field
Definition: qgslabel.cpp:499
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
const QColor & color() const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
static QString alignmentName(int alignment)
void scale(qreal sx, qreal sy)
void setUnderline(bool enable)
QColor bufferColor() const
void save()
Container of fields for a vector layer.
Definition: qgsfield.h:252
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
WkbType
Used for symbology operations.
Definition: qgis.h:61
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
void setFields(const QgsFields &fields)
Set available fields.
Definition: qgslabel.cpp:481
void rotate(qreal angle)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
const QString text() const
double toDouble(bool *ok) const
int wkbSize() const
Returns the size of the WKB in asWkb().
int count() const
Return number of items.
Definition: qgsfield.cpp:402
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
int size() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
QgsLabelAttributes * labelAttributes()
Pointer to default attributes.
Definition: qgslabel.cpp:510
bool isNull() const
QDomElement toElement() const
void setAutoAngle(bool state)
void setBold(bool enable)
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
static QString unitsName(int units)
void setPixelSize(int pixelSize)
void setFont(const QFont &font)
QString number(int n, int base)
const QString family() const
void append(const T &value)
#define FALLTHROUGH
Definition: qgis.h:539
bool isInScaleRange(double scale) const
Return true if the label is visible at the given scale.
Definition: qgslabel.cpp:1418
static int alignmentCode(const QString &name)
bool hasAttribute(const QString &name) const
int red() const
void setPen(const QColor &color)
void setAttribute(const QString &name, const QString &value)
void setBufferSize(double size, int type)
int toInt(bool *ok, int base) const
void setScaleBasedVisibility(bool theVisibilityFlag)
Accessor and mutator for the scale based visilibility flag.
Definition: qgslabel.cpp:1388
QString nodeName() const
bool isEmpty() const
#define M_PI
const QgsCoordinateTransform * coordinateTransform() const
void drawText(const QPointF &position, const QString &text)
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
QgsFields & fields()
Available vector fields.
Definition: qgslabel.cpp:486
void setColor(const QColor &color)
void setText(const QString &text)
void readXML(const QDomNode &node)
Reads the renderer configuration from an XML file.
Definition: qgslabel.cpp:745
bool scaleBasedVisibility() const
Definition: qgslabel.cpp:1393
void setAngle(double angle)
void set(double x, double y)
Sets the x and y value of the point.
Definition: qgspoint.h:176
A class to represent a point.
Definition: qgspoint.h:117
QString fieldValue(int attr, QgsFeature &feature)
Get field value if : 1) field name is not empty 2) field exists 3) value is defined otherwise returns...
Definition: qgslabel.cpp:66
int green() const
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
iterator end()
QString toLower() const
QDomNode namedItem(const QString &name) const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
void setX(double x)
Sets the x value of the point.
Definition: qgspoint.h:162
void setY(double y)
Sets the y value of the point.
Definition: qgspoint.h:170
int width(const QString &text, int len) const
void setItalic(bool enable)
void setStrikeOut(bool enable)
void restore()
void renderLabel(QgsRenderContext &renderContext, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=nullptr)
render label
Definition: qgslabel.cpp:72
int blue() const
Contains information about the context of a rendering operation.
void setMaxScale(float theMaxScale)
Accessor and mutator for the maximum scale member.
Definition: qgslabel.cpp:1408
void setAlignment(int alignment)
QPainter * painter()
const QgsMapToPixel & mapToPixel() const
void setOffset(double x, double y, int type)
QgsLabel(const QgsFields &fields)
Definition: qgslabel.cpp:47
void setFamily(const QString &family)
float maxScale() const
Definition: qgslabel.cpp:1413
int height() const
void setStrikeOut(bool enable)
void translate(const QPointF &offset)
~QgsLabel()
Definition: qgslabel.cpp:61
void addRequiredFields(QgsAttributeList &fields) const
add vector of required fields to existing list of fields
Definition: qgslabel.cpp:459
void setMinScale(float theMinScale)
Accessor and mutator for the minimum scale member.
Definition: qgslabel.cpp:1398
Custom exception class for Coordinate Reference System related exceptions.
double rasterScaleFactor() const
float minScale() const
Definition: qgslabel.cpp:1403
QDomElement createElement(const QString &tagName)
A class to store attributes needed for label rendering.
void setColor(const QColor &color)
double scaleFactor() const
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
int compare(const QString &other) const
void setBufferEnabled(bool useBufferFlag)
QString toString() const
static double SCALE_PRECISION
Fudge factor used to compare two scales.
Definition: qgis.h:257
iterator begin()
void setItalic(bool enable)
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
void writeXML(QDomNode &label_node, QDomDocument &document) const
Writes the contents of the renderer to a configuration file.
Definition: qgslabel.cpp:1038