Gfx: Avoid clipping with D2D when not needed

This commit is contained in:
Birunthan Mohanathas 2013-08-12 18:50:24 +03:00
parent a8467674fe
commit 12e0564f3e
4 changed files with 47 additions and 35 deletions

View File

@ -52,7 +52,8 @@ Microsoft::WRL::ComPtr<IWICImagingFactory> CanvasD2D::c_WICFactory;
CanvasD2D::CanvasD2D() : Canvas(), CanvasD2D::CanvasD2D() : Canvas(),
m_Bitmap(), m_Bitmap(),
m_TextAntiAliasing(false) m_TextAntiAliasing(false),
m_CanUseAxisAlignClip(false)
{ {
} }
@ -169,8 +170,8 @@ bool CanvasD2D::BeginTargetDraw()
m_Target->BeginDraw(); m_Target->BeginDraw();
// Apply any transforms that occurred before creation of m_Target // Apply any transforms that occurred before creation of |m_Target|.
m_Target->SetTransform(GetCurrentTransform()); UpdateTargetTransform();
return true; return true;
} }
@ -227,13 +228,18 @@ bool CanvasD2D::IsTransparentPixel(int x, int y)
return transparent; return transparent;
} }
D2D1_MATRIX_3X2_F CanvasD2D::GetCurrentTransform() void CanvasD2D::UpdateTargetTransform()
{ {
D2D1_MATRIX_3X2_F d2dMatrix;
Gdiplus::Matrix gdipMatrix; Gdiplus::Matrix gdipMatrix;
m_GdipGraphics->GetTransform(&gdipMatrix); m_GdipGraphics->GetTransform(&gdipMatrix);
D2D1_MATRIX_3X2_F d2dMatrix;
gdipMatrix.GetElements((Gdiplus::REAL*)&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) void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
@ -242,7 +248,7 @@ void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
if (m_Target) 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) 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; return yPos;
} (); } ();
DWRITE_OVERHANG_METRICS overhangMetrics; if (formatD2D.m_Trimming)
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)
{ {
m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED); D2D1_RECT_F clipRect = ToRectF(rect);
}
else if (m_CanUseAxisAlignClip)
{ {
const D2D1_LAYER_PARAMETERS layerParams = m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED); }
m_Target->PushLayer(layerParams, nullptr); 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()); m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
if (identityTransform) if (formatD2D.m_Trimming)
{ {
m_Target->PopAxisAlignedClip(); if (m_CanUseAxisAlignClip)
} {
else m_Target->PopAxisAlignedClip();
{ }
m_Target->PopLayer(); else
{
m_Target->PopLayer();
}
} }
} }
} }

View File

@ -86,8 +86,8 @@ private:
bool BeginTargetDraw(); bool BeginTargetDraw();
void EndTargetDraw(); void EndTargetDraw();
// Retrieves current GDI+ transform (if any) and converts to a D2D Matrix // Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|.
D2D1_MATRIX_3X2_F GetCurrentTransform(); void UpdateTargetTransform();
Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target; Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target;
Util::WICBitmapDIB m_Bitmap; Util::WICBitmapDIB m_Bitmap;
@ -98,6 +98,9 @@ private:
bool m_TextAntiAliasing; bool m_TextAntiAliasing;
// |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used.
bool m_CanUseAxisAlignClip;
static UINT c_Instances; static UINT c_Instances;
static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory; static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory;
static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory; static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory;

View File

@ -24,7 +24,8 @@ namespace Gfx {
TextFormatD2D::TextFormatD2D() : TextFormatD2D::TextFormatD2D() :
m_ExtraHeight(), m_ExtraHeight(),
m_LineGap() m_LineGap(),
m_Trimming()
{ {
} }
@ -297,6 +298,7 @@ DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics(
void TextFormatD2D::SetTrimming(bool trim) void TextFormatD2D::SetTrimming(bool trim)
{ {
m_Trimming = trim;
IDWriteInlineObject* inlineObject = nullptr; IDWriteInlineObject* inlineObject = nullptr;
DWRITE_TRIMMING trimming = {}; DWRITE_TRIMMING trimming = {};
DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP; DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP;

View File

@ -70,6 +70,9 @@ private:
// Used to emulate GDI+ behaviour. // Used to emulate GDI+ behaviour.
float m_ExtraHeight; float m_ExtraHeight;
float m_LineGap; float m_LineGap;
// Contains the value passed to the last call of of SetTrimming().
bool m_Trimming;
}; };
} // namespace Gfx } // namespace Gfx