QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 ) const
163 {
164  QFont font = d->textFont;
165  if ( scaleFactor == 1 )
166  {
167  int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits,
168  d->fontSizeMapUnitScale );
169  font.setPixelSize( fontPixelSize );
170  }
171  else
172  {
173  double fontPixelSize = context.convertToPainterUnits( d->fontSize, d->fontSizeUnits, d->fontSizeMapUnitScale );
174  font.setPixelSize( std::round( scaleFactor * fontPixelSize + 0.5 ) );
175  }
176 
177  font.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( d->textFont.letterSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor );
178  font.setWordSpacing( context.convertToPainterUnits( d->textFont.wordSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor * scaleFactor );
179 
180  return font;
181 }
182 
183 void QgsTextFormat::setFont( const QFont &font )
184 {
185  d->isValid = true;
186  d->textFont = font;
187 }
188 
190 {
191  if ( !d->textNamedStyle.isEmpty() )
192  return d->textNamedStyle;
193 
194  QFontDatabase db;
195  return db.styleString( d->textFont );
196 }
197 
198 void QgsTextFormat::setNamedStyle( const QString &style )
199 {
200  d->isValid = true;
201  QgsFontUtils::updateFontViaStyle( d->textFont, style );
202  d->textNamedStyle = style;
203 }
204 
205 QStringList QgsTextFormat::families() const
206 {
207  return d->families;
208 }
209 
210 void QgsTextFormat::setFamilies( const QStringList &families )
211 {
212  d->isValid = true;
213  d->families = families;
214 }
215 
217 {
218  return d->fontSizeUnits;
219 }
220 
222 {
223  d->isValid = true;
224  d->fontSizeUnits = unit;
225 }
226 
228 {
229  return d->fontSizeMapUnitScale;
230 }
231 
233 {
234  d->isValid = true;
235  d->fontSizeMapUnitScale = scale;
236 }
237 
238 double QgsTextFormat::size() const
239 {
240  return d->fontSize;
241 }
242 
243 void QgsTextFormat::setSize( double size )
244 {
245  d->isValid = true;
246  d->fontSize = size;
247 }
248 
249 QColor QgsTextFormat::color() const
250 {
251  return d->textColor;
252 }
253 
254 void QgsTextFormat::setColor( const QColor &color )
255 {
256  d->isValid = true;
257  d->textColor = color;
258 }
259 
261 {
262  return d->opacity;
263 }
264 
265 void QgsTextFormat::setOpacity( double opacity )
266 {
267  d->isValid = true;
268  d->opacity = opacity;
269 }
270 
271 QPainter::CompositionMode QgsTextFormat::blendMode() const
272 {
273  return d->blendMode;
274 }
275 
276 void QgsTextFormat::setBlendMode( QPainter::CompositionMode mode )
277 {
278  d->isValid = true;
279  d->blendMode = mode;
280 }
281 
283 {
284  return d->multilineHeight;
285 }
286 
287 void QgsTextFormat::setLineHeight( double height )
288 {
289  d->isValid = true;
290  d->multilineHeight = height;
291 }
292 
294 {
295  return d->orientation;
296 }
297 
299 {
300  d->isValid = true;
301  d->orientation = orientation;
302 }
303 
305 {
306  // bit of complexity here to maintain API..
307  return d->capitalization == QgsStringUtils::MixedCase && d->textFont.capitalization() != QFont::MixedCase ? static_cast< QgsStringUtils::Capitalization >( d->textFont.capitalization() ) : d->capitalization ;
308 }
309 
311 {
312  d->isValid = true;
313  d->capitalization = capitalization;
314  d->textFont.setCapitalization( QFont::MixedCase );
315 }
316 
318 {
319  return d->allowHtmlFormatting;
320 }
321 
323 {
324  d->isValid = true;
325  d->allowHtmlFormatting = allow;
326 }
327 
329 {
330  return d->previewBackgroundColor;
331 }
332 
333 void QgsTextFormat::setPreviewBackgroundColor( const QColor &color )
334 {
335  d->isValid = true;
336  d->previewBackgroundColor = color;
337 }
338 
340 {
341  d->isValid = true;
342  QFont appFont = QApplication::font();
343  mTextFontFamily = layer->customProperty( QStringLiteral( "labeling/fontFamily" ), QVariant( appFont.family() ) ).toString();
344  QString fontFamily = mTextFontFamily;
345  if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
346  {
347  // trigger to notify about font family substitution
348  mTextFontFound = false;
349 
350  // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
351  // currently only defaults to matching algorithm for resolving [foundry], if a font of similar family is found (default for QFont)
352 
353  // for now, do not use matching algorithm for substitution if family not found, substitute default instead
354  fontFamily = appFont.family();
355  }
356  else
357  {
358  mTextFontFound = true;
359  }
360 
361  if ( !layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).isValid() )
362  {
363  d->fontSize = appFont.pointSizeF();
364  }
365  else
366  {
367  d->fontSize = layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).toDouble();
368  }
369 
370  if ( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString().isEmpty() )
371  {
372  d->fontSizeUnits = layer->customProperty( QStringLiteral( "labeling/fontSizeInMapUnits" ), QVariant( false ) ).toBool() ?
374  }
375  else
376  {
377  bool ok = false;
378  d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString(), &ok );
379  if ( !ok )
380  d->fontSizeUnits = QgsUnitTypes::RenderPoints;
381  }
382  if ( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString().isEmpty() )
383  {
384  //fallback to older property
385  double oldMin = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMinScale" ), 0.0 ).toDouble();
386  d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
387  double oldMax = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMaxScale" ), 0.0 ).toDouble();
388  d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
389  }
390  else
391  {
392  d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString() );
393  }
394  int fontWeight = layer->customProperty( QStringLiteral( "labeling/fontWeight" ) ).toInt();
395  bool fontItalic = layer->customProperty( QStringLiteral( "labeling/fontItalic" ) ).toBool();
396  d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
397  d->textNamedStyle = QgsFontUtils::translateNamedStyle( layer->customProperty( QStringLiteral( "labeling/namedStyle" ), QVariant( "" ) ).toString() );
398  QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
399  d->capitalization = static_cast< QgsStringUtils::Capitalization >( layer->customProperty( QStringLiteral( "labeling/fontCapitals" ), QVariant( 0 ) ).toUInt() );
400  d->textFont.setUnderline( layer->customProperty( QStringLiteral( "labeling/fontUnderline" ) ).toBool() );
401  d->textFont.setStrikeOut( layer->customProperty( QStringLiteral( "labeling/fontStrikeout" ) ).toBool() );
402  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( QStringLiteral( "labeling/fontLetterSpacing" ), QVariant( 0.0 ) ).toDouble() );
403  d->textFont.setWordSpacing( layer->customProperty( QStringLiteral( "labeling/fontWordSpacing" ), QVariant( 0.0 ) ).toDouble() );
404  d->textColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/textColor" ), Qt::black, false );
405  if ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toString().isEmpty() )
406  {
407  d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/textTransp" ) ).toInt() / 100.0 ); //0 -100
408  }
409  else
410  {
411  d->opacity = ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toDouble() );
412  }
413  d->blendMode = QgsPainting::getCompositionMode(
414  static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/blendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
415  d->multilineHeight = layer->customProperty( QStringLiteral( "labeling/multilineHeight" ), QVariant( 1.0 ) ).toDouble();
416  d->previewBackgroundColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/previewBkgrdColor" ), QColor( 255, 255, 255 ), false );
417 
418  mBufferSettings.readFromLayer( layer );
419  mShadowSettings.readFromLayer( layer );
420  mBackgroundSettings.readFromLayer( layer );
421 }
422 
423 void QgsTextFormat::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
424 {
425  d->isValid = true;
426  QDomElement textStyleElem;
427  if ( elem.nodeName() == QLatin1String( "text-style" ) )
428  textStyleElem = elem;
429  else
430  textStyleElem = elem.firstChildElement( QStringLiteral( "text-style" ) );
431  QFont appFont = QApplication::font();
432  mTextFontFamily = textStyleElem.attribute( QStringLiteral( "fontFamily" ), appFont.family() );
433  QString fontFamily = mTextFontFamily;
434 
435  const QDomElement familiesElem = textStyleElem.firstChildElement( QStringLiteral( "families" ) );
436  const QDomNodeList familyNodes = familiesElem.childNodes();
437  QStringList families;
438  families.reserve( familyNodes.size() );
439  for ( int i = 0; i < familyNodes.count(); ++i )
440  {
441  const QDomElement familyElem = familyNodes.at( i ).toElement();
442  families << familyElem.attribute( QStringLiteral( "name" ) );
443  }
444  d->families = families;
445 
446  mTextFontFound = false;
447  if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
448  {
449  for ( const QString &family : std::as_const( families ) )
450  {
452  {
453  mTextFontFound = true;
454  fontFamily = family;
455  break;
456  }
457  }
458 
459  if ( !mTextFontFound )
460  {
461  // couldn't even find a matching font in the backup list -- substitute default instead
462  fontFamily = appFont.family();
463  }
464  }
465  else
466  {
467  mTextFontFound = true;
468  }
469 
470  if ( !mTextFontFound )
471  {
472  context.pushMessage( QObject::tr( "Font “%1” not available on system" ).arg( mTextFontFamily ) );
473  }
474 
475  if ( textStyleElem.hasAttribute( QStringLiteral( "fontSize" ) ) )
476  {
477  d->fontSize = textStyleElem.attribute( QStringLiteral( "fontSize" ) ).toDouble();
478  }
479  else
480  {
481  d->fontSize = appFont.pointSizeF();
482  }
483 
484  if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeUnit" ) ) )
485  {
486  d->fontSizeUnits = textStyleElem.attribute( QStringLiteral( "fontSizeInMapUnits" ) ).toUInt() == 0 ? QgsUnitTypes::RenderPoints
488  }
489  else
490  {
491  d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( QStringLiteral( "fontSizeUnit" ) ) );
492  }
493 
494  if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeMapUnitScale" ) ) )
495  {
496  //fallback to older property
497  double oldMin = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
498  d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
499  double oldMax = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
500  d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
501  }
502  else
503  {
504  d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitScale" ) ) );
505  }
506  int fontWeight = textStyleElem.attribute( QStringLiteral( "fontWeight" ) ).toInt();
507  bool fontItalic = textStyleElem.attribute( QStringLiteral( "fontItalic" ) ).toInt();
508  d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
509  d->textFont.setPointSizeF( d->fontSize ); //double precision needed because of map units
510  d->textNamedStyle = QgsFontUtils::translateNamedStyle( textStyleElem.attribute( QStringLiteral( "namedStyle" ) ) );
511  QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
512  d->textFont.setUnderline( textStyleElem.attribute( QStringLiteral( "fontUnderline" ) ).toInt() );
513  d->textFont.setStrikeOut( textStyleElem.attribute( QStringLiteral( "fontStrikeout" ) ).toInt() );
514  d->textFont.setKerning( textStyleElem.attribute( QStringLiteral( "fontKerning" ), QStringLiteral( "1" ) ).toInt() );
515  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( QStringLiteral( "fontLetterSpacing" ), QStringLiteral( "0" ) ).toDouble() );
516  d->textFont.setWordSpacing( textStyleElem.attribute( QStringLiteral( "fontWordSpacing" ), QStringLiteral( "0" ) ).toDouble() );
517  d->textColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( Qt::black ) ) );
518  if ( !textStyleElem.hasAttribute( QStringLiteral( "textOpacity" ) ) )
519  {
520  d->opacity = ( 1 - textStyleElem.attribute( QStringLiteral( "textTransp" ) ).toInt() / 100.0 ); //0 -100
521  }
522  else
523  {
524  d->opacity = ( textStyleElem.attribute( QStringLiteral( "textOpacity" ) ).toDouble() );
525  }
526  d->orientation = QgsTextRendererUtils::decodeTextOrientation( textStyleElem.attribute( QStringLiteral( "textOrientation" ) ) );
527  d->previewBackgroundColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
528 
529  d->blendMode = QgsPainting::getCompositionMode(
530  static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( QStringLiteral( "blendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
531 
532  if ( !textStyleElem.hasAttribute( QStringLiteral( "multilineHeight" ) ) )
533  {
534  QDomElement textFormatElem = elem.firstChildElement( QStringLiteral( "text-format" ) );
535  d->multilineHeight = textFormatElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
536  }
537  else
538  {
539  d->multilineHeight = textStyleElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
540  }
541 
542  if ( textStyleElem.hasAttribute( QStringLiteral( "capitalization" ) ) )
543  d->capitalization = static_cast< QgsStringUtils::Capitalization >( textStyleElem.attribute( QStringLiteral( "capitalization" ), QString::number( QgsStringUtils::MixedCase ) ).toInt() );
544  else
545  d->capitalization = static_cast< QgsStringUtils::Capitalization >( textStyleElem.attribute( QStringLiteral( "fontCapitals" ), QStringLiteral( "0" ) ).toUInt() );
546 
547  d->allowHtmlFormatting = textStyleElem.attribute( QStringLiteral( "allowHtml" ), QStringLiteral( "0" ) ).toInt();
548 
549  if ( textStyleElem.firstChildElement( QStringLiteral( "text-buffer" ) ).isNull() )
550  {
551  mBufferSettings.readXml( elem );
552  }
553  else
554  {
555  mBufferSettings.readXml( textStyleElem );
556  }
557  if ( textStyleElem.firstChildElement( QStringLiteral( "text-mask" ) ).isNull() )
558  {
559  mMaskSettings.readXml( elem );
560  }
561  else
562  {
563  mMaskSettings.readXml( textStyleElem );
564  }
565  if ( textStyleElem.firstChildElement( QStringLiteral( "shadow" ) ).isNull() )
566  {
567  mShadowSettings.readXml( elem );
568  }
569  else
570  {
571  mShadowSettings.readXml( textStyleElem );
572  }
573  if ( textStyleElem.firstChildElement( QStringLiteral( "background" ) ).isNull() )
574  {
575  mBackgroundSettings.readXml( elem, context );
576  }
577  else
578  {
579  mBackgroundSettings.readXml( textStyleElem, context );
580  }
581 
582  QDomElement ddElem = textStyleElem.firstChildElement( QStringLiteral( "dd_properties" ) );
583  if ( ddElem.isNull() )
584  {
585  ddElem = elem.firstChildElement( QStringLiteral( "dd_properties" ) );
586  }
587  if ( !ddElem.isNull() )
588  {
589  d->mDataDefinedProperties.readXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
590  mBackgroundSettings.upgradeDataDefinedProperties( d->mDataDefinedProperties );
591  }
592  else
593  {
594  d->mDataDefinedProperties.clear();
595  }
596 }
597 
598 QDomElement QgsTextFormat::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
599 {
600  // text style
601  QDomElement textStyleElem = doc.createElement( QStringLiteral( "text-style" ) );
602  textStyleElem.setAttribute( QStringLiteral( "fontFamily" ), d->textFont.family() );
603 
604  QDomElement familiesElem = doc.createElement( QStringLiteral( "families" ) );
605  for ( const QString &family : std::as_const( d->families ) )
606  {
607  QDomElement familyElem = doc.createElement( QStringLiteral( "family" ) );
608  familyElem.setAttribute( QStringLiteral( "name" ), family );
609  familiesElem.appendChild( familyElem );
610  }
611  textStyleElem.appendChild( familiesElem );
612 
613  textStyleElem.setAttribute( QStringLiteral( "namedStyle" ), QgsFontUtils::untranslateNamedStyle( d->textNamedStyle ) );
614  textStyleElem.setAttribute( QStringLiteral( "fontSize" ), d->fontSize );
615  textStyleElem.setAttribute( QStringLiteral( "fontSizeUnit" ), QgsUnitTypes::encodeUnit( d->fontSizeUnits ) );
616  textStyleElem.setAttribute( QStringLiteral( "fontSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->fontSizeMapUnitScale ) );
617  textStyleElem.setAttribute( QStringLiteral( "fontWeight" ), d->textFont.weight() );
618  textStyleElem.setAttribute( QStringLiteral( "fontItalic" ), d->textFont.italic() );
619  textStyleElem.setAttribute( QStringLiteral( "fontStrikeout" ), d->textFont.strikeOut() );
620  textStyleElem.setAttribute( QStringLiteral( "fontUnderline" ), d->textFont.underline() );
621  textStyleElem.setAttribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( d->textColor ) );
622  textStyleElem.setAttribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( d->previewBackgroundColor ) );
623  textStyleElem.setAttribute( QStringLiteral( "fontLetterSpacing" ), d->textFont.letterSpacing() );
624  textStyleElem.setAttribute( QStringLiteral( "fontWordSpacing" ), d->textFont.wordSpacing() );
625  textStyleElem.setAttribute( QStringLiteral( "fontKerning" ), d->textFont.kerning() );
626  textStyleElem.setAttribute( QStringLiteral( "textOpacity" ), d->opacity );
627  textStyleElem.setAttribute( QStringLiteral( "textOrientation" ), QgsTextRendererUtils::encodeTextOrientation( d->orientation ) );
628  textStyleElem.setAttribute( QStringLiteral( "blendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
629  textStyleElem.setAttribute( QStringLiteral( "multilineHeight" ), d->multilineHeight );
630  textStyleElem.setAttribute( QStringLiteral( "allowHtml" ), d->allowHtmlFormatting ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
631  textStyleElem.setAttribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( d->capitalization ) ) );
632 
633  QDomElement ddElem = doc.createElement( QStringLiteral( "dd_properties" ) );
634  d->mDataDefinedProperties.writeXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
635 
636  textStyleElem.appendChild( mBufferSettings.writeXml( doc ) );
637  textStyleElem.appendChild( mMaskSettings.writeXml( doc ) );
638  textStyleElem.appendChild( mBackgroundSettings.writeXml( doc, context ) );
639  textStyleElem.appendChild( mShadowSettings.writeXml( doc ) );
640  textStyleElem.appendChild( ddElem );
641 
642  return textStyleElem;
643 }
644 
645 QMimeData *QgsTextFormat::toMimeData() const
646 {
647  //set both the mime color data, and the text (format settings).
648 
649  QMimeData *mimeData = new QMimeData;
650  mimeData->setColorData( QVariant( color() ) );
651 
652  QgsReadWriteContext rwContext;
653  QDomDocument textDoc;
654  QDomElement textElem = writeXml( textDoc, rwContext );
655  textDoc.appendChild( textElem );
656  mimeData->setText( textDoc.toString() );
657 
658  return mimeData;
659 }
660 
662 {
663  QgsTextFormat format;
664  format.setFont( font );
665  if ( font.pointSizeF() > 0 )
666  {
667  format.setSize( font.pointSizeF() );
669  }
670  else if ( font.pixelSize() > 0 )
671  {
672  format.setSize( font.pixelSize() );
674  }
675 
676  return format;
677 }
678 
680 {
681  QFont f = font();
682  switch ( sizeUnit() )
683  {
685  f.setPointSizeF( size() );
686  break;
687 
689  f.setPointSizeF( size() * 2.83464567 );
690  break;
691 
693  f.setPointSizeF( size() * 72 );
694  break;
695 
697  f.setPixelSize( static_cast< int >( std::round( size() ) ) );
698  break;
699 
704  // no meaning here
705  break;
706  }
707  return f;
708 }
709 
710 QgsTextFormat QgsTextFormat::fromMimeData( const QMimeData *data, bool *ok )
711 {
712  if ( ok )
713  *ok = false;
714  QgsTextFormat format;
715  if ( !data )
716  return format;
717 
718  QString text = data->text();
719  if ( !text.isEmpty() )
720  {
721  QDomDocument doc;
722  QDomElement elem;
723  QgsReadWriteContext rwContext;
724 
725  if ( doc.setContent( text ) )
726  {
727  elem = doc.documentElement();
728 
729  format.readXml( elem, rwContext );
730  if ( ok )
731  *ok = true;
732  return format;
733  }
734  }
735  return format;
736 }
737 
739 {
740  if ( d->blendMode != QPainter::CompositionMode_SourceOver )
741  return true;
742 
743  if ( mBufferSettings.enabled() && mBufferSettings.blendMode() != QPainter::CompositionMode_SourceOver )
744  return true;
745 
746  if ( mBackgroundSettings.enabled() && mBackgroundSettings.blendMode() != QPainter::CompositionMode_SourceOver )
747  return true;
748 
749  if ( mShadowSettings.enabled() && mShadowSettings.blendMode() != QPainter::CompositionMode_SourceOver )
750  return true;
751 
752  return false;
753 }
754 
756 {
757  d->isValid = true;
758  return d->mDataDefinedProperties;
759 }
760 
762 {
763  return d->mDataDefinedProperties;
764 }
765 
766 QSet<QString> QgsTextFormat::referencedFields( const QgsRenderContext &context ) const
767 {
768  QSet< QString > fields = d->mDataDefinedProperties.referencedFields( context.expressionContext(), true );
769  fields.unite( mBufferSettings.referencedFields( context ) );
770  fields.unite( mBackgroundSettings.referencedFields( context ) );
771  fields.unite( mShadowSettings.referencedFields( context ) );
772  fields.unite( mMaskSettings.referencedFields( context ) );
773  return fields;
774 }
775 
777 {
778  d->isValid = true;
779  d->mDataDefinedProperties = collection;
780 }
781 
783 {
784  d->isValid = true;
785  if ( !d->mDataDefinedProperties.hasActiveProperties() )
786  return;
787 
788  QString ddFontFamily;
789  context.expressionContext().setOriginalValueVariable( d->textFont.family() );
790  QVariant exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::Family, context.expressionContext() );
791  if ( !exprVal.isNull() )
792  {
793  QString family = exprVal.toString().trimmed();
794  if ( d->textFont.family() != family )
795  {
796  // testing for ddFontFamily in QFontDatabase.families() may be slow to do for every feature
797  // (i.e. don't use QgsFontUtils::fontFamilyMatchOnSystem( family ) here)
798  if ( QgsFontUtils::fontFamilyOnSystem( family ) )
799  {
800  ddFontFamily = family;
801  }
802  }
803  }
804 
805  // data defined named font style?
806  QString ddFontStyle;
807  context.expressionContext().setOriginalValueVariable( d->textNamedStyle );
808  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontStyle, context.expressionContext() );
809  if ( !exprVal.isNull() )
810  {
811  QString fontstyle = exprVal.toString().trimmed();
812  ddFontStyle = fontstyle;
813  }
814 
815  bool ddBold = false;
816  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Bold ) )
817  {
818  context.expressionContext().setOriginalValueVariable( d->textFont.bold() );
819  ddBold = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Bold, context.expressionContext(), false ) ;
820  }
821 
822  bool ddItalic = false;
823  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Italic ) )
824  {
825  context.expressionContext().setOriginalValueVariable( d->textFont.italic() );
826  ddItalic = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Italic, context.expressionContext(), false );
827  }
828 
829  // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
830  // (currently defaults to what has been read in from layer settings)
831  QFont newFont;
832  QFontDatabase fontDb;
833  QFont appFont = QApplication::font();
834  bool newFontBuilt = false;
835  if ( ddBold || ddItalic )
836  {
837  // new font needs built, since existing style needs removed
838  newFont = QFont( !ddFontFamily.isEmpty() ? ddFontFamily : d->textFont.family() );
839  newFontBuilt = true;
840  newFont.setBold( ddBold );
841  newFont.setItalic( ddItalic );
842  }
843  else if ( !ddFontStyle.isEmpty()
844  && ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
845  {
846  if ( !ddFontFamily.isEmpty() )
847  {
848  // both family and style are different, build font from database
849  QFont styledfont = fontDb.font( ddFontFamily, ddFontStyle, appFont.pointSize() );
850  if ( appFont != styledfont )
851  {
852  newFont = styledfont;
853  newFontBuilt = true;
854  }
855  }
856 
857  // update the font face style
858  QgsFontUtils::updateFontViaStyle( newFontBuilt ? newFont : d->textFont, ddFontStyle );
859  }
860  else if ( !ddFontFamily.isEmpty() )
861  {
862  if ( ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
863  {
864  // just family is different, build font from database
865  QFont styledfont = fontDb.font( ddFontFamily, d->textNamedStyle, appFont.pointSize() );
866  if ( appFont != styledfont )
867  {
868  newFont = styledfont;
869  newFontBuilt = true;
870  }
871  }
872  else
873  {
874  newFont = QFont( ddFontFamily );
875  newFontBuilt = true;
876  }
877  }
878 
879  if ( newFontBuilt )
880  {
881  // copy over existing font settings
882  newFont.setUnderline( d->textFont.underline() );
883  newFont.setStrikeOut( d->textFont.strikeOut() );
884  newFont.setWordSpacing( d->textFont.wordSpacing() );
885  newFont.setLetterSpacing( QFont::AbsoluteSpacing, d->textFont.letterSpacing() );
886  d->textFont = newFont;
887  }
888 
889  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Underline ) )
890  {
891  context.expressionContext().setOriginalValueVariable( d->textFont.underline() );
892  d->textFont.setUnderline( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Underline, context.expressionContext(), d->textFont.underline() ) );
893  }
894 
895  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Strikeout ) )
896  {
897  context.expressionContext().setOriginalValueVariable( d->textFont.strikeOut() );
898  d->textFont.setStrikeOut( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Strikeout, context.expressionContext(), d->textFont.strikeOut() ) );
899  }
900 
901  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Color ) )
902  {
904  d->textColor = d->mDataDefinedProperties.valueAsColor( QgsPalLayerSettings::Color, context.expressionContext(), d->textColor );
905  }
906 
907  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Size ) )
908  {
910  d->fontSize = d->mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::Size, context.expressionContext(), d->fontSize );
911  }
912 
913  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontSizeUnit, context.expressionContext() );
914  if ( !exprVal.isNull() )
915  {
916  QString units = exprVal.toString();
917  if ( !units.isEmpty() )
918  {
919  bool ok;
921  if ( ok )
922  d->fontSizeUnits = res;
923  }
924  }
925 
926  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontOpacity ) )
927  {
928  context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
929  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontOpacity, context.expressionContext(), d->opacity * 100 );
930  if ( !val.isNull() )
931  {
932  d->opacity = val.toDouble() / 100.0;
933  }
934  }
935 
936  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::TextOrientation ) )
937  {
938  const QString encoded = QgsTextRendererUtils::encodeTextOrientation( d->orientation );
939  context.expressionContext().setOriginalValueVariable( encoded );
940  d->orientation = QgsTextRendererUtils::decodeTextOrientation( d->mDataDefinedProperties.value( QgsPalLayerSettings::TextOrientation, context.expressionContext(), encoded ).toString() );
941  }
942 
943  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontLetterSpacing ) )
944  {
945  context.expressionContext().setOriginalValueVariable( d->textFont.letterSpacing() );
946  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontLetterSpacing, context.expressionContext(), d->textFont.letterSpacing() );
947  if ( !val.isNull() )
948  {
949  d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, val.toDouble() );
950  }
951  }
952 
953  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontWordSpacing ) )
954  {
955  context.expressionContext().setOriginalValueVariable( d->textFont.wordSpacing() );
956  const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontWordSpacing, context.expressionContext(), d->textFont.wordSpacing() );
957  if ( !val.isNull() )
958  {
959  d->textFont.setWordSpacing( val.toDouble() );
960  }
961  }
962 
963  if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontBlendMode ) )
964  {
965  exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontBlendMode, context.expressionContext() );
966  QString blendstr = exprVal.toString().trimmed();
967  if ( !blendstr.isEmpty() )
968  d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
969  }
970 
971  mShadowSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
972  mBackgroundSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
973  mBufferSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
974  mMaskSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
975 }
976 
977 QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText, int padding )
978 {
979  QgsTextFormat tempFormat = format;
980  QPixmap pixmap( size );
981  pixmap.fill( Qt::transparent );
982  QPainter painter;
983  painter.begin( &pixmap );
984 
985  painter.setRenderHint( QPainter::Antialiasing );
986 
987  QRect rect( 0, 0, size.width(), size.height() );
988 
989  // shameless eye candy - use a subtle gradient when drawing background
990  painter.setPen( Qt::NoPen );
991  QColor background1 = tempFormat.previewBackgroundColor();
992  if ( ( background1.lightnessF() < 0.7 ) )
993  {
994  background1 = background1.darker( 125 );
995  }
996  else
997  {
998  background1 = background1.lighter( 125 );
999  }
1000  QColor background2 = tempFormat.previewBackgroundColor();
1001  QLinearGradient linearGrad( QPointF( 0, 0 ), QPointF( 0, rect.height() ) );
1002  linearGrad.setColorAt( 0, background1 );
1003  linearGrad.setColorAt( 1, background2 );
1004  painter.setBrush( QBrush( linearGrad ) );
1005  if ( size.width() > 30 )
1006  {
1007  painter.drawRoundedRect( rect, 6, 6 );
1008  }
1009  else
1010  {
1011  // don't use rounded rect for small previews
1012  painter.drawRect( rect );
1013  }
1014  painter.setBrush( Qt::NoBrush );
1015  painter.setPen( Qt::NoPen );
1016  padding += 1; // move text away from background border
1017 
1018  QgsRenderContext context;
1019  QgsMapToPixel newCoordXForm;
1020  newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
1021  context.setMapToPixel( newCoordXForm );
1022 
1023 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1024  const double logicalDpiX = QgsApplication::desktop()->logicalDpiX();
1025 #else
1026  QWidget *activeWindow = QApplication::activeWindow();
1027  const double logicalDpiX = activeWindow && activeWindow->screen() ? activeWindow->screen()->logicalDotsPerInchX() : 96.0;
1028 #endif
1029  context.setScaleFactor( logicalDpiX / 25.4 );
1030 
1031  context.setUseAdvancedEffects( true );
1032  context.setFlag( QgsRenderContext::Antialiasing, true );
1033  context.setPainter( &painter );
1034  context.setFlag( QgsRenderContext::Antialiasing, true );
1035 
1036  // slightly inset text to account for buffer/background
1037  double xtrans = 0;
1038  if ( tempFormat.buffer().enabled() )
1039  xtrans = context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
1040  if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
1041  xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1042 
1043  double ytrans = 0.0;
1044  if ( tempFormat.buffer().enabled() )
1045  ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
1046  if ( tempFormat.background().enabled() )
1047  ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1048 
1049  const QStringList text = QStringList() << ( previewText.isEmpty() ? QObject::tr( "Aa" ) : previewText );
1050  const double textHeight = QgsTextRenderer::textHeight( context, tempFormat, text, QgsTextRenderer::Rect );
1051  QRectF textRect = rect;
1052  textRect.setLeft( xtrans + padding );
1053  textRect.setWidth( rect.width() - xtrans - 2 * padding );
1054 
1055  if ( textRect.width() > 2000 )
1056  textRect.setWidth( 2000 - 2 * padding );
1057 
1058  const double bottom = textRect.height() / 2 + textHeight / 2;
1059  textRect.setTop( bottom - textHeight );
1060  textRect.setBottom( bottom );
1061 
1062  QgsTextRenderer::drawText( textRect, 0, QgsTextRenderer::AlignCenter, text, context, tempFormat );
1063 
1064  // draw border on top of text
1065  painter.setBrush( Qt::NoBrush );
1066  painter.setPen( QPen( tempFormat.previewBackgroundColor().darker( 150 ), 0 ) );
1067  if ( size.width() > 30 )
1068  {
1069  painter.drawRoundedRect( rect, 6, 6 );
1070  }
1071  else
1072  {
1073  // don't use rounded rect for small previews
1074  painter.drawRect( rect );
1075  }
1076  painter.end();
1077  return pixmap;
1078 }
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)
Set 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.
void setFlag(Flag 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...
@ Antialiasing
Use antialiasing while drawing.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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.
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.
QFont scaledFont(const QgsRenderContext &context, double scaleFactor=1.0) const
Returns a font with the size scaled to match the format's size settings (including units and map unit...
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.