25 #include "qgsconfig.h"
26 #include <QFontDatabase>
30 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
31 #include <QDesktopWidget>
36 d =
new QgsTextSettingsPrivate();
40 : mBufferSettings( other.mBufferSettings )
41 , mBackgroundSettings( other.mBackgroundSettings )
42 , mShadowSettings( other.mShadowSettings )
43 , mMaskSettings( other.mMaskSettings )
44 , mTextFontFamily( other.mTextFontFamily )
45 , mTextFontFound( other.mTextFontFound )
54 mBufferSettings = other.mBufferSettings;
55 mBackgroundSettings = other.mBackgroundSettings;
56 mShadowSettings = other.mShadowSettings;
57 mMaskSettings = other.mMaskSettings;
58 mTextFontFamily = other.mTextFontFamily;
59 mTextFontFound = other.mTextFontFound;
70 if ( d->isValid != other.
isValid()
71 || d->textFont != other.
font()
73 || d->fontSizeUnits != other.
sizeUnit()
75 || d->fontSize != other.
size()
76 || d->textColor != other.
color()
77 || d->opacity != other.
opacity()
86 || mBufferSettings != other.mBufferSettings
87 || mBackgroundSettings != other.mBackgroundSettings
88 || mShadowSettings != other.mShadowSettings
89 || mMaskSettings != other.mMaskSettings
99 return !( *
this == other );
115 return mBufferSettings;
121 mBufferSettings = bufferSettings;
127 return mBackgroundSettings;
133 mBackgroundSettings = backgroundSettings;
139 return mShadowSettings;
145 mShadowSettings = shadowSettings;
151 return mMaskSettings;
157 mMaskSettings = maskSettings;
170 QFont
font = d->textFont;
171 if ( scaleFactor == 1 )
174 d->fontSizeMapUnitScale );
175 if ( fontPixelSize == 0 )
182 font.setPixelSize( fontPixelSize );
186 double fontPixelSize = context.
convertToPainterUnits( d->fontSize, d->fontSizeUnits, d->fontSizeMapUnitScale );
193 const int roundedPixelSize =
static_cast< int >( std::round( scaleFactor * fontPixelSize + 0.5 ) );
194 font.setPixelSize( roundedPixelSize );
197 font.setLetterSpacing( QFont::AbsoluteSpacing, context.
convertToPainterUnits( d->textFont.letterSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor );
198 font.setWordSpacing( context.
convertToPainterUnits( d->textFont.wordSpacing(), d->fontSizeUnits, d->fontSizeMapUnitScale ) * scaleFactor * scaleFactor );
202 font.setCapitalization( QFont::SmallCaps );
215 if ( !d->textNamedStyle.isEmpty() )
216 return d->textNamedStyle;
219 return db.styleString( d->textFont );
226 d->textNamedStyle = style;
231 return d->forcedBold;
237 d->textFont.setBold( forced );
238 d->forcedBold =
true;
243 return d->forcedItalic;
249 d->textFont.setItalic( forced );
250 d->forcedItalic =
true;
266 return d->fontSizeUnits;
272 d->fontSizeUnits = unit;
277 return d->fontSizeMapUnitScale;
283 d->fontSizeMapUnitScale = scale;
305 d->textColor =
color;
321 return d->textFont.stretch() > 0 ? d->textFont.stretch() : 100;
327 d->textFont.setStretch( factor );
343 return d->multilineHeight;
349 d->multilineHeight = height;
354 return d->orientation;
368 : d->capitalization ;
375 #if defined(HAS_KDE_QT5_SMALL_CAPS_FIX) || QT_VERSION >= QT_VERSION_CHECK(6, 3, 0)
378 d->textFont.setCapitalization( QFont::MixedCase );
384 return d->allowHtmlFormatting;
390 d->allowHtmlFormatting = allow;
395 return d->previewBackgroundColor;
401 d->previewBackgroundColor =
color;
407 QFont appFont = QApplication::font();
408 mTextFontFamily = layer->
customProperty( QStringLiteral(
"labeling/fontFamily" ), QVariant( appFont.family() ) ).toString();
409 QString fontFamily = mTextFontFamily;
413 mTextFontFound =
false;
419 fontFamily = appFont.family();
423 mTextFontFound =
true;
428 d->fontSize = appFont.pointSizeF();
432 d->fontSize = layer->
customProperty( QStringLiteral(
"labeling/fontSize" ) ).toDouble();
435 if ( layer->
customProperty( QStringLiteral(
"labeling/fontSizeUnit" ) ).toString().isEmpty() )
437 d->fontSizeUnits = layer->
customProperty( QStringLiteral(
"labeling/fontSizeInMapUnits" ), QVariant(
false ) ).toBool() ?
447 if ( layer->
customProperty( QStringLiteral(
"labeling/fontSizeMapUnitScale" ) ).toString().isEmpty() )
450 double oldMin = layer->
customProperty( QStringLiteral(
"labeling/fontSizeMapUnitMinScale" ), 0.0 ).toDouble();
451 d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
452 double oldMax = layer->
customProperty( QStringLiteral(
"labeling/fontSizeMapUnitMaxScale" ), 0.0 ).toDouble();
453 d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
459 int fontWeight = layer->
customProperty( QStringLiteral(
"labeling/fontWeight" ) ).toInt();
460 bool fontItalic = layer->
customProperty( QStringLiteral(
"labeling/fontItalic" ) ).toBool();
461 d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
465 d->textFont.setUnderline( layer->
customProperty( QStringLiteral(
"labeling/fontUnderline" ) ).toBool() );
466 d->textFont.setStrikeOut( layer->
customProperty( QStringLiteral(
"labeling/fontStrikeout" ) ).toBool() );
467 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->
customProperty( QStringLiteral(
"labeling/fontLetterSpacing" ), QVariant( 0.0 ) ).toDouble() );
468 d->textFont.setWordSpacing( layer->
customProperty( QStringLiteral(
"labeling/fontWordSpacing" ), QVariant( 0.0 ) ).toDouble() );
470 if ( layer->
customProperty( QStringLiteral(
"labeling/textOpacity" ) ).toString().isEmpty() )
472 d->opacity = ( 1 - layer->
customProperty( QStringLiteral(
"labeling/textTransp" ) ).toInt() / 100.0 );
476 d->opacity = ( layer->
customProperty( QStringLiteral(
"labeling/textOpacity" ) ).toDouble() );
480 d->multilineHeight = layer->
customProperty( QStringLiteral(
"labeling/multilineHeight" ), QVariant( 1.0 ) ).toDouble();
491 QDomElement textStyleElem;
492 if ( elem.nodeName() == QLatin1String(
"text-style" ) )
493 textStyleElem = elem;
495 textStyleElem = elem.firstChildElement( QStringLiteral(
"text-style" ) );
496 QFont appFont = QApplication::font();
497 mTextFontFamily = textStyleElem.attribute( QStringLiteral(
"fontFamily" ), appFont.family() );
498 QString fontFamily = mTextFontFamily;
500 const QDomElement familiesElem = textStyleElem.firstChildElement( QStringLiteral(
"families" ) );
501 const QDomNodeList familyNodes = familiesElem.childNodes();
503 families.reserve( familyNodes.size() );
504 for (
int i = 0; i < familyNodes.count(); ++i )
506 const QDomElement familyElem = familyNodes.at( i ).toElement();
507 families << familyElem.attribute( QStringLiteral(
"name" ) );
511 mTextFontFound =
false;
514 for (
const QString &family : std::as_const(
families ) )
518 mTextFontFound =
true;
524 if ( !mTextFontFound )
527 fontFamily = appFont.family();
532 mTextFontFound =
true;
535 if ( !mTextFontFound )
537 context.
pushMessage( QObject::tr(
"Font “%1” not available on system" ).arg( mTextFontFamily ) );
540 if ( textStyleElem.hasAttribute( QStringLiteral(
"fontSize" ) ) )
542 d->fontSize = textStyleElem.attribute( QStringLiteral(
"fontSize" ) ).toDouble();
546 d->fontSize = appFont.pointSizeF();
549 if ( !textStyleElem.hasAttribute( QStringLiteral(
"fontSizeUnit" ) ) )
551 d->fontSizeUnits = textStyleElem.attribute( QStringLiteral(
"fontSizeInMapUnits" ) ).toUInt() == 0 ?
QgsUnitTypes::RenderPoints
559 if ( !textStyleElem.hasAttribute( QStringLiteral(
"fontSizeMapUnitScale" ) ) )
562 double oldMin = textStyleElem.attribute( QStringLiteral(
"fontSizeMapUnitMinScale" ), QStringLiteral(
"0" ) ).toDouble();
563 d->fontSizeMapUnitScale.minScale = oldMin != 0 ? 1.0 / oldMin : 0;
564 double oldMax = textStyleElem.attribute( QStringLiteral(
"fontSizeMapUnitMaxScale" ), QStringLiteral(
"0" ) ).toDouble();
565 d->fontSizeMapUnitScale.maxScale = oldMax != 0 ? 1.0 / oldMax : 0;
571 int fontWeight = textStyleElem.attribute( QStringLiteral(
"fontWeight" ) ).toInt();
572 bool fontItalic = textStyleElem.attribute( QStringLiteral(
"fontItalic" ) ).toInt();
573 d->textFont = QFont( fontFamily, d->fontSize, fontWeight, fontItalic );
574 d->textFont.setPointSizeF( d->fontSize );
577 d->forcedBold = textStyleElem.attribute( QStringLiteral(
"forcedBold" ) ).toInt();
578 d->forcedItalic = textStyleElem.attribute( QStringLiteral(
"forcedItalic" ) ).toInt();
579 d->textFont.setUnderline( textStyleElem.attribute( QStringLiteral(
"fontUnderline" ) ).toInt() );
580 d->textFont.setStrikeOut( textStyleElem.attribute( QStringLiteral(
"fontStrikeout" ) ).toInt() );
581 d->textFont.setKerning( textStyleElem.attribute( QStringLiteral(
"fontKerning" ), QStringLiteral(
"1" ) ).toInt() );
582 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, textStyleElem.attribute( QStringLiteral(
"fontLetterSpacing" ), QStringLiteral(
"0" ) ).toDouble() );
583 d->textFont.setWordSpacing( textStyleElem.attribute( QStringLiteral(
"fontWordSpacing" ), QStringLiteral(
"0" ) ).toDouble() );
585 if ( !textStyleElem.hasAttribute( QStringLiteral(
"textOpacity" ) ) )
587 d->opacity = ( 1 - textStyleElem.attribute( QStringLiteral(
"textTransp" ) ).toInt() / 100.0 );
591 d->opacity = ( textStyleElem.attribute( QStringLiteral(
"textOpacity" ) ).toDouble() );
593 #ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
594 d->textFont.setStretch( textStyleElem.attribute( QStringLiteral(
"stretchFactor" ), QStringLiteral(
"100" ) ).toInt() );
602 if ( !textStyleElem.hasAttribute( QStringLiteral(
"multilineHeight" ) ) )
604 QDomElement textFormatElem = elem.firstChildElement( QStringLiteral(
"text-format" ) );
605 d->multilineHeight = textFormatElem.attribute( QStringLiteral(
"multilineHeight" ), QStringLiteral(
"1" ) ).toDouble();
609 d->multilineHeight = textStyleElem.attribute( QStringLiteral(
"multilineHeight" ), QStringLiteral(
"1" ) ).toDouble();
612 if ( textStyleElem.hasAttribute( QStringLiteral(
"capitalization" ) ) )
615 d->capitalization =
static_cast< Qgis::Capitalization >( textStyleElem.attribute( QStringLiteral(
"fontCapitals" ), QStringLiteral(
"0" ) ).toUInt() );
618 d->textFont.setCapitalization( QFont::SmallCaps );
620 d->allowHtmlFormatting = textStyleElem.attribute( QStringLiteral(
"allowHtml" ), QStringLiteral(
"0" ) ).toInt();
622 if ( textStyleElem.firstChildElement( QStringLiteral(
"text-buffer" ) ).isNull() )
624 mBufferSettings.
readXml( elem );
628 mBufferSettings.
readXml( textStyleElem );
630 if ( textStyleElem.firstChildElement( QStringLiteral(
"text-mask" ) ).isNull() )
636 mMaskSettings.
readXml( textStyleElem );
638 if ( textStyleElem.firstChildElement( QStringLiteral(
"shadow" ) ).isNull() )
640 mShadowSettings.
readXml( elem );
644 mShadowSettings.
readXml( textStyleElem );
646 if ( textStyleElem.firstChildElement( QStringLiteral(
"background" ) ).isNull() )
648 mBackgroundSettings.
readXml( elem, context );
652 mBackgroundSettings.
readXml( textStyleElem, context );
655 QDomElement ddElem = textStyleElem.firstChildElement( QStringLiteral(
"dd_properties" ) );
656 if ( ddElem.isNull() )
658 ddElem = elem.firstChildElement( QStringLiteral(
"dd_properties" ) );
660 if ( !ddElem.isNull() )
667 d->mDataDefinedProperties.clear();
674 QDomElement textStyleElem = doc.createElement( QStringLiteral(
"text-style" ) );
675 textStyleElem.setAttribute( QStringLiteral(
"fontFamily" ), d->textFont.family() );
677 QDomElement familiesElem = doc.createElement( QStringLiteral(
"families" ) );
678 for (
const QString &family : std::as_const( d->families ) )
680 QDomElement familyElem = doc.createElement( QStringLiteral(
"family" ) );
681 familyElem.setAttribute( QStringLiteral(
"name" ), family );
682 familiesElem.appendChild( familyElem );
684 textStyleElem.appendChild( familiesElem );
687 textStyleElem.setAttribute( QStringLiteral(
"fontSize" ), d->fontSize );
690 textStyleElem.setAttribute( QStringLiteral(
"fontWeight" ), d->textFont.weight() );
691 textStyleElem.setAttribute( QStringLiteral(
"fontItalic" ), d->textFont.italic() );
692 textStyleElem.setAttribute( QStringLiteral(
"fontStrikeout" ), d->textFont.strikeOut() );
693 textStyleElem.setAttribute( QStringLiteral(
"fontUnderline" ), d->textFont.underline() );
694 textStyleElem.setAttribute( QStringLiteral(
"forcedBold" ), d->forcedBold );
695 textStyleElem.setAttribute( QStringLiteral(
"forcedItalic" ), d->forcedItalic );
698 textStyleElem.setAttribute( QStringLiteral(
"fontLetterSpacing" ), d->textFont.letterSpacing() );
699 textStyleElem.setAttribute( QStringLiteral(
"fontWordSpacing" ), d->textFont.wordSpacing() );
700 textStyleElem.setAttribute( QStringLiteral(
"fontKerning" ), d->textFont.kerning() );
701 textStyleElem.setAttribute( QStringLiteral(
"textOpacity" ), d->opacity );
702 #ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
703 if ( d->textFont.stretch() > 0 )
704 textStyleElem.setAttribute( QStringLiteral(
"stretchFactor" ), d->textFont.stretch() );
708 textStyleElem.setAttribute( QStringLiteral(
"multilineHeight" ), d->multilineHeight );
709 textStyleElem.setAttribute( QStringLiteral(
"allowHtml" ), d->allowHtmlFormatting ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) );
710 textStyleElem.setAttribute( QStringLiteral(
"capitalization" ), QString::number(
static_cast< int >( d->capitalization ) ) );
712 QDomElement ddElem = doc.createElement( QStringLiteral(
"dd_properties" ) );
715 textStyleElem.appendChild( mBufferSettings.
writeXml( doc ) );
716 textStyleElem.appendChild( mMaskSettings.
writeXml( doc ) );
717 textStyleElem.appendChild( mBackgroundSettings.
writeXml( doc, context ) );
718 textStyleElem.appendChild( mShadowSettings.
writeXml( doc ) );
719 textStyleElem.appendChild( ddElem );
721 return textStyleElem;
728 QMimeData *mimeData =
new QMimeData;
729 mimeData->setColorData( QVariant(
color() ) );
732 QDomDocument textDoc;
733 QDomElement textElem =
writeXml( textDoc, rwContext );
734 textDoc.appendChild( textElem );
735 mimeData->setText( textDoc.toString() );
744 if (
font.pointSizeF() > 0 )
749 else if (
font.pixelSize() > 0 )
764 f.setPointSizeF(
size() );
768 f.setPointSizeF(
size() * 2.83464567 );
772 f.setPointSizeF(
size() * 72 );
776 f.setPixelSize(
static_cast< int >( std::round(
size() ) ) );
797 QString text = data->text();
798 if ( !text.isEmpty() )
804 if ( doc.setContent( text ) )
806 elem = doc.documentElement();
808 format.
readXml( elem, rwContext );
819 if ( d->blendMode != QPainter::CompositionMode_SourceOver )
822 if ( mBufferSettings.
enabled() && mBufferSettings.
blendMode() != QPainter::CompositionMode_SourceOver )
825 if ( mBackgroundSettings.
enabled() && mBackgroundSettings.
blendMode() != QPainter::CompositionMode_SourceOver )
828 if ( mShadowSettings.
enabled() && mShadowSettings.
blendMode() != QPainter::CompositionMode_SourceOver )
837 return d->mDataDefinedProperties;
842 return d->mDataDefinedProperties;
847 QSet< QString > fields = d->mDataDefinedProperties.referencedFields( context.
expressionContext(),
true );
858 d->mDataDefinedProperties = collection;
864 if ( !d->mDataDefinedProperties.hasActiveProperties() )
867 QString ddFontFamily;
870 if ( !exprVal.isNull() )
872 QString family = exprVal.toString().trimmed();
873 if ( d->textFont.family() != family )
879 ddFontFamily = family;
888 if ( !exprVal.isNull() )
890 QString fontstyle = exprVal.toString().trimmed();
891 ddFontStyle = fontstyle;
901 bool ddItalic =
false;
911 QFontDatabase fontDb;
912 QFont appFont = QApplication::font();
913 bool newFontBuilt =
false;
914 if ( ddBold || ddItalic )
917 newFont = QFont( !ddFontFamily.isEmpty() ? ddFontFamily : d->textFont.family() );
919 newFont.setBold( ddBold );
920 newFont.setItalic( ddItalic );
922 else if ( !ddFontStyle.isEmpty()
923 && ddFontStyle.compare( QLatin1String(
"Ignore" ), Qt::CaseInsensitive ) != 0 )
925 if ( !ddFontFamily.isEmpty() )
928 QFont styledfont = fontDb.font( ddFontFamily, ddFontStyle, appFont.pointSize() );
929 if ( appFont != styledfont )
931 newFont = styledfont;
939 else if ( !ddFontFamily.isEmpty() )
941 if ( ddFontStyle.compare( QLatin1String(
"Ignore" ), Qt::CaseInsensitive ) != 0 )
944 QFont styledfont = fontDb.font( ddFontFamily, d->textNamedStyle, appFont.pointSize() );
945 if ( appFont != styledfont )
947 newFont = styledfont;
953 newFont = QFont( ddFontFamily );
961 newFont.setUnderline( d->textFont.underline() );
962 newFont.setStrikeOut( d->textFont.strikeOut() );
963 newFont.setWordSpacing( d->textFont.wordSpacing() );
964 newFont.setLetterSpacing( QFont::AbsoluteSpacing, d->textFont.letterSpacing() );
965 d->textFont = newFont;
993 if ( !exprVal.isNull() )
995 QString units = exprVal.toString();
996 if ( !units.isEmpty() )
1001 d->fontSizeUnits = res;
1009 if ( !val.isNull() )
1011 d->opacity = val.toDouble() / 100.0;
1015 #ifdef HAS_KDE_QT5_FONT_STRETCH_FIX
1020 if ( !val.isNull() )
1022 d->textFont.setStretch( val.toInt() );
1038 if ( !val.isNull() )
1040 d->textFont.setLetterSpacing( QFont::AbsoluteSpacing, val.toDouble() );
1048 if ( !val.isNull() )
1050 d->textFont.setWordSpacing( val.toDouble() );
1057 QString blendstr = exprVal.toString().trimmed();
1058 if ( !blendstr.isEmpty() )
1071 QPixmap pixmap(
size );
1072 pixmap.fill( Qt::transparent );
1074 painter.begin( &pixmap );
1076 painter.setRenderHint( QPainter::Antialiasing );
1078 QRect rect( 0, 0,
size.width(),
size.height() );
1081 painter.setPen( Qt::NoPen );
1083 if ( ( background1.lightnessF() < 0.7 ) )
1085 background1 = background1.darker( 125 );
1089 background1 = background1.lighter( 125 );
1092 QLinearGradient linearGrad( QPointF( 0, 0 ), QPointF( 0, rect.height() ) );
1093 linearGrad.setColorAt( 0, background1 );
1094 linearGrad.setColorAt( 1, background2 );
1095 painter.setBrush( QBrush( linearGrad ) );
1096 if (
size.width() > 30 )
1098 painter.drawRoundedRect( rect, 6, 6 );
1103 painter.drawRect( rect );
1105 painter.setBrush( Qt::NoBrush );
1106 painter.setPen( Qt::NoPen );
1114 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
1115 const double logicalDpiX = QgsApplication::desktop()->logicalDpiX();
1117 QWidget *activeWindow = QApplication::activeWindow();
1118 const double logicalDpiX = activeWindow && activeWindow->screen() ? activeWindow->screen()->logicalDotsPerInchX() : 96.0;
1132 ? fontSize * tempFormat.
buffer().
size() / 100
1137 double ytrans = 0.0;
1140 ? fontSize * tempFormat.
buffer().
size() / 100
1145 const QStringList text = QStringList() << ( previewText.isEmpty() ? QObject::tr(
"Aa" ) : previewText );
1147 QRectF textRect = rect;
1148 textRect.setLeft( xtrans + padding );
1149 textRect.setWidth( rect.width() - xtrans - 2 * padding );
1151 if ( textRect.width() > 2000 )
1152 textRect.setWidth( 2000 - 2 * padding );
1154 const double bottom = textRect.height() / 2 + textHeight / 2;
1155 textRect.setTop( bottom - textHeight );
1156 textRect.setBottom( bottom );
1161 painter.setBrush( Qt::NoBrush );
1163 if (
size.width() > 30 )
1165 painter.drawRoundedRect( rect, 6, 6 );
1170 painter.drawRect( rect );