Add wxDC::SetTransformMatrix() and related methods and implement them in wxMSW.

Add support for world transformations to wxDC too. Currently this is
implemented in wxMSW only but could be easily provided in the ports that use
wxGraphicsContext for wxDC implementation later.

Closes #13092.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67588 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2011-04-23 16:03:10 +00:00
parent 54580df4e2
commit e71508e160
19 changed files with 429 additions and 0 deletions

View File

@@ -273,6 +273,98 @@ private:
IMPLEMENT_DYNAMIC_CLASS(wxGDIDLLsCleanupModule, wxModule)
namespace
{
#if wxUSE_DC_TRANSFORM_MATRIX
// Class used to dynamically load world transform related API functions.
class GdiWorldTransformFuncs
{
public:
static bool IsOk()
{
if ( !ms_worldTransformSymbolsLoaded )
LoadWorldTransformSymbols();
return ms_pfnSetGraphicsMode &&
ms_pfnSetWorldTransform &&
ms_pfnGetWorldTransform &&
ms_pfnModifyWorldTransform;
}
typedef int (WINAPI *SetGraphicsMode_t)(HDC, int);
static SetGraphicsMode_t SetGraphicsMode()
{
if ( !ms_worldTransformSymbolsLoaded )
LoadWorldTransformSymbols();
return ms_pfnSetGraphicsMode;
}
typedef BOOL (WINAPI *SetWorldTransform_t)(HDC, const XFORM *);
static SetWorldTransform_t SetWorldTransform()
{
if ( !ms_worldTransformSymbolsLoaded )
LoadWorldTransformSymbols();
return ms_pfnSetWorldTransform;
}
typedef BOOL (WINAPI *GetWorldTransform_t)(HDC, LPXFORM);
static GetWorldTransform_t GetWorldTransform()
{
if ( !ms_worldTransformSymbolsLoaded )
LoadWorldTransformSymbols();
return ms_pfnGetWorldTransform;
}
typedef BOOL (WINAPI *ModifyWorldTransform_t)(HDC, const XFORM *, DWORD);
static ModifyWorldTransform_t ModifyWorldTransform()
{
if ( !ms_worldTransformSymbolsLoaded )
LoadWorldTransformSymbols();
return ms_pfnModifyWorldTransform;
}
private:
static void LoadWorldTransformSymbols()
{
wxDynamicLibrary dll(wxT("gdi32.dll"));
wxDL_INIT_FUNC(ms_pfn, SetGraphicsMode, dll);
wxDL_INIT_FUNC(ms_pfn, SetWorldTransform, dll);
wxDL_INIT_FUNC(ms_pfn, GetWorldTransform, dll);
wxDL_INIT_FUNC(ms_pfn, ModifyWorldTransform, dll);
ms_worldTransformSymbolsLoaded = true;
}
static SetGraphicsMode_t ms_pfnSetGraphicsMode;
static SetWorldTransform_t ms_pfnSetWorldTransform;
static GetWorldTransform_t ms_pfnGetWorldTransform;
static ModifyWorldTransform_t ms_pfnModifyWorldTransform;
static bool ms_worldTransformSymbolsLoaded;
};
GdiWorldTransformFuncs::SetGraphicsMode_t
GdiWorldTransformFuncs::ms_pfnSetGraphicsMode = NULL;
GdiWorldTransformFuncs::SetWorldTransform_t
GdiWorldTransformFuncs::ms_pfnSetWorldTransform = NULL;
GdiWorldTransformFuncs::GetWorldTransform_t
GdiWorldTransformFuncs::ms_pfnGetWorldTransform = NULL;
GdiWorldTransformFuncs::ModifyWorldTransform_t
GdiWorldTransformFuncs::ms_pfnModifyWorldTransform = NULL;
bool GdiWorldTransformFuncs::ms_worldTransformSymbolsLoaded = false;
#endif // wxUSE_DC_TRANSFORM_MATRIX
} // anonymous namespace
#endif // wxUSE_DYNLIB_CLASS
// ===========================================================================
@@ -2005,6 +2097,87 @@ void wxMSWDCImpl::SetDeviceOrigin(wxCoord x, wxCoord y)
::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
}
// ----------------------------------------------------------------------------
// Transform matrix
// ----------------------------------------------------------------------------
#if wxUSE_DC_TRANSFORM_MATRIX
bool wxMSWDCImpl::CanUseTransformMatrix() const
{
return GdiWorldTransformFuncs::IsOk();
}
bool wxMSWDCImpl::SetTransformMatrix(const wxAffineMatrix2D &matrix)
{
if ( !GdiWorldTransformFuncs::IsOk() )
return false;
if ( matrix.IsIdentity() )
{
ResetTransformMatrix();
return true;
}
if ( !GdiWorldTransformFuncs::SetGraphicsMode()(GetHdc(), GM_ADVANCED) )
{
wxLogLastError(wxT("SetGraphicsMode"));
return false;
}
wxMatrix2D mat;
wxPoint2DDouble tr;
matrix.Get(&mat, &tr);
XFORM xform;
xform.eM11 = mat.m_11;
xform.eM12 = mat.m_12;
xform.eM21 = mat.m_21;
xform.eM22 = mat.m_22;
xform.eDx = tr.m_x;
xform.eDy = tr.m_y;
if ( !GdiWorldTransformFuncs::SetWorldTransform()(GetHdc(), &xform) )
{
wxLogLastError(wxT("SetWorldTransform"));
return false;
}
return true;
}
wxAffineMatrix2D wxMSWDCImpl::GetTransformMatrix() const
{
wxAffineMatrix2D transform;
if ( !GdiWorldTransformFuncs::IsOk() )
return transform;
XFORM xform;
if ( !GdiWorldTransformFuncs::GetWorldTransform()(GetHdc(), &xform) )
{
wxLogLastError(wxT("GetWorldTransform"));
return transform;
}
wxMatrix2D m(xform.eM11, xform.eM12, xform.eM21, xform.eM22);
wxPoint2DDouble p(xform.eDx, xform.eDy);
transform.Set(m, p);
return transform;
}
void wxMSWDCImpl::ResetTransformMatrix()
{
if ( GdiWorldTransformFuncs::IsOk() )
{
GdiWorldTransformFuncs::ModifyWorldTransform()(GetHdc(), NULL, MWT_IDENTITY);
GdiWorldTransformFuncs::SetGraphicsMode()(GetHdc(), GM_COMPATIBLE);
}
}
#endif // wxUSE_DC_TRANSFORM_MATRIX
// ---------------------------------------------------------------------------
// bit blit
// ---------------------------------------------------------------------------