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)