mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-29 02:40:05 +00:00
DirectWriteTypeface: Use GDI fallback behaviour for missing fonts
Previously, when attempting to create a font with a name different to that of any font on the system, the returned typeface could be nullptr. This could lead to crashes when attempting to use the typeface. Now, if we fail to find a matching font using DirectWrite, we fall back to the older LOGFONT and DC approach, which will generally locate a usable typeface, though not necessarily an exact match. The new behaviour more closely matches the behaviour of JUCE 7, which would attempt to construct a DirectWrite typeface, but would fall back to creating an HFONT on failure.
This commit is contained in:
parent
1e0f23baf8
commit
54b157bb8c
1 changed files with 60 additions and 1 deletions
|
|
@ -181,6 +181,19 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
ComSmartPtr<IDWriteFont> findFontForFace (IDWriteFontFace* face)
|
||||
{
|
||||
for (const auto& collection : collections)
|
||||
{
|
||||
ComSmartPtr<IDWriteFont> result;
|
||||
|
||||
if (SUCCEEDED (collection->GetFontFromFontFace (face, result.resetAndGetPointerAddress())))
|
||||
return result;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void addCollection (ComSmartPtr<IDWriteFontCollection> collection)
|
||||
{
|
||||
const std::scoped_lock lock { mutex };
|
||||
|
|
@ -552,7 +565,7 @@ public:
|
|||
const auto family = factories->getFonts().getFamilyByName (name.toWideCharPointer());
|
||||
|
||||
if (family == nullptr)
|
||||
return {};
|
||||
return getLastResortTypeface (f);
|
||||
|
||||
const auto weight = f.isBold() ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_NORMAL;
|
||||
const auto italic = f.isItalic() ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
|
||||
|
|
@ -831,6 +844,52 @@ private:
|
|||
collection);
|
||||
}
|
||||
|
||||
// This attempts to replicate the behaviour of the non-directwrite typeface lookup in JUCE 7 and older
|
||||
static Typeface::Ptr getLastResortTypeface (const Font& font)
|
||||
{
|
||||
auto* dc = CreateCompatibleDC (nullptr);
|
||||
const ScopeGuard deleteDC { [&] { DeleteDC (dc); } };
|
||||
|
||||
SetMapperFlags (dc, 0);
|
||||
SetMapMode (dc, MM_TEXT);
|
||||
|
||||
const auto style = font.getTypefaceStyle();
|
||||
|
||||
LOGFONTW lf{};
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
lf.lfOutPrecision = OUT_OUTLINE_PRECIS;
|
||||
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||||
lf.lfQuality = PROOF_QUALITY;
|
||||
lf.lfItalic = (BYTE) (style.contains ("Italic") ? TRUE : FALSE);
|
||||
lf.lfWeight = style.contains ("Bold") ? FW_BOLD : FW_NORMAL;
|
||||
lf.lfHeight = -256;
|
||||
font.getTypefaceName().copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName));
|
||||
|
||||
auto* hfont = CreateFontIndirectW (&lf);
|
||||
const ScopeGuard deleteFont { [&] { DeleteObject (hfont); } };
|
||||
|
||||
auto* prevFont = hfont != nullptr ? SelectObject (dc, hfont) : nullptr;
|
||||
const ScopeGuard reinstateFont { [&] { if (prevFont != nullptr) SelectObject (dc, prevFont); } };
|
||||
|
||||
SharedResourcePointer<Direct2DFactories> factories;
|
||||
|
||||
ComSmartPtr<IDWriteGdiInterop> interop;
|
||||
if (FAILED (factories->getDWriteFactory()->GetGdiInterop (interop.resetAndGetPointerAddress())) || interop == nullptr)
|
||||
return {};
|
||||
|
||||
ComSmartPtr<IDWriteFontFace> dwFontFace;
|
||||
if (FAILED (interop->CreateFontFaceFromHdc (dc, dwFontFace.resetAndGetPointerAddress())) || dwFontFace == nullptr)
|
||||
return {};
|
||||
|
||||
const auto dwFont = factories->getFonts().findFontForFace (dwFontFace);
|
||||
|
||||
if (dwFont == nullptr)
|
||||
return {};
|
||||
|
||||
return fromFont (dwFont, nullptr, nullptr, MetricsMechanism::gdiWithDwriteFallback);
|
||||
}
|
||||
|
||||
SharedResourcePointer<Direct2DFactories> factories;
|
||||
ComSmartPtr<IDWriteFontCollection> collection;
|
||||
ComSmartPtr<IDWriteFont> dwFont;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue