📄 scemfgdiparser.cpp
字号:
#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 + -