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

📄 scemfgdiparser.cpp

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

	SCFinishTextout(pRec, pTextRec, pwStr, uiOptions);
	return SC_BRK_NOERROR;
}

void CSCEMFgdiParser::SCFinishTextout(EMREXTTEXTOUTA* pRec, EMRTEXT* pTextRec, LPWSTR pwStr, UINT uiOptions)
{
	ASSERT(m_pRenderer);

	INT iNbChars = pTextRec->nChars;
	// Get intercharacter spacing array.
	DWORD OffDx = pTextRec->offDx;
	INT *lpDx = (INT*)((BYTE*)pRec + OffDx);
	if (0==OffDx)
	{
		// 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 (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
			ASSERT(lpDx[iNbChars-1]);
		}
	}

	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);

	// Clean up
	if (0==OffDx)
		delete [] lpDx;
}
///////////////////////////////////////////////////////////////////////////////////////////

SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTTEXTOUTW()
{
	// TRACE0("**EMR_EXTTEXTOUTW\n");
	//EMREXTTEXTOUTW *pRec = (EMREXTTEXTOUTW*)m_pRecord;

	// pass the record to 
	return OnEmfEXTTEXTOUTA();
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIER16()
{
	// TRACE0("**EMR_POLYBEZIER16\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCDrawBezierS(((EMRPOLYBEZIER16*)m_pRecord)->apts,
							  ((EMRPOLYBEZIER16*)m_pRecord)->cpts);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYGON16()
{
	// TRACE0("**EMR_POLYGON16\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCDrawPolygonS(((EMRPOLYGON16*)m_pRecord)->apts,
								((EMRPOLYGON16*)m_pRecord)->cpts);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINE16()
{
	// TRACE0("**EMR_POLYLINE16\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCDrawLinesS(((EMRPOLYLINE16*)m_pRecord)->apts,
							 ((EMRPOLYLINE16*)m_pRecord)->cpts);
	return SC_BRK_NOERROR;
}


SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYBEZIERTO16()
{
	// TRACE0("**EMR_POLYBEZIERTO16\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCDrawBezierToS(((EMRPOLYBEZIERTO16*)m_pRecord)->apts,
								((EMRPOLYBEZIERTO16*)m_pRecord)->cpts);
	return SC_BRK_NOERROR;
}


SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYLINETO16()
{
	// TRACE0("**EMR_POLYLINETO16\n");
	ASSERT(m_pRenderer);

	m_pRenderer->SCDrawLinesToS(((EMRPOLYLINETO16*)m_pRecord)->apts,
								((EMRPOLYLINETO16*)m_pRecord)->cpts);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYLINE16()
{
	// TRACE0("**EMR_POLYPOLYLINE16\n");
	ASSERT(m_pRenderer);

	EMRPOLYPOLYLINE16 *pRec = (EMRPOLYPOLYLINE16*)m_pRecord;
	LPPOINTS pPts = (LPPOINTS)((DWORD*)pRec->aPolyCounts + pRec->nPolys);
	m_pRenderer->SCDrawPolyPolylineS(pPts, pRec->cpts, (DWORD*)pRec->aPolyCounts, pRec->nPolys);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYPOLYGON16()
{
	// TRACE0("**EMR_POLYPOLYGON16\n");
	ASSERT(m_pRenderer);

	EMRPOLYPOLYGON16 *pRec = (EMRPOLYPOLYGON16*)m_pRecord;
	LPPOINTS pPts = (LPPOINTS)((DWORD*)pRec->aPolyCounts + pRec->nPolys);
	m_pRenderer->SCDrawPolyPolygonS(pPts, pRec->cpts, (DWORD*)pRec->aPolyCounts, pRec->nPolys);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYDRAW16()
{
	// TRACE0("**EMR_POLYDRAW16\n");
	ASSERT(m_pRenderer);

	EMRPOLYDRAW16 *pRec = (EMRPOLYDRAW16*)m_pRecord;

	BYTE* pTypes = (BYTE*)((POINTS*)pRec->apts + pRec->cpts);
	m_pRenderer->SCDrawPolyDrawS(pRec->apts,
								pRec->cpts,
								pTypes);
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEMONOBRUSH()
{
	// TRACE0("**EMR_CREATEMONOBRUSH\n");
	ASSERT(m_pRenderer);

	EMRCREATEMONOBRUSH *pRec = (EMRCREATEMONOBRUSH*)m_pRecord;

	// SCPlayRecord() won't work: the brush will reference a deleted bitmap (XP specific bug?).
	// See comments in the final block.
	SCPlayRecord();

	#ifndef DIB_PAL_INDICES
		#define DIB_PAL_INDICES	2
	#endif
	ASSERT(DIB_PAL_INDICES==pRec->iUsage);

	// DIB_PAL_INDICES management. Special case: the DIB has no color table.
	BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmi); 
	DWORD *pBitsDW     = (DWORD *) ((BYTE *) pRec + pRec->offBits);
	// Attach a monochrome palette to the DIB specification,
	// and create a device-dependent bitmap
	HBITMAP hBm = NULL;
	DWORD dwSize = pBmi->bmiHeader.biSize + 2*sizeof(RGBQUAD);
	BITMAPINFO* pBmi2 = (BITMAPINFO*) new BYTE[dwSize];
	memmove(pBmi2, pBmi, dwSize);
	
	HDC hMonoDC = CreateCompatibleDC(m_hPlayDC); // must be monochrome
	ASSERT(hMonoDC);
	SCFillMonochromePalette(hMonoDC, (PPALETTEENTRY)pBmi2->bmiColors);

	// May create resource leak, as we don't call DeleteObject on hBm (see comments in the final block)
	hBm = CreateDIBitmap(hMonoDC, &pBmi2->bmiHeader, CBM_INIT, pBitsDW, pBmi2, DIB_RGB_COLORS);
	
	DeleteDC(hMonoDC);
	delete [] (BYTE*)pBmi2;
	ASSERT(hBm);

#ifdef _DEBUG
	{// check
		BITMAP bm;
		int iRes = GetObject(hBm, sizeof(BITMAP), &bm);
		ASSERT(iRes);
	}
#endif

	HBRUSH hBrush = CreatePatternBrush(hBm);
	ASSERT(hBrush);
	m_lpEnumHandleTable->objectHandle[pRec->ihBrush] = hBrush;

#if 0
	// Don't do this normal step of the code:
	//		DeleteObject(hBm);
	// It seems that XP's CreatePatternBrush does not make a copy of the given bitmap.
	// To prove it, activate this code, and you will see that GetObjectType
	// will fail on the LogBrushVerif2.lbHatch handle returned by GetObject.
	{
		// Check before delete
		LOGBRUSH LogBrushVerif1;
		ASSERT(::GetObject(hBrush, sizeof(LogBrushVerif1), &LogBrushVerif1));
		ASSERT(LogBrushVerif1.lbStyle==BS_PATTERN);
		int iType1 = GetObjectType((HGDIOBJ)LogBrushVerif1.lbHatch);
		ASSERT(iType1==OBJ_BITMAP);
		
		// Suppose we delete it
		DeleteObject(hBm);
		
		// Check after delete
		LOGBRUSH LogBrushVerif2;
		ASSERT(::GetObject(hBrush, sizeof(LogBrushVerif2), &LogBrushVerif2));
		ASSERT(LogBrushVerif2.lbStyle==BS_PATTERN);
		int iType2 = GetObjectType((HGDIOBJ)LogBrushVerif2.lbHatch);
		ASSERT(iType2==OBJ_BITMAP); // fails
	}
#endif

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATEDIBPATTERNBRUSHPT()
{
	// TRACE0("**EMR_CREATEDIBPATTERNBRUSHPT\n");
	ASSERT(m_pRenderer);

#if 0
	// On NT.SP5, Same problem as monobrush
	SCPlayRecord();
#else
	EMRCREATEDIBPATTERNBRUSHPT *pRec = (EMRCREATEDIBPATTERNBRUSHPT*)m_pRecord;
	ASSERT(DIB_PAL_COLORS==pRec->iUsage || DIB_RGB_COLORS==pRec->iUsage);
	BITMAPINFO *pBmi    = (BITMAPINFO *) ((BYTE *)pRec + pRec->offBmi);

	// Note: On Windows 95 and Windows 98, "creating brushes from bitmaps or DIBs
	//	larger than 8x8 pixels is not supported". So we should restrict the pattern to 8x8.
	// But what if the EMF was created on NT/2K/XP? It seems that GDI doesn't shrink the
	// pattern in order to render the EMF OS-independently.

	DWORD dwSize = pRec->cbBmi + pRec->cbBits;
	// should agree with:
	// BITMAPINFOHEADER* pBmih = &pBmi->bmiHeader;
	// DWORD dwSize = pBmih->biSize +
	//						ColorTableSize(pBmih) +
	//						((pBmih->biSizeImage) ? pBmih->biSizeImage :
	//						abs(pBmih->biHeight)*WIDTHBYTES(pBmih->biWidth*pBmih->biBitCount));

	// May create resource leak, as we don't call GlobalFree on hMem
	// (in fact, this is the sole purpose of this code)
	HGLOBAL hMem = GlobalAlloc(GPTR, dwSize);
	BITMAPINFO* pBmi2 = (BITMAPINFO*)GlobalLock(hMem);
	memmove(pBmi2, pBmi, dwSize);

	HBRUSH hBrush = CreateDIBPatternBrushPt(pBmi2, pRec->iUsage);

	GlobalUnlock(hMem);
	ASSERT(hBrush);
	m_lpEnumHandleTable->objectHandle[pRec->ihBrush] = hBrush;

	#ifdef _DEBUG
	{// Check after play
		LOGBRUSH LogBrushVerif;
		ASSERT(::GetObject((HBRUSH)m_lpEnumHandleTable->objectHandle[pRec->ihBrush], sizeof(LogBrushVerif), &LogBrushVerif));
		ASSERT(LogBrushVerif.lbStyle==BS_DIBPATTERN);
	}
	#endif
#endif
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTCREATEPEN()
{
	// TRACE0("**EMR_EXTCREATEPEN\n");
	ASSERT(m_pRenderer);

	SCPlayRecord();

	// EMREXTCREATEPEN *pRec = (EMREXTCREATEPEN*)m_pRecord;
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYTEXTOUTA()
{
	// TRACE0("**EMR_POLYTEXTOUTA\n");
	ASSERT(m_pRenderer);

	EMRPOLYTEXTOUTA *pRec = (EMRPOLYTEXTOUTA*)m_pRecord;
	for (int i=0; (i<pRec->cStrings); i++)
	{
		SCEmfTextoutA((EMREXTTEXTOUTA*)pRec, &pRec->aemrtext[i]);
	}

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPOLYTEXTOUTW()
{
	// TRACE0("**EMR_POLYTEXTOUTW\n");
	ASSERT(m_pRenderer);

	EMRPOLYTEXTOUTW *pRec = (EMRPOLYTEXTOUTW*)m_pRecord;
	for (int i=0; (i<pRec->cStrings); i++)
	{
		SCEmfTextoutW((EMREXTTEXTOUTW*)pRec, &pRec->aemrtext[i]);
	}

	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSETICMMODE()
{
	// TRACE0("**EMR_SETICMMODE\n");
	ASSERT(m_pRenderer);

//		EMRSETICMMODE *pRec = (EMRSETICMMODE*)m_pRecord;

	// MSDN: see "DIBINFO.C"
	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATECOLORSPACE()
{
	// TRACE0("**EMR_CREATECOLORSPACE\n");
	ASSERT(m_pRenderer);

//		EMRCREATECOLORSPACE *pRec = (EMRCREATECOLORSPACE*)m_pRecord;

	// MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context"
	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfCREATECOLORSPACEW()
{
	// TRACE0("**EMR_CREATECOLORSPACE\n");
	ASSERT(m_pRenderer);

	//EMRCREATECOLORSPACEW *pRec = (EMRCREATECOLORSPACEW*)m_pRecord;

	// MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context"
	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSETCOLORSPACE()
{
	// TRACE0("**EMR_SETCOLORSPACE\n");
	ASSERT(m_pRenderer);

//		EMRSELECTCOLORSPACE *pRec = (EMRSELECTCOLORSPACE*)m_pRecord;

	// MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context"
	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfDELETECOLORSPACE()
{
	// TRACE0("**EMR_DELETECOLORSPACE\n");
	ASSERT(m_pRenderer);

//		EMRDELETECOLORSPACE *pRec = (EMRDELETECOLORSPACE*)m_pRecord;

	// MSDN: see "Basic ICM 2.0 Functions for Use Within a Device Context"
	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfGLSRECORD()
{
	// TRACE0("**EMR_GLSRECORD\n");
	ASSERT(m_pRenderer);

	SC_BRKRESULT error(SC_BRK_NOERROR);
	EMRGLSRECORD *pRec = (EMRGLSRECORD*)m_pRecord;

	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return error;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfGLSBOUNDEDRECORD()
{
	// TRACE0("**EMR_GLSBOUNDEDRECORD\n");
	ASSERT(m_pRenderer);

//		EMRGLSBOUNDEDRECORD *pRec = (EMRGLSBOUNDEDRECORD*)m_pRecord;

	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfPIXELFORMAT()
{
	// TRACE0("**EMR_PIXELFORMAT\n");
	ASSERT(m_pRenderer);

//		EMRPIXELFORMAT *pRec = (EMRPIXELFORMAT*)m_pRecord;

	// TODO_EMF: Place code here to handle EMF record
	SCPlayRecord();
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfDRAWESCAPE()
{
	// TRACE0("**EMR_DRAWESCAPE\n");
	ASSERT(m_pRenderer);

	// EMR *pRec = (EMR*)m_pRecord;

	// Do not play Escape
	// Anyway, now it's SCEMF_RESERVED_105
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfEXTESCAPE()
{
	// TRACE0("**EMR_EXTESCAPE\n");
	ASSERT(m_pRenderer);

	// EMR *pRec = (EMR*)m_pRecord;

	// Do not play Escape
	// Anyway, now it's SCEMF_RESERVED_106
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSTARTDOC()
{
	// TRACE0("**EMR_STARTDOC\n");
	ASSERT(m_pRenderer);

	// EMR *pRec = (EMR*)m_pRecord;

	// Do not play Escape
	// Anyway, now it's SCEMF_RESERVED_107
	return SC_BRK_NOERROR;
}

SC_BRKRESULT CSCEMFgdiParser::OnEmfSMALLTEXTOUT()
{
	// TRACE0("**EMR_SMALLTEXTOUT\n");
	ASSERT(m_pRenderer);

	// WARNING: it's SCEMF_RESERVED_108
	SCEMRSMALLTEXTOUTA *pRec = (SCEMRSMALLTEXTOUTA*)m_pRecord;
	// TODO: review this line

⌨️ 快捷键说明

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