23 #include <QApplication> 
   26 #include <QFontDatabase> 
   28 #include <QStringList> 
   34   const QFontInfo fi = QFontInfo( f );
 
   35   return fi.exactMatch();
 
   40   const QFont tmpFont = QFont( family );
 
   42   return tmpFont.family().startsWith( family, Qt::CaseInsensitive );
 
   47   const QFontDatabase fontDB;
 
   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 ) )
 
   71   const QFontDatabase fontDB;
 
   72   const 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       const QFont f = QFont( family );
 
  103       *chosen = f.family();
 
  124   if ( fontstyle.isEmpty() )
 
  129   QFontDatabase fontDB;
 
  142   if ( fontstyle == fontDB.styleString( f ) )
 
  147   const QFont appfont = QApplication::font();
 
  148   const 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     const QString fontstyle( f.key() );
 
  241     const 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         const 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 );
 
  266         QgsDebugMsgLevel( QStringLiteral( 
"font families in %1: %2" ).arg( fontID ).arg( QFontDatabase().applicationFontFamilies( fontID ).join( 
"," ) ), 2 );
 
  270         QFile fontResource( 
":/testdata/font/" + fontpath );
 
  271         if ( fontResource.open( QIODevice::ReadOnly ) )
 
  273           const int fontID = QFontDatabase::addApplicationFontFromData( fontResource.readAll() );
 
  274           loaded = ( fontID != -1 );
 
  275           fontsLoaded = ( fontsLoaded || loaded );
 
  277         QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1' (%2) %3 from testdata.qrc" )
 
  278                           .arg( fontFamily, fontstyle, loaded ? 
"loaded" : 
"FAILED to load" ), 2 );
 
  293   const QFontDatabase fontDB;
 
  296   if ( !f.exactMatch() )
 
  299     if ( style == 
"Roman" )
 
  301     else if ( style == 
"Oblique" )
 
  303     else if ( style == 
"Bold Oblique" )
 
  304       modified = 
"Bold Italic";
 
  305     if ( !modified.isEmpty() )
 
  308   if ( !f.exactMatch() )
 
  311     QgsDebugMsg( QStringLiteral( 
"Requested: %1" ).arg( f.toString() ) );
 
  313     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() ) );
 
  317   f.setBold( style.contains( QLatin1String( 
"Bold" ) ) );
 
  318   f.setItalic( style.contains( QLatin1String( 
"Oblique" ) ) || style.contains( QLatin1String( 
"Italic" ) ) );
 
  325   QDomElement fontElem = document.createElement( elementName );
 
  326   fontElem.setAttribute( QStringLiteral( 
"description" ), font.toString() );
 
  333   if ( element.isNull() )
 
  338   font.fromString( element.attribute( QStringLiteral( 
"description" ) ) );
 
  339   if ( element.hasAttribute( QStringLiteral( 
"style" ) ) )
 
  349   if ( element.isNull() )
 
  354   const QDomNodeList nodeList = element.elementsByTagName( childNode );
 
  355   if ( !nodeList.isEmpty() )
 
  357     const QDomElement fontElem = nodeList.at( 0 ).toElement();
 
  368   std::unique_ptr< QMimeData >mimeData( 
new QMimeData );
 
  370   QDomDocument fontDoc;
 
  371   const QDomElement fontElem = 
toXmlElement( font, fontDoc, QStringLiteral( 
"font" ) );
 
  372   fontDoc.appendChild( fontElem );
 
  373   mimeData->setText( fontDoc.toString() );
 
  375   return mimeData.release();
 
  387   const QString text = data->text();
 
  388   if ( !text.isEmpty() )
 
  393     if ( doc.setContent( text ) )
 
  395       elem = doc.documentElement();
 
  397       if ( elem.nodeName() != QLatin1String( 
"font" ) )
 
  398         elem = elem.firstChildElement( QStringLiteral( 
"font" ) );
 
  411 static QMap<QString, QString> createTranslatedStyleMap()
 
  413   QMap<QString, QString> translatedStyleMap;
 
  414   const QStringList words = QStringList()
 
  415                             << QStringLiteral( 
"Normal" )
 
  416                             << QStringLiteral( 
"Regular" )
 
  417                             << QStringLiteral( 
"Light" )
 
  418                             << QStringLiteral( 
"Bold" )
 
  419                             << QStringLiteral( 
"Black" )
 
  420                             << QStringLiteral( 
"Demi" )
 
  421                             << QStringLiteral( 
"Italic" )
 
  422                             << QStringLiteral( 
"Oblique" );
 
  423   const auto constWords = words;
 
  424   for ( 
const QString &word : constWords )
 
  426     translatedStyleMap.insert( QCoreApplication::translate( 
"QFontDatabase", qPrintable( word ) ), word );
 
  428   return translatedStyleMap;
 
  433 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  434   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  436   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  438   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  440     words[i] = QCoreApplication::translate( 
"QFontDatabase", words[i].toLocal8Bit().constData() );
 
  442   return words.join( QLatin1Char( 
' ' ) );
 
  447   static const QMap<QString, QString> translatedStyleMap = createTranslatedStyleMap();
 
  448 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  449   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  451   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  454   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  456     if ( translatedStyleMap.contains( words[i] ) )
 
  458       words[i] = translatedStyleMap.value( words[i] );
 
  462       QgsDebugMsgLevel( QStringLiteral( 
"Warning: style map does not contain %1" ).arg( words[i] ), 2 );
 
  465   return words.join( QLatin1Char( 
' ' ) );
 
  470   QString css = QStringLiteral( 
"font-family: " ) + font.family() + 
';';
 
  473   css += QLatin1String( 
"font-style: " );
 
  474   switch ( font.style() )
 
  476     case QFont::StyleNormal:
 
  477       css += QLatin1String( 
"normal" );
 
  479     case QFont::StyleItalic:
 
  480       css += QLatin1String( 
"italic" );
 
  482     case QFont::StyleOblique:
 
  483       css += QLatin1String( 
"oblique" );
 
  490   switch ( font.weight() )
 
  498     case QFont::DemiBold:
 
  510     case QFont::ExtraLight:
 
  516     case QFont::ExtraBold:
 
  520   css += QStringLiteral( 
"font-weight: %1;" ).arg( cssWeight );
 
  523   css += QStringLiteral( 
"font-size: %1px;" ).arg( font.pointSizeF() >= 0 ? font.pointSizeF() * pointToPixelScale : font.pixelSize() );
 
  530   if ( family.isEmpty() )
 
  536   QStringList recentFamilies = settings.
value( QStringLiteral( 
"fonts/recent" ) ).toStringList();
 
  539   recentFamilies.removeAll( family );
 
  542   recentFamilies.prepend( family );
 
  545   recentFamilies = recentFamilies.mid( 0, 10 );
 
  547   settings.
setValue( QStringLiteral( 
"fonts/recent" ), recentFamilies );
 
  553   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.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
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)