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();