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

📄 scemfgdiparser.cpp

📁 Source code for EMFexplorer 1.0
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#pragma message( __FILE__  "(894): TODO: Recurse parser on embedded WMF? ")
#if 0
	EMRGDICOMMENT *pRec = (EMRGDICOMMENT*)m_pRecord;

	DWORD* pDW = (DWORD*)pRec->Data;
	if (GDICOMMENT_IDENTIFIER==*pDW)
	{
		pDW++;
		switch(*pDW)
		{
		case GDICOMMENT_WINDOWS_METAFILE:
			// embedded WMF
				// TODO:
			break;
			
		case GDICOMMENT_MULTIFORMATS:
			// embedded formats
				// TODO:
			break;
		}
	}
#endif

	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfFILLRGN()
{
	// TRACE0("**EMR_FILLRGN\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCFillRgn((HBRUSH)m_lpEnumHandleTable->objectHandle[((EMRFILLRGN*)m_pRecord)->ihBrush],
						   ((EMRFILLRGN*)m_pRecord)->RgnData,
						   ((EMRFILLRGN*)m_pRecord)->cbRgnData);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfFRAMERGN()
{
	// TRACE0("**EMR_FRAMERGN\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCFrameRgn((HBRUSH)m_lpEnumHandleTable->objectHandle[((EMRFRAMERGN*)m_pRecord)->ihBrush],
							((EMRFRAMERGN*)m_pRecord)->szlStroke,
							((EMRFRAMERGN*)m_pRecord)->RgnData,
							((EMRFRAMERGN*)m_pRecord)->cbRgnData);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfINVERTRGN()
{
	// TRACE0("**EMR_INVERTRGN\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCInvertRgn(((EMRINVERTRGN*)m_pRecord)->RgnData,
							 ((EMRINVERTRGN*)m_pRecord)->cbRgnData);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPAINTRGN()
{
	// TRACE0("**EMR_PAINTRGN\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCPaintRgn(((EMRPAINTRGN*)m_pRecord)->RgnData,
							((EMRPAINTRGN*)m_pRecord)->cbRgnData);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTSELECTCLIPRGN()
{
	// TRACE0("**EMR_EXTSELECTCLIPRGN\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCSelectClipRgn(((EMREXTSELECTCLIPRGN*)m_pRecord)->RgnData,
								 ((EMREXTSELECTCLIPRGN*)m_pRecord)->cbRgnData,
								 ((EMREXTSELECTCLIPRGN*)m_pRecord)->iMode);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfBITBLT()
{
	// TRACE0("**EMR_BITBLT\n");
	ASSERT(m_pRenderer);

	EMRBITBLT *pRec = (EMRBITBLT*)m_pRecord;

	// Destination
	CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest);
	// Check if there is a bitmap
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits     = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc);
		// Source and Destination have same size for BitBlt function
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxDest, pRec->ySrc + pRec->cyDest);
		m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc);
	} else
		m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc);

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSTRETCHBLT()
{
	// TRACE0("**EMR_STRETCHBLT\n");
	ASSERT(m_pRenderer);

	EMRSTRETCHBLT *pRec = (EMRSTRETCHBLT*)m_pRecord;

	// Destination
	CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest);
	// Check if there is a bitmap
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits     = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc);
		// Source
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc);
		m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc);
	} else
		m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc);

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfMASKBLT()
{
	// TRACE0("**EMR_MASKBLT\n");
	ASSERT(m_pRenderer);

	EMRMASKBLT *pRec = (EMRMASKBLT*)m_pRecord;

	// Destination
	CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest);
	// Check if there is a bitmap
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		// the source bitmap
		BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits     = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc);

		// the mask bitmap is optional
		BITMAPINFO *pBmiMask = NULL;
		BYTE *pBitsMask = NULL;
		if (pRec->offBmiMask && pRec->offBitsMask)
		{
			pBmiMask = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiMask); 
			pBitsMask = (BYTE *)((BYTE *)pRec + pRec->offBitsMask);
		}

		// Source equals dest in dimensions
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxDest, pRec->ySrc + pRec->cyDest);

		m_pRenderer->SCDrawImageMsk(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop, &pRec->xformSrc,
		pRec->crBkColorSrc, pRec->xMask, pRec->yMask, pBitsMask, pBmiMask, pRec->iUsageMask);
	} else
		m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop, &pRec->xformSrc);

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPLGBLT()
{
	// TRACE0("**EMR_PLGBLT\n");
	ASSERT(m_pRenderer);

	EMRPLGBLT *pRec = (EMRPLGBLT*)m_pRecord;

	ASSERT(pRec->offBmiSrc && pRec->offBitsSrc);
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		// the source bitmap
		BITMAPINFO *pBmi = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits = (BYTE *)((BYTE *)pRec + pRec->offBitsSrc);

		// the mask bitmap is optional
		BITMAPINFO *pBmiMask = NULL;
		BYTE *pBitsMask = NULL;
		if (pRec->offBmiMask && pRec->offBitsMask)
		{
			pBmiMask = (BITMAPINFO *)((BYTE *)pRec + pRec->offBmiMask); 
			pBitsMask = (BYTE *)((BYTE *)pRec + pRec->offBitsMask);
		}

		// Source
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc);

		m_pRenderer->SCDrawImagePlg(pRec->aptlDest,
		&RcSrc, pBits, pBmi, pRec->iUsageSrc, &pRec->xformSrc, pRec->crBkColorSrc,
		pRec->xMask, pRec->yMask, pBitsMask, pBmiMask, pRec->iUsageMask);
		
	}
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSETDIBITSTODEVICE()
{
	// TRACE0("**EMR_SETDIBITSTODEVICE\n");
	ASSERT(m_pRenderer);

	EMRSETDIBITSTODEVICE *pRec = (EMRSETDIBITSTODEVICE*)m_pRecord;

	// Destination
	CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxSrc, pRec->yDest + pRec->cySrc);
	// Check if there is a bitmap
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits     = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc);
		// Source
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc);
		m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, SRCCOPY);
	} else
		m_pRenderer->SCPatBlt(&RcDest, SRCCOPY);

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSTRETCHDIBITS()
{
	ASSERT(m_pRenderer);

	// TRACE0("**EMR_STRETCHDIBITS\n");
	EMRSTRETCHDIBITS *pRec = (EMRSTRETCHDIBITS*)m_pRecord;

	// Destination
	CRect RcDest(pRec->xDest, pRec->yDest, pRec->xDest + pRec->cxDest, pRec->yDest + pRec->cyDest);
	// Check if there is a bitmap
	if (pRec->offBmiSrc && pRec->offBitsSrc)
	{
		BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmiSrc); 
		BYTE *pBits     = (BYTE *) ((BYTE *) pRec + pRec->offBitsSrc);
		// Source
		CRect RcSrc(pRec->xSrc, pRec->ySrc, pRec->xSrc + pRec->cxSrc, pRec->ySrc + pRec->cySrc);
		m_pRenderer->SCDrawImage(&RcDest, &RcSrc, pBits, pBmi, pRec->iUsageSrc, pRec->dwRop);
	} else
		m_pRenderer->SCPatBlt(&RcDest, pRec->dwRop);

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTCREATEFONTINDIRECTW()
{
	// TRACE0("**EMR_EXTCREATEFONTINDIRECTW\n");
	ASSERT(m_pRenderer);

	// Play the record on the DC, in order to get information about the physical font,
	// which is the font really used by the DC.
#if 0
	// Raster and vector fonts should be replaced by substitutes.

	// Example of early font substitution.
	// This is cleaner than late substitution (SCTTFontFromLOGFONT in SCGdiplusUtils.cpp);
	// but it penalizes good TT fonts
	// (memory allocations and string comparisons)
	EMREXTCREATEFONTINDIRECTW *pSubs = (EMREXTCREATEFONTINDIRECTW *)SCCloneRecord();
	if (pSubs)
	{
		LOGFONTW& rLogFont = pSubs->elfw.elfLogFont;
		DWORD dwFamily = SCFontFamilyApproximantW((WCHAR*)rLogFont.lfFaceName);
		if (FF_DONTCARE!=dwFamily)
		{
			rLogFont.lfPitchAndFamily |= dwFamily;
			rLogFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
		}
		
		SCPlayRecordAndFree(pSubs);
	} else
		SCPlayRecord();
#else
	SCPlayRecord();
#endif
	return SC_BRK_NOERROR;
}


SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTTEXTOUTA()
{
	// TRACE0("**EMR_EXTTEXTOUTA or **EMR_EXTTEXTOUTW\n");
	ASSERT(m_pRenderer);

	SC_BRKRESULT error(SC_BRK_NOERROR);

	// the structure EMREXTTEXTOUTA is same as EMREXTTEXTOUTW
	EMREXTTEXTOUTA *pRec = (EMREXTTEXTOUTA*)m_pRecord;

	// get the EMRTEXT
	EMRTEXT *pTextRec = &(pRec->emrtext);

	// number of characters	
	INT iNbChars = pTextRec->nChars;
	if (iNbChars<=0)
	{
		// We don't know the behavior of ExtTextOut:
		// - if number of characters is 0
		// - if, moreover, TA_UPDATECP is set in the DC
#if 0
		// if required, play the record
		SCPlayRecord();
#endif
		return 0;
	}

	UINT uiOptions = pTextRec->fOptions; // we might have to alter it

	// Build the string
	LPWSTR pwStr = NULL;
	if (pRec->emr.iType == EMR_EXTTEXTOUTW) 
	{
		// The string is in unicode -> we let it as is.
		// Offset is from the beginning of the struct and is in bytes.
		// 	
		// Get the unicode string
		pwStr = (LPWSTR) ((BYTE *)pRec + pTextRec->offString);

#if 0
		// TODO:
		// Translate glyph indices to code points when the rasterizer does not
		// support string measurement for glyph indices.
		if ((uiOptions & ETO_GLYPH_INDEX) && (!m_pRenderer->SCCanMeasureGlyphs())
		{
			int iRes = SCUnicodeCharsFromGlyphs(m_hPlayDC, pString, iNbChars);
			if (iRes)
				uiOptions &= ~ETO_GLYPH_INDEX;
		}
#endif
	} else
	{
		// The string is single-byte encoded.
		// Get adress of the string	then construct the string.			
		LPSTR pString = (char *)pRec + pTextRec->offString;
		pwStr = new wchar_t[iNbChars+1];
		if (pwStr)
		{// We will use UNICODE strings exclusively
			pwStr[iNbChars] = 0;
			int iNum = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pString, iNbChars, pwStr, iNbChars+1);
			ASSERT(iNum==iNbChars);
		}
	}
	ASSERT(pwStr);

	// Get intercharacter spacing array.
	// Be careful ! there are cases where OffDx==0.
	DWORD OffDx = pTextRec->offDx;
	INT *lpDx = (INT*)((BYTE*)pRec + OffDx);
	if (0==OffDx)
	{
		// If the lpDx parameter is NULL, the ExtTextOut function uses the default
		// spacing between characters. So we do.
		//
		// Compute intercharacter spacing, based on each character width.
		lpDx = new INT[iNbChars];
		BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr, iNbChars, lpDx);
		ASSERT(bOk);
	}
	else
	{ // else use distances between origins of adjacent character cells as passed to ExtTextOut.
		// except that, sometimes, the last character is given a spacing of 0, which is
		// not good for us if this character has a non-null width.
		if (0==lpDx[iNbChars-1])
		{
			INT* pInts = new INT[iNbChars];
			memmove(pInts, lpDx, iNbChars*sizeof(INT));

			// compute only the last character's width
			BOOL bOk = SCGetTextCharWidthsW(m_hPlayDC, pwStr+iNbChars-1, 1, pInts+iNbChars-1);
			ASSERT(bOk);
			lpDx = pInts;
			OffDx = 0; // for cleanup
			//at this point, 0 is accepted
			//ASSERT(lpDx[iNbChars-1]);
		}
	}

#if 0
	// This thing is not accurate. We prefer to let the rasterizer use its computed rectangle
	// when no opaquing rectangle is supplied
	CRect rcText = (LPCRECT)&pTextRec->rcl;
	if (rcText.IsRectEmpty())
	{
		rcText.CopyRect((LPCRECT)&pRec->rclBounds);
		DPtoLP(m_hPlayDC, (LPPOINT)&rcText, 2);
	}
	if (GM_COMPATIBLE==pRec->iGraphicsMode)
		m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions,
		(LPCRECT)&rcText, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale);
	else
		m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions,
		(LPCRECT)&rcText, pwStr, iNbChars, lpDx, 1, 1);
#else
	if (GM_COMPATIBLE==pRec->iGraphicsMode)
		m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions,
		(LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, pRec->exScale, pRec->eyScale);
	else
		m_pRenderer->SCDrawText(pTextRec->ptlReference.x, pTextRec->ptlReference.y, uiOptions,
		(LPCRECT)&pTextRec->rcl, pwStr, iNbChars, lpDx, 1, 1);
#endif

	// Clean up
	if (pRec->emr.iType == EMR_EXTTEXTOUTA) 
		delete [] pwStr;
	if (0==OffDx)
		delete [] lpDx;

	return error;
}

//////////////////////////////////////////////////////////////////////////////////////
// It is unlikely that SCEmfTextoutA/SCEmfTextoutW are called. So I prefer to let
// them separated (with duplicated code). See OnEmfTextoutA for documentation
SC_BRKRESULT CSCEMFgdiParser::SCEmfTextoutA(EMREXTTEXTOUTA* pRec, EMRTEXT* pTextRec)
{
	INT iNbChars = pTextRec->nChars;
	if (iNbChars<=0)
		return SC_BRK_NOERROR;

	// Get adress of the string	then construct the widestring.			
	LPWSTR pwStr = new wchar_t[iNbChars + 1];
	if (pwStr)
	{// We will use UNICODE strings exclusively
		pwStr[iNbChars] = 0;
		int iNum = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)((char *)pRec + pTextRec->offString),
			iNbChars, pwStr, iNbChars + 1);
		ASSERT(iNum==iNbChars);
		
		SCFinishTextout(pRec, pTextRec, pwStr, pTextRec->fOptions);
		
		// Clean up
		delete [] pwStr;
	}
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::SCEmfTextoutW(EMREXTTEXTOUTW* pRec, EMRTEXT* pTextRec)
{
	INT iNbChars = pTextRec->nChars;
	if (iNbChars<=0)
		return SC_BRK_NOERROR;

	UINT uiOptions = pTextRec->fOptions; // we might have to alter it

	// Get the unicode string
	LPWSTR pwStr = (LPWSTR) ((BYTE *)pRec + pTextRec->offString);

#if 0
	ASSERT(m_pRenderer);

	// TODO:
	// Translate glyph indices to code points when the rasterizer does not
	// support string measurement for glyph indices.
	if ((uiOptions & ETO_GLYPH_INDEX) && (!m_pRenderer->SCCanMeasureGlyphs())
	{
		int iRes = SCUnicodeCharsFromGlyphs(m_hPlayDC, pwStr, iNbChars);
		if (iRes)
			uiOptions &= ~ETO_GLYPH_INDEX;
	}
#endif

⌨️ 快捷键说明

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