From 12e0564f3ebe961265a7b49edfa083111c862f48 Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 12 Aug 2013 18:50:24 +0300 Subject: [PATCH] Gfx: Avoid clipping with D2D when not needed --- Common/Gfx/CanvasD2D.cpp | 68 +++++++++++++++++++----------------- Common/Gfx/CanvasD2D.h | 7 ++-- Common/Gfx/TextFormatD2D.cpp | 4 ++- Common/Gfx/TextFormatD2D.h | 3 ++ 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/Common/Gfx/CanvasD2D.cpp b/Common/Gfx/CanvasD2D.cpp index 306e5746..7366d94a 100644 --- a/Common/Gfx/CanvasD2D.cpp +++ b/Common/Gfx/CanvasD2D.cpp @@ -52,7 +52,8 @@ Microsoft::WRL::ComPtr CanvasD2D::c_WICFactory; CanvasD2D::CanvasD2D() : Canvas(), m_Bitmap(), - m_TextAntiAliasing(false) + m_TextAntiAliasing(false), + m_CanUseAxisAlignClip(false) { } @@ -169,8 +170,8 @@ bool CanvasD2D::BeginTargetDraw() m_Target->BeginDraw(); - // Apply any transforms that occurred before creation of m_Target - m_Target->SetTransform(GetCurrentTransform()); + // Apply any transforms that occurred before creation of |m_Target|. + UpdateTargetTransform(); return true; } @@ -227,13 +228,18 @@ bool CanvasD2D::IsTransparentPixel(int x, int y) return transparent; } -D2D1_MATRIX_3X2_F CanvasD2D::GetCurrentTransform() +void CanvasD2D::UpdateTargetTransform() { - D2D1_MATRIX_3X2_F d2dMatrix; Gdiplus::Matrix gdipMatrix; m_GdipGraphics->GetTransform(&gdipMatrix); + + D2D1_MATRIX_3X2_F d2dMatrix; gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix); - return d2dMatrix; + + m_Target->SetTransform(d2dMatrix); + m_CanUseAxisAlignClip = + d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f && + d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f; } void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix) @@ -242,7 +248,7 @@ void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix) if (m_Target) { - m_Target->SetTransform(GetCurrentTransform()); + UpdateTargetTransform(); } } @@ -264,7 +270,7 @@ void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float d if (m_Target) { - m_Target->SetTransform(GetCurrentTransform()); + UpdateTargetTransform(); } } @@ -344,36 +350,34 @@ void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& forma return yPos; } (); - DWRITE_OVERHANG_METRICS overhangMetrics; - formatD2D.m_TextLayout->GetOverhangMetrics(&overhangMetrics); - - D2D1::Matrix3x2F transformMatrix; - m_Target->GetTransform(&transformMatrix); - const bool identityTransform = transformMatrix.IsIdentity(); - - // TODO: Determine if we can avoid clipping. - D2D1_RECT_F clipRect = ToRectF(rect); - clipRect.bottom += ceil(overhangMetrics.bottom); - if (identityTransform) + if (formatD2D.m_Trimming) { - 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); + 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 (identityTransform) + if (formatD2D.m_Trimming) { - m_Target->PopAxisAlignedClip(); - } - else - { - m_Target->PopLayer(); + if (m_CanUseAxisAlignClip) + { + m_Target->PopAxisAlignedClip(); + } + else + { + m_Target->PopLayer(); + } } } } diff --git a/Common/Gfx/CanvasD2D.h b/Common/Gfx/CanvasD2D.h index bb15b4eb..94179b8b 100644 --- a/Common/Gfx/CanvasD2D.h +++ b/Common/Gfx/CanvasD2D.h @@ -86,8 +86,8 @@ private: bool BeginTargetDraw(); void EndTargetDraw(); - // Retrieves current GDI+ transform (if any) and converts to a D2D Matrix - D2D1_MATRIX_3X2_F GetCurrentTransform(); + // Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|. + void UpdateTargetTransform(); Microsoft::WRL::ComPtr m_Target; Util::WICBitmapDIB m_Bitmap; @@ -98,6 +98,9 @@ private: bool m_TextAntiAliasing; + // |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used. + bool m_CanUseAxisAlignClip; + static UINT c_Instances; static Microsoft::WRL::ComPtr c_D2DFactory; static Microsoft::WRL::ComPtr c_DWFactory; diff --git a/Common/Gfx/TextFormatD2D.cpp b/Common/Gfx/TextFormatD2D.cpp index 7314322d..5a395bfa 100644 --- a/Common/Gfx/TextFormatD2D.cpp +++ b/Common/Gfx/TextFormatD2D.cpp @@ -24,7 +24,8 @@ namespace Gfx { TextFormatD2D::TextFormatD2D() : m_ExtraHeight(), - m_LineGap() + m_LineGap(), + m_Trimming() { } @@ -297,6 +298,7 @@ DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics( void TextFormatD2D::SetTrimming(bool trim) { + m_Trimming = trim; IDWriteInlineObject* inlineObject = nullptr; DWRITE_TRIMMING trimming = {}; DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP; diff --git a/Common/Gfx/TextFormatD2D.h b/Common/Gfx/TextFormatD2D.h index 543c71d4..777c2d8f 100644 --- a/Common/Gfx/TextFormatD2D.h +++ b/Common/Gfx/TextFormatD2D.h @@ -70,6 +70,9 @@ private: // Used to emulate GDI+ behaviour. float m_ExtraHeight; float m_LineGap; + + // Contains the value passed to the last call of of SetTrimming(). + bool m_Trimming; }; } // namespace Gfx