📄 scemfdcrenderer.cpp
字号:
#if 1
// 3) Attempt copying TT font in local private collection
ASSERT(!m_pFont);
ASSERT(g_pFontCopies);
BOOL bFound = g_pFontCopies->SCIsInstalledFacename((LPTSTR)LogFont.lfFaceName);
if (!bFound)
{
long lDataSize = ::GetFontData(m_hDC, 0, 0, NULL, 0);
if (GDI_ERROR==lDataSize)
{
DWORD dwError = ::GetLastError();
//ASSERT(0);
} else
{// read font data
LPBYTE pData = new BYTE[lDataSize];
ASSERT(pData);
if (pData)
{
if (bFound=(::GetFontData(m_hDC, 0, 0, pData, lDataSize)>0))
{
g_pFontCopies->AddMemoryFont(pData, lDataSize);
}
delete [] pData;
ASSERT(bFound);
}
}
}
if (bFound)
SCSelectPrivateFont(LogFont, g_pFontCopies, dwSimul);
#endif
// 4) Last chance: approximate font.
// We are lived to the good will of GDI to give us a TT font
if (!m_pFont)
{
HFONT hFontSubs = SCTTFontFromLOGFONT(LogFont, m_hDC);
// hFontSubs is selected
m_pFont = new SCFont(m_hDC, &LogFont);
// along with other attributes, store hFontSubs for deletion
m_pFont->SCFinalInit(m_hDC, LogFont.lfEscapement, dwSimul, hFontSubs);
SC_OBJHOLDER_RENEW_T(m_pFontHolder, m_pFont, SCFont);
}
// Yet GDI+ may refuse it
ASSERT(m_pFont && m_pFont->IsAvailable());
}
///
/// Convert the newly selected palette in m_hDC to its corresponding GDI+ object.
///
void CSCEMFdcRenderer::SCOnChangePalette(HPALETTE hPal)
{
#pragma message( __FILE__ "(880): TODO: Palette management.")
}
///////////////////////////////////////////////////////////////////////////////////
/// Transforms
///
/// Force the transform to be exactly what is given
///
void CSCEMFdcRenderer::SCApplyTransform(XFORM& xform)
{
ASSERT(m_pGraphics);
Matrix matrix(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
m_pGraphics->SetTransform(&matrix);
}
///
/// Combine World to Page and Page to Device into a single World to Device transform
/// (since we don't have the possibility to make the distinction)
///
void CSCEMFdcRenderer::SCSetWorldTransform(XFORM& xform)
{
ASSERT(m_pGraphics);
// World to page
Matrix matrix(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
#if 1
// Page to device
POINT PtOrg;
PtOrg.x = MulDiv(m_PtViewOrg.x, m_WinSize.cx, m_ViewSize.cx) - m_PtWinOrg.x;
PtOrg.y = MulDiv(m_PtViewOrg.y, m_WinSize.cy, m_ViewSize.cy) - m_PtWinOrg.y;
Matrix MatOrg(1, 0, 0, 1, (REAL)PtOrg.x, (REAL)PtOrg.y);
matrix.Multiply(&MatOrg);
#endif
m_pGraphics->SetTransform(&matrix);
}
///
/// .
///
void CSCEMFdcRenderer::SCModifyWorldTransform(XFORM& xform, DWORD dwMode)
{
ASSERT(m_pGraphics);
#if 0
// Won't work. We have seen dwMode=4 (?), exceeding MWT_MAX;
if (MWT_IDENTITY==dwMode)
{
m_pGraphics->ResetTransform();
} else
{
Matrix matrix(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
m_pGraphics->MultiplyTransform(&matrix, (MWT_LEFTMULTIPLY==dwMode)? MatrixOrderPrepend : MatrixOrderAppend);
}
#else
// So we just ignore bad values.
// ASSERT(dwMode>=MWT_MIN && dwMode<=MWT_MAX); // Would fail too often
switch (dwMode)
{
case MWT_IDENTITY:
m_pGraphics->ResetTransform();
//SCOnExtentChanged();
break;
case MWT_LEFTMULTIPLY:
{
Matrix matrix(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
m_pGraphics->MultiplyTransform(&matrix, MatrixOrderPrepend);
}
break;
case MWT_RIGHTMULTIPLY:
{
Matrix matrix(xform.eM11, xform.eM12, xform.eM21, xform.eM22, xform.eDx, xform.eDy);
m_pGraphics->MultiplyTransform(&matrix, MatrixOrderAppend);
}
break;
case 4:
{// Maybe a printer driver calling a Microsoft private, hidden, function into GDI
// Tests (but how on Earth could it work?)
// 1) do nothing => no image
// 2) reset => big image
// 3) append => no image
// 4) prepend => no image
// // 5) panic, panic
// XFORM xformp;
// if (GetWorldTransform(m_hDC, &xformp))
// {
// //Matrix matrix(xformp.eM11, xformp.eM12, xformp.eM21, xformp.eM22, xformp.eDx, xformp.eDy);
// //m_pGraphics->SetTransform(&matrix);
// break;
// } // else sing "Desperado..."
}
// the man is falling through
default:
{
//ASSERT(0);
}
}
#endif
}
///////////////////////////////////////////////////////////////////////////////////
/// Mapping modes and scaling
void CSCEMFdcRenderer::SCSetMapMode(DWORD dwMode)
{
m_dwMapMode = dwMode;
switch (m_dwMapMode)
{
case MM_ANISOTROPIC:
return;
case MM_TEXT:
m_WinSize.cx = 1;
m_WinSize.cy = 1;
m_ViewSize.cx = 1;
m_ViewSize.cy = 1;
SCOnExtentChanged();
return;
}
#pragma message( __FILE__ "(997): TODO: use destination DC, not m_hDC ")
INT horzSize = GetDeviceCaps( m_hDC, HORZSIZE ); // in mm
INT vertSize = GetDeviceCaps( m_hDC, VERTSIZE ); // in mm
INT horzRes = GetDeviceCaps( m_hDC, HORZRES ); // in pixels
INT vertRes = GetDeviceCaps( m_hDC, VERTRES ); // in pixels
switch (m_dwMapMode)
{
case MM_LOMETRIC:
m_WinSize.cx = horzSize;
m_WinSize.cy = vertSize;
m_ViewSize.cx = horzRes / 10;
m_ViewSize.cy = -vertRes / 10;
break;
case MM_ISOTROPIC:
{
// MSDN: "Coordinate Mapping"
// yVE = (yWE * ((xVE * xA) / yA)) / xWE
// where:
//
// yVE : viewport y-extent
// yWE : window y-extent
// xVE : viewport x-extent
// xWE : window x-extent
// xA : device x-aspect (XASPECT index to GetDeviceCaps)
// yA : device y-aspect (YASPECT index to GetDeviceCaps)
INT xA = GetDeviceCaps( m_hDC, ASPECTX );
INT yA = GetDeviceCaps( m_hDC, ASPECTY );
m_WinSize.cx = horzSize;
m_WinSize.cy = vertSize;
m_ViewSize.cx = horzRes / 10;
m_ViewSize.cy = -(INT)((m_WinSize.cy * ((m_ViewSize.cx * xA) / yA)) / m_WinSize.cx);
// TODO: revise to keep the smallest between horzRes and vertRes, and reduce the other
}
break;
case MM_HIMETRIC:
m_WinSize.cx = horzSize * 10;
m_WinSize.cy = vertSize * 10;
m_ViewSize.cx = horzRes / 10;
m_ViewSize.cy = -vertRes / 10;
break;
case MM_LOENGLISH:
m_WinSize.cx = horzSize;
m_WinSize.cy = vertSize;
m_ViewSize.cx = MulDiv(254, horzRes, 1000);
m_ViewSize.cy = -MulDiv(254, vertRes, 1000);
break;
case MM_HIENGLISH:
m_WinSize.cx = horzSize * 10;
m_WinSize.cy = vertSize * 10;
m_ViewSize.cx = MulDiv(254, horzRes, 1000);
m_ViewSize.cy = -MulDiv(254, vertRes, 1000);
break;
case MM_TWIPS:
m_WinSize.cx = MulDiv(144, horzSize, 10);
m_WinSize.cy = MulDiv(144, vertSize, 10);
m_ViewSize.cx = MulDiv(254, horzRes, 1000);
m_ViewSize.cy = -MulDiv(254, vertRes, 1000);
break;
default:
ASSERT(0);
}
SCOnExtentChanged();
}
void CSCEMFdcRenderer::SCSetWindowOrg(INT iX, INT iY)
{
ASSERT(m_pGraphics);
m_PtWinOrg.x = iX;
m_PtWinOrg.y = iY;
SCOnExtentChanged();
}
void CSCEMFdcRenderer::SCSetViewportOrg(INT iX, INT iY)
{
ASSERT(m_pGraphics);
m_PtViewOrg.x = iX;
m_PtViewOrg.y = iY;
SCOnExtentChanged();
}
// "When the following mapping modes are set, calls to the SetWindowExtEx and
// SetViewportExtEx functions are ignored.
//
// MM_HIENGLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRIC, MM_TEXT, MM_TWIPS"
//
void CSCEMFdcRenderer::SCSetWindowExtent(INT iCx, INT iCy)
{
ASSERT(m_pGraphics);
switch (m_dwMapMode)
{
case MM_ANISOTROPIC:
m_WinSize.cx = iCx;
m_WinSize.cy = iCy;
break;
case MM_ISOTROPIC:
m_WinSize.cx = iCx;
m_WinSize.cy = iCy;
// For MM_ISOTROPIC, adjust viewport extent
// "An application must call the SetWindowExtEx function before it calls
// SetViewportExtEx"
{
ASSERT(m_WinSize.cx);
INT xA = GetDeviceCaps( m_hDC, ASPECTX );
INT yA = GetDeviceCaps( m_hDC, ASPECTY );
m_ViewSize.cx = GetDeviceCaps( m_hDC, HORZRES ) / 10;
m_ViewSize.cy = -(INT)((m_WinSize.cy * ((m_ViewSize.cx * xA) / yA)) / m_WinSize.cx);
}
break;
// just to see
case MM_TEXT:
// and I saw MM_TEXT
m_WinSize.cx = 1;
m_WinSize.cy = 1;
break;
default:
ASSERT(0); // just to see
}
SCOnExtentChanged();
}
// "When the following mapping modes are set, calls to the SetWindowExtEx and
// SetViewportExtEx functions are ignored.
//
// MM_HIENGLISH, MM_HIMETRIC, MM_LOENGLISH, MM_LOMETRIC, MM_TEXT, MM_TWIPS"
//
void CSCEMFdcRenderer::SCSetViewportExtent(INT iCx, INT iCy)
{
ASSERT(m_pGraphics);
switch (m_dwMapMode)
{
case MM_ANISOTROPIC:
m_ViewSize.cx = iCx;
m_ViewSize.cy = iCy;
break;
case MM_ISOTROPIC:
m_ViewSize.cx = iCx;
m_ViewSize.cy = iCy;
// For MM_ISOTROPIC, adjust viewport extent
// "An application must call the SetWindowExtEx function before it calls
// SetViewportExtEx"
#pragma message( __FILE__ "(1153): TODO: use destination DC ")
{
INT xA = GetDeviceCaps( m_hDC, ASPECTX );
INT yA = GetDeviceCaps( m_hDC, ASPECTY );
m_ViewSize.cy = -(INT)((m_WinSize.cy * ((m_ViewSize.cx * xA) / yA)) / m_WinSize.cx);
// TODO: revise to keep the smallest between iCx and iCy, and reduce the other
}
break;
// just to see
case MM_TEXT:
// and I saw MM_TEXT
m_ViewSize.cx = 1;
m_ViewSize.cy = 1;
break;
default:
ASSERT(0); // just to see
}
SCOnExtentChanged();
}
void CSCEMFdcRenderer::SCScaleWindow(LONG lxNum, LONG lxDenom, LONG lyNum, LONG lyDenom)
{
ASSERT(m_pGraphics);
if (MM_ANISOTROPIC==m_dwMapMode || MM_ISOTROPIC==m_dwMapMode)
{// Note: We have no specification about these conditions (seem natural)
m_WinSize.cx = MulDiv(m_WinSize.cx, lxNum, lxDenom);
m_WinSize.cy = MulDiv(m_WinSize.cy, lyNum, lyDenom);
}
#if 1
// Normally, origin is not concerned (this seems to reproduce a GDI bug)
m_PtWinOrg.x = MulDiv(m_PtWinOrg.x, lxNum, lxDenom);
m_PtWinOrg.y = MulDiv(m_PtWinOrg.y, lyNum, lyDenom);
#endif
SCOnExtentChanged();
}
void CSCEMFdcRenderer::SCScaleViewport(LONG lxNum, LONG lxDenom, LONG lyNum, LONG lyDenom)
{
ASSERT(m_pGraphics);
if (MM_ANISOTROPIC==m_dwMapMode || MM_ISOTROPIC==m_dwMapMode)
{// Note: We have no specification about these conditions (seem natural)
m_ViewSize.cx = MulDiv(m_ViewSize.cx, lxNum, lxDenom);
m_ViewSize.cy = MulDiv(m_ViewSize.cy, lyNum, lyDenom);
}
#if 1
// Normally, origin is not concerned (this seems to reproduce a GDI bug)
m_PtViewOrg.x = MulDiv(m_PtViewOrg.x, lxNum, lxDenom);
m_PtViewOrg.y = MulDiv(m_PtViewOrg.y, lyNum, lyDenom);
#endif
SCOnExtentChanged();
}
void CSCEMFdcRenderer::SCOnExtentChanged()
{
ASSERT(m_pGraphics);
ASSERT(m_WinSize.cx && m_WinSize.cy);
Matrix matrix;
matrix.Scale(float(m_ViewSize.cx)/float(m_WinSize.cx), float(m_ViewSize.cy)/float(m_WinSize.cy));
POINT PtOrg;
PtOrg.x = MulDiv(m_PtViewOrg.x, m_WinSize.cx, m_ViewSize.cx) - m_PtWinOrg.x;
PtOrg.y = MulDiv(m_PtViewOrg.y, m_WinSize.cy, m_ViewSize.cy) - m_PtWinOrg.y;
matrix.Translate((REAL)PtOrg.x, (REAL)PtOrg.y);
// Combine the new transform with the original one that
// was in the destitation DC before rendering started.
#pragma message( __FILE__ "(1227): TODO: Investigation: revise the use of m_DestMatrix")
matrix.Multiply(&m_DestMatrix);
m_pGraphics->SetTransform(&matrix);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -