From ca41a4575ccedfbd8cef3d87697ccc27b6d8166c Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 15 Oct 2013 17:08:40 +0300 Subject: [PATCH] Gfx: Handle failed creation of D2D text layout --- Common/Gfx/CanvasD2D.cpp | 109 +++++++++++++++++------------------ Common/Gfx/TextFormatD2D.cpp | 50 ++++++++-------- Common/Gfx/TextFormatD2D.h | 4 +- 3 files changed, 81 insertions(+), 82 deletions(-) diff --git a/Common/Gfx/CanvasD2D.cpp b/Common/Gfx/CanvasD2D.cpp index f4fac908..1a09f401 100644 --- a/Common/Gfx/CanvasD2D.cpp +++ b/Common/Gfx/CanvasD2D.cpp @@ -318,69 +318,68 @@ void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& forma Microsoft::WRL::ComPtr solidBrush; HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf()); - if (SUCCEEDED(hr)) + if (FAILED(hr)) return; + + TextFormatD2D& formatD2D = (TextFormatD2D&)format; + if (!formatD2D.CreateLayout( + str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return; + + D2D1_POINT_2F drawPosition; + drawPosition.x = [&]() { - TextFormatD2D& formatD2D = (TextFormatD2D&)format; - formatD2D.CreateLayout( - str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing); - - D2D1_POINT_2F drawPosition; - drawPosition.x = [&]() + if (!m_AccurateText) { - if (!m_AccurateText) + const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f; + switch (formatD2D.GetHorizontalAlignment()) { - const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f; - switch (formatD2D.GetHorizontalAlignment()) - { - case HorizontalAlignment::Left: return rect.X + xOffset; - case HorizontalAlignment::Right: return rect.X - xOffset; - } - } - - return rect.X; - } (); - - drawPosition.y = [&]() - { - // GDI+ compatibility. - float yPos = rect.Y - formatD2D.m_LineGap; - switch (formatD2D.GetVerticalAlignment()) - { - case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break; - case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break; - } - - return yPos; - } (); - - if (formatD2D.m_Trimming) - { - D2D1_RECT_F clipRect = ToRectF(rect); - - if (m_CanUseAxisAlignClip) - { - m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED); - } - else - { - const D2D1_LAYER_PARAMETERS layerParams = - D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED); - m_Target->PushLayer(layerParams, nullptr); + case HorizontalAlignment::Left: return rect.X + xOffset; + case HorizontalAlignment::Right: return rect.X - xOffset; } } - m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get()); + return rect.X; + } (); - if (formatD2D.m_Trimming) + drawPosition.y = [&]() + { + // GDI+ compatibility. + float yPos = rect.Y - formatD2D.m_LineGap; + switch (formatD2D.GetVerticalAlignment()) { - if (m_CanUseAxisAlignClip) - { - m_Target->PopAxisAlignedClip(); - } - else - { - m_Target->PopLayer(); - } + case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break; + case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break; + } + + return yPos; + } (); + + if (formatD2D.m_Trimming) + { + D2D1_RECT_F clipRect = ToRectF(rect); + + if (m_CanUseAxisAlignClip) + { + m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED); + } + else + { + const D2D1_LAYER_PARAMETERS layerParams = + D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED); + m_Target->PushLayer(layerParams, nullptr); + } + } + + m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get()); + + if (formatD2D.m_Trimming) + { + if (m_CanUseAxisAlignClip) + { + m_Target->PopAxisAlignedClip(); + } + else + { + m_Target->PopLayer(); } } } diff --git a/Common/Gfx/TextFormatD2D.cpp b/Common/Gfx/TextFormatD2D.cpp index ca44fb80..a92c31af 100644 --- a/Common/Gfx/TextFormatD2D.cpp +++ b/Common/Gfx/TextFormatD2D.cpp @@ -43,7 +43,7 @@ void TextFormatD2D::Dispose() m_LineGap = 0.0f; } -void TextFormatD2D::CreateLayout( +bool TextFormatD2D::CreateLayout( const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation) { bool strChanged = false; @@ -84,38 +84,38 @@ void TextFormatD2D::CreateLayout( { CanvasD2D::c_DWFactory->CreateTextLayout( str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf()); + if (!m_TextLayout) return false; - if (m_TextLayout) + if (gdiEmulation) { - if (gdiEmulation) - { - Microsoft::WRL::ComPtr textLayout1; - m_TextLayout.As(&textLayout1); + Microsoft::WRL::ComPtr textLayout1; + m_TextLayout.As(&textLayout1); - const float xOffset = m_TextFormat->GetFontSize() / 6.0f; - const float emOffset = xOffset / 24.0f; - const DWRITE_TEXT_RANGE range = {0, strLen}; - textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); - } + const float xOffset = m_TextFormat->GetFontSize() / 6.0f; + const float emOffset = xOffset / 24.0f; + const DWRITE_TEXT_RANGE range = {0, strLen}; + textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range); + } - UINT32 lineCount = 0; - DWRITE_LINE_METRICS lineMetrics[2]; - HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount); - if (SUCCEEDED(hr)) + UINT32 lineCount = 0; + DWRITE_LINE_METRICS lineMetrics[2]; + HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount); + if (SUCCEEDED(hr)) + { + // If only one line is visible, disable wrapping so that as much text as possible is shown + // after trimming. + // TODO: Fix this for when more than one line is visible. + if (lineCount >= 2 && + lineMetrics[0].isTrimmed && + lineMetrics[1].isTrimmed && + lineMetrics[1].height == 0.0f) { - // If only one line is visible, disable wrapping so that as much text as possible is shown - // after trimming. - // TODO: Fix this for when more than one line is visible. - if (lineCount >= 2 && - lineMetrics[0].isTrimmed && - lineMetrics[1].isTrimmed && - lineMetrics[1].height == 0.0f) - { - m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); - } + m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); } } } + + return true; } void TextFormatD2D::SetProperties( diff --git a/Common/Gfx/TextFormatD2D.h b/Common/Gfx/TextFormatD2D.h index 777c2d8f..5e79a7a7 100644 --- a/Common/Gfx/TextFormatD2D.h +++ b/Common/Gfx/TextFormatD2D.h @@ -55,8 +55,8 @@ private: // Creates a new DirectWrite text layout if |str| has changed since last call. Since creating // the layout is costly, it is more efficient to keep reusing the text layout until the text - // changes. - void CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation); + // changes. Returns true if the layout is valid for use. + bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation); DWRITE_TEXT_METRICS GetMetrics( const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);