void addAttributedRange (const AttributedString::Attribute& attr, IDWriteTextLayout* textLayout,
                             const int textLen, ID2D1RenderTarget* const renderTarget, IDWriteFontCollection* const fontCollection)
    {
        DWRITE_TEXT_RANGE range;
        range.startPosition = attr.range.getStart();
        range.length = jmin (attr.range.getLength(), textLen - attr.range.getStart());

        const Font* const font = attr.getFont();

        if (font != nullptr)
        {
            BOOL fontFound = false;
            uint32 fontIndex;
            fontCollection->FindFamilyName (FontStyleHelpers::getConcreteFamilyName (*font).toWideCharPointer(),
                                            &fontIndex, &fontFound);

            if (! fontFound)
                fontIndex = 0;

            ComSmartPtr<IDWriteFontFamily> fontFamily;
            HRESULT hr = fontCollection->GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());

            ComSmartPtr<IDWriteFont> dwFont;
            uint32 fontFacesCount = 0;
            fontFacesCount = fontFamily->GetFontCount();

            for (int i = fontFacesCount; --i >= 0;)
            {
                hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());

                if (font->getTypefaceStyle() == getFontFaceName (dwFont))
                    break;
            }

            textLayout->SetFontFamilyName (attr.getFont()->getTypefaceName().toWideCharPointer(), range);
            textLayout->SetFontWeight (dwFont->GetWeight(), range);
            textLayout->SetFontStretch (dwFont->GetStretch(), range);
            textLayout->SetFontStyle (dwFont->GetStyle(), range);

            const float fontHeightToEmSizeFactor = getFontHeightToEmSizeFactor (dwFont);
            textLayout->SetFontSize (font->getHeight() * fontHeightToEmSizeFactor, range);
        }

        if (attr.getColour() != nullptr)
        {
            ComSmartPtr<ID2D1SolidColorBrush> d2dBrush;
            renderTarget->CreateSolidColorBrush (D2D1::ColorF (D2D1::ColorF (attr.getColour()->getFloatRed(),
                                                                             attr.getColour()->getFloatGreen(),
                                                                             attr.getColour()->getFloatBlue(),
                                                                             attr.getColour()->getFloatAlpha())),
                                                 d2dBrush.resetAndGetPointerAddress());

            // We need to call SetDrawingEffect with a legimate brush to get DirectWrite to break text based on colours
            textLayout->SetDrawingEffect (d2dBrush, range);
        }
    }
        void getFontFamilyAndStyle (DWRITE_GLYPH_RUN const* glyphRun, String& family, String& style) const
        {
            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);
            }

            style = getFontFaceName (dwFont);
        }
StringArray Font::findAllTypefaceStyles (const String& family)
{
    if (FontStyleHelpers::isPlaceholderFamilyName (family))
        return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family));

    StringArray results;

   #if JUCE_USE_DIRECTWRITE
    const Direct2DFactories& factories = Direct2DFactories::getInstance();

    if (factories.systemFonts != nullptr)
    {
        BOOL fontFound = false;
        uint32 fontIndex = 0;
        HRESULT hr = factories.systemFonts->FindFamilyName (family.toWideCharPointer(), &fontIndex, &fontFound);
        if (! fontFound)
            fontIndex = 0;

        // Get the font family using the search results
        // Fonts like: Times New Roman, Times New Roman Bold, Times New Roman Italic are all in the same font family
        ComSmartPtr<IDWriteFontFamily> fontFamily;
        hr = factories.systemFonts->GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());

        // Get the font faces
        ComSmartPtr<IDWriteFont> dwFont;
        uint32 fontFacesCount = 0;
        fontFacesCount = fontFamily->GetFontCount();

        for (uint32 i = 0; i < fontFacesCount; ++i)
        {
            hr = fontFamily->GetFont (i, dwFont.resetAndGetPointerAddress());

            // Ignore any algorithmically generated bold and oblique styles..
            if (dwFont->GetSimulations() == DWRITE_FONT_SIMULATIONS_NONE)
                results.addIfNotAlreadyThere (getFontFaceName (dwFont));
        }
    }
    else
   #endif
    {
        results.add ("Regular");
        results.add ("Italic");
        results.add ("Bold");
        results.add ("Bold Italic");
    }

    return results;
}
        Font getFontForRun (const DWRITE_GLYPH_RUN& 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());

            return Font (getFontFamilyName (dwFontFamily), getFontFaceName (dwFont), fontHeight);
        }