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() != QStringLiteral(
"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 QStringList words = namedStyle.split(
' ', QString::SkipEmptyParts );
435 for (
int i = 0, n = words.length(); i < n; ++i )
437 words[i] = QCoreApplication::translate(
"QFontDatabase", words[i].toLocal8Bit().constData() );
439 return words.join( QStringLiteral(
" " ) );
444 static QMap<QString, QString> translatedStyleMap = createTranslatedStyleMap();
445 QStringList words = namedStyle.split(
' ', QString::SkipEmptyParts );
446 for (
int i = 0, n = words.length(); i < n; ++i )
448 if ( translatedStyleMap.contains( words[i] ) )
450 words[i] = translatedStyleMap.value( words[i] );
454 QgsDebugMsgLevel( QStringLiteral(
"Warning: style map does not contain %1" ).arg( words[i] ), 2 );
457 return words.join( QStringLiteral(
" " ) );
462 QString css = QStringLiteral(
"font-family: " ) + font.family() +
';';
465 css += QLatin1String(
"font-style: " );
466 switch ( font.style() )
468 case QFont::StyleNormal:
469 css += QLatin1String(
"normal" );
471 case QFont::StyleItalic:
472 css += QLatin1String(
"italic" );
474 case QFont::StyleOblique:
475 css += QLatin1String(
"oblique" );
482 switch ( font.weight() )
490 case QFont::DemiBold:
502 case QFont::ExtraLight:
508 case QFont::ExtraBold:
512 css += QStringLiteral(
"font-weight: %1;" ).arg( cssWeight );
515 css += QStringLiteral(
"font-size: %1px;" ).arg( font.pointSizeF() >= 0 ? font.pointSizeF() * pointToPixelScale : font.pixelSize() );
522 if ( family.isEmpty() )
528 QStringList recentFamilies = settings.
value( QStringLiteral(
"fonts/recent" ) ).toStringList();
531 recentFamilies.removeAll( family );
534 recentFamilies.prepend( family );
537 recentFamilies = recentFamilies.mid( 0, 10 );
539 settings.
setValue( QStringLiteral(
"fonts/recent" ), recentFamilies );
545 return settings.
value( QStringLiteral(
"fonts/recent" ) ).toStringList();