20 #include "qgssettings.h" 
   23 #include <QApplication> 
   26 #include <QFontDatabase> 
   28 #include <QStringList> 
   34   QFontInfo fi = QFontInfo( f );
 
   35   return fi.exactMatch();
 
   40   QFont tmpFont = QFont( family );
 
   42   return tmpFont.family().startsWith( family, Qt::CaseInsensitive );
 
   51   if ( fontDB.styles( family ).contains( style ) )
 
   55   QString modified( style );
 
   56   if ( style == 
"Roman" )
 
   58   if ( style == 
"Oblique" )
 
   60   if ( style == 
"Bold Oblique" )
 
   61     modified = 
"Bold Italic";
 
   62   if ( fontDB.styles( family ).contains( modified ) )
 
   72   QStringList fontFamilies = fontDB.families();
 
   75   QList<QString>::const_iterator it = fontFamilies.constBegin();
 
   76   for ( ; it != fontFamilies.constEnd(); ++it )
 
   79     if ( it->startsWith( family, Qt::CaseInsensitive ) )
 
   86         *match = ( *it == family );
 
  102       QFont f = QFont( family );
 
  103       *chosen = f.family();
 
  124   if ( fontstyle.isEmpty() )
 
  129   QFontDatabase fontDB;
 
  142   if ( fontstyle == fontDB.styleString( f ) )
 
  147   QFont appfont = QApplication::font();
 
  148   int defaultSize = appfont.pointSize(); 
 
  151   bool foundmatch = 
false;
 
  154   styledfont = fontDB.font( f.family(), fontstyle, defaultSize );
 
  155   if ( appfont != styledfont || fontstyle != fontDB.styleString( f ) )
 
  162   if ( fallback && !foundmatch )
 
  164     QFont testFont = QFont( f );
 
  165     testFont.setPointSize( defaultSize );
 
  168     const auto constFamily = fontDB.styles( f.family() );
 
  169     for ( 
const QString &style : constFamily )
 
  171       styledfont = fontDB.font( f.family(), style, defaultSize );
 
  172       styledfont = styledfont.resolve( f );
 
  173       if ( testFont.toString() == styledfont.toString() )
 
  183       for ( 
const QString &style : constFamily )
 
  185         styledfont = fontDB.font( f.family(), style, defaultSize );
 
  186         if ( QApplication::font() != styledfont )
 
  201       styledfont.setPointSizeF( f.pointSizeF() );
 
  203     else if ( f.pixelSize() != -1 )
 
  205       styledfont.setPixelSize( f.pixelSize() );
 
  207     styledfont.setCapitalization( f.capitalization() );
 
  208     styledfont.setUnderline( f.underline() );
 
  209     styledfont.setStrikeOut( f.strikeOut() );
 
  210     styledfont.setWordSpacing( f.wordSpacing() );
 
  211     styledfont.setLetterSpacing( QFont::AbsoluteSpacing, f.letterSpacing() );
 
  222   return QStringLiteral( 
"QGIS Vera Sans" );
 
  228   bool fontsLoaded = 
false;
 
  231   QMap<QString, QString> fontStyles;
 
  232   fontStyles.insert( QStringLiteral( 
"Roman" ), QStringLiteral( 
"QGIS-Vera/QGIS-Vera.ttf" ) );
 
  233   fontStyles.insert( QStringLiteral( 
"Oblique" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraIt.ttf" ) );
 
  234   fontStyles.insert( QStringLiteral( 
"Bold" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraBd.ttf" ) );
 
  235   fontStyles.insert( QStringLiteral( 
"Bold Oblique" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraBI.ttf" ) );
 
  237   QMap<QString, QString>::const_iterator f = fontStyles.constBegin();
 
  238   for ( ; f != fontStyles.constEnd(); ++f )
 
  240     QString fontstyle( f.key() );
 
  241     QString fontpath( f.value() );
 
  242     if ( !( loadstyles.contains( fontstyle ) || loadstyles.contains( QStringLiteral( 
"All" ) ) ) )
 
  249       QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1 %2' already available" ).arg( fontFamily, fontstyle ), 2 );
 
  261         int fontID = QFontDatabase::addApplicationFont( fontPath );
 
  262         loaded = ( fontID != -1 );
 
  263         fontsLoaded = ( fontsLoaded || loaded );
 
  264         QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1 %2' %3 from filesystem [%4]" )
 
  265                           .arg( fontFamily, fontstyle, loaded ? 
"loaded" : 
"FAILED to load", fontPath ), 2 );
 
  267         QgsDebugMsgLevel( QStringLiteral( 
"font families in %1: %2" ).arg( fontID ).arg( db.applicationFontFamilies( fontID ).join( 
"," ) ), 2 );
 
  271         QFile fontResource( 
":/testdata/font/" + fontpath );
 
  272         if ( fontResource.open( QIODevice::ReadOnly ) )
 
  274           int fontID = QFontDatabase::addApplicationFontFromData( fontResource.readAll() );
 
  275           loaded = ( fontID != -1 );
 
  276           fontsLoaded = ( fontsLoaded || loaded );
 
  278         QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1' (%2) %3 from testdata.qrc" )
 
  279                           .arg( fontFamily, fontstyle, loaded ? 
"loaded" : 
"FAILED to load" ), 2 );
 
  294   QFontDatabase fontDB;
 
  297   if ( !f.exactMatch() )
 
  300     if ( style == 
"Roman" )
 
  302     else if ( style == 
"Oblique" )
 
  304     else if ( style == 
"Bold Oblique" )
 
  305       modified = 
"Bold Italic";
 
  306     if ( !modified.isEmpty() )
 
  309   if ( !f.exactMatch() )
 
  312     QgsDebugMsg( QStringLiteral( 
"Requested: %1" ).arg( f.toString() ) );
 
  314     QgsDebugMsg( QStringLiteral( 
"Replaced:  %1,%2,%3,%4,%5,%6,%7,%8,%9" ).arg( fi.family() ).arg( fi.pointSizeF() ).arg( fi.pixelSize() ).arg( fi.styleHint() ).arg( fi.weight() ).arg( fi.style() ).arg( fi.underline() ).arg( fi.strikeOut() ).arg( fi.fixedPitch() ) );
 
  318   f.setBold( style.contains( QLatin1String( 
"Bold" ) ) );
 
  319   f.setItalic( style.contains( QLatin1String( 
"Oblique" ) ) || style.contains( QLatin1String( 
"Italic" ) ) );
 
  326   QDomElement fontElem = document.createElement( elementName );
 
  327   fontElem.setAttribute( QStringLiteral( 
"description" ), font.toString() );
 
  334   if ( element.isNull() )
 
  339   font.fromString( element.attribute( QStringLiteral( 
"description" ) ) );
 
  340   if ( element.hasAttribute( QStringLiteral( 
"style" ) ) )
 
  350   if ( element.isNull() )
 
  355   QDomNodeList nodeList = element.elementsByTagName( childNode );
 
  356   if ( !nodeList.isEmpty() )
 
  358     QDomElement fontElem = nodeList.at( 0 ).toElement();
 
  369   std::unique_ptr< QMimeData >mimeData( 
new QMimeData );
 
  371   QDomDocument fontDoc;
 
  372   QDomElement fontElem = 
toXmlElement( font, fontDoc, QStringLiteral( 
"font" ) );
 
  373   fontDoc.appendChild( fontElem );
 
  374   mimeData->setText( fontDoc.toString() );
 
  376   return mimeData.release();
 
  388   QString text = data->text();
 
  389   if ( !text.isEmpty() )
 
  394     if ( doc.setContent( text ) )
 
  396       elem = doc.documentElement();
 
  398       if ( elem.nodeName() != QLatin1String( 
"font" ) )
 
  399         elem = elem.firstChildElement( QStringLiteral( 
"font" ) );
 
  412 static QMap<QString, QString> createTranslatedStyleMap()
 
  414   QMap<QString, QString> translatedStyleMap;
 
  415   QStringList words = QStringList()
 
  416                       << QStringLiteral( 
"Normal" )
 
  417                       << QStringLiteral( 
"Regular" )
 
  418                       << QStringLiteral( 
"Light" )
 
  419                       << QStringLiteral( 
"Bold" )
 
  420                       << QStringLiteral( 
"Black" )
 
  421                       << QStringLiteral( 
"Demi" )
 
  422                       << QStringLiteral( 
"Italic" )
 
  423                       << QStringLiteral( 
"Oblique" );
 
  424   const auto constWords = words;
 
  425   for ( 
const QString &word : constWords )
 
  427     translatedStyleMap.insert( QCoreApplication::translate( 
"QFontDatabase", qPrintable( word ) ), word );
 
  429   return translatedStyleMap;
 
  434 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  435   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  437   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  439   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  441     words[i] = QCoreApplication::translate( 
"QFontDatabase", words[i].toLocal8Bit().constData() );
 
  443   return words.join( QLatin1Char( 
' ' ) );
 
  448   static QMap<QString, QString> translatedStyleMap = createTranslatedStyleMap();
 
  449 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  450   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  452   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  455   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  457     if ( translatedStyleMap.contains( words[i] ) )
 
  459       words[i] = translatedStyleMap.value( words[i] );
 
  463       QgsDebugMsgLevel( QStringLiteral( 
"Warning: style map does not contain %1" ).arg( words[i] ), 2 );
 
  466   return words.join( QLatin1Char( 
' ' ) );
 
  471   QString css = QStringLiteral( 
"font-family: " ) + font.family() + 
';';
 
  474   css += QLatin1String( 
"font-style: " );
 
  475   switch ( font.style() )
 
  477     case QFont::StyleNormal:
 
  478       css += QLatin1String( 
"normal" );
 
  480     case QFont::StyleItalic:
 
  481       css += QLatin1String( 
"italic" );
 
  483     case QFont::StyleOblique:
 
  484       css += QLatin1String( 
"oblique" );
 
  491   switch ( font.weight() )
 
  499     case QFont::DemiBold:
 
  511     case QFont::ExtraLight:
 
  517     case QFont::ExtraBold:
 
  521   css += QStringLiteral( 
"font-weight: %1;" ).arg( cssWeight );
 
  524   css += QStringLiteral( 
"font-size: %1px;" ).arg( font.pointSizeF() >= 0 ? font.pointSizeF() * pointToPixelScale : font.pixelSize() );
 
  531   if ( family.isEmpty() )
 
  536   QgsSettings settings;
 
  537   QStringList recentFamilies = settings.value( QStringLiteral( 
"fonts/recent" ) ).toStringList();
 
  540   recentFamilies.removeAll( family );
 
  543   recentFamilies.prepend( family );
 
  546   recentFamilies = recentFamilies.mid( 0, 10 );
 
  548   settings.setValue( QStringLiteral( 
"fonts/recent" ), recentFamilies );
 
  553   QgsSettings settings;
 
  554   return settings.value( QStringLiteral( 
"fonts/recent" ) ).toStringList();
 
static QString buildSourcePath()
Returns path to the source directory. Valid only when running from build directory.
static bool isRunningFromBuildDir()
Indicates whether running from build directory (not installed)
static QString asCSS(const QFont &font, double pointToPixelMultiplier=1.0)
Returns a CSS string representing the specified font as closely as possible.
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 setFromXmlElement(QFont &font, const QDomElement &element)
Sets the properties of a font to match the properties stored in an XML element.
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
static QMimeData * toMimeData(const QFont &font)
Returns new mime data representing the specified font settings.
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.
static bool fontMatchOnSystem(const QFont &f)
Check whether exact font is on system.
static bool loadStandardTestFonts(const QStringList &loadstyles)
Loads standard test fonts from filesystem or qrc resource.
static QFont getStandardTestFont(const QString &style="Roman", int pointsize=12)
Gets standard test font with specific style.
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
static void addRecentFontFamily(const QString &family)
Adds a font family to the list of recently used font families.
static QString standardTestFontFamily()
Gets standard test font family.
static QFont fromMimeData(const QMimeData *data, bool *ok=nullptr)
Attempts to parse the provided mime data as a QFont.
static bool fontFamilyHasStyle(const QString &family, const QString &style)
Check whether font family on system has specific style.
static QStringList recentFontFamilies()
Returns a list of recently used font families.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define QgsDebugMsgLevel(str, level)