106void QWindowsDirectWriteFontDatabase::populateFamily(
const QString &familyName)
108 auto it = m_populatedFonts.find(familyName);
109 if (it == m_populatedFonts.end() && m_populatedBitmapFonts.contains(familyName)) {
110 qCDebug(lcQpaFonts) <<
"Populating bitmap font" << familyName;
111 QWindowsFontDatabase::populateFamily(familyName);
115 IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() :
nullptr;
116 if (fontFamily ==
nullptr) {
117 qCWarning(lcQpaFonts) <<
"Cannot find" << familyName <<
"in list of fonts";
121 qCDebug(lcQpaFonts) <<
"Populate family:" << familyName;
123 wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
124 bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
125 wchar_t englishLocale[] = L"en-us";
127 static const int SMOOTH_SCALABLE = 0xffff;
128 const QString foundryName;
129 const bool scalable =
true;
130 const bool antialias =
false;
131 const int size = SMOOTH_SCALABLE;
133 DirectWriteScope<IDWriteFontList> matchingFonts;
134 if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR,
135 DWRITE_FONT_STRETCH_NORMAL,
136 DWRITE_FONT_STYLE_NORMAL,
138 for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) {
139 DirectWriteScope<IDWriteFont> font;
140 if (SUCCEEDED(matchingFonts->GetFont(j, &font))) {
141 DirectWriteScope<IDWriteFont2> font2;
142 if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont2),
143 reinterpret_cast<
void **>(&font2)))) {
144 qCWarning(lcQpaFonts) <<
"COM object does not support IDWriteFont1";
148 QString defaultLocaleFamilyName;
149 QString englishLocaleFamilyName;
151 DirectWriteScope<IDWriteFontFamily> fontFamily2;
152 if (SUCCEEDED(font2->GetFontFamily(&fontFamily2))) {
153 DirectWriteScope<IDWriteLocalizedStrings> names;
154 if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) {
155 defaultLocaleFamilyName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
156 englishLocaleFamilyName = localeString(*names, englishLocale);
160 if (defaultLocaleFamilyName.isEmpty() && englishLocaleFamilyName.isEmpty())
161 englishLocaleFamilyName = familyName;
164 DirectWriteScope<IDWriteLocalizedStrings> names;
165 if (SUCCEEDED(font2->GetFaceNames(&names))) {
166 QString defaultLocaleStyleName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
167 QString englishLocaleStyleName = localeString(*names, englishLocale);
169 QFont::Stretch stretch = fromDirectWriteStretch(font2->GetStretch());
170 QFont::Style style = fromDirectWriteStyle(font2->GetStyle());
171 QFont::Weight weight = fromDirectWriteWeight(font2->GetWeight());
172 bool fixed = font2->IsMonospacedFont();
173 bool color = font2->IsColorFont();
175 qCDebug(lcQpaFonts) <<
"Family" << familyName <<
"has english variant" << englishLocaleStyleName <<
", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed;
177 DirectWriteScope<IDWriteFontFace> face;
178 if (SUCCEEDED(font->CreateFontFace(&face))) {
179 QSupportedWritingSystems writingSystems = supportedWritingSystems(*face);
181 if (!englishLocaleStyleName.isEmpty() || defaultLocaleStyleName.isEmpty()) {
182 qCDebug(lcQpaFonts) <<
"Font" << englishLocaleFamilyName << englishLocaleStyleName <<
"supports writing systems:" << writingSystems;
184 QPlatformFontDatabase::registerFont(englishLocaleFamilyName,
185 englishLocaleStyleName,
196 new FontHandle(*face, englishLocaleFamilyName));
199 if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) {
200 QPlatformFontDatabase::registerFont(defaultLocaleFamilyName,
201 defaultLocaleStyleName,
212 new FontHandle(*face, defaultLocaleFamilyName));
283QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(
const QFontDef &fontDef,
void *handle)
285 const FontHandle *fontHandle =
static_cast<
const FontHandle *>(handle);
286 IDWriteFontFace *face = fontHandle->fontFace;
287 if (face ==
nullptr) {
288 qCDebug(lcQpaFonts) <<
"Falling back to GDI";
289 return QWindowsFontDatabase::fontEngine(fontDef, handle);
292 DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE;
293 if (fontDef.weight >= QFont::DemiBold || fontDef.style != QFont::StyleNormal) {
294 DirectWriteScope<IDWriteFontFace3> face3;
295 if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3),
296 reinterpret_cast<
void **>(&face3)))) {
297 if (fontDef.weight >= QFont::DemiBold && face3->GetWeight() < DWRITE_FONT_WEIGHT_DEMI_BOLD)
298 simulations |= DWRITE_FONT_SIMULATIONS_BOLD;
300 if (fontDef.style != QFont::StyleNormal && face3->GetStyle() == DWRITE_FONT_STYLE_NORMAL)
301 simulations |= DWRITE_FONT_SIMULATIONS_OBLIQUE;
305 DirectWriteScope<IDWriteFontFace5> newFace;
306 if (!fontDef.variableAxisValues.isEmpty() || simulations != DWRITE_FONT_SIMULATIONS_NONE) {
307 DirectWriteScope<IDWriteFontFace5> face5;
308 if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace5),
309 reinterpret_cast<
void **>(&face5)))) {
310 DirectWriteScope<IDWriteFontResource> font;
311 if (SUCCEEDED(face5->GetFontResource(&font))) {
312 UINT32 fontAxisCount = font->GetFontAxisCount();
313 QVarLengthArray<DWRITE_FONT_AXIS_VALUE, 8> fontAxisValues(fontAxisCount);
315 if (!fontDef.variableAxisValues.isEmpty()) {
316 if (SUCCEEDED(face5->GetFontAxisValues(fontAxisValues.data(), fontAxisCount))) {
317 for (UINT32 i = 0; i < fontAxisCount; ++i) {
318 if (
auto maybeTag = QFont::Tag::fromValue(qToBigEndian<UINT32>(fontAxisValues[i].axisTag))) {
319 if (fontDef.variableAxisValues.contains(*maybeTag))
320 fontAxisValues[i].value = fontDef.variableAxisValues.value(*maybeTag);
326 if (SUCCEEDED(font->CreateFontFace(simulations,
327 !fontDef.variableAxisValues.isEmpty() ? fontAxisValues.data() :
nullptr,
328 !fontDef.variableAxisValues.isEmpty() ? fontAxisCount : 0,
332 qCWarning(lcQpaFonts) <<
"DirectWrite: Can't create font face for variable axis values";
338 QWindowsFontEngineDirectWrite *fontEngine =
new QWindowsFontEngineDirectWrite(face, fontDef.pixelSize, data());
339 fontEngine->initFontInfo(fontDef, defaultVerticalDPI());
360QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(
const QByteArray &fontData,
const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
362 qCDebug(lcQpaFonts) <<
"Adding application font" << fileName;
364 QByteArray loadedData = fontData;
365 if (loadedData.isEmpty()) {
366 QFile file(fileName);
367 if (!file.open(QIODevice::ReadOnly)) {
368 qCWarning(lcQpaFonts) <<
"Cannot open" << fileName <<
"for reading.";
369 return QStringList();
371 loadedData = file.readAll();
374 QList<IDWriteFontFace *> faces = createDirectWriteFaces(loadedData, fileName);
375 if (faces.isEmpty()) {
376 qCWarning(lcQpaFonts) <<
"Failed to create DirectWrite face from font data. Font may be unsupported.";
377 return QStringList();
381 for (
int i = 0; i < faces.size(); ++i) {
382 IDWriteFontFace *face = faces.at(i);
383 wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
384 bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
385 wchar_t englishLocale[] = L"en-us";
387 static const int SMOOTH_SCALABLE = 0xffff;
388 const bool scalable =
true;
389 const bool antialias =
false;
390 const int size = SMOOTH_SCALABLE;
392 QSupportedWritingSystems writingSystems = supportedWritingSystems(face);
393 DirectWriteScope<IDWriteFontFace3> face3;
394 if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3),
395 reinterpret_cast<
void **>(&face3)))) {
396 QString defaultLocaleFamilyName;
397 QString englishLocaleFamilyName;
399 IDWriteLocalizedStrings *names =
nullptr;
400 if (SUCCEEDED(face3->GetFamilyNames(&names))) {
401 defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
402 englishLocaleFamilyName = localeString(names, englishLocale);
407 QString defaultLocaleStyleName;
408 QString englishLocaleStyleName;
409 if (SUCCEEDED(face3->GetFaceNames(&names))) {
410 defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
411 englishLocaleStyleName = localeString(names, englishLocale);
417 QString defaultLocaleGdiCompatibleFamilyName;
418 QString englishLocaleGdiCompatibleFamilyName;
419 if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &ok)) && ok) {
420 defaultLocaleGdiCompatibleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
421 englishLocaleGdiCompatibleFamilyName = localeString(names, englishLocale);
426 QString defaultLocaleGdiCompatibleStyleName;
427 QString englishLocaleGdiCompatibleStyleName;
428 if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, &names, &ok)) && ok) {
429 defaultLocaleGdiCompatibleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
430 englishLocaleGdiCompatibleStyleName = localeString(names, englishLocale);
435 QString defaultLocaleTypographicFamilyName;
436 QString englishLocaleTypographicFamilyName;
437 if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, &names, &ok)) && ok) {
438 defaultLocaleTypographicFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
439 englishLocaleTypographicFamilyName = localeString(names, englishLocale);
444 QString defaultLocaleTypographicStyleName;
445 QString englishLocaleTypographicStyleName;
446 if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, &names, &ok)) && ok) {
447 defaultLocaleTypographicStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
448 englishLocaleTypographicStyleName = localeString(names, englishLocale);
453 QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch());
454 QFont::Style style = fromDirectWriteStyle(face3->GetStyle());
455 QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight());
456 bool fixed = face3->IsMonospacedFont();
457 bool color = face3->IsColorFont();
459 qCDebug(lcQpaFonts) <<
"\tFont names:" << englishLocaleFamilyName <<
", " << defaultLocaleFamilyName
460 <<
", style names:" << englishLocaleStyleName <<
", " << defaultLocaleStyleName
461 <<
", stretch:" << stretch
462 <<
", style:" << style
463 <<
", weight:" << weight
464 <<
", fixed:" << fixed;
466 if (!englishLocaleFamilyName.isEmpty()) {
467 if (applicationFont !=
nullptr) {
468 QFontDatabasePrivate::ApplicationFont::Properties properties;
469 properties.style = style;
470 properties.weight = weight;
471 properties.familyName = englishLocaleFamilyName;
472 properties.styleName = englishLocaleStyleName;
473 applicationFont->properties.append(properties);
476 ret.insert(englishLocaleFamilyName);
477 QPlatformFontDatabase::registerFont(englishLocaleFamilyName,
478 englishLocaleStyleName,
489 new FontHandle(face, englishLocaleFamilyName));
492 if (!defaultLocaleFamilyName.isEmpty() && !ret.contains(defaultLocaleFamilyName)) {
493 if (applicationFont !=
nullptr) {
494 QFontDatabasePrivate::ApplicationFont::Properties properties;
495 properties.style = style;
496 properties.weight = weight;
497 properties.familyName = englishLocaleFamilyName;
498 properties.styleName = englishLocaleStyleName;
499 applicationFont->properties.append(properties);
502 ret.insert(defaultLocaleFamilyName);
503 QPlatformFontDatabase::registerFont(defaultLocaleFamilyName,
504 defaultLocaleStyleName,
515 new FontHandle(face, defaultLocaleFamilyName));
518 if (!englishLocaleGdiCompatibleFamilyName.isEmpty() &&
519 !ret.contains(englishLocaleGdiCompatibleFamilyName)) {
520 if (applicationFont !=
nullptr) {
521 QFontDatabasePrivate::ApplicationFont::Properties properties;
522 properties.style = style;
523 properties.weight = weight;
524 properties.familyName = englishLocaleGdiCompatibleFamilyName;
525 applicationFont->properties.append(properties);
528 ret.insert(englishLocaleGdiCompatibleFamilyName);
529 QPlatformFontDatabase::registerFont(englishLocaleGdiCompatibleFamilyName,
530 englishLocaleGdiCompatibleStyleName,
541 new FontHandle(face, englishLocaleGdiCompatibleFamilyName));
544 if (!defaultLocaleGdiCompatibleFamilyName.isEmpty()
545 && !ret.contains(defaultLocaleGdiCompatibleFamilyName)) {
546 if (applicationFont !=
nullptr) {
547 QFontDatabasePrivate::ApplicationFont::Properties properties;
548 properties.style = style;
549 properties.weight = weight;
550 properties.familyName = defaultLocaleGdiCompatibleFamilyName;
551 applicationFont->properties.append(properties);
554 ret.insert(defaultLocaleGdiCompatibleFamilyName);
555 QPlatformFontDatabase::registerFont(defaultLocaleGdiCompatibleFamilyName,
556 defaultLocaleGdiCompatibleStyleName,
567 new FontHandle(face, defaultLocaleGdiCompatibleFamilyName));
570 if (!englishLocaleTypographicFamilyName.isEmpty()
571 && !ret.contains(englishLocaleTypographicFamilyName)) {
572 if (applicationFont !=
nullptr) {
573 QFontDatabasePrivate::ApplicationFont::Properties properties;
574 properties.style = style;
575 properties.weight = weight;
576 properties.familyName = englishLocaleTypographicFamilyName;
577 applicationFont->properties.append(properties);
580 ret.insert(englishLocaleTypographicFamilyName);
581 QPlatformFontDatabase::registerFont(englishLocaleTypographicFamilyName,
582 englishLocaleTypographicStyleName,
593 new FontHandle(face, englishLocaleTypographicFamilyName));
596 if (!defaultLocaleTypographicFamilyName.isEmpty()
597 && !ret.contains(defaultLocaleTypographicFamilyName)) {
598 if (applicationFont !=
nullptr) {
599 QFontDatabasePrivate::ApplicationFont::Properties properties;
600 properties.style = style;
601 properties.weight = weight;
602 properties.familyName = defaultLocaleTypographicFamilyName;
603 applicationFont->properties.append(properties);
606 ret.insert(defaultLocaleTypographicFamilyName);
607 QPlatformFontDatabase::registerFont(defaultLocaleTypographicFamilyName,
608 defaultLocaleTypographicStyleName,
619 new FontHandle(face, defaultLocaleTypographicFamilyName));
623 qCWarning(lcQpaFonts) <<
"Unable to query IDWriteFontFace3 interface from font face.";
661void QWindowsDirectWriteFontDatabase::populateFontDatabase()
663 wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
664 bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
665 wchar_t englishLocale[] = L"en-us";
667 const QString defaultFontName = defaultFont().families().constFirst();
668 const QString systemDefaultFontName = systemDefaultFont().families().constFirst();
670 DirectWriteScope<IDWriteFontCollection2> fontCollection;
671 DirectWriteScope<IDWriteFactory6> factory6;
672 if (FAILED(data()->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory6),
673 reinterpret_cast<
void **>(&factory6)))) {
674 qCWarning(lcQpaFonts) <<
"Can't initialize IDWriteFactory6. Use GDI font engine instead.";
678 if (SUCCEEDED(factory6->GetSystemFontCollection(
false,
679 DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC,
681 for (uint i = 0; i < fontCollection->GetFontFamilyCount(); ++i) {
682 DirectWriteScope<IDWriteFontFamily2> fontFamily;
683 if (SUCCEEDED(fontCollection->GetFontFamily(i, &fontFamily))) {
684 QString defaultLocaleName;
685 QString englishLocaleName;
687 DirectWriteScope<IDWriteLocalizedStrings> names;
688 if (SUCCEEDED(fontFamily->GetFamilyNames(&names))) {
689 if (hasDefaultLocale)
690 defaultLocaleName = localeString(*names, defaultLocale);
692 englishLocaleName = localeString(*names, englishLocale);
695 qCDebug(lcQpaFonts) <<
"Registering font, english name = " << englishLocaleName <<
", name in current locale = " << defaultLocaleName;
696 if (!defaultLocaleName.isEmpty()) {
697 registerFontFamily(defaultLocaleName);
698 m_populatedFonts.insert(defaultLocaleName, *fontFamily);
699 fontFamily->AddRef();
701 if (defaultLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) {
702 qCDebug(lcQpaFonts) <<
"Adding default font" << systemDefaultFontName <<
"as alternative to" << defaultLocaleName;
704 m_populatedFonts.insert(systemDefaultFontName, *fontFamily);
705 fontFamily->AddRef();
709 if (!englishLocaleName.isEmpty() && englishLocaleName != defaultLocaleName) {
710 registerFontFamily(englishLocaleName);
711 m_populatedFonts.insert(englishLocaleName, *fontFamily);
712 fontFamily->AddRef();
714 if (englishLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) {
715 qCDebug(lcQpaFonts) <<
"Adding default font" << systemDefaultFontName <<
"as alternative to" << englishLocaleName;
717 m_populatedFonts.insert(systemDefaultFontName, *fontFamily);
718 fontFamily->AddRef();
727 HDC dummy = GetDC(0);
729 lf.lfCharSet = DEFAULT_CHARSET;
730 lf.lfFaceName[0] = 0;
731 lf.lfPitchAndFamily = 0;
732 EnumFontFamiliesEx(dummy, &lf, populateBitmapFonts,
reinterpret_cast<intptr_t>(
this), 0);