QGIS API Documentation  3.21.0-Master (5b68dc587e)
qgstextformat.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstextformat.cpp
3  ---------------
4  begin : May 2020
5  copyright : (C) Nyall Dawson
6  email : nyall dot dawson 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 
16 #include "qgstextformat.h"
17 #include "qgstextrenderer_p.h"
18 #include "qgstextrenderer.h"
19 #include "qgsvectorlayer.h"
20 #include "qgsfontutils.h"
21 #include "qgssymbollayerutils.h"
22 #include "qgspainting.h"
23 #include "qgstextrendererutils.h"
24 #include "qgspallabeling.h"
25 #include <QFontDatabase>
26 #include <QMimeData>
27 #include <QWidget>
28 #include <QScreen>
29 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
30 #include <QDesktopWidget>
31 #endif
32 
34 {
35  d = new QgsTextSettingsPrivate();
36 }
37 
39  : mBufferSettings( other.mBufferSettings )
40  , mBackgroundSettings( other.mBackgroundSettings )
41  , mShadowSettings( other.mShadowSettings )
42  , mMaskSettings( other.mMaskSettings )
43  , mTextFontFamily( other.mTextFontFamily )
44  , mTextFontFound( other.mTextFontFound )
45  , d( other.d )
46 {
47 
48 }
49 
51 {
52  d = other.d;
53  mBufferSettings = other.mBufferSettings;
54  mBackgroundSettings = other.mBackgroundSettings;
55  mShadowSettings = other.mShadowSettings;
56  mMaskSettings = other.mMaskSettings;
57  mTextFontFamily = other.mTextFontFamily;
58  mTextFontFound = other.mTextFontFound;
59  return *this;
60 }
61 
63 {
64 
65 }
66 
67 bool QgsTextFormat::operator==( const QgsTextFormat &other ) const
68 {
69  if ( d->isValid != other.isValid()
70  || d->textFont != other.font()
71  || namedStyle() != other.namedStyle()
72  || d->fontSizeUnits != other.sizeUnit()
73  || d->fontSizeMapUnitScale != other.sizeMapUnitScale()
74  || d->fontSize != other.size()
75  || d->textColor != other.color()
76  || d->opacity != other.opacity()
77  || d->blendMode != other.blendMode()
78  || d->multilineHeight != other.lineHeight()
79  || d->orientation != other.orientation()
80  || d->previewBackgroundColor != other.previewBackgroundColor()
81  || d->allowHtmlFormatting != other.allowHtmlFormatting()
82  || d->capitalization != other.capitalization()
83  || mBufferSettings != other.mBufferSettings
84  || mBackgroundSettings != other.mBackgroundSettings
85  || mShadowSettings != other.mShadowSettings
86  || mMaskSettings != other.mMaskSettings
87  || d->families != other.families()
88  || d->mDataDefinedProperties != other.dataDefinedProperties() )
89  return false;
90 
91  return true;
92 }
93 
94 bool QgsTextFormat::operator!=( const QgsTextFormat &other ) const
95 {
96  return !( *this == other );
97 }
98 
100 {
101  return d->isValid;
102 }
103 
105 {
106  d->isValid = true;
107 }
108 
110 {
111  d->isValid = true;
112  return mBufferSettings;
113 }
114 
115 void QgsTextFormat::setBuffer( const QgsTextBufferSettings &bufferSettings )
116 {
117  d->isValid = true;
118  mBufferSettings = bufferSettings;
119 }
120 
122 {
123  d->isValid = true;
124  return mBackgroundSettings;
125 }
126 
128 {
129  d->isValid = true;
130  mBackgroundSettings = backgroundSettings;
131 }
132 
134 {
135  d->isValid = true;
136  return mShadowSettings;
137 }
138 
139 void QgsTextFormat::setShadow( const QgsTextShadowSettings &shadowSettings )
140 {
141  d->isValid = true;
142  mShadowSettings = shadowSettings;
143 }
144 
146 {
147  d->isValid = true;
148  return mMaskSettings;
149 }
150 
151 void QgsTextFormat::setMask( const QgsTextMaskSettings &maskSettings )
152 {
153  d->isValid = true;
154  mMaskSettings = maskSettings;
155 }
156 
157 QFont QgsTextFormat::font() const
158 {
159  return d->textFont;
160 }
161 
162 QFont QgsTextFormat::scaledFont( const QgsRenderContext &context, double scaleFactor, bool *isZeroSize ) const
163 {
164  if ( isZeroSize )
165  *isZeroSize = false;
166 
167  QFont font = d->textFont;
168  if ( scaleFactor == 1 )
169  {
170  int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits,
171  d->fontSizeMapUnitScale );
172  if ( fontPixelSize == 0 )
173  {
174  if ( isZeroSize )
175  *isZeroSize = true;
176  return QFont();
177  }
178 
179  font.setPixelSize( fontPixelSize );
180  }
181  else
182  {
183  double fontPixelSize = context.convertToPainterUnits( d->fontSize, d->fontSizeUnits, d->fontSizeMapUnitScale );
184  if ( qgsDoubleNear( fontPixelSize, 0 ) )
185  {
186  if ( isZeroSize )
187  *isZeroSize = true;
188  return QFont();
189  }
190  const int roundedPixelSize = static_cast< int >( std::round( scaleFactor * fontPixelSize + 0.5 ) );
191  font.setPixelSize( roundedPixelSize );
192  }
193 
194  font.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( d->textFont.letterSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor );
195  font.setWordSpacing( context.convertToPainterUnits( d->textFont.wordSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor * scaleFactor );
196 
197  return font;
198 }
199 
200 void QgsTextFormat::setFont( const QFont &font )
201 {
202  d->isValid = true;
203  d->textFont = font;
204 }
205 
207 {
208  if ( !d->textNamedStyle.isEmpty() )
209  return d->textNamedStyle;
210 
211  QFontDatabase db;
212  return db.styleString( d->textFont );
213 }
214 
215 void QgsTextFormat::setNamedStyle( const QString &style )
216 {
217  d->isValid = true;
218  QgsFontUtils::updateFontViaStyle( d->textFont, style );
219  d->textNamedStyle = style;
220 }
221 
222 QStringList QgsTextFormat::families() const
223 {
224  return d->families;
225 }
226 
227 void QgsTextFormat::setFamilies( const QStringList &families )
228 {
229  d->isValid = true;
230  d->families = families;
231 }
232 
234 {
235  return d->fontSizeUnits;
236 }
237 
239 {
240  d->isValid = true;
241  d->fontSizeUnits = unit;
242 }
243 
245 {
246  return d->fontSizeMapUnitScale;
247 }
248 
250 {
251  d->isValid = true;
252  d->fontSizeMapUnitScale = scale;
253 }
254 
255 double QgsTextFormat::size() const
256 {
257  return d->fontSize;
258 }
259 
260 void QgsTextFormat::setSize( double size )
261 {
262  d->isValid = true;
263  d->fontSize = size;
264 }
265 
266 QColor QgsTextFormat::color() const
267 {
268  return d->textColor;
269 }
270 
271 void QgsTextFormat::setColor( const QColor &color )
272 {
273  d->isValid = true;
274  d->textColor = color;
275 }
276 
278 {
279  return d->opacity;
280 }
281 
282 void QgsTextFormat::setOpacity( double opacity )
283 {
284  d->isValid = true;
285  d->opacity = opacity;
286 }
287 
288 QPainter::CompositionMode QgsTextFormat::blendMode() const
289 {
290  return d->blendMode;
291 }
292 
293 void QgsTextFormat::setBlendMode( QPainter::CompositionMode mode )
294 {
295  d->isValid = true;
296  d->blendMode = mode;
297 }
298 
300 {
301  return d->multilineHeight;
302 }
303 
304 void QgsTextFormat::setLineHeight( double height )
305 {
306  d->isValid = true;
307  d->multilineHeight = height;
308 }
309 
311 {
312  return d->orientation;
313 }
314 
316 {
317  d->isValid = true;
318  d->orientation = orientation;
319 }
320 
322 {
323  // bit of complexity here to maintain API..
324  return d->capitalization == QgsStringUtils::MixedCase && d->textFont.capitalization() != QFont::MixedCase ? static_cast< QgsStringUtils::Capitalization >( d->textFont.capitalization() ) : d->capitalization ;
325 }
326 
328 {
329  d->isValid = true;
330  d->capitalization = capitalization;
331  d->textFont.setCapitalization( QFont::MixedCase );
332 }
333 
335 {
336  return d->allowHtmlFormatting;
337 }
338 
340 {
341  d->isValid = true;
342  d->allowHtmlFormatting = allow;
343 }
344 
346 {
347  return d->previewBackgroundColor;
348 }
349 
350 void QgsTextFormat::setPreviewBackgroundColor( const QColor &color )
351 {
352  d->isValid = true;
353  d->previewBackgroundColor = color;
354 }
355 
357 {
358  d->isValid = true;
359  QFont appFont = QApplication::font();
360  mTextFontFamily = layer->customProperty( QStringLiteral( "labeling/fontFamily" ), QVariant( appFont.family() ) ).toString();
361  QString fontFamily = mTextFontFamily;
362  if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
363  {
364  // trigger to notify about font family substitution
365  mTextFontFound = false;
366 
367  // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
368  // currently only defaults to matching algorithm for resolving [foundry], if a font of similar family is found (default for QFont)
369 
370  // for now, do not use matching algorithm for substitution if family not found, substitute default instead
371  fontFamily = appFont.family();
372  }
373  else
374  {
375  mTextFontFound = true;
376  }
377 
378  if ( !layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).isValid() )
379  {
380  d->fontSize = appFont.pointSizeF();
381  }
382  else
383  {
384  d->fontSize = layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).toDouble();
385  }
386 
387  if ( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString().isEmpty() )
388  {
389  d->fontSizeUnits = layer->customProperty( QStringLiteral( "labeling/fontSizeInMapUnits" ), QVariant( false ) ).toBool() ?
391  }
392  else
393  {
394  bool ok = false;
395  d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString(), &ok );
396  if ( !ok )
397  d->fontSizeUnits = QgsUnitTypes::RenderPoints;
398  }
399  if ( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString().isEmpty() )
400  {
401  //fallback to older property
402  double oldMin = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMinScale" ), 0.0 ).toDouble();
403  d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
404  double oldMax = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMaxScale" ), 0.0 ).toDouble();
405  d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
406  }
407  else
408  {
409  d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString() );
410  }
411  int fontWeight = layer->customProperty( QStringLiteral( "labeling/fontWeight" ) ).toInt();
412  bool fontItalic = layer->customProperty( QStringLiteral( "labeling/fontItalic" ) ).toBool();
413  d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
414  d->textNamedStyle = QgsFontUtils::translateNamedStyle( layer->customProperty( QStringLiteral( "labeling/namedStyle" ), QVariant( "" ) ).toString() );
415  QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
416  d->capitalization = static_cast< QgsStringUtils::Capitalization >( layer->customProperty( QStringLiteral( "labeling/fontCapitals" ), QVariant( 0 ) ).toUInt() );
417  d->textFont.setUnderline( layer->customProperty( QStringLiteral( "labeling/fontUnderline" ) ).toBool() );
418  d->textFont.setStrikeOut( layer->customProperty( QStringLiteral( "labeling/fontStrikeout" ) ).toBool() );
419  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( QStringLiteral( "labeling/fontLetterSpacing" ), QVariant( 0.0 ) ).toDouble() );
420  d->textFont.setWordSpacing( layer->customProperty( QStringLiteral( "labeling/fontWordSpacing" ), QVariant( 0.0 ) ).toDouble() );
421  d->textColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/textColor" ), Qt::black, false );
422  if ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toString().isEmpty() )
423  {
424  d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/textTransp" ) ).toInt() / 100.0 ); //0 -100
425  }
426  else
427  {
428  d->opacity = ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toDouble() );
429  }
430  d->blendMode = QgsPainting::getCompositionMode(
431  static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/blendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
432  d->multilineHeight = layer->customProperty( QStringLiteral( "labeling/multilineHeight" ), QVariant( 1.0 ) ).toDouble();
433  d->previewBackgroundColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/previewBkgrdColor" ), QColor( 255, 255, 255 ), false );
434 
435  mBufferSettings.readFromLayer( layer );
436  mShadowSettings.readFromLayer( layer );
437  mBackgroundSettings.readFromLayer( layer );
438 }
439 
440 void QgsTextFormat::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
441 {
442  d->isValid = true;
443  QDomElement textStyleElem;
444  if ( elem.nodeName() == QLatin1String( "text-style" ) )
445  textStyleElem = elem;
446  else
447  textStyleElem = elem.firstChildElement( QStringLiteral( "text-style" ) );
448  QFont appFont = QApplication::font();
449  mTextFontFamily = textStyleElem.attribute( QStringLiteral( "fontFamily" ), appFont.family() );
450  QString fontFamily = mTextFontFamily;
451 
452  const QDomElement familiesElem = textStyleElem.firstChildElement( QStringLiteral( "families" ) );
453  const QDomNodeList familyNodes = familiesElem.childNodes();
454  QStringList families;
455  families.reserve( familyNodes.size() );
456  for ( int i = 0; i < familyNodes.count(); ++i )
457  {
458  const QDomElement familyElem = familyNodes.at( i ).toElement();
459  families << familyElem.attribute( QStringLiteral( "name" ) );
460  }
461  d->families = families;
462 
463  mTextFontFound = false;
464  if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
465  {
466  for ( const QString &family : std::as_const( families ) )
467  {
469  {
470  mTextFontFound = true;
471  fontFamily = family;
472  break;
473  }
474  }
475 
476  if ( !mTextFontFound )
477  {
478  // couldn't even find a matching font in the backup list -- substitute default instead
479  fontFamily = appFont.family();
480  }
481  }
482  else
483  {
484  mTextFontFound = true;
485  }
486 
487  if ( !mTextFontFound )
488  {
489  context.pushMessage( QObject::tr( "Font “%1” not available on system" ).arg( mTextFontFamily ) );
490  }
491 
492  if ( textStyleElem.hasAttribute( QStringLiteral( "fontSize" ) ) )
493  {
494  d->fontSize = textStyleElem.attribute( QStringLiteral( "fontSize" ) ).toDouble();
495  }
496  else
497  {
498  d->fontSize = appFont.pointSizeF();
499  }
500 
501  if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeUnit" ) ) )
502  {
503  d->fontSizeUnits = textStyleElem.attribute( QStringLiteral( "fontSizeInMapUnits" ) ).toUInt() == 0 ? QgsUnitTypes::RenderPoints
505  }
506  else
507  {
508  d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( QStringLiteral( "fontSizeUnit" ) ) );
509  }
510 
511  if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeMapUnitScale" ) ) )
512  {
513  //fallback to older property
514  double oldMin = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
515  d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
516  double oldMax = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
517  d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
518  }
519  else
520  {
521  d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitScale" ) ) );
522  }
523  int fontWeight = textStyleElem.attribute( QStringLiteral( "fontWeight" ) ).toInt();
524  bool fontItalic = textStyleElem.attribute( QStringLiteral( "fontItalic" ) ).toInt();
525  d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
526  d->textFont.setPointSizeF( d->fontSize ); //double precision needed because of map units
527  d->textNamedStyle = QgsFontUtils::translateNamedStyle( textStyleElem.attribute( QStringLiteral( "namedStyle" ) ) );
528  QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
529  d->textFont.setUnderline( textStyleElem.attribute( QStringLiteral( "fontUnderline" ) ).toInt() );
530  d->textFont.setStrikeOut( textStyleElem.attribute( QStringLiteral( "fontStrikeout" ) ).toInt() );
531  d->textFont.setKerning( textStyleElem.attribute( QStringLiteral( "fontKerning" ), QStringLiteral( "1" ) ).toInt() );
532  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( QStringLiteral( "fontLetterSpacing" ), QStringLiteral( "0" ) ).toDouble() );
533  d->textFont.setWordSpacing( textStyleElem.attribute( QStringLiteral( "fontWordSpacing" ), QStringLiteral( "0" ) ).toDouble() );
534  d->textColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( Qt::black ) ) );
535  if ( !textStyleElem.hasAttribute( QStringLiteral( "textOpacity" ) ) )
536  {
537  d->opacity = ( 1 - textStyleElem.attribute( QStringLiteral( "textTransp" ) ).toInt() / 100.0 ); //0 -100
538  }
539  else
540  {
541  d->opacity = ( textStyleElem.attribute( QStringLiteral( "textOpacity" ) ).toDouble() );
542  }
543  d->orientation = QgsTextRendererUtils::decodeTextOrientation( textStyleElem.attribute( QStringLiteral( "textOrientation" ) ) );
544  d->previewBackgroundColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
545 
546  d->blendMode = QgsPainting::getCompositionMode(
547  static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( QStringLiteral( "blendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
548 
549  if ( !textStyleElem.hasAttribute( QStringLiteral( "multilineHeight" ) ) )
550  {
551  QDomElement textFormatElem = elem.firstChildElement( QStringLiteral( "text-format" ) );
552  d->multilineHeight = textFormatElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
553  }
554  else
555  {
556  d->multilineHeight = textStyleElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
557  }
558 
559  if ( textStyleElem.hasAttribute( QStringLiteral( "capitalization" ) ) )
560  d->capitalization = static_cast< QgsStringUtils::Capitalization >( textStyleElem.attribute( QStringLiteral( "capitalization" ), QString::number( QgsStringUtils::MixedCase ) ).toInt() );
561  else
562  d->capitalization = static_cast< QgsStringUtils::Capitalization >( textStyleElem.attribute( QStringLiteral( "fontCapitals" ), QStringLiteral( "0" ) ).toUInt() );
563 
564  d->allowHtmlFormatting = textStyleElem.attribute( QStringLiteral( "allowHtml" ), QStringLiteral( "0" ) ).toInt();
565 
566  if ( textStyleElem.firstChildElement( QStringLiteral( "text-buffer" ) ).isNull() )
567  {
568  mBufferSettings.readXml( elem );
569  }
570  else
571  {
572  mBufferSettings.readXml( textStyleElem );
573  }
574  if ( textStyleElem.firstChildElement( QStringLiteral( "text-mask" ) ).isNull() )
575  {
576  mMaskSettings.readXml( elem );
577  }
578  else
579  {
580  mMaskSettings.readXml( textStyleElem );
581  }
582  if ( textStyleElem.firstChildElement( QStringLiteral( "shadow" ) ).isNull() )
583  {
584  mShadowSettings.readXml( elem );
585  }
586  else
587  {
588  mShadowSettings.readXml( textStyleElem );
589  }
590  if ( textStyleElem.firstChildElement( QStringLiteral( "background" ) ).isNull() )
591  {
592  mBackgroundSettings.readXml( elem, context );
593  }
594  else
595  {
596  mBackgroundSettings.readXml( textStyleElem, context );
597  }
598 
599  QDomElement ddElem = textStyleElem.firstChildElement( QStringLiteral( "dd_properties" ) );
600  if ( ddElem.isNull() )
601  {
602  ddElem = elem.firstChildElement( QStringLiteral( "dd_properties" ) );
603  }
604  if ( !ddElem.isNull() )
605  {
606  d->mDataDefinedProperties.readXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
607  mBackgroundSettings.upgradeDataDefinedProperties( d->mDataDefinedProperties );
608  }
609  else
610  {
611  d->mDataDefinedProperties.clear();
612  }
613 }
614 
615 QDomElement QgsTextFormat::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
616 {
617  // text style
618  QDomElement textStyleElem = doc.createElement( QStringLiteral( "text-style" ) );
619  textStyleElem.setAttribute( QStringLiteral( "fontFamily" ), d->textFont.family() );
620 
621  QDomElement familiesElem = doc.createElement( QStringLiteral( "families" ) );
622  for ( const QString &family : std::as_const( d->families ) )
623  {
624  QDomElement familyElem = doc.createElement( QStringLiteral( "family" ) );
625  familyElem.setAttribute( QStringLiteral( "name" ), family );
626  familiesElem.appendChild( familyElem );
627  }
628  textStyleElem.appendChild( familiesElem );
629 
630  textStyleElem.setAttribute( QStringLiteral( "namedStyle" ), QgsFontUtils::untranslateNamedStyle( d->textNamedStyle ) );
631  textStyleElem.setAttribute( QStringLiteral( "fontSize" ), d->fontSize );
632  textStyleElem.setAttribute( QStringLiteral( "fontSizeUnit" ), QgsUnitTypes::encodeUnit( d->fontSizeUnits ) );
633  textStyleElem.setAttribute( QStringLiteral( "fontSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->fontSizeMapUnitScale ) );
634  textStyleElem.setAttribute( QStringLiteral( "fontWeight" ), d->textFont.weight() );
635  textStyleElem.setAttribute( QStringLiteral( "fontItalic" ), d->textFont.italic() );
636  textStyleElem.setAttribute( QStringLiteral( "fontStrikeout" ), d->textFont.strikeOut() );
637  textStyleElem.setAttribute( QStringLiteral( "fontUnderline" ), d->textFont.underline() );
638  textStyleElem.setAttribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( d->textColor ) );
639  textStyleElem.setAttribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( d->previewBackgroundColor ) );
640  textStyleElem.setAttribute( QStringLiteral( "fontLetterSpacing" ), d->textFont.letterSpacing() );
641  textStyleElem.setAttribute( QStringLiteral( "fontWordSpacing" ), d->textFont.wordSpacing() );
642  textStyleElem.setAttribute( QStringLiteral( "fontKerning" ), d->textFont.kerning() );
643  textStyleElem.setAttribute( QStringLiteral( "textOpacity" ), d->opacity );
644  textStyleElem.setAttribute( QStringLiteral( "textOrientation" ), QgsTextRendererUtils::encodeTextOrientation( d->orientation ) );
645  textStyleElem.setAttribute( QStringLiteral( "blendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
646  textStyleElem.setAttribute( QStringLiteral( "multilineHeight" ), d->multilineHeight );
647  textStyleElem.setAttribute( QStringLiteral( "allowHtml" ), d->allowHtmlFormatting ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
648  textStyleElem.setAttribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( d->capitalization ) ) );
649 
650  QDomElement ddElem = doc.createElement( QStringLiteral( "dd_properties" ) );
651  d->mDataDefinedProperties.writeXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
652 
653  textStyleElem.appendChild( mBufferSettings.writeXml( doc ) );
654  textStyleElem.appendChild( mMaskSettings.writeXml( doc ) );
655  textStyleElem.appendChild( mBackgroundSettings.writeXml( doc, context ) );
656  textStyleElem.appendChild( mShadowSettings.writeXml( doc ) );
657  textStyleElem.appendChild( ddElem );
658 
659  return textStyleElem;
660 }
661 
662 QMimeData *QgsTextFormat::toMimeData() const
663 {
664  //set both the mime color data, and the text (format settings).
665 
666  QMimeData *mimeData = new QMimeData;
667  mimeData->setColorData( QVariant( color() ) );
668 
669  QgsReadWriteContext rwContext;
670  QDomDocument textDoc;
671  QDomElement textElem = writeXml( textDoc, rwContext );
672  textDoc.appendChild( textElem );
673  mimeData->setText( textDoc.toString() );
674 
675  return mimeData;
676 }
677 
679 {
680  QgsTextFormat format;
681  format.setFont( font );
682  if ( font.pointSizeF() > 0 )
683  {
684  format.setSize( font.pointSizeF() );
686  }
687  else if ( font.pixelSize() > 0 )
688  {
689  format.setSize( font.pixelSize() );
691  }
692 
693  return format;
694 }
695 
697 {
698  QFont f = font();
699  switch ( sizeUnit() )
700  {
702  f.setPointSizeF( size() );
703  break;
704 
706  f.setPointSizeF( size() * 2.83464567 );
707  break;
708 
710  f.setPointSizeF( size() * 72 );
711  break;
712 
714  f.setPixelSize( static_cast< int >( std::round( size() ) ) );
715  break;
716 
721  // no meaning here
722  break;
723  }
724  return f;
725 }
726 
727 QgsTextFormat QgsTextFormat::fromMimeData( const QMimeData *data, bool *ok )
728 {
729  if ( ok )
730  *ok = false;
731  QgsTextFormat format;
732  if ( !data )
733  return format;
734 
735  QString text = data->text();
736  if ( !text.isEmpty() )
737  {
738  QDomDocument doc;
739  QDomElement elem;
740  QgsReadWriteContext rwContext;
741 
742  if ( doc.setContent( text ) )
743  {
744  elem = doc.documentElement();
745 
746  format.readXml( elem, rwContext );
747  if ( ok )
748  *ok = true;
749  return format;
750  }
751  }
752  return format;
753 }
754 
756 {
757  if ( d->blendMode != QPainter::CompositionMode_SourceOver )
758  return true;
759 
760  if ( mBufferSettings.enabled() && mBufferSettings.blendMode() != QPainter::CompositionMode_SourceOver )
761  return true;
762 
763  if ( mBackgroundSettings.enabled() && mBackgroundSettings.blendMode() != QPainter::CompositionMode_SourceOver )
764  return true;
765 
766  if ( mShadowSettings.enabled() && mShadowSettings.blendMode() != QPainter::CompositionMode_SourceOver )
767  return true;
768 
769  return false;
770 }
771 
773 {
774  d->isValid = true;
775  return d->mDataDefinedProperties;
776 }
777 
779 {
780  return d->mDataDefinedProperties;
781 }
782 
783 QSet<QString> QgsTextFormat::referencedFields( const QgsRenderContext &context ) const
784 {
785  QSet< QString > fields = d->mDataDefinedProperties.referencedFields( context.expressionContext(), true );
786  fields.unite( mBufferSettings.referencedFields( context ) );
787  fields.unite( mBackgroundSettings.referencedFields( context ) );
788  fields.unite( mShadowSettings.referencedFields( context ) );
789  fields.unite( mMaskSettings.referencedFields( context ) );
790  return fields;
791 }
792 
794 {
795  d->isValid = true;
796  d->mDataDefinedProperties = collection;
797 }
798 
800 {
801  d->isValid = true;
802  if ( !d->mDataDefinedProperties.hasActiveProperties() )
803  return;
804 
805  QString ddFontFamily;
806  context.expressionContext().setOriginalValueVariable( d->textFont.family() );
807  QVariant exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::Family, context.expressionContext() );
808  if ( !exprVal.isNull() )
809  {
810  QString family = exprVal.toString().trimmed();
811  if ( d->textFont.family() != family )
812  {
813  // testing for ddFontFamily in QFontDatabase.families() may be slow to do for every feature
814  // (i.e. don't use QgsFontUtils::fontFamilyMatchOnSystem( family ) here)
815  if ( QgsFontUtils::fontFamilyOnSystem( family ) )
816  {
817  ddFontFamily = family;
818  }
819  }
820  }
821 
822  // data defined named font style?
823  QString ddFontStyle;
824  context.expressionContext().setOriginalValueVariable( d->textNamedStyle );
825  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontStyle, context.expressionContext() );
826  if ( !exprVal.isNull() )
827  {
828  QString fontstyle = exprVal.toString().trimmed();
829  ddFontStyle = fontstyle;
830  }
831 
832  bool ddBold = false;
833  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Bold ) )
834  {
835  context.expressionContext().setOriginalValueVariable( d->textFont.bold() );
836  ddBold = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Bold, context.expressionContext(), false ) ;
837  }
838 
839  bool ddItalic = false;
840  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Italic ) )
841  {
842  context.expressionContext().setOriginalValueVariable( d->textFont.italic() );
843  ddItalic = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Italic, context.expressionContext(), false );
844  }
845 
846  // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
847  // (currently defaults to what has been read in from layer settings)
848  QFont newFont;
849  QFontDatabase fontDb;
850  QFont appFont = QApplication::font();
851  bool newFontBuilt = false;
852  if ( ddBold || ddItalic )
853  {
854  // new font needs built, since existing style needs removed
855  newFont = QFont( !ddFontFamily.isEmpty() ? ddFontFamily : d->textFont.family() );
856  newFontBuilt = true;
857  newFont.setBold( ddBold );
858  newFont.setItalic( ddItalic );
859  }
860  else if ( !ddFontStyle.isEmpty()
861  && ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
862  {
863  if ( !ddFontFamily.isEmpty() )
864  {
865  // both family and style are different, build font from database
866  QFont styledfont = fontDb.font( ddFontFamily, ddFontStyle, appFont.pointSize() );
867  if ( appFont != styledfont )
868  {
869  newFont = styledfont;
870  newFontBuilt = true;
871  }
872  }
873 
874  // update the font face style
875  QgsFontUtils::updateFontViaStyle( newFontBuilt ? newFont : d->textFont, ddFontStyle );
876  }
877  else if ( !ddFontFamily.isEmpty() )
878  {
879  if ( ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
880  {
881  // just family is different, build font from database
882  QFont styledfont = fontDb.font( ddFontFamily, d->textNamedStyle, appFont.pointSize() );
883  if ( appFont != styledfont )
884  {
885  newFont = styledfont;
886  newFontBuilt = true;
887  }
888  }
889  else
890  {
891  newFont = QFont( ddFontFamily );
892  newFontBuilt = true;
893  }
894  }
895 
896  if ( newFontBuilt )
897  {
898  // copy over existing font settings
899  newFont.setUnderline( d->textFont.underline() );
900  newFont.setStrikeOut( d->textFont.strikeOut() );
901  newFont.setWordSpacing( d->textFont.wordSpacing() );
902  newFont.setLetterSpacing( QFont::AbsoluteSpacing, d->textFont.letterSpacing() );
903  d->textFont = newFont;
904  }
905 
906  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Underline ) )
907  {
908  context.expressionContext().setOriginalValueVariable( d->textFont.underline() );
909  d->textFont.setUnderline( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Underline, context.expressionContext(), d->textFont.underline() ) );
910  }
911 
912  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Strikeout ) )
913  {
914  context.expressionContext().setOriginalValueVariable( d->textFont.strikeOut() );
915  d->textFont.setStrikeOut( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Strikeout, context.expressionContext(), d->textFont.strikeOut() ) );
916  }
917 
918  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Color ) )
919  {
921  d->textColor = d->mDataDefinedProperties.valueAsColor( QgsPalLayerSettings::Color, context.expressionContext(), d->textColor );
922  }
923 
924  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Size ) )
925  {
927  d->fontSize = d->mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::Size, context.expressionContext(), d->fontSize );
928  }
929 
930  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontSizeUnit, context.expressionContext() );
931  if ( !exprVal.isNull() )
932  {
933  QString units = exprVal.toString();
934  if ( !units.isEmpty() )
935  {
936  bool ok;
938  if ( ok )
939  d->fontSizeUnits = res;
940  }
941  }
942 
943  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontOpacity ) )
944  {
945  context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
946  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontOpacity, context.expressionContext(), d->opacity * 100 );
947  if ( !val.isNull() )
948  {
949  d->opacity = val.toDouble() / 100.0;
950  }
951  }
952 
953  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::TextOrientation ) )
954  {
955  const QString encoded = QgsTextRendererUtils::encodeTextOrientation( d->orientation );
956  context.expressionContext().setOriginalValueVariable( encoded );
957  d->orientation = QgsTextRendererUtils::decodeTextOrientation( d->mDataDefinedProperties.value( QgsPalLayerSettings::TextOrientation, context.expressionContext(), encoded ).toString() );
958  }
959 
960  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontLetterSpacing ) )
961  {
962  context.expressionContext().setOriginalValueVariable( d->textFont.letterSpacing() );
963  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontLetterSpacing, context.expressionContext(), d->textFont.letterSpacing() );
964  if ( !val.isNull() )
965  {
966  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, val.toDouble() );
967  }
968  }
969 
970  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontWordSpacing ) )
971  {
972  context.expressionContext().setOriginalValueVariable( d->textFont.wordSpacing() );
973  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontWordSpacing, context.expressionContext(), d->textFont.wordSpacing() );
974  if ( !val.isNull() )
975  {
976  d->textFont.setWordSpacing( val.toDouble() );
977  }
978  }
979 
980  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontBlendMode ) )
981  {
982  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontBlendMode, context.expressionContext() );
983  QString blendstr = exprVal.toString().trimmed();
984  if ( !blendstr.isEmpty() )
985  d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
986  }
987 
988  mShadowSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
989  mBackgroundSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
990  mBufferSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
991  mMaskSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
992 }
993 
994 QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText, int padding )
995 {
996  QgsTextFormat tempFormat = format;
997  QPixmap pixmap( size );
998  pixmap.fill( Qt::transparent );
999  QPainter painter;
1000  painter.begin( &pixmap );
1001 
1002  painter.setRenderHint( QPainter::Antialiasing );
1003 
1004  QRect rect( 0, 0, size.width(), size.height() );
1005 
1006  // shameless eye candy - use a subtle gradient when drawing background
1007  painter.setPen( Qt::NoPen );
1008  QColor background1 = tempFormat.previewBackgroundColor();
1009  if ( ( background1.lightnessF() < 0.7 ) )
1010  {
1011  background1 = background1.darker( 125 );
1012  }
1013  else
1014  {
1015  background1 = background1.lighter( 125 );
1016  }
1017  QColor background2 = tempFormat.previewBackgroundColor();
1018  QLinearGradient linearGrad( QPointF( 0, 0 ), QPointF( 0, rect.height() ) );
1019  linearGrad.setColorAt( 0, background1 );
1020  linearGrad.setColorAt( 1, background2 );
1021  painter.setBrush( QBrush( linearGrad ) );
1022  if ( size.width() > 30 )
1023  {
1024  painter.drawRoundedRect( rect, 6, 6 );
1025  }
1026  else
1027  {
1028  // don't use rounded rect for small previews
1029  painter.drawRect( rect );
1030  }
1031  painter.setBrush( Qt::NoBrush );
1032  painter.setPen( Qt::NoPen );
1033  padding += 1; // move text away from background border
1034 
1035  QgsRenderContext context;
1036  QgsMapToPixel newCoordXForm;
1037  newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
1038  context.setMapToPixel( newCoordXForm );
1039 
1040 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1041  const double logicalDpiX = QgsApplication::desktop()->logicalDpiX();
1042 #else
1043  QWidget *activeWindow = QApplication::activeWindow();
1044  const double logicalDpiX = activeWindow && activeWindow->screen() ? activeWindow->screen()->logicalDotsPerInchX() : 96.0;
1045 #endif
1046  context.setScaleFactor( logicalDpiX / 25.4 );
1047 
1048  context.setUseAdvancedEffects( true );
1050  context.setPainter( &painter );
1052 
1053  // slightly inset text to account for buffer/background
1054  double xtrans = 0;
1055  if ( tempFormat.buffer().enabled() )
1056  xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
1057  if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
1058  xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1059 
1060  double ytrans = 0.0;
1061  if ( tempFormat.buffer().enabled() )
1062  ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
1063  if ( tempFormat.background().enabled() )
1064  ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1065 
1066  const QStringList text = QStringList() << ( previewText.isEmpty() ? QObject::tr( "Aa" ) : previewText );
1067  const double textHeight = QgsTextRenderer::textHeight( context, tempFormat, text, QgsTextRenderer::Rect );
1068  QRectF textRect = rect;
1069  textRect.setLeft( xtrans + padding );
1070  textRect.setWidth( rect.width() - xtrans - 2 * padding );
1071 
1072  if ( textRect.width() > 2000 )
1073  textRect.setWidth( 2000 - 2 * padding );
1074 
1075  const double bottom = textRect.height() / 2 + textHeight / 2;
1076  textRect.setTop( bottom - textHeight );
1077  textRect.setBottom( bottom );
1078 
1079  QgsTextRenderer::drawText( textRect, 0, QgsTextRenderer::AlignCenter, text, context, tempFormat );
1080 
1081  // draw border on top of text
1082  painter.setBrush( Qt::NoBrush );
1083  painter.setPen( QPen( tempFormat.previewBackgroundColor().darker( 150 ), 0 ) );
1084  if ( size.width() > 30 )
1085  {
1086  painter.drawRoundedRect( rect, 6, 6 );
1087  }
1088  else
1089  {
1090  // don't use rounded rect for small previews
1091  painter.drawRect( rect );
1092  }
1093  painter.end();
1094  return pixmap;
1095 }
@ Antialiasing
Use antialiasing while drawing.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
static QString translateNamedStyle(const QString &namedStyle)
Returns the localized named style of a font, if such a translation is available.
static QString untranslateNamedStyle(const QString &namedStyle)
Returns the english named style of a font, if possible.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
static bool fontFamilyOnSystem(const QString &family)
Check whether font family is on system in a quick manner, which does not compare [foundry].
static bool updateFontViaStyle(QFont &f, const QString &fontstyle, bool fallback=false)
Updates font with named style and retain all font properties.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Sets parameters for use in transforming coordinates.
Struct for storing maximum and minimum scales for measurements in map units.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
@ Strikeout
Use strikeout.
@ FontStyle
Font style name.
@ Underline
Use underline.
@ FontLetterSpacing
Letter spacing.
@ Bold
Use bold style.
@ FontSizeUnit
Font size units.
@ Italic
Use italic style.
@ FontWordSpacing
Word spacing.
@ FontBlendMode
Text blend mode.
@ Family
Font family.
@ FontOpacity
Text opacity.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the labeling property definitions.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
The class is used as a container of context for various read/write operations on other objects.
void pushMessage(const QString &message, Qgis::MessageLevel level=Qgis::MessageLevel::Warning) const
Append a message to the context.
Contains information about the context of a rendering operation.
void setScaleFactor(double factor)
Sets the scaling factor for the render to convert painter units to physical sizes.
void setUseAdvancedEffects(bool enabled)
Used to enable or disable advanced effects such as blend modes.
QgsExpressionContext & expressionContext()
Gets the expression context.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
Capitalization
Capitalization options.
@ MixedCase
Mixed case, ie no change.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
static QColor decodeColor(const QString &str)
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
static QPainter::CompositionMode decodeBlendMode(const QString &s)
static QString encodeColor(const QColor &color)
Container for settings relating to a text background object.
QSizeF size() const
Returns the size of the background shape.
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
void upgradeDataDefinedProperties(QgsPropertyCollection &properties)
Upgrade data defined properties when reading a project file saved in QGIS prior to version 3....
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the background shape.
bool enabled() const
Returns whether the background is enabled.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
SizeType sizeType() const
Returns the method used to determine the size of the background shape (e.g., fixed size or buffer aro...
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the shape size.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units used for the shape's size.
Container for settings relating to a text buffer.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
double size() const
Returns the size of the buffer.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the buffer size.
bool enabled() const
Returns whether the buffer is enabled.
QDomElement writeXml(QDomDocument &doc) const
Write settings into a DOM element.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the buffer size.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the buffer.
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
void readXml(const QDomElement &elem)
Read settings from a DOM element.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
QgsTextFormat()
Default constructor for QgsTextFormat.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setBlendMode(QPainter::CompositionMode mode)
Sets the blending mode used for drawing the text.
void setSize(double size)
Sets the size for rendered text.
QgsMapUnitScale sizeMapUnitScale() const
Returns the map unit scale object for the size.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the format's property collection, used for data defined overrides.
QStringList families() const
Returns the list of font families to use when restoring the text format, in order of precedence.
void setFont(const QFont &font)
Sets the font used for rendering text.
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
void setFamilies(const QStringList &families)
Sets a list of font families to use for the text format, in order of precedence.
static QgsTextFormat fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QgsTextFormat.
double lineHeight() const
Returns the line height for text.
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the size of rendered text.
void setOrientation(TextOrientation orientation)
Sets the orientation for the text.
void updateDataDefinedProperties(QgsRenderContext &context)
Updates the format by evaluating current values of data defined properties.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the format's property collection, used for data defined overrides.
void setShadow(const QgsTextShadowSettings &shadowSettings)
Sets the text's drop shadow settings.
void setMask(const QgsTextMaskSettings &maskSettings)
Sets the text's masking settings.
void setPreviewBackgroundColor(const QColor &color)
Sets the background color that text will be rendered on for previews.
QFont scaledFont(const QgsRenderContext &context, double scaleFactor=1.0, bool *isZeroSize=nullptr) const
Returns a font with the size scaled to match the format's size settings (including units and map unit...
void setOpacity(double opacity)
Sets the text's opacity.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the text.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Read settings from a DOM element.
bool operator==(const QgsTextFormat &other) const
TextOrientation orientation() const
Returns the orientation of the text.
void setAllowHtmlFormatting(bool allow)
Sets whether text should be treated as a HTML document and HTML tags should be used for formatting th...
QgsTextMaskSettings & mask()
Returns a reference to the masking settings.
static QPixmap textFormatPreviewPixmap(const QgsTextFormat &format, QSize size, const QString &previewText=QString(), int padding=0)
Returns a pixmap preview for a text format.
bool isValid() const
Returns true if the format is valid.
void setCapitalization(QgsStringUtils::Capitalization capitalization)
Sets the text capitalization style.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
TextOrientation
Text orientation.
Definition: qgstextformat.h:46
static QgsTextFormat fromQFont(const QFont &font)
Returns a text format matching the settings from an input font.
void setValid()
Sets the format to a valid state, without changing any of the default format settings.
bool allowHtmlFormatting() const
Returns true if text should be treated as a HTML document and HTML tags should be used for formatting...
QFont toQFont() const
Returns a QFont matching the relevant settings from this text format.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
bool operator!=(const QgsTextFormat &other) const
double opacity() const
Returns the text's opacity.
QString namedStyle() const
Returns the named style for the font used for rendering text (e.g., "bold").
double size() const
Returns the size for rendered text.
QgsTextShadowSettings & shadow()
Returns a reference to the text drop shadow settings.
QgsTextFormat & operator=(const QgsTextFormat &other)
void setBackground(const QgsTextBackgroundSettings &backgroundSettings)
Sets the text's background settings.q.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Write settings into a DOM element.
QMimeData * toMimeData() const
Returns new mime data representing the text format settings.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the size.
void setNamedStyle(const QString &style)
Sets the named style for the font used for rendering text.
QgsStringUtils::Capitalization capitalization() const
Returns the text capitalization style.
QColor color() const
Returns the color that text will be rendered in.
QFont font() const
Returns the font used for rendering text.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
QColor previewBackgroundColor() const
Returns the background color for text previews.
bool containsAdvancedEffects() const
Returns true if any component of the font format requires advanced effects such as blend modes,...
QgsTextBufferSettings & buffer()
Returns a reference to the text buffer settings.
void setLineHeight(double height)
Sets the line height for text.
Container for settings relating to a selective masking around a text.
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
void readXml(const QDomElement &elem)
Read settings from a DOM element.
QDomElement writeXml(QDomDocument &doc) const
Write settings into a DOM element.
static QString encodeTextOrientation(QgsTextFormat::TextOrientation orientation)
Encodes a text orientation.
static QColor readColor(QgsVectorLayer *layer, const QString &property, const QColor &defaultColor=Qt::black, bool withAlpha=true)
Converts an encoded color value from a layer property.
static QgsTextFormat::TextOrientation decodeTextOrientation(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of a text orientation.
@ AlignCenter
Center align.
static double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, DrawMode mode=Point, QFontMetricsF *fontMetrics=nullptr)
Returns the height of a text based on a given format.
static int sizeToPixel(double size, const QgsRenderContext &c, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Calculates pixel size (considering output size should be in pixel or map units, scale factors and opt...
static void drawText(const QRectF &rect, double rotation, HAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, VAlignment vAlignment=AlignTop)
Draws text within a rectangle using the specified settings.
@ Rect
Text within rectangle draw mode.
Container for settings relating to a text shadow.
bool enabled() const
Returns whether the shadow is enabled.
void readXml(const QDomElement &elem)
Read settings from a DOM element.
QDomElement writeXml(QDomDocument &doc) const
Write settings into a DOM element.
void updateDataDefinedProperties(QgsRenderContext &context, const QgsPropertyCollection &properties)
Updates the format by evaluating current values of data defined properties.
QPainter::CompositionMode blendMode() const
Returns the blending mode used for drawing the drop shadow.
QSet< QString > referencedFields(const QgsRenderContext &context) const
Returns all field names referenced by the configuration (e.g.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
static Q_INVOKABLE QgsUnitTypes::RenderUnit decodeRenderUnit(const QString &string, bool *ok=nullptr)
Decodes a render unit from a string.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:168
@ RenderUnknownUnit
Mixed or unknown units.
Definition: qgsunittypes.h:175
@ RenderMetersInMapUnits
Meters value as Map units.
Definition: qgsunittypes.h:176
@ RenderPercentage
Percentage of another measurement (e.g., canvas size, feature size)
Definition: qgsunittypes.h:172
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
@ RenderInches
Inches.
Definition: qgsunittypes.h:174
@ RenderMillimeters
Millimeters.
Definition: qgsunittypes.h:169
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
Represents a vector layer which manages a vector based data sets.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:1234