⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scemfdcrenderer.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 3 页
字号:

#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 + -