Gfx: Make text rendering with D2D more efficient by reusing layout

This commit is contained in:
Birunthan Mohanathas 2013-03-28 15:51:12 +02:00
parent 71a454f954
commit e5100d9a9f
3 changed files with 57 additions and 13 deletions

View File

@ -278,21 +278,15 @@ void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& forma
HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), &solidBrush); HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), &solidBrush);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
const bool right = ((TextFormatD2D&)format).GetHorizontalAlignment() == Gfx::HorizontalAlignment::Right; TextFormatD2D& formatD2D = (TextFormatD2D&)format;
const bool right = formatD2D.GetHorizontalAlignment() == Gfx::HorizontalAlignment::Right;
// TODO: Draw cached layout? formatD2D.CreateLayout(str, strLen, rect.Width, rect.Height);
//m_Target->DrawTextLayout(
// D2D1::Point2F(right ? rect.X - 2 : rect.X + 2.0f, rect.Y - 1.0f),
// textLayout,
// solidBrush);
auto dst = D2D1::RectF( m_Target->DrawTextLayout(
right ? rect.X - 2 : rect.X + 2.0f, D2D1::Point2F(right ? rect.X - 2 : rect.X + 2.0f, rect.Y - 1.0f),
rect.Y - 1.0f, formatD2D.m_TextLayout,
(right ? rect.X - 2 : rect.X + 2.0f) + rect.Width, solidBrush);
rect.Y + rect.Height - 1.0f);
m_Target->DrawTextW(str, strLen, ((TextFormatD2D&)format).m_TextFormat, dst, solidBrush);
solidBrush->Release(); solidBrush->Release();
} }

View File

@ -23,6 +23,7 @@ namespace Gfx {
TextFormatD2D::TextFormatD2D() : TextFormatD2D::TextFormatD2D() :
m_TextFormat(), m_TextFormat(),
m_TextLayout(),
m_InlineEllipsis() m_InlineEllipsis()
{ {
} }
@ -40,6 +41,12 @@ void TextFormatD2D::Dispose()
m_TextFormat = nullptr; m_TextFormat = nullptr;
} }
if (m_TextLayout)
{
m_TextLayout->Release();
m_TextLayout = nullptr;
}
if (m_InlineEllipsis) if (m_InlineEllipsis)
{ {
m_InlineEllipsis->Release(); m_InlineEllipsis->Release();
@ -47,6 +54,40 @@ void TextFormatD2D::Dispose()
} }
} }
void TextFormatD2D::CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH)
{
bool strChanged = false;
if (strLen != m_LastString.length() ||
memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0)
{
strChanged = true;
m_LastString.assign(str, strLen);
}
if (m_TextLayout && !strChanged)
{
if (maxW != m_TextLayout->GetMaxWidth())
{
m_TextLayout->SetMaxWidth(maxW);
}
if (maxH != m_TextLayout->GetMaxHeight())
{
m_TextLayout->SetMaxWidth(maxH);
}
}
else
{
if (m_TextLayout)
{
m_TextLayout->Release();
m_TextLayout = nullptr;
}
CanvasD2D::c_DW->CreateTextLayout(str, strLen, m_TextFormat, maxW, maxH, &m_TextLayout);
}
}
void TextFormatD2D::SetProperties(const WCHAR* fontFamily, int size, bool bold, bool italic, Gdiplus::PrivateFontCollection* fontCollection) void TextFormatD2D::SetProperties(const WCHAR* fontFamily, int size, bool bold, bool italic, Gdiplus::PrivateFontCollection* fontCollection)
{ {
Dispose(); Dispose();

View File

@ -20,6 +20,7 @@
#define RM_GFX_TEXTFORMATD2D_H_ #define RM_GFX_TEXTFORMATD2D_H_
#include "TextFormat.h" #include "TextFormat.h"
#include <string>
#include <dwrite.h> #include <dwrite.h>
namespace Gfx { namespace Gfx {
@ -44,8 +45,16 @@ private:
void Dispose(); void Dispose();
// 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);
IDWriteTextFormat* m_TextFormat; IDWriteTextFormat* m_TextFormat;
IDWriteTextLayout* m_TextLayout;
IDWriteInlineObject* m_InlineEllipsis; IDWriteInlineObject* m_InlineEllipsis;
std::wstring m_LastString;
}; };
} // namespace Gfx } // namespace Gfx