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   auto styleNameIsMatch = [&font]( 
const QString & candidate ) -> 
bool 
   74     QFont testFont( font.family() );
 
   75     testFont.setStyleName( candidate );
 
   76     return testFont.italic() == font.italic() && testFont.weight() == font.weight();
 
   80   const QFontInfo fontInfo( font );
 
   81   QString styleName = fontInfo.styleName();
 
   82   if ( !styleName.isEmpty() )
 
   84     if ( styleNameIsMatch( styleName ) )
 
   89   styleName = QFontDatabase().styleString( font );
 
   90   if ( !styleName.isEmpty() )
 
   92     if ( styleNameIsMatch( styleName ) )
 
  102   const QFontDatabase fontDB;
 
  103   const QStringList fontFamilies = fontDB.families();
 
  106   QList<QString>::const_iterator it = fontFamilies.constBegin();
 
  107   for ( ; it != fontFamilies.constEnd(); ++it )
 
  110     if ( it->startsWith( family, Qt::CaseInsensitive ) )
 
  117         *match = ( *it == family );
 
  133       const QFont f = QFont( family );
 
  134       *chosen = f.family();
 
  155   if ( fontstyle.isEmpty() )
 
  160   QFontDatabase fontDB;
 
  173   if ( fontstyle == fontDB.styleString( f ) )
 
  178   const QFont appfont = QApplication::font();
 
  179   const int defaultSize = appfont.pointSize(); 
 
  182   bool foundmatch = 
false;
 
  185   styledfont = fontDB.font( f.family(), fontstyle, defaultSize );
 
  186   if ( appfont != styledfont || fontstyle != fontDB.styleString( f ) )
 
  193   if ( fallback && !foundmatch )
 
  195     QFont testFont = QFont( f );
 
  196     testFont.setPointSize( defaultSize );
 
  199     const auto constFamily = fontDB.styles( f.family() );
 
  200     for ( 
const QString &style : constFamily )
 
  202       styledfont = fontDB.font( f.family(), style, defaultSize );
 
  203       styledfont = styledfont.resolve( f );
 
  204       if ( testFont.toString() == styledfont.toString() )
 
  214       for ( 
const QString &style : constFamily )
 
  216         styledfont = fontDB.font( f.family(), style, defaultSize );
 
  217         if ( QApplication::font() != styledfont )
 
  232       styledfont.setPointSizeF( f.pointSizeF() );
 
  234     else if ( f.pixelSize() != -1 )
 
  236       styledfont.setPixelSize( f.pixelSize() );
 
  238     styledfont.setCapitalization( f.capitalization() );
 
  239     styledfont.setUnderline( f.underline() );
 
  240     styledfont.setStrikeOut( f.strikeOut() );
 
  241     styledfont.setWordSpacing( f.wordSpacing() );
 
  242     styledfont.setLetterSpacing( QFont::AbsoluteSpacing, f.letterSpacing() );
 
  253   return QStringLiteral( 
"QGIS Vera Sans" );
 
  259   bool fontsLoaded = 
false;
 
  262   QMap<QString, QString> fontStyles;
 
  263   fontStyles.insert( QStringLiteral( 
"Roman" ), QStringLiteral( 
"QGIS-Vera/QGIS-Vera.ttf" ) );
 
  264   fontStyles.insert( QStringLiteral( 
"Oblique" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraIt.ttf" ) );
 
  265   fontStyles.insert( QStringLiteral( 
"Bold" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraBd.ttf" ) );
 
  266   fontStyles.insert( QStringLiteral( 
"Bold Oblique" ), QStringLiteral( 
"QGIS-Vera/QGIS-VeraBI.ttf" ) );
 
  268   QMap<QString, QString>::const_iterator f = fontStyles.constBegin();
 
  269   for ( ; f != fontStyles.constEnd(); ++f )
 
  271     const QString fontstyle( f.key() );
 
  272     const QString fontpath( f.value() );
 
  273     if ( !( loadstyles.contains( fontstyle ) || loadstyles.contains( QStringLiteral( 
"All" ) ) ) )
 
  280       QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1 %2' already available" ).arg( fontFamily, fontstyle ), 2 );
 
  292         const int fontID = QFontDatabase::addApplicationFont( fontPath );
 
  293         loaded = ( fontID != -1 );
 
  294         fontsLoaded = ( fontsLoaded || loaded );
 
  295         QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1 %2' %3 from filesystem [%4]" )
 
  296                           .arg( fontFamily, fontstyle, loaded ? 
"loaded" : 
"FAILED to load", fontPath ), 2 );
 
  297         QgsDebugMsgLevel( QStringLiteral( 
"font families in %1: %2" ).arg( fontID ).arg( QFontDatabase().applicationFontFamilies( fontID ).join( 
"," ) ), 2 );
 
  301         QFile fontResource( 
":/testdata/font/" + fontpath );
 
  302         if ( fontResource.open( QIODevice::ReadOnly ) )
 
  304           const int fontID = QFontDatabase::addApplicationFontFromData( fontResource.readAll() );
 
  305           loaded = ( fontID != -1 );
 
  306           fontsLoaded = ( fontsLoaded || loaded );
 
  308         QgsDebugMsgLevel( QStringLiteral( 
"Test font '%1' (%2) %3 from testdata.qrc" )
 
  309                           .arg( fontFamily, fontstyle, loaded ? 
"loaded" : 
"FAILED to load" ), 2 );
 
  324   const QFontDatabase fontDB;
 
  327   if ( !f.exactMatch() )
 
  330     if ( style == 
"Roman" )
 
  332     else if ( style == 
"Oblique" )
 
  334     else if ( style == 
"Bold Oblique" )
 
  335       modified = 
"Bold Italic";
 
  336     if ( !modified.isEmpty() )
 
  339   if ( !f.exactMatch() )
 
  342     QgsDebugMsg( QStringLiteral( 
"Requested: %1" ).arg( f.toString() ) );
 
  344     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() ) );
 
  348   f.setBold( style.contains( QLatin1String( 
"Bold" ) ) );
 
  349   f.setItalic( style.contains( QLatin1String( 
"Oblique" ) ) || style.contains( QLatin1String( 
"Italic" ) ) );
 
  356   QDomElement fontElem = document.createElement( elementName );
 
  357   fontElem.setAttribute( QStringLiteral( 
"description" ), font.toString() );
 
  359   fontElem.setAttribute( QStringLiteral( 
"bold" ), font.bold() ? QChar( 
'1' ) : QChar( 
'0' ) );
 
  360   fontElem.setAttribute( QStringLiteral( 
"italic" ), font.italic() ? QChar( 
'1' ) : QChar( 
'0' ) );
 
  361   fontElem.setAttribute( QStringLiteral( 
"underline" ), font.underline() ? QChar( 
'1' ) : QChar( 
'0' ) );
 
  362   fontElem.setAttribute( QStringLiteral( 
"strikethrough" ), font.strikeOut() ? QChar( 
'1' ) : QChar( 
'0' ) );
 
  368   if ( element.isNull() )
 
  373   font.fromString( element.attribute( QStringLiteral( 
"description" ) ) );
 
  375   if ( element.hasAttribute( QStringLiteral( 
"bold" ) ) && element.attribute( QStringLiteral( 
"bold" ) ) == QChar( 
'1' ) )
 
  377     font.setBold( 
true );
 
  379   if ( element.hasAttribute( QStringLiteral( 
"italic" ) ) )
 
  381     font.setItalic( element.attribute( QStringLiteral( 
"italic" ) ) == QChar( 
'1' ) );
 
  383   if ( element.hasAttribute( QStringLiteral( 
"underline" ) ) )
 
  385     font.setUnderline( element.attribute( QStringLiteral( 
"underline" ) ) == QChar( 
'1' ) );
 
  387   if ( element.hasAttribute( QStringLiteral( 
"strikethrough" ) ) )
 
  389     font.setStrikeOut( element.attribute( QStringLiteral( 
"strikethrough" ) ) == QChar( 
'1' ) );
 
  392   if ( element.hasAttribute( QStringLiteral( 
"style" ) ) )
 
  402   if ( element.isNull() )
 
  407   const QDomNodeList nodeList = element.elementsByTagName( childNode );
 
  408   if ( !nodeList.isEmpty() )
 
  410     const QDomElement fontElem = nodeList.at( 0 ).toElement();
 
  421   std::unique_ptr< QMimeData >mimeData( 
new QMimeData );
 
  423   QDomDocument fontDoc;
 
  424   const QDomElement fontElem = 
toXmlElement( font, fontDoc, QStringLiteral( 
"font" ) );
 
  425   fontDoc.appendChild( fontElem );
 
  426   mimeData->setText( fontDoc.toString() );
 
  428   return mimeData.release();
 
  440   const QString text = data->text();
 
  441   if ( !text.isEmpty() )
 
  446     if ( doc.setContent( text ) )
 
  448       elem = doc.documentElement();
 
  450       if ( elem.nodeName() != QLatin1String( 
"font" ) )
 
  451         elem = elem.firstChildElement( QStringLiteral( 
"font" ) );
 
  464 static QMap<QString, QString> createTranslatedStyleMap()
 
  466   QMap<QString, QString> translatedStyleMap;
 
  467   const QStringList words = QStringList()
 
  468                             << QStringLiteral( 
"Normal" )
 
  469                             << QStringLiteral( 
"Regular" )
 
  470                             << QStringLiteral( 
"Light" )
 
  471                             << QStringLiteral( 
"Bold" )
 
  472                             << QStringLiteral( 
"Black" )
 
  473                             << QStringLiteral( 
"Demi" )
 
  474                             << QStringLiteral( 
"Italic" )
 
  475                             << QStringLiteral( 
"Oblique" );
 
  476   const auto constWords = words;
 
  477   for ( 
const QString &word : constWords )
 
  479     translatedStyleMap.insert( QCoreApplication::translate( 
"QFontDatabase", qPrintable( word ) ), word );
 
  481   return translatedStyleMap;
 
  486 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  487   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  489   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  491   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  493     words[i] = QCoreApplication::translate( 
"QFontDatabase", words[i].toLocal8Bit().constData() );
 
  495   return words.join( QLatin1Char( 
' ' ) );
 
  500   static const QMap<QString, QString> translatedStyleMap = createTranslatedStyleMap();
 
  501 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  502   QStringList words = namedStyle.split( 
' ', QString::SkipEmptyParts );
 
  504   QStringList words = namedStyle.split( 
' ', Qt::SkipEmptyParts );
 
  507   for ( 
int i = 0, n = words.length(); i < n; ++i )
 
  509     if ( translatedStyleMap.contains( words[i] ) )
 
  511       words[i] = translatedStyleMap.value( words[i] );
 
  515       QgsDebugMsgLevel( QStringLiteral( 
"Warning: style map does not contain %1" ).arg( words[i] ), 2 );
 
  518   return words.join( QLatin1Char( 
' ' ) );
 
  523   QString css = QStringLiteral( 
"font-family: " ) + font.family() + 
';';
 
  526   css += QLatin1String( 
"font-style: " );
 
  527   switch ( font.style() )
 
  529     case QFont::StyleNormal:
 
  530       css += QLatin1String( 
"normal" );
 
  532     case QFont::StyleItalic:
 
  533       css += QLatin1String( 
"italic" );
 
  535     case QFont::StyleOblique:
 
  536       css += QLatin1String( 
"oblique" );
 
  543   switch ( font.weight() )
 
  551     case QFont::DemiBold:
 
  563     case QFont::ExtraLight:
 
  569     case QFont::ExtraBold:
 
  573   css += QStringLiteral( 
"font-weight: %1;" ).arg( cssWeight );
 
  576   css += QStringLiteral( 
"font-size: %1px;" ).arg( font.pointSizeF() >= 0 ? font.pointSizeF() * pointToPixelScale : font.pixelSize() );
 
  583   if ( family.isEmpty() )
 
  589   QStringList recentFamilies = settings.
value( QStringLiteral( 
"fonts/recent" ) ).toStringList();
 
  592   recentFamilies.removeAll( family );
 
  595   recentFamilies.prepend( family );
 
  598   recentFamilies = recentFamilies.mid( 0, 10 );
 
  600   settings.
setValue( QStringLiteral( 
"fonts/recent" ), recentFamilies );
 
  606   return settings.
value( QStringLiteral( 
"fonts/recent" ) ).toStringList();