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

📄 scemfdcrenderer.cpp

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

	m_States.Add(pStat);
}

///
///	Pop the indicated graphic state, and discard all states from its index to top of stack.
///
void CSCEMFdcRenderer::SCOnDCRestored(INT iRelative)
{
	ASSERT(m_pGraphics);

	INT iPos;
	if (iRelative<0)
		iPos = m_States.GetSize() + iRelative;	// count from top of stack
	else
		iPos = iRelative;						// count from bottom of stack
	//ASSERT(iPos>=0 && iPos<m_States.GetSize());
	if (iPos<0 || iPos>=m_States.GetSize())
		return;

	// GDI+ state
	CSCGDIState* pStat = m_States[iPos];
	m_pGraphics->Restore(pStat->m_SvdGraphicsState);

	// Additional state information
		// Get flat data 
	m_PtCurPos = pStat->m_PtSvdCurPos;
	m_dwMapMode = pStat->m_dwSvdMapMode;
	m_dwBkMode = pStat->m_dwSvdBkMode;
	m_dwFillMode = pStat->m_dwSvdFillMode;
	m_dwStretchBltMode = pStat->m_dwSvdStretchBltMode;
	m_dwTextAlign = pStat->m_dwSvdTextAlign;
	m_dwROP2 = pStat->m_dwSvdROP2;
	m_BkColor = pStat->m_SvdBkColor;
	m_TextColor = pStat->m_SvdTextColor;
	m_dwArcDirection = pStat->m_dwSvdArcDirection;
	m_fMiterLimit = pStat->m_fSvdMiterLimit;
	m_WinSize = pStat->m_SvdWinSize;
	m_ViewSize = pStat->m_SvdViewSize;
	m_PtWinOrg = pStat->m_PtSvdWinOrg;
	m_PtViewOrg = pStat->m_PtSvdViewOrg;
	CopyRect(&m_RcClipBox, &pStat->m_RcSvdClipBox);

		// Get objects 
	SC_OBJHOLDER_RESTORE_T(m_pPenHolder, m_pPen, pStat->m_pSvdPenHolder, GDPPen);
	SC_OBJCONTAINER_RESTORE_T(m_pBrushHolder, m_pBrush, pStat->m_pSvdBrushHolder, GDPBrush, SCBrush);
	SC_OBJHOLDER_RESTORE_T(m_pFontHolder, m_pFont, pStat->m_pSvdFontHolder, SCFont);
	SC_OBJHOLDER_RESTORE_T(m_pPathHolder, m_pPath, pStat->m_pSvdPathHolder, SCPath);

	// Delete all states, starting from iPos
	INT iLen = m_States.GetSize();
	for (INT i=iPos; (i<iLen); i++)
	{
		delete m_States[i];
	}
	m_States.RemoveAt(iPos, iLen - iPos);

#ifdef _DEBUG
	// Check dangling pointers
	SC_CHECKGDIP_OBJ(m_pPen);
	SC_CHECKGDIP_OBJ(m_pBrush);
	SC_CHECKGDIP_OBJ(m_pFont);
	SC_CHECKGDIP_OBJ(m_pPath);
#endif
}

///
///	Move the current position.
///
void CSCEMFdcRenderer::SCMoveToEx(POINTL& PtDest)
{
	if (m_pPath)
	{
		if (m_pPath->SCGetEnd())
			SC_OBJHOLDER_RELEASE_T(m_pPathHolder, m_pPath, SCPath);
		else
			m_pPath->StartFigure();
	}
	m_PtCurPos.X = PtDest.x;
	m_PtCurPos.Y = PtDest.y;
}


///
///	Change the background mode and update hatched brush transparency.
///
void CSCEMFdcRenderer::SCSetBkMode(DWORD dwMode)
{
	ASSERT(m_pGraphics);
	m_dwBkMode = dwMode;
	if (m_pBrush && m_pBrush->GetType()==BrushTypeHatchFill)
	{// We must update transparency
		SCColor FgColor;
		((HatchBrush*)m_pBrush)->GetForegroundColor(&FgColor);

		SCColor BkColor;
		((HatchBrush*)m_pBrush)->GetBackgroundColor(&BkColor);
		BkColor.SCSetAlpha(((TRANSPARENT==m_dwBkMode) ? 0 : 255));

		HatchBrush* pBrush = new HatchBrush(((HatchBrush*)m_pBrush)->GetHatchStyle(), FgColor, BkColor);

		// Refresh the brush object
		SCRefreshBrush(pBrush);
	}
}

///
///	Change the text color and update monochrome brush color.
///
void CSCEMFdcRenderer::SCSetBkColor(COLORREF BkColor)
{
	m_BkColor = SCGetFinalColor(BkColor);

	if (!m_pBrushHolder)
		return;

	SCBrush* pSCBrush = m_pBrushHolder->SCGetSubObj();
	ASSERT(pSCBrush);

	if (!pSCBrush->SCIsMonoPattern())
		return;

	HBRUSH hBrush;
	if (hBrush = pSCBrush->SCGetHandle())
	{
		SCOnChangeBrush(hBrush);
	}
}

///
///	Change the background color and update monochrome brush color.
///
void CSCEMFdcRenderer::SCSetTextColor(COLORREF TxtColor)
{
	m_TextColor = SCGetFinalColor(TxtColor);

	if (!m_pBrushHolder)
		return;

	SCBrush* pSCBrush = m_pBrushHolder->SCGetSubObj();
	ASSERT(pSCBrush);

	if (!pSCBrush->SCIsMonoPattern())
		return;

	HBRUSH hBrush;
	if (hBrush = pSCBrush->SCGetHandle())
	{
		SCOnChangeBrush(hBrush);
	}
}

///////////////////////////////////////////////////////////////////////////////////
// Drawing objects
//

///
///	Convert the newly selected pen in m_hDC to its corresponding GDI+ object.
///
void CSCEMFdcRenderer::SCOnChangePen(HPEN hPen)
{
	ASSERT(m_pGraphics);
	SC_OBJHOLDER_RELEASE_T(m_pPenHolder, m_pPen, GDPPen);

	ASSERT(hPen);
	LOGPEN LogPen;
	if (::GetObject(hPen, sizeof(LogPen), &LogPen))
	{
		LogPen.lopnColor = SCGetFinalColor(LogPen.lopnColor);

		m_pPen = SCPenFromLogPen(LogPen);
	} else
	{// most likely the handle is not valid (maybe a deleted object)
		TRACE0("Invalid pen handle in DC");
	}

	SC_OBJHOLDER_RENEW_T(m_pPenHolder, m_pPen, GDPPen);
}

///
///	Convert the newly selected pen in m_hDC to its corresponding GDI+ object.
///
void CSCEMFdcRenderer::SCOnChangeExtPen(HPEN hPen)
{
	ASSERT(m_pGraphics);
	SC_OBJHOLDER_RELEASE_T(m_pPenHolder, m_pPen, GDPPen);

	ASSERT(hPen);
	DWORD dwSize = ::GetObject(hPen, sizeof(EXTLOGPEN), NULL);
	BYTE* pBytes = new BYTE[dwSize];
	if (::GetObject(hPen, dwSize, pBytes))
	{
		EXTLOGPEN* pExtLogPen = (EXTLOGPEN*)pBytes;
		if (BS_SOLID==pExtLogPen->elpBrushStyle || BS_HATCHED==pExtLogPen->elpBrushStyle)
		{
			pExtLogPen->elpColor = SCGetFinalColor(pExtLogPen->elpColor);
		}

		SCShortDCState TmpDCState(m_bMonochrome, m_dwROP2, m_TextColor, m_BkColor, m_dwBkMode);
		m_pPen = SCPenFromExtLogPen(pExtLogPen, TmpDCState);

		// Since a GDI+ pen has its own matrix, scaling problems may arise some day
		// (see comments in SCOnChangeBrush). In that event, think about something like:
		//		m_pPen->SetTransform(&BogusMatrix);
		// This looks as if, after giving the width of a pen, we should give a matrix
		// to scale it. Poor us, we don't have such information.
	}
	else
	{// most likely the handle is not valid (maybe a deleted object)
		TRACE0("Invalid extpen handle in DC");
	}
	delete [] pBytes;
	SC_OBJHOLDER_RENEW_T(m_pPenHolder, m_pPen, GDPPen);
}


///
///	Convert the newly selected brush in m_hDC to its corresponding GDI+ object.
///
void CSCEMFdcRenderer::SCOnChangeBrush(HBRUSH hBrush)
{
	ASSERT(m_pGraphics);
	SC_OBJCONTAINER_RELEASE_T(m_pBrushHolder, m_pBrush, GDPBrush, SCBrush);
	
	ASSERT(hBrush);
	LOGBRUSH LogBrush;
	LogBrush.lbHatch = 0;
	BOOL bMonoBrush = FALSE;
	if (::GetObject(hBrush, sizeof(LogBrush), &LogBrush))
	{
		if (BS_SOLID==LogBrush.lbStyle)
		{
			LogBrush.lbColor = SCGetFinalColor(LogBrush.lbColor);
		}
		SCShortDCState TmpDCState(m_bMonochrome, m_dwROP2, m_TextColor, m_BkColor, m_dwBkMode);

		m_pBrush = SCBrushFromLogBrush(LogBrush, TmpDCState);

		bMonoBrush = TmpDCState.bMonoBrush; // for brush update

#if 1
	// Strange!!
		if (m_pBrush && m_pBrush->GetType()==BrushTypeTextureFill)
		{
			// Note: When the brush is used, GDI+ won't use the transform in m_pGraphics
			// to properly display the brush.
			// I must exerce a strong moral on myself to just say that:
			// - GDI+ is a BS_... PATTERN!

			// Back to civilization.
			// Try to guess what these lines are doing.
			Matrix CurMatrix;
			m_pGraphics->GetTransform(&CurMatrix);
			if (CurMatrix.IsInvertible())
			{
				// Note: unexpected results in perspective, as we are setting up this
				// brush with the CURRENT state of m_pGraphics
				CurMatrix.Invert();
				((TextureBrush*)m_pBrush)->SetTransform(&CurMatrix);
			} else
			{ // else, let things fall down
				ASSERT(0);
			}
		}
#endif
	} else
	{// most likely the handle is not valid (maybe a deleted object)
		TRACE0("Invalid brush handle in DC");
	}
	SCBrush* pSCbrush = m_pBrush ? new SCBrush(hBrush, bMonoBrush) : NULL;
	SC_OBJCONTAINER_RENEW_T(m_pBrushHolder, m_pBrush, GDPBrush, pSCbrush, SCBrush);

	// Brush origin should be set. But it seems to have no effect on GDI+.
	// See comments in SCSetBrushOrg.
}

void CSCEMFdcRenderer::SCSetBrushOrg(POINTL& PtOrg)
{
	ASSERT(m_pGraphics);
#if 0
	// won't work? Maybe a device/world units problem (PtOrg is in device units)
	m_pGraphics->SetRenderingOrigin(PtOrg.x, PtOrg.y);
#else
	// won't work either. TODO: find the bug.
	Point Pts[2];
	Pts[1].X = PtOrg.x;
	Pts[1].Y = PtOrg.y;
	Pts[0].X = 0;
	Pts[0].Y = 0;
	
	Matrix matrix;
	m_pGraphics->GetTransform(&matrix);
	matrix.Invert();
	matrix.TransformPoints((Point*)&Pts, 2);
	Pts[1].X -= Pts[0].X;
	Pts[1].Y -= Pts[0].Y;
	
	m_pGraphics->SetRenderingOrigin(Pts[1].X, Pts[1].Y);
#endif
	// Origin should be stored for brush update. But since SetRenderingOrigin is called
	// on GDPGraphics, not on the brush, the setting is likely to stay until the next
	// SCSetBrushOrg call.
}


void CSCEMFdcRenderer::SCSelectPrivateFont(LOGFONT& rLogFont, SCFontCollection* pFontCollection, DWORD dwSimul)
{
	ASSERT(pFontCollection);

	// VC6 compiler won't accept the assignment OR with an enum (and that's correct).
	// FontStyle Style = FontStyleRegular;
	INT Style = FontStyleRegular;
	if (rLogFont.lfWeight>=FW_BOLD)
		Style = FontStyleBold;
	if (rLogFont.lfItalic)
		Style |= FontStyleItalic;
#if 0
	// You know what? The text would disappear as well (see attributes simulation).
	if (rLogFont.lfUnderline)
		Style |= FontStyleUnderline;
	if (rLogFont.lfStrikeOut)
		Style |= FontStyleStrikeout;
#endif

#ifdef _UNICODE
		WCHAR*	wFaceName = (WCHAR*)rLogFont.lfFaceName;
#else
		WCHAR	wFaceName[LF_FACESIZE];
		MultiByteToWideChar(CP_ACP, 0, (LPSTR)rLogFont.lfFaceName, LF_FACESIZE, wFaceName, LF_FACESIZE);
#endif

	TEXTMETRIC tm;
	GetTextMetrics(m_hDC, &tm);
	m_pFont = new SCFont(wFaceName, (REAL)(tm.tmHeight - tm.tmInternalLeading), (FontStyle)Style, pFontCollection);
	if (m_pFont)
	{
		if (m_pFont->IsAvailable())
		{
			m_pFont->SCFinalInit(m_hDC, rLogFont.lfEscapement, dwSimul, NULL);
			SC_OBJHOLDER_RENEW_T(m_pFontHolder, m_pFont, SCFont);
		} else
		{
			SMC_SAFEDELETE(m_pFont);
		}
	}
}

///
///	Convert the newly selected font in m_hDC to its corresponding GDI+ object.
///
void CSCEMFdcRenderer::SCOnChangeFont(HFONT hFont)
{
	ASSERT(m_pGraphics);
	SC_OBJHOLDER_RELEASE_T(m_pFontHolder, m_pFont, SCFont);

	// get the logfont
	ASSERT(hFont);
	LOGFONT LogFont;
	INT iRes = ::GetObject(hFont, sizeof(LogFont), &LogFont);
	if (!iRes)
	{// most likely the handle is not valid (maybe a deleted object)
		TRACE0("Invalid font handle in DC");
		SC_OBJHOLDER_RENEW_T(m_pFontHolder, m_pFont, SCFont);
		return;
	}

	ASSERT(abs(LogFont.lfEscapement)<=3600);

	// TODO: solve the case of GM_ADVANCED. For now, assume GM_COMPATIBLE.
	ASSERT((LogFont.lfEscapement==LogFont.lfOrientation)||
		   (GetGraphicsMode(m_hDC)==GM_ADVANCED));

	DWORD dwSimul = 0;
	// 0) Check attributes
	// We can't do:
	// m_pFont = new SCFont(m_hDC);
	// GDI+ does not support underlined/overstriked/symbol fonts (this is not a joke).
	// We must remove unsupported attributes. Otherwise, the text would simply disappear,
	// though m_pFont->IsAvailable() would return TRUE.
	if (LogFont.lfUnderline)
	{
		LogFont.lfUnderline = 0;
		dwSimul |= SC_FONT_SIMUL_UNDERLINE;
		// I know, I can use FontStyleUnderline in a FontStyle.
		// But, what am I doing here? Am I creating a font? What is a font now?
	}
	if (LogFont.lfStrikeOut)
	{
		LogFont.lfStrikeOut = 0;
		dwSimul |= SC_FONT_SIMUL_OVERSTRIKE;
		// I know, I can use FontStyleStrikeout in a FontStyle.
	}

	// 1) Check application installed fonts
	// GDI+ is unable to recognize a temporary/private GDI TT font installed by the
	// application. It bogusly replies: 'NotTrueTypeFont!'
	// So the caller must install temporary fonts in a SCFontCollection and pass it
	// to the renderer. And we check this collection first.
	if (m_pFontCollection &&
		m_pFontCollection->SCIsInstalledFacename((LPTSTR)LogFont.lfFaceName))
	{
		SCSelectPrivateFont(LogFont, m_pFontCollection, dwSimul);
		ASSERT(m_pFont);
		return;
	}

	// 2) Check DC font. Don't forget, We can't do: m_pFont = new SCFont(m_hDC);
	m_pFont = new SCFont(m_hDC, &LogFont);
	if (m_pFont)
	{
		if (m_pFont->IsAvailable())
		{
			m_pFont->SCFinalInit(m_hDC, LogFont.lfEscapement, dwSimul, NULL);
			SC_OBJHOLDER_RENEW_T(m_pFontHolder, m_pFont, SCFont);
			return;
		}
		SMC_SAFEDELETE(m_pFont);
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -