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() != QLatin1String(
"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 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
435 QStringList words = namedStyle.split(
' ', QString::SkipEmptyParts );
437 QStringList words = namedStyle.split(
' ', Qt::SkipEmptyParts );
439 for (
int i = 0, n = words.length(); i < n; ++i )
441 words[i] = QCoreApplication::translate(
"QFontDatabase", words[i].toLocal8Bit().constData() );
443 return words.join( QLatin1Char(
' ' ) );
448 static QMap<QString, QString> translatedStyleMap = createTranslatedStyleMap();
449 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
450 QStringList words = namedStyle.split(
' ', QString::SkipEmptyParts );
452 QStringList words = namedStyle.split(
' ', Qt::SkipEmptyParts );
455 for (
int i = 0, n = words.length(); i < n; ++i )
457 if ( translatedStyleMap.contains( words[i] ) )
459 words[i] = translatedStyleMap.value( words[i] );
463 QgsDebugMsgLevel( QStringLiteral(
"Warning: style map does not contain %1" ).arg( words[i] ), 2 );
466 return words.join( QLatin1Char(
' ' ) );
471 QString css = QStringLiteral(
"font-family: " ) + font.family() +
';';
474 css += QLatin1String(
"font-style: " );
475 switch ( font.style() )
477 case QFont::StyleNormal:
478 css += QLatin1String(
"normal" );
480 case QFont::StyleItalic:
481 css += QLatin1String(
"italic" );
483 case QFont::StyleOblique:
484 css += QLatin1String(
"oblique" );
491 switch ( font.weight() )
499 case QFont::DemiBold:
511 case QFont::ExtraLight:
517 case QFont::ExtraBold:
521 css += QStringLiteral(
"font-weight: %1;" ).arg( cssWeight );
524 css += QStringLiteral(
"font-size: %1px;" ).arg( font.pointSizeF() >= 0 ? font.pointSizeF() * pointToPixelScale : font.pixelSize() );
531 if ( family.isEmpty() )
537 QStringList recentFamilies = settings.
value( QStringLiteral(
"fonts/recent" ) ).toStringList();
540 recentFamilies.removeAll( family );
543 recentFamilies.prepend( family );
546 recentFamilies = recentFamilies.mid( 0, 10 );
548 settings.
setValue( QStringLiteral(
"fonts/recent" ), recentFamilies );
554 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)