From 171ef8dd4b38ef4db31b6aa2cd6901171d59ccf7 Mon Sep 17 00:00:00 2001 From: jules Date: Sat, 28 Jun 2014 21:36:01 +0100 Subject: [PATCH] Workarounds for AttributedString layout when using from-memory fonts on Windows. --- modules/juce_graphics/fonts/juce_Font.h | 2 +- .../juce_win32_DirectWriteTypeLayout.cpp | 47 +++++++++++++------ .../native/juce_win32_DirectWriteTypeface.cpp | 30 ++++++------ 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/modules/juce_graphics/fonts/juce_Font.h b/modules/juce_graphics/fonts/juce_Font.h index 6649d36d90..9888b27887 100644 --- a/modules/juce_graphics/fonts/juce_Font.h +++ b/modules/juce_graphics/fonts/juce_Font.h @@ -449,7 +449,7 @@ public: private: //============================================================================== class SharedFontInternal; - ReferenceCountedObjectPtr font; + ReferenceCountedObjectPtr font; void dupeInternalIfShared(); void checkTypefaceSuitability(); float getHeightToPointsFactor() const; diff --git a/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp b/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp index 89ab8f6bc6..83e3c9d94f 100644 --- a/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp +++ b/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp @@ -29,8 +29,9 @@ namespace DirectWriteTypeLayout class CustomDirectWriteTextRenderer : public ComBaseClassHelper { public: - CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts) + CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts, const AttributedString& as) : ComBaseClassHelper (0), + attributedString (as), fontCollection (fonts), currentLine (-1), lastOriginY (-10000.0f) @@ -89,20 +90,16 @@ namespace DirectWriteTypeLayout glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun)); glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun)); - String fontFamily, fontStyle; - getFontFamilyAndStyle (glyphRun, fontFamily, fontStyle); - TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range (runDescription->textPosition, runDescription->textPosition + runDescription->stringLength), glyphRun->glyphCount); glyphLine.runs.add (glyphRunLayout); glyphRun->fontFace->GetMetrics (&dwFontMetrics); - const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent); const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight; - glyphRunLayout->font = Font (fontFamily, fontStyle, glyphRun->fontEmSize / fontHeightToEmSizeFactor); + glyphRunLayout->font = getFontForRun (glyphRun, glyphRun->fontEmSize / fontHeightToEmSizeFactor); glyphRunLayout->colour = getColourOf (static_cast (clientDrawingEffect)); const Point lineOrigin (layout->getLine (currentLine).lineOrigin); @@ -127,6 +124,7 @@ namespace DirectWriteTypeLayout } private: + const AttributedString& attributedString; IDWriteFontCollection* const fontCollection; int currentLine; float lastOriginY; @@ -145,19 +143,22 @@ namespace DirectWriteTypeLayout return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a); } - void getFontFamilyAndStyle (DWRITE_GLYPH_RUN const* glyphRun, String& family, String& style) const + Font getFontForRun (DWRITE_GLYPH_RUN const* glyphRun, float fontHeight) { + for (int i = 0; i < attributedString.getNumAttributes(); ++i) + if (const Font* font = attributedString.getAttribute(i)->getFont()) + if (WindowsDirectWriteTypeface* wt = dynamic_cast (font->getTypeface())) + if (wt->getIDWriteFontFace() == glyphRun->fontFace) + return font->withHeight (fontHeight); + ComSmartPtr dwFont; HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress()); jassert (dwFont != nullptr); - { - ComSmartPtr dwFontFamily; - hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress()); - family = getFontFamilyName (dwFontFamily); - } + ComSmartPtr dwFontFamily; + hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress()); - style = getFontFaceName (dwFont); + return Font (getFontFamilyName (dwFontFamily), getFontFaceName (dwFont), fontHeight); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer) @@ -352,11 +353,11 @@ namespace DirectWriteTypeLayout layout.ensureStorageAllocated (actualLineCount); { - ComSmartPtr textRenderer (new CustomDirectWriteTextRenderer (fontCollection)); + ComSmartPtr textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text)); hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0); } - HeapBlock dwLineMetrics (actualLineCount); + HeapBlock dwLineMetrics (actualLineCount); hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount); int lastLocation = 0; const int numLines = jmin ((int) actualLineCount, layout.getNumLines()); @@ -384,11 +385,27 @@ namespace DirectWriteTypeLayout } } } + +static bool canAllTypefacesBeUsedInLayout (const AttributedString& text) +{ + const int numCharacterAttributes = text.getNumAttributes(); + + for (int i = 0; i < numCharacterAttributes; ++i) + if (const Font* const font = text.getAttribute (i)->getFont()) + if (dynamic_cast (font->getTypeface()) == nullptr) + return false; + + return true; +} + #endif bool TextLayout::createNativeLayout (const AttributedString& text) { #if JUCE_USE_DIRECTWRITE + if (! canAllTypefacesBeUsedInLayout (text)) + return false; + SharedResourcePointer factories; if (factories->d2dFactory != nullptr && factories->systemFonts != nullptr) diff --git a/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp b/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp index 72401421af..0673aa556b 100644 --- a/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp +++ b/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp @@ -139,27 +139,27 @@ public: hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress()); // Get a specific font in the font family using typeface style - ComSmartPtr dwFont; - uint32 fontFacesCount = 0; - fontFacesCount = dwFontFamily->GetFontCount(); - - for (int i = fontFacesCount; --i >= 0;) { - hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); + ComSmartPtr dwFont; - if (i == 0) - break; + for (int i = (int) dwFontFamily->GetFontCount(); --i >= 0;) + { + hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); - ComSmartPtr faceNames; - hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress()); + if (i == 0) + break; - if (font.getTypefaceStyle() == getLocalisedName (faceNames)) - break; + ComSmartPtr faceNames; + hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress()); + + if (font.getTypefaceStyle() == getLocalisedName (faceNames)) + break; + } + + jassert (dwFont != nullptr); + hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); } - jassert (dwFont != nullptr); - hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); - if (dwFontFace != nullptr) { DWRITE_FONT_METRICS dwFontMetrics;