QGIS API Documentation 3.29.0-Master (ade4f0cf0f)
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"
24#include "qgspallabeling.h"
25#include "qgsconfig.h"
26#include "qgsfontmanager.h"
27#include "qgsapplication.h"
28
29#include <QFontDatabase>
30#include <QMimeData>
31#include <QWidget>
32#include <QScreen>
33
35{
36 d = new QgsTextSettingsPrivate();
37}
38
40 : mBufferSettings( other.mBufferSettings )
41 , mBackgroundSettings( other.mBackgroundSettings )
42 , mShadowSettings( other.mShadowSettings )
43 , mMaskSettings( other.mMaskSettings )
44 , mTextFontFamily( other.mTextFontFamily )
45 , mTextFontFound( other.mTextFontFound )
46 , d( other.d )
47{
48
49}
50
52{
53 d = other.d;
54 mBufferSettings = other.mBufferSettings;
55 mBackgroundSettings = other.mBackgroundSettings;
56 mShadowSettings = other.mShadowSettings;
57 mMaskSettings = other.mMaskSettings;
58 mTextFontFamily = other.mTextFontFamily;
59 mTextFontFound = other.mTextFontFound;
60 return *this;
61}
62
64{
65
66}
67
68bool QgsTextFormat::operator==( const QgsTextFormat &other ) const
69{
70 if ( d->isValid != other.isValid()
71 || d->textFont != other.font()
72 || namedStyle() != other.namedStyle()
73 || d->fontSizeUnits != other.sizeUnit()
74 || d->fontSizeMapUnitScale != other.sizeMapUnitScale()
75 || d->fontSize != other.size()
76 || d->textColor != other.color()
77 || d->opacity != other.opacity()
78 || d->blendMode != other.blendMode()
79 || d->multilineHeight != other.lineHeight()
80 || d->multilineHeightUnits != other.lineHeightUnit()
81 || d->orientation != other.orientation()
82 || d->previewBackgroundColor != other.previewBackgroundColor()
83 || d->allowHtmlFormatting != other.allowHtmlFormatting()
84 || d->forcedBold != other.forcedBold()
85 || d->forcedItalic != other.forcedItalic()
86 || d->capitalization != other.capitalization()
87 || mBufferSettings != other.mBufferSettings
88 || mBackgroundSettings != other.mBackgroundSettings
89 || mShadowSettings != other.mShadowSettings
90 || mMaskSettings != other.mMaskSettings
91 || d->families != other.families()
92 || d->mDataDefinedProperties != other.dataDefinedProperties() )
93 return false;
94
95 return true;
96}
97
98bool QgsTextFormat::operator!=( const QgsTextFormat &other ) const
99{
100 return !( *this == other );
101}
102
104{
105 return d->isValid;
106}
107
109{
110 d->isValid = true;
111}
112
114{
115 d->isValid = true;
116 return mBufferSettings;
117}
118
120{
121 d->isValid = true;
122 mBufferSettings = bufferSettings;
123}
124
126{
127 d->isValid = true;
128 return mBackgroundSettings;
129}
130
132{
133 d->isValid = true;
134 mBackgroundSettings = backgroundSettings;
135}
136
138{
139 d->isValid = true;
140 return mShadowSettings;
141}
142
144{
145 d->isValid = true;
146 mShadowSettings = shadowSettings;
147}
148
150{
151 d->isValid = true;
152 return mMaskSettings;
153}
154
156{
157 d->isValid = true;
158 mMaskSettings = maskSettings;
159}
160
162{
163 return d->textFont;
164}
165
166QFont QgsTextFormat::scaledFont( const QgsRenderContext &context, double scaleFactor, bool *isZeroSize ) const
167{
168 if ( isZeroSize )
169 *isZeroSize = false;
170
171 QFont font = d->textFont;
172 if ( scaleFactor == 1 )
173 {
174 int fontPixelSize = QgsTextRenderer::sizeToPixel( d->fontSize, context, d->fontSizeUnits,
175 d->fontSizeMapUnitScale );
176 if ( fontPixelSize == 0 )
177 {
178 if ( isZeroSize )
179 *isZeroSize = true;
180 return QFont();
181 }
182
183 font.setPixelSize( fontPixelSize );
184 }
185 else
186 {
187 double fontPixelSize = context.convertToPainterUnits( d->fontSize, d->fontSizeUnits, d->fontSizeMapUnitScale );
188 if ( qgsDoubleNear( fontPixelSize, 0 ) )
189 {
190 if ( isZeroSize )
191 *isZeroSize = true;
192 return QFont();
193 }
194 const int roundedPixelSize = static_cast< int >( std::round( scaleFactor * fontPixelSize + 0.5 ) );
195 font.setPixelSize( roundedPixelSize );
196 }
197
198 font.setLetterSpacing( QFont::AbsoluteSpacing, context.convertToPainterUnits( d->textFont.letterSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor );
199 font.setWordSpacing( context.convertToPainterUnits( d->textFont.wordSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor * scaleFactor );
200
201 if ( d->capitalization == Qgis::Capitalization::SmallCaps
202 || d->capitalization == Qgis::Capitalization::AllSmallCaps )
203 font.setCapitalization( QFont::SmallCaps );
204
205 return font;
206}
207
208void QgsTextFormat::setFont( const QFont &font )
209{
210 d->isValid = true;
211 d->textFont = font;
212}
213
215{
216 if ( !d->textNamedStyle.isEmpty() )
217 return d->textNamedStyle;
218
219 QFontDatabase db;
220 return db.styleString( d->textFont );
221}
222
223void QgsTextFormat::setNamedStyle( const QString &style )
224{
225 d->isValid = true;
226 QgsFontUtils::updateFontViaStyle( d->textFont, style );
227 d->textNamedStyle = style;
228}
229
231{
232 return d->forcedBold;
233}
234
236{
237 d->isValid = true;
238 d->textFont.setBold( forced );
239 d->forcedBold = true;
240}
241
243{
244 return d->forcedItalic;
245}
246
248{
249 d->isValid = true;
250 d->textFont.setItalic( forced );
251 d->forcedItalic = true;
252}
253
254QStringList QgsTextFormat::families() const
255{
256 return d->families;
257}
258
259void QgsTextFormat::setFamilies( const QStringList &families )
260{
261 d->isValid = true;
262 d->families = families;
263}
264
266{
267 return d->fontSizeUnits;
268}
269
271{
272 d->isValid = true;
273 d->fontSizeUnits = unit;
274}
275
277{
278 return d->fontSizeMapUnitScale;
279}
280
282{
283 d->isValid = true;
284 d->fontSizeMapUnitScale = scale;
285}
286
288{
289 return d->fontSize;
290}
291
292void QgsTextFormat::setSize( double size )
293{
294 d->isValid = true;
295 d->fontSize = size;
296}
297
299{
300 return d->textColor;
301}
302
303void QgsTextFormat::setColor( const QColor &color )
304{
305 d->isValid = true;
306 d->textColor = color;
307}
308
310{
311 return d->opacity;
312}
313
314void QgsTextFormat::setOpacity( double opacity )
315{
316 d->isValid = true;
317 d->opacity = opacity;
318}
319
321{
322 return d->textFont.stretch() > 0 ? d->textFont.stretch() : 100;
323}
324
326{
327 d->isValid = true;
328 d->textFont.setStretch( factor );
329}
330
331QPainter::CompositionMode QgsTextFormat::blendMode() const
332{
333 return d->blendMode;
334}
335
336void QgsTextFormat::setBlendMode( QPainter::CompositionMode mode )
337{
338 d->isValid = true;
339 d->blendMode = mode;
340}
341
343{
344 return d->multilineHeight;
345}
346
347void QgsTextFormat::setLineHeight( double height )
348{
349 d->isValid = true;
350 d->multilineHeight = height;
351}
352
354{
355 return d->multilineHeightUnits;
356}
357
359{
360 d->isValid = true;
361 d->multilineHeightUnits = unit;
362}
363
365{
366 return d->orientation;
367}
368
370{
371 d->isValid = true;
372 d->orientation = orientation;
373}
374
376{
377 // bit of complexity here to maintain API..
378 return d->capitalization == Qgis::Capitalization::MixedCase && d->textFont.capitalization() != QFont::MixedCase
379 ? static_cast< Qgis::Capitalization >( d->textFont.capitalization() )
380 : d->capitalization ;
381}
382
384{
385 d->isValid = true;
386 d->capitalization = capitalization;
387#if defined(HAS_KDE_QT5_SMALL_CAPS_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
388 d->textFont.setCapitalization( capitalization == Qgis::Capitalization::SmallCaps || capitalization == Qgis::Capitalization::AllSmallCaps ? QFont::SmallCaps : QFont::MixedCase );
389#else
390 d->textFont.setCapitalization( QFont::MixedCase );
391#endif
392}
393
395{
396 return d->allowHtmlFormatting;
397}
398
400{
401 d->isValid = true;
402 d->allowHtmlFormatting = allow;
403}
404
406{
407 return d->previewBackgroundColor;
408}
409
411{
412 d->isValid = true;
413 d->previewBackgroundColor = color;
414}
415
417{
418 d->isValid = true;
419 QFont appFont = QApplication::font();
420 mTextFontFamily = QgsApplication::fontManager()->processFontFamilyName( layer->customProperty( QStringLiteral( "labeling/fontFamily" ), QVariant( appFont.family() ) ).toString() );
421 QString fontFamily = mTextFontFamily;
422 if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
423 {
424 // trigger to notify about font family substitution
425 mTextFontFound = false;
426
427 // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
428 // currently only defaults to matching algorithm for resolving [foundry], if a font of similar family is found (default for QFont)
429
430 // for now, do not use matching algorithm for substitution if family not found, substitute default instead
431 fontFamily = appFont.family();
432 }
433 else
434 {
435 mTextFontFound = true;
436 }
437
438 if ( !layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).isValid() )
439 {
440 d->fontSize = appFont.pointSizeF();
441 }
442 else
443 {
444 d->fontSize = layer->customProperty( QStringLiteral( "labeling/fontSize" ) ).toDouble();
445 }
446
447 if ( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString().isEmpty() )
448 {
449 d->fontSizeUnits = layer->customProperty( QStringLiteral( "labeling/fontSizeInMapUnits" ), QVariant( false ) ).toBool() ?
451 }
452 else
453 {
454 bool ok = false;
455 d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( layer->customProperty( QStringLiteral( "labeling/fontSizeUnit" ) ).toString(), &ok );
456 if ( !ok )
457 d->fontSizeUnits = QgsUnitTypes::RenderPoints;
458 }
459 if ( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString().isEmpty() )
460 {
461 //fallback to older property
462 double oldMin = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMinScale" ), 0.0 ).toDouble();
463 d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
464 double oldMax = layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitMaxScale" ), 0.0 ).toDouble();
465 d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
466 }
467 else
468 {
469 d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( layer->customProperty( QStringLiteral( "labeling/fontSizeMapUnitScale" ) ).toString() );
470 }
471 int fontWeight = layer->customProperty( QStringLiteral( "labeling/fontWeight" ) ).toInt();
472 bool fontItalic = layer->customProperty( QStringLiteral( "labeling/fontItalic" ) ).toBool();
473 d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
474 d->textNamedStyle = QgsFontUtils::translateNamedStyle( layer->customProperty( QStringLiteral( "labeling/namedStyle" ), QVariant( "" ) ).toString() );
475 QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
476 d->capitalization = static_cast< Qgis::Capitalization >( layer->customProperty( QStringLiteral( "labeling/fontCapitals" ), QVariant( 0 ) ).toUInt() );
477 d->textFont.setUnderline( layer->customProperty( QStringLiteral( "labeling/fontUnderline" ) ).toBool() );
478 d->textFont.setStrikeOut( layer->customProperty( QStringLiteral( "labeling/fontStrikeout" ) ).toBool() );
479 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( QStringLiteral( "labeling/fontLetterSpacing" ), QVariant( 0.0 ) ).toDouble() );
480 d->textFont.setWordSpacing( layer->customProperty( QStringLiteral( "labeling/fontWordSpacing" ), QVariant( 0.0 ) ).toDouble() );
481 d->textColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/textColor" ), Qt::black, false );
482 if ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toString().isEmpty() )
483 {
484 d->opacity = ( 1 - layer->customProperty( QStringLiteral( "labeling/textTransp" ) ).toInt() / 100.0 ); //0 -100
485 }
486 else
487 {
488 d->opacity = ( layer->customProperty( QStringLiteral( "labeling/textOpacity" ) ).toDouble() );
489 }
490 d->blendMode = QgsPainting::getCompositionMode(
491 static_cast< QgsPainting::BlendMode >( layer->customProperty( QStringLiteral( "labeling/blendMode" ), QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
492 d->multilineHeight = layer->customProperty( QStringLiteral( "labeling/multilineHeight" ), QVariant( 1.0 ) ).toDouble();
493 d->previewBackgroundColor = QgsTextRendererUtils::readColor( layer, QStringLiteral( "labeling/previewBkgrdColor" ), QColor( 255, 255, 255 ), false );
494
495 mBufferSettings.readFromLayer( layer );
496 mShadowSettings.readFromLayer( layer );
497 mBackgroundSettings.readFromLayer( layer );
498}
499
500void QgsTextFormat::readXml( const QDomElement &elem, const QgsReadWriteContext &context )
501{
502 d->isValid = true;
503 QDomElement textStyleElem;
504 if ( elem.nodeName() == QLatin1String( "text-style" ) )
505 textStyleElem = elem;
506 else
507 textStyleElem = elem.firstChildElement( QStringLiteral( "text-style" ) );
508 QFont appFont = QApplication::font();
509 mTextFontFamily = QgsApplication::fontManager()->processFontFamilyName( textStyleElem.attribute( QStringLiteral( "fontFamily" ), appFont.family() ) );
510 QString fontFamily = mTextFontFamily;
511
512 const QDomElement familiesElem = textStyleElem.firstChildElement( QStringLiteral( "families" ) );
513 const QDomNodeList familyNodes = familiesElem.childNodes();
514 QStringList families;
515 families.reserve( familyNodes.size() );
516 for ( int i = 0; i < familyNodes.count(); ++i )
517 {
518 const QDomElement familyElem = familyNodes.at( i ).toElement();
519 families << familyElem.attribute( QStringLiteral( "name" ) );
520 }
521 d->families = families;
522
523 mTextFontFound = false;
524 QString matched;
525 if ( mTextFontFamily != appFont.family() && !QgsFontUtils::fontFamilyMatchOnSystem( mTextFontFamily ) )
526 {
527 if ( QgsApplication::fontManager()->tryToDownloadFontFamily( mTextFontFamily, matched ) )
528 {
529 mTextFontFound = true;
530 }
531 else
532 {
533 for ( const QString &family : std::as_const( families ) )
534 {
535 const QString processedFamily = QgsApplication::fontManager()->processFontFamilyName( family );
536 if ( QgsFontUtils::fontFamilyMatchOnSystem( processedFamily ) ||
537 QgsApplication::fontManager()->tryToDownloadFontFamily( processedFamily, matched ) )
538 {
539 mTextFontFound = true;
540 fontFamily = processedFamily;
541 break;
542 }
543 }
544
545 if ( !mTextFontFound )
546 {
547 // couldn't even find a matching font in the backup list -- substitute default instead
548 fontFamily = appFont.family();
549 }
550 }
551 }
552 else
553 {
554 mTextFontFound = true;
555 }
556
557 if ( !mTextFontFound )
558 {
559 context.pushMessage( QObject::tr( "Font “%1” not available on system" ).arg( mTextFontFamily ) );
560 }
561
562 if ( textStyleElem.hasAttribute( QStringLiteral( "fontSize" ) ) )
563 {
564 d->fontSize = textStyleElem.attribute( QStringLiteral( "fontSize" ) ).toDouble();
565 }
566 else
567 {
568 d->fontSize = appFont.pointSizeF();
569 }
570
571 if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeUnit" ) ) )
572 {
573 d->fontSizeUnits = textStyleElem.attribute( QStringLiteral( "fontSizeInMapUnits" ) ).toUInt() == 0 ? QgsUnitTypes::RenderPoints
575 }
576 else
577 {
578 d->fontSizeUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( QStringLiteral( "fontSizeUnit" ) ) );
579 }
580
581 if ( !textStyleElem.hasAttribute( QStringLiteral( "fontSizeMapUnitScale" ) ) )
582 {
583 //fallback to older property
584 double oldMin = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMinScale" ), QStringLiteral( "0" ) ).toDouble();
585 d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
586 double oldMax = textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitMaxScale" ), QStringLiteral( "0" ) ).toDouble();
587 d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
588 }
589 else
590 {
591 d->fontSizeMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( QStringLiteral( "fontSizeMapUnitScale" ) ) );
592 }
593 int fontWeight = textStyleElem.attribute( QStringLiteral( "fontWeight" ) ).toInt();
594 bool fontItalic = textStyleElem.attribute( QStringLiteral( "fontItalic" ) ).toInt();
595 d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
596 d->textFont.setPointSizeF( d->fontSize ); //double precision needed because of map units
597 d->textNamedStyle = QgsFontUtils::translateNamedStyle( textStyleElem.attribute( QStringLiteral( "namedStyle" ) ) );
598 QgsFontUtils::updateFontViaStyle( d->textFont, d->textNamedStyle ); // must come after textFont.setPointSizeF()
599 d->forcedBold = textStyleElem.attribute( QStringLiteral( "forcedBold" ) ).toInt();
600 d->forcedItalic = textStyleElem.attribute( QStringLiteral( "forcedItalic" ) ).toInt();
601 d->textFont.setUnderline( textStyleElem.attribute( QStringLiteral( "fontUnderline" ) ).toInt() );
602 d->textFont.setStrikeOut( textStyleElem.attribute( QStringLiteral( "fontStrikeout" ) ).toInt() );
603 d->textFont.setKerning( textStyleElem.attribute( QStringLiteral( "fontKerning" ), QStringLiteral( "1" ) ).toInt() );
604 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( QStringLiteral( "fontLetterSpacing" ), QStringLiteral( "0" ) ).toDouble() );
605 d->textFont.setWordSpacing( textStyleElem.attribute( QStringLiteral( "fontWordSpacing" ), QStringLiteral( "0" ) ).toDouble() );
606 d->textColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( Qt::black ) ) );
607 if ( !textStyleElem.hasAttribute( QStringLiteral( "textOpacity" ) ) )
608 {
609 d->opacity = ( 1 - textStyleElem.attribute( QStringLiteral( "textTransp" ) ).toInt() / 100.0 ); //0 -100
610 }
611 else
612 {
613 d->opacity = ( textStyleElem.attribute( QStringLiteral( "textOpacity" ) ).toDouble() );
614 }
615#ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
616 d->textFont.setStretch( textStyleElem.attribute( QStringLiteral( "stretchFactor" ), QStringLiteral( "100" ) ).toInt() );
617#endif
618 d->orientation = QgsTextRendererUtils::decodeTextOrientation( textStyleElem.attribute( QStringLiteral( "textOrientation" ) ) );
619 d->previewBackgroundColor = QgsSymbolLayerUtils::decodeColor( textStyleElem.attribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( Qt::white ) ) );
620
621 d->blendMode = QgsPainting::getCompositionMode(
622 static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( QStringLiteral( "blendMode" ), QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
623
624 if ( !textStyleElem.hasAttribute( QStringLiteral( "multilineHeight" ) ) )
625 {
626 QDomElement textFormatElem = elem.firstChildElement( QStringLiteral( "text-format" ) );
627 d->multilineHeight = textFormatElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
628 }
629 else
630 {
631 d->multilineHeight = textStyleElem.attribute( QStringLiteral( "multilineHeight" ), QStringLiteral( "1" ) ).toDouble();
632 }
633 bool ok = false;
634 d->multilineHeightUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( QStringLiteral( "multilineHeightUnit" ), QStringLiteral( "percent" ) ), &ok );
635
636 if ( textStyleElem.hasAttribute( QStringLiteral( "capitalization" ) ) )
637 d->capitalization = static_cast< Qgis::Capitalization >( textStyleElem.attribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( Qgis::Capitalization::MixedCase ) ) ).toInt() );
638 else
639 d->capitalization = static_cast< Qgis::Capitalization >( textStyleElem.attribute( QStringLiteral( "fontCapitals" ), QStringLiteral( "0" ) ).toUInt() );
640
641 if ( d->capitalization == Qgis::Capitalization::SmallCaps || d->capitalization == Qgis::Capitalization::AllSmallCaps )
642 d->textFont.setCapitalization( QFont::SmallCaps );
643
644 d->allowHtmlFormatting = textStyleElem.attribute( QStringLiteral( "allowHtml" ), QStringLiteral( "0" ) ).toInt();
645
646 if ( textStyleElem.firstChildElement( QStringLiteral( "text-buffer" ) ).isNull() )
647 {
648 mBufferSettings.readXml( elem );
649 }
650 else
651 {
652 mBufferSettings.readXml( textStyleElem );
653 }
654 if ( textStyleElem.firstChildElement( QStringLiteral( "text-mask" ) ).isNull() )
655 {
656 mMaskSettings.readXml( elem );
657 }
658 else
659 {
660 mMaskSettings.readXml( textStyleElem );
661 }
662 if ( textStyleElem.firstChildElement( QStringLiteral( "shadow" ) ).isNull() )
663 {
664 mShadowSettings.readXml( elem );
665 }
666 else
667 {
668 mShadowSettings.readXml( textStyleElem );
669 }
670 if ( textStyleElem.firstChildElement( QStringLiteral( "background" ) ).isNull() )
671 {
672 mBackgroundSettings.readXml( elem, context );
673 }
674 else
675 {
676 mBackgroundSettings.readXml( textStyleElem, context );
677 }
678
679 QDomElement ddElem = textStyleElem.firstChildElement( QStringLiteral( "dd_properties" ) );
680 if ( ddElem.isNull() )
681 {
682 ddElem = elem.firstChildElement( QStringLiteral( "dd_properties" ) );
683 }
684 if ( !ddElem.isNull() )
685 {
686 d->mDataDefinedProperties.readXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
687 mBackgroundSettings.upgradeDataDefinedProperties( d->mDataDefinedProperties );
688 }
689 else
690 {
691 d->mDataDefinedProperties.clear();
692 }
693}
694
695QDomElement QgsTextFormat::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
696{
697 // text style
698 QDomElement textStyleElem = doc.createElement( QStringLiteral( "text-style" ) );
699 textStyleElem.setAttribute( QStringLiteral( "fontFamily" ), d->textFont.family() );
700
701 QDomElement familiesElem = doc.createElement( QStringLiteral( "families" ) );
702 for ( const QString &family : std::as_const( d->families ) )
703 {
704 QDomElement familyElem = doc.createElement( QStringLiteral( "family" ) );
705 familyElem.setAttribute( QStringLiteral( "name" ), family );
706 familiesElem.appendChild( familyElem );
707 }
708 textStyleElem.appendChild( familiesElem );
709
710 textStyleElem.setAttribute( QStringLiteral( "namedStyle" ), QgsFontUtils::untranslateNamedStyle( d->textNamedStyle ) );
711 textStyleElem.setAttribute( QStringLiteral( "fontSize" ), d->fontSize );
712 textStyleElem.setAttribute( QStringLiteral( "fontSizeUnit" ), QgsUnitTypes::encodeUnit( d->fontSizeUnits ) );
713 textStyleElem.setAttribute( QStringLiteral( "fontSizeMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->fontSizeMapUnitScale ) );
714 textStyleElem.setAttribute( QStringLiteral( "fontWeight" ), d->textFont.weight() );
715 textStyleElem.setAttribute( QStringLiteral( "fontItalic" ), d->textFont.italic() );
716 textStyleElem.setAttribute( QStringLiteral( "fontStrikeout" ), d->textFont.strikeOut() );
717 textStyleElem.setAttribute( QStringLiteral( "fontUnderline" ), d->textFont.underline() );
718 textStyleElem.setAttribute( QStringLiteral( "forcedBold" ), d->forcedBold );
719 textStyleElem.setAttribute( QStringLiteral( "forcedItalic" ), d->forcedItalic );
720 textStyleElem.setAttribute( QStringLiteral( "textColor" ), QgsSymbolLayerUtils::encodeColor( d->textColor ) );
721 textStyleElem.setAttribute( QStringLiteral( "previewBkgrdColor" ), QgsSymbolLayerUtils::encodeColor( d->previewBackgroundColor ) );
722 textStyleElem.setAttribute( QStringLiteral( "fontLetterSpacing" ), d->textFont.letterSpacing() );
723 textStyleElem.setAttribute( QStringLiteral( "fontWordSpacing" ), d->textFont.wordSpacing() );
724 textStyleElem.setAttribute( QStringLiteral( "fontKerning" ), d->textFont.kerning() );
725 textStyleElem.setAttribute( QStringLiteral( "textOpacity" ), d->opacity );
726#ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
727 if ( d->textFont.stretch() > 0 )
728 textStyleElem.setAttribute( QStringLiteral( "stretchFactor" ), d->textFont.stretch() );
729#endif
730 textStyleElem.setAttribute( QStringLiteral( "textOrientation" ), QgsTextRendererUtils::encodeTextOrientation( d->orientation ) );
731 textStyleElem.setAttribute( QStringLiteral( "blendMode" ), QgsPainting::getBlendModeEnum( d->blendMode ) );
732 textStyleElem.setAttribute( QStringLiteral( "multilineHeight" ), d->multilineHeight );
733 textStyleElem.setAttribute( QStringLiteral( "multilineHeightUnit" ), QgsUnitTypes::encodeUnit( d->multilineHeightUnits ) );
734
735 textStyleElem.setAttribute( QStringLiteral( "allowHtml" ), d->allowHtmlFormatting ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
736 textStyleElem.setAttribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( d->capitalization ) ) );
737
738 QDomElement ddElem = doc.createElement( QStringLiteral( "dd_properties" ) );
739 d->mDataDefinedProperties.writeXml( ddElem, QgsPalLayerSettings::propertyDefinitions() );
740
741 textStyleElem.appendChild( mBufferSettings.writeXml( doc ) );
742 textStyleElem.appendChild( mMaskSettings.writeXml( doc ) );
743 textStyleElem.appendChild( mBackgroundSettings.writeXml( doc, context ) );
744 textStyleElem.appendChild( mShadowSettings.writeXml( doc ) );
745 textStyleElem.appendChild( ddElem );
746
747 return textStyleElem;
748}
749
751{
752 //set both the mime color data, and the text (format settings).
753
754 QMimeData *mimeData = new QMimeData;
755 mimeData->setColorData( QVariant( color() ) );
756
757 QgsReadWriteContext rwContext;
758 QDomDocument textDoc;
759 QDomElement textElem = writeXml( textDoc, rwContext );
760 textDoc.appendChild( textElem );
761 mimeData->setText( textDoc.toString() );
762
763 return mimeData;
764}
765
767{
768 QgsTextFormat format;
769 format.setFont( font );
770 if ( font.pointSizeF() > 0 )
771 {
772 format.setSize( font.pointSizeF() );
774 }
775 else if ( font.pixelSize() > 0 )
776 {
777 format.setSize( font.pixelSize() );
779 }
780
781 return format;
782}
783
785{
786 QFont f = font();
787 switch ( sizeUnit() )
788 {
790 f.setPointSizeF( size() );
791 break;
792
794 f.setPointSizeF( size() * 2.83464567 );
795 break;
796
798 f.setPointSizeF( size() * 72 );
799 break;
800
802 f.setPixelSize( static_cast< int >( std::round( size() ) ) );
803 break;
804
809 // no meaning here
810 break;
811 }
812 return f;
813}
814
815QgsTextFormat QgsTextFormat::fromMimeData( const QMimeData *data, bool *ok )
816{
817 if ( ok )
818 *ok = false;
819 QgsTextFormat format;
820 if ( !data )
821 return format;
822
823 QString text = data->text();
824 if ( !text.isEmpty() )
825 {
826 QDomDocument doc;
827 QDomElement elem;
828 QgsReadWriteContext rwContext;
829
830 if ( doc.setContent( text ) )
831 {
832 elem = doc.documentElement();
833
834 format.readXml( elem, rwContext );
835 if ( ok )
836 *ok = true;
837 return format;
838 }
839 }
840 return format;
841}
842
844{
845 if ( d->blendMode != QPainter::CompositionMode_SourceOver )
846 return true;
847
848 if ( mBufferSettings.enabled() && mBufferSettings.blendMode() != QPainter::CompositionMode_SourceOver )
849 return true;
850
851 if ( mBackgroundSettings.enabled() && mBackgroundSettings.blendMode() != QPainter::CompositionMode_SourceOver )
852 return true;
853
854 if ( mShadowSettings.enabled() && mShadowSettings.blendMode() != QPainter::CompositionMode_SourceOver )
855 return true;
856
857 return false;
858}
859
861{
862 d->isValid = true;
863 return d->mDataDefinedProperties;
864}
865
867{
868 return d->mDataDefinedProperties;
869}
870
871QSet<QString> QgsTextFormat::referencedFields( const QgsRenderContext &context ) const
872{
873 QSet< QString > fields = d->mDataDefinedProperties.referencedFields( context.expressionContext(), true );
874 fields.unite( mBufferSettings.referencedFields( context ) );
875 fields.unite( mBackgroundSettings.referencedFields( context ) );
876 fields.unite( mShadowSettings.referencedFields( context ) );
877 fields.unite( mMaskSettings.referencedFields( context ) );
878 return fields;
879}
880
882{
883 d->isValid = true;
884 d->mDataDefinedProperties = collection;
885}
886
888{
889 d->isValid = true;
890 if ( !d->mDataDefinedProperties.hasActiveProperties() )
891 return;
892
893 QString ddFontFamily;
894 context.expressionContext().setOriginalValueVariable( d->textFont.family() );
895 QVariant exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::Family, context.expressionContext() );
896 if ( !QgsVariantUtils::isNull( exprVal ) )
897 {
898 QString family = exprVal.toString().trimmed();
900 if ( d->textFont.family() != family )
901 {
902 // testing for ddFontFamily in QFontDatabase.families() may be slow to do for every feature
903 // (i.e. don't use QgsFontUtils::fontFamilyMatchOnSystem( family ) here)
904 if ( QgsFontUtils::fontFamilyOnSystem( family ) )
905 {
906 ddFontFamily = family;
907 }
908 }
909 }
910
911 // data defined named font style?
912 QString ddFontStyle;
913 context.expressionContext().setOriginalValueVariable( d->textNamedStyle );
914 exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontStyle, context.expressionContext() );
915 if ( !QgsVariantUtils::isNull( exprVal ) )
916 {
917 QString fontstyle = exprVal.toString().trimmed();
918 ddFontStyle = fontstyle;
919 }
920
921 bool ddBold = false;
922 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Bold ) )
923 {
924 context.expressionContext().setOriginalValueVariable( d->textFont.bold() );
925 ddBold = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Bold, context.expressionContext(), false ) ;
926 }
927
928 bool ddItalic = false;
929 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Italic ) )
930 {
931 context.expressionContext().setOriginalValueVariable( d->textFont.italic() );
932 ddItalic = d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Italic, context.expressionContext(), false );
933 }
934
935 // TODO: update when pref for how to resolve missing family (use matching algorithm or just default font) is implemented
936 // (currently defaults to what has been read in from layer settings)
937 QFont newFont;
938 QFontDatabase fontDb;
939 QFont appFont = QApplication::font();
940 bool newFontBuilt = false;
941 if ( ddBold || ddItalic )
942 {
943 // new font needs built, since existing style needs removed
944 newFont = QFont( !ddFontFamily.isEmpty() ? ddFontFamily : d->textFont.family() );
945 newFontBuilt = true;
946 newFont.setBold( ddBold );
947 newFont.setItalic( ddItalic );
948 }
949 else if ( !ddFontStyle.isEmpty()
950 && ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
951 {
952 if ( !ddFontFamily.isEmpty() )
953 {
954 // both family and style are different, build font from database
955 QFont styledfont = fontDb.font( ddFontFamily, ddFontStyle, appFont.pointSize() );
956 if ( appFont != styledfont )
957 {
958 newFont = styledfont;
959 newFontBuilt = true;
960 }
961 }
962
963 // update the font face style
964 QgsFontUtils::updateFontViaStyle( newFontBuilt ? newFont : d->textFont, ddFontStyle );
965 }
966 else if ( !ddFontFamily.isEmpty() )
967 {
968 if ( ddFontStyle.compare( QLatin1String( "Ignore" ), Qt::CaseInsensitive ) != 0 )
969 {
970 // just family is different, build font from database
971 QFont styledfont = fontDb.font( ddFontFamily, d->textNamedStyle, appFont.pointSize() );
972 if ( appFont != styledfont )
973 {
974 newFont = styledfont;
975 newFontBuilt = true;
976 }
977 }
978 else
979 {
980 newFont = QFont( ddFontFamily );
981 newFontBuilt = true;
982 }
983 }
984
985 if ( newFontBuilt )
986 {
987 // copy over existing font settings
988 newFont.setUnderline( d->textFont.underline() );
989 newFont.setStrikeOut( d->textFont.strikeOut() );
990 newFont.setWordSpacing( d->textFont.wordSpacing() );
991 newFont.setLetterSpacing( QFont::AbsoluteSpacing, d->textFont.letterSpacing() );
992 d->textFont = newFont;
993 }
994
995 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Underline ) )
996 {
997 context.expressionContext().setOriginalValueVariable( d->textFont.underline() );
998 d->textFont.setUnderline( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Underline, context.expressionContext(), d->textFont.underline() ) );
999 }
1000
1001 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Strikeout ) )
1002 {
1003 context.expressionContext().setOriginalValueVariable( d->textFont.strikeOut() );
1004 d->textFont.setStrikeOut( d->mDataDefinedProperties.valueAsBool( QgsPalLayerSettings::Strikeout, context.expressionContext(), d->textFont.strikeOut() ) );
1005 }
1006
1007 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Color ) )
1008 {
1010 d->textColor = d->mDataDefinedProperties.valueAsColor( QgsPalLayerSettings::Color, context.expressionContext(), d->textColor );
1011 }
1012
1013 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::Size ) )
1014 {
1016 d->fontSize = d->mDataDefinedProperties.valueAsDouble( QgsPalLayerSettings::Size, context.expressionContext(), d->fontSize );
1017 }
1018
1019 exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontSizeUnit, context.expressionContext() );
1020 if ( !QgsVariantUtils::isNull( exprVal ) )
1021 {
1022 QString units = exprVal.toString();
1023 if ( !units.isEmpty() )
1024 {
1025 bool ok;
1027 if ( ok )
1028 d->fontSizeUnits = res;
1029 }
1030 }
1031
1032 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontOpacity ) )
1033 {
1034 context.expressionContext().setOriginalValueVariable( d->opacity * 100 );
1035 const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontOpacity, context.expressionContext(), d->opacity * 100 );
1036 if ( !QgsVariantUtils::isNull( val ) )
1037 {
1038 d->opacity = val.toDouble() / 100.0;
1039 }
1040 }
1041
1042#ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
1043 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontStretchFactor ) )
1044 {
1045 context.expressionContext().setOriginalValueVariable( d->textFont.stretch() );
1046 const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontStretchFactor, context.expressionContext(), d->textFont.stretch() );
1047 if ( !QgsVariantUtils::isNull( val ) )
1048 {
1049 d->textFont.setStretch( val.toInt() );
1050 }
1051 }
1052#endif
1053
1054 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::TextOrientation ) )
1055 {
1056 const QString encoded = QgsTextRendererUtils::encodeTextOrientation( d->orientation );
1057 context.expressionContext().setOriginalValueVariable( encoded );
1058 d->orientation = QgsTextRendererUtils::decodeTextOrientation( d->mDataDefinedProperties.value( QgsPalLayerSettings::TextOrientation, context.expressionContext(), encoded ).toString() );
1059 }
1060
1061 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontLetterSpacing ) )
1062 {
1063 context.expressionContext().setOriginalValueVariable( d->textFont.letterSpacing() );
1064 const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontLetterSpacing, context.expressionContext(), d->textFont.letterSpacing() );
1065 if ( !QgsVariantUtils::isNull( val ) )
1066 {
1067 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, val.toDouble() );
1068 }
1069 }
1070
1071 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontWordSpacing ) )
1072 {
1073 context.expressionContext().setOriginalValueVariable( d->textFont.wordSpacing() );
1074 const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontWordSpacing, context.expressionContext(), d->textFont.wordSpacing() );
1075 if ( !QgsVariantUtils::isNull( val ) )
1076 {
1077 d->textFont.setWordSpacing( val.toDouble() );
1078 }
1079 }
1080
1081 if ( d->mDataDefinedProperties.isActive( QgsPalLayerSettings::FontBlendMode ) )
1082 {
1083 exprVal = d->mDataDefinedProperties.value( QgsPalLayerSettings::FontBlendMode, context.expressionContext() );
1084 QString blendstr = exprVal.toString().trimmed();
1085 if ( !blendstr.isEmpty() )
1086 d->blendMode = QgsSymbolLayerUtils::decodeBlendMode( blendstr );
1087 }
1088
1089 mShadowSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
1090 mBackgroundSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
1091 mBufferSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
1092 mMaskSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
1093}
1094
1095QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText, int padding )
1096{
1097 QgsTextFormat tempFormat = format;
1098 QPixmap pixmap( size );
1099 pixmap.fill( Qt::transparent );
1100 QPainter painter;
1101 painter.begin( &pixmap );
1102
1103 painter.setRenderHint( QPainter::Antialiasing );
1104
1105 QRect rect( 0, 0, size.width(), size.height() );
1106
1107 // shameless eye candy - use a subtle gradient when drawing background
1108 painter.setPen( Qt::NoPen );
1109 QColor background1 = tempFormat.previewBackgroundColor();
1110 if ( ( background1.lightnessF() < 0.7 ) )
1111 {
1112 background1 = background1.darker( 125 );
1113 }
1114 else
1115 {
1116 background1 = background1.lighter( 125 );
1117 }
1118 QColor background2 = tempFormat.previewBackgroundColor();
1119 QLinearGradient linearGrad( QPointF( 0, 0 ), QPointF( 0, rect.height() ) );
1120 linearGrad.setColorAt( 0, background1 );
1121 linearGrad.setColorAt( 1, background2 );
1122 painter.setBrush( QBrush( linearGrad ) );
1123 if ( size.width() > 30 )
1124 {
1125 painter.drawRoundedRect( rect, 6, 6 );
1126 }
1127 else
1128 {
1129 // don't use rounded rect for small previews
1130 painter.drawRect( rect );
1131 }
1132 painter.setBrush( Qt::NoBrush );
1133 painter.setPen( Qt::NoPen );
1134 padding += 1; // move text away from background border
1135
1136 QgsRenderContext context;
1137 QgsMapToPixel newCoordXForm;
1138 newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
1139 context.setMapToPixel( newCoordXForm );
1140
1141 QWidget *activeWindow = QApplication::activeWindow();
1142 const double logicalDpiX = activeWindow && activeWindow->screen() ? activeWindow->screen()->logicalDotsPerInchX() : 96.0;
1143 context.setScaleFactor( logicalDpiX / 25.4 );
1144
1145 context.setUseAdvancedEffects( true );
1147 context.setPainter( &painter );
1149
1150 // slightly inset text to account for buffer/background
1151 const double fontSize = context.convertToPainterUnits( tempFormat.size(), tempFormat.sizeUnit(), tempFormat.sizeMapUnitScale() );
1152 double xtrans = 0;
1153 if ( tempFormat.buffer().enabled() )
1154 xtrans = tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage
1155 ? fontSize * tempFormat.buffer().size() / 100
1156 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() );
1157 if ( tempFormat.background().enabled() && tempFormat.background().sizeType() != QgsTextBackgroundSettings::SizeFixed )
1158 xtrans = std::max( xtrans, context.convertToPainterUnits( tempFormat.background().size().width(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1159
1160 double ytrans = 0.0;
1161 if ( tempFormat.buffer().enabled() )
1162 ytrans = std::max( ytrans, tempFormat.buffer().sizeUnit() == QgsUnitTypes::RenderPercentage
1163 ? fontSize * tempFormat.buffer().size() / 100
1164 : context.convertToPainterUnits( tempFormat.buffer().size(), tempFormat.buffer().sizeUnit(), tempFormat.buffer().sizeMapUnitScale() ) );
1165 if ( tempFormat.background().enabled() )
1166 ytrans = std::max( ytrans, context.convertToPainterUnits( tempFormat.background().size().height(), tempFormat.background().sizeUnit(), tempFormat.background().sizeMapUnitScale() ) );
1167
1168 const QStringList text = QStringList() << ( previewText.isEmpty() ? QObject::tr( "Aa" ) : previewText );
1169 const double textHeight = QgsTextRenderer::textHeight( context, tempFormat, text, Qgis::TextLayoutMode::Rectangle );
1170 QRectF textRect = rect;
1171 textRect.setLeft( xtrans + padding );
1172 textRect.setWidth( rect.width() - xtrans - 2 * padding );
1173
1174 if ( textRect.width() > 2000 )
1175 textRect.setWidth( 2000 - 2 * padding );
1176
1177 const double bottom = textRect.height() / 2 + textHeight / 2;
1178 textRect.setTop( bottom - textHeight );
1179 textRect.setBottom( bottom );
1180
1181 QgsTextRenderer::drawText( textRect, 0, Qgis::TextHorizontalAlignment::Center, text, context, tempFormat );
1182
1183 // draw border on top of text
1184 painter.setBrush( Qt::NoBrush );
1185 painter.setPen( QPen( tempFormat.previewBackgroundColor().darker( 150 ), 0 ) );
1186 if ( size.width() > 30 )
1187 {
1188 painter.drawRoundedRect( rect, 6, 6 );
1189 }
1190 else
1191 {
1192 // don't use rounded rect for small previews
1193 painter.drawRect( rect );
1194 }
1195 painter.end();
1196 return pixmap;
1197}
Capitalization
String capitalization options.
Definition: qgis.h:1969
@ AllSmallCaps
Force all characters to small caps (since QGIS 3.24)
@ MixedCase
Mixed case, ie no change.
@ SmallCaps
Mixed case small caps (since QGIS 3.24)
TextOrientation
Text orientations.
Definition: qgis.h:1616
@ Antialiasing
Use antialiasing while drawing.
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
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.
@ FontStretchFactor
Font stretch factor, since QGIS 3.24.
@ 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.
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).
QgsExpressionContext & expressionContext()
Gets the expression context.
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.
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 setCapitalization(Qgis::Capitalization capitalization)
Sets the text capitalization style.
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 setOrientation(Qgis::TextOrientation orientation)
Sets the orientation for the text.
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.
void setForcedItalic(bool forced)
Sets whether the format is set to force an italic style.
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 setLineHeightUnit(QgsUnitTypes::RenderUnit unit)
Sets the unit for the line height for text.
int stretchFactor() const
Returns the text's stretch factor.
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 setStretchFactor(int factor)
Sets the text's stretch factor.
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.
QgsUnitTypes::RenderUnit lineHeightUnit() const
Returns the units for the line height for text.
bool operator==(const QgsTextFormat &other) const
void setAllowHtmlFormatting(bool allow)
Sets whether text should be treated as a HTML document and HTML tags should be used for formatting th...
Qgis::Capitalization capitalization() const
Returns the text capitalization style.
bool forcedItalic() const
Returns true if the format is set to force an italic style.
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.
void setForcedBold(bool forced)
Sets whether the format is set to force a bold style.
bool isValid() const
Returns true if the format is valid.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
QgsTextBackgroundSettings & background()
Returns a reference to the text background settings.
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.
Qgis::TextOrientation orientation() const
Returns the orientation of the text.
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)
bool forcedBold() const
Returns true if the format is set to force a bold style.
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.
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 Qgis::TextOrientation decodeTextOrientation(const QString &name, bool *ok=nullptr)
Attempts to decode a string representation of 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 QString encodeTextOrientation(Qgis::TextOrientation orientation)
Encodes a text orientation.
static void drawText(const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, bool drawAsOutlines=true, Qgis::TextVerticalAlignment vAlignment=Qgis::TextVerticalAlignment::Top, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Rectangle)
Draws text within a rectangle using the specified settings.
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 double textHeight(const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, Qgis::TextLayoutMode mode=Qgis::TextLayoutMode::Point, QFontMetricsF *fontMetrics=nullptr, Qgis::TextRendererFlags flags=Qgis::TextRendererFlags(), double maxLineWidth=0)
Returns the height of a text based on a given format.
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
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
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:2782