mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-11 23:54:18 +00:00
Workarounds for AttributedString layout when using from-memory fonts on Windows.
This commit is contained in:
parent
993d4a6e59
commit
171ef8dd4b
3 changed files with 48 additions and 31 deletions
|
|
@ -449,7 +449,7 @@ public:
|
|||
private:
|
||||
//==============================================================================
|
||||
class SharedFontInternal;
|
||||
ReferenceCountedObjectPtr <SharedFontInternal> font;
|
||||
ReferenceCountedObjectPtr<SharedFontInternal> font;
|
||||
void dupeInternalIfShared();
|
||||
void checkTypefaceSuitability();
|
||||
float getHeightToPointsFactor() const;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ namespace DirectWriteTypeLayout
|
|||
class CustomDirectWriteTextRenderer : public ComBaseClassHelper<IDWriteTextRenderer>
|
||||
{
|
||||
public:
|
||||
CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts)
|
||||
CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts, const AttributedString& as)
|
||||
: ComBaseClassHelper<IDWriteTextRenderer> (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<int> (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<ID2D1SolidColorBrush*> (clientDrawingEffect));
|
||||
|
||||
const Point<float> 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<WindowsDirectWriteTypeface*> (font->getTypeface()))
|
||||
if (wt->getIDWriteFontFace() == glyphRun->fontFace)
|
||||
return font->withHeight (fontHeight);
|
||||
|
||||
ComSmartPtr<IDWriteFont> dwFont;
|
||||
HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress());
|
||||
jassert (dwFont != nullptr);
|
||||
|
||||
{
|
||||
ComSmartPtr<IDWriteFontFamily> dwFontFamily;
|
||||
hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress());
|
||||
family = getFontFamilyName (dwFontFamily);
|
||||
}
|
||||
ComSmartPtr<IDWriteFontFamily> 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<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection));
|
||||
ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text));
|
||||
hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0);
|
||||
}
|
||||
|
||||
HeapBlock <DWRITE_LINE_METRICS> dwLineMetrics (actualLineCount);
|
||||
HeapBlock<DWRITE_LINE_METRICS> 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<WindowsDirectWriteTypeface*> (font->getTypeface()) == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool TextLayout::createNativeLayout (const AttributedString& text)
|
||||
{
|
||||
#if JUCE_USE_DIRECTWRITE
|
||||
if (! canAllTypefacesBeUsedInLayout (text))
|
||||
return false;
|
||||
|
||||
SharedResourcePointer<Direct2DFactories> factories;
|
||||
|
||||
if (factories->d2dFactory != nullptr && factories->systemFonts != nullptr)
|
||||
|
|
|
|||
|
|
@ -139,27 +139,27 @@ public:
|
|||
hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress());
|
||||
|
||||
// Get a specific font in the font family using typeface style
|
||||
ComSmartPtr<IDWriteFont> dwFont;
|
||||
uint32 fontFacesCount = 0;
|
||||
fontFacesCount = dwFontFamily->GetFontCount();
|
||||
|
||||
for (int i = fontFacesCount; --i >= 0;)
|
||||
{
|
||||
hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
|
||||
ComSmartPtr<IDWriteFont> dwFont;
|
||||
|
||||
if (i == 0)
|
||||
break;
|
||||
for (int i = (int) dwFontFamily->GetFontCount(); --i >= 0;)
|
||||
{
|
||||
hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());
|
||||
|
||||
ComSmartPtr<IDWriteLocalizedStrings> faceNames;
|
||||
hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress());
|
||||
if (i == 0)
|
||||
break;
|
||||
|
||||
if (font.getTypefaceStyle() == getLocalisedName (faceNames))
|
||||
break;
|
||||
ComSmartPtr<IDWriteLocalizedStrings> 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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue