PatBlt()s get recorded as EMR_BITBLT records with offBmiSrc == 0, so

ensure that we pick these out in playback.
EMR_STRETCHBLT should behave like EMR_BITBLT if there are no bits
(ie. it's a PalBlt).
Set the text and bkgnd colour to black and white respectively before
enumerating an emf.
Print out the record names to make debugging easier.
Add a few TRACE()s.
This commit is contained in:
Huw Davies 2003-11-11 00:43:03 +00:00 committed by Alexandre Julliard
parent e459f7a681
commit 47e9ad4dce
1 changed files with 215 additions and 72 deletions

View File

@ -54,6 +54,146 @@ typedef struct
BOOL on_disk; /* true if metafile is on disk */ BOOL on_disk; /* true if metafile is on disk */
} ENHMETAFILEOBJ; } ENHMETAFILEOBJ;
static const struct emr_name {
DWORD type;
const char *name;
} emr_names[] = {
#define X(p) {p, #p}
X(EMR_HEADER),
X(EMR_POLYBEZIER),
X(EMR_POLYGON),
X(EMR_POLYLINE),
X(EMR_POLYBEZIERTO),
X(EMR_POLYLINETO),
X(EMR_POLYPOLYLINE),
X(EMR_POLYPOLYGON),
X(EMR_SETWINDOWEXTEX),
X(EMR_SETWINDOWORGEX),
X(EMR_SETVIEWPORTEXTEX),
X(EMR_SETVIEWPORTORGEX),
X(EMR_SETBRUSHORGEX),
X(EMR_EOF),
X(EMR_SETPIXELV),
X(EMR_SETMAPPERFLAGS),
X(EMR_SETMAPMODE),
X(EMR_SETBKMODE),
X(EMR_SETPOLYFILLMODE),
X(EMR_SETROP2),
X(EMR_SETSTRETCHBLTMODE),
X(EMR_SETTEXTALIGN),
X(EMR_SETCOLORADJUSTMENT),
X(EMR_SETTEXTCOLOR),
X(EMR_SETBKCOLOR),
X(EMR_OFFSETCLIPRGN),
X(EMR_MOVETOEX),
X(EMR_SETMETARGN),
X(EMR_EXCLUDECLIPRECT),
X(EMR_INTERSECTCLIPRECT),
X(EMR_SCALEVIEWPORTEXTEX),
X(EMR_SCALEWINDOWEXTEX),
X(EMR_SAVEDC),
X(EMR_RESTOREDC),
X(EMR_SETWORLDTRANSFORM),
X(EMR_MODIFYWORLDTRANSFORM),
X(EMR_SELECTOBJECT),
X(EMR_CREATEPEN),
X(EMR_CREATEBRUSHINDIRECT),
X(EMR_DELETEOBJECT),
X(EMR_ANGLEARC),
X(EMR_ELLIPSE),
X(EMR_RECTANGLE),
X(EMR_ROUNDRECT),
X(EMR_ARC),
X(EMR_CHORD),
X(EMR_PIE),
X(EMR_SELECTPALETTE),
X(EMR_CREATEPALETTE),
X(EMR_SETPALETTEENTRIES),
X(EMR_RESIZEPALETTE),
X(EMR_REALIZEPALETTE),
X(EMR_EXTFLOODFILL),
X(EMR_LINETO),
X(EMR_ARCTO),
X(EMR_POLYDRAW),
X(EMR_SETARCDIRECTION),
X(EMR_SETMITERLIMIT),
X(EMR_BEGINPATH),
X(EMR_ENDPATH),
X(EMR_CLOSEFIGURE),
X(EMR_FILLPATH),
X(EMR_STROKEANDFILLPATH),
X(EMR_STROKEPATH),
X(EMR_FLATTENPATH),
X(EMR_WIDENPATH),
X(EMR_SELECTCLIPPATH),
X(EMR_ABORTPATH),
X(EMR_GDICOMMENT),
X(EMR_FILLRGN),
X(EMR_FRAMERGN),
X(EMR_INVERTRGN),
X(EMR_PAINTRGN),
X(EMR_EXTSELECTCLIPRGN),
X(EMR_BITBLT),
X(EMR_STRETCHBLT),
X(EMR_MASKBLT),
X(EMR_PLGBLT),
X(EMR_SETDIBITSTODEVICE),
X(EMR_STRETCHDIBITS),
X(EMR_EXTCREATEFONTINDIRECTW),
X(EMR_EXTTEXTOUTA),
X(EMR_EXTTEXTOUTW),
X(EMR_POLYBEZIER16),
X(EMR_POLYGON16),
X(EMR_POLYLINE16),
X(EMR_POLYBEZIERTO16),
X(EMR_POLYLINETO16),
X(EMR_POLYPOLYLINE16),
X(EMR_POLYPOLYGON16),
X(EMR_POLYDRAW16),
X(EMR_CREATEMONOBRUSH),
X(EMR_CREATEDIBPATTERNBRUSHPT),
X(EMR_EXTCREATEPEN),
X(EMR_POLYTEXTOUTA),
X(EMR_POLYTEXTOUTW),
X(EMR_SETICMMODE),
X(EMR_CREATECOLORSPACE),
X(EMR_SETCOLORSPACE),
X(EMR_DELETECOLORSPACE),
X(EMR_GLSRECORD),
X(EMR_GLSBOUNDEDRECORD),
X(EMR_PIXELFORMAT),
X(EMR_DRAWESCAPE),
X(EMR_EXTESCAPE),
X(EMR_STARTDOC),
X(EMR_SMALLTEXTOUT),
X(EMR_FORCEUFIMAPPING),
X(EMR_NAMEDESCAPE),
X(EMR_COLORCORRECTPALETTE),
X(EMR_SETICMPROFILEA),
X(EMR_SETICMPROFILEW),
X(EMR_ALPHABLEND),
X(EMR_SETLAYOUT),
X(EMR_TRANSPARENTBLT),
X(EMR_RESERVED_117),
X(EMR_GRADIENTFILL),
X(EMR_SETLINKEDUFI),
X(EMR_SETTEXTJUSTIFICATION),
X(EMR_COLORMATCHTOTARGETW),
X(EMR_CREATECOLORSPACEW)
#undef X
};
/****************************************************************************
* get_emr_name
*/
static const char *get_emr_name(DWORD type)
{
int i;
for(i = 0; i < sizeof(emr_names) / sizeof(emr_names[0]); i++)
if(type == emr_names[i].type) return emr_names[i].name;
TRACE("Unknown record type %ld\n", type);
return NULL;
}
/**************************************************************************** /****************************************************************************
* EMF_Create_HENHMETAFILE * EMF_Create_HENHMETAFILE
@ -500,7 +640,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
if ( IS_WIN9X() && emr_produces_output(type) ) if ( IS_WIN9X() && emr_produces_output(type) )
EMF_Update_MF_Xform(hdc, info); EMF_Update_MF_Xform(hdc, info);
TRACE(" type=%d\n", type); TRACE("record %s\n", get_emr_name(type));
switch(type) switch(type)
{ {
case EMR_HEADER: case EMR_HEADER:
@ -574,14 +714,18 @@ BOOL WINAPI PlayEnhMetaFileRecord(
case EMR_RESTOREDC: case EMR_RESTOREDC:
{ {
PEMRRESTOREDC pRestoreDC = (PEMRRESTOREDC) mr; PEMRRESTOREDC pRestoreDC = (PEMRRESTOREDC) mr;
TRACE("EMR_RESTORE: %ld\n", pRestoreDC->iRelative);
RestoreDC(hdc, pRestoreDC->iRelative); RestoreDC(hdc, pRestoreDC->iRelative);
break; break;
} }
case EMR_INTERSECTCLIPRECT: case EMR_INTERSECTCLIPRECT:
{ {
PEMRINTERSECTCLIPRECT pClipRect = (PEMRINTERSECTCLIPRECT) mr; PEMRINTERSECTCLIPRECT pClipRect = (PEMRINTERSECTCLIPRECT) mr;
IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top, TRACE("EMR_INTERSECTCLIPRECT: rect %ld,%ld - %ld, %ld\n",
pClipRect->rclClip.right, pClipRect->rclClip.bottom); pClipRect->rclClip.left, pClipRect->rclClip.top,
pClipRect->rclClip.right, pClipRect->rclClip.bottom);
IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top,
pClipRect->rclClip.right, pClipRect->rclClip.bottom);
break; break;
} }
case EMR_SELECTOBJECT: case EMR_SELECTOBJECT:
@ -861,6 +1005,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
rc.top = pExtTextOutW->emrtext.rcl.top; rc.top = pExtTextOutW->emrtext.rcl.top;
rc.right = pExtTextOutW->emrtext.rcl.right; rc.right = pExtTextOutW->emrtext.rcl.right;
rc.bottom = pExtTextOutW->emrtext.rcl.bottom; rc.bottom = pExtTextOutW->emrtext.rcl.bottom;
TRACE("EMR_EXTTEXTOUTW: x,y = %ld, %ld. rect = %ld, %ld - %ld, %ld. flags %08lx\n",
pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
rc.left, rc.top, rc.right, rc.bottom, pExtTextOutW->emrtext.fOptions);
ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y, ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y,
pExtTextOutW->emrtext.fOptions, &rc, pExtTextOutW->emrtext.fOptions, &rc,
(LPWSTR)((BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars, (LPWSTR)((BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars,
@ -1446,92 +1594,80 @@ BOOL WINAPI PlayEnhMetaFileRecord(
case EMR_BITBLT: case EMR_BITBLT:
{ {
PEMRBITBLT pBitBlt = (PEMRBITBLT)mr; PEMRBITBLT pBitBlt = (PEMRBITBLT)mr;
HDC hdcSrc = CreateCompatibleDC(hdc);
HBRUSH hBrush, hBrushOld;
HBITMAP hBmp = 0, hBmpOld = 0;
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pBitBlt->offBmiSrc);
SetWorldTransform(hdcSrc, &pBitBlt->xformSrc); if(pBitBlt->offBmiSrc == 0) { /* Record is a PatBlt */
PatBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest,
pBitBlt->dwRop);
} else { /* BitBlt */
HDC hdcSrc = CreateCompatibleDC(hdc);
HBRUSH hBrush, hBrushOld;
HBITMAP hBmp = 0, hBmpOld = 0;
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pBitBlt->offBmiSrc);
hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc); SetWorldTransform(hdcSrc, &pBitBlt->xformSrc);
hBrushOld = SelectObject(hdcSrc, hBrush);
PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top,
pBitBlt->rclBounds.right - pBitBlt->rclBounds.left,
pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY);
SelectObject(hdcSrc, hBrushOld);
DeleteObject(hBrush);
if (pBitBlt->offBmiSrc > 0) hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
{ hBrushOld = SelectObject(hdcSrc, hBrush);
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT, PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top,
(BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc); pBitBlt->rclBounds.right - pBitBlt->rclBounds.left,
hBmpOld = SelectObject(hdcSrc, hBmp); pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY);
} SelectObject(hdcSrc, hBrushOld);
DeleteObject(hBrush);
BitBlt(hdc, hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
pBitBlt->xDest, (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
pBitBlt->yDest, hBmpOld = SelectObject(hdcSrc, hBmp);
pBitBlt->cxDest,
pBitBlt->cyDest,
hdcSrc,
pBitBlt->xSrc,
pBitBlt->ySrc,
pBitBlt->dwRop);
if (pBitBlt->offBmiSrc > 0) BitBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest,
{ hdcSrc, pBitBlt->xSrc, pBitBlt->ySrc, pBitBlt->dwRop);
SelectObject(hdcSrc, hBmpOld);
DeleteObject(hBmp); SelectObject(hdcSrc, hBmpOld);
} DeleteObject(hBmp);
DeleteDC(hdcSrc); DeleteDC(hdcSrc);
}
break; break;
} }
case EMR_STRETCHBLT: case EMR_STRETCHBLT:
{ {
PEMRSTRETCHBLT pStretchBlt= (PEMRSTRETCHBLT)mr; PEMRSTRETCHBLT pStretchBlt= (PEMRSTRETCHBLT)mr;
HDC hdcSrc = CreateCompatibleDC(hdc);
HBRUSH hBrush, hBrushOld;
HBITMAP hBmp = 0, hBmpOld = 0;
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pStretchBlt->offBmiSrc);
SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc); TRACE("EMR_STRETCHBLT: %ld, %ld %ldx%ld -> %ld, %ld %ldx%ld. rop %08lx offBitsSrc %ld\n",
pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc,
pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
pStretchBlt->dwRop, pStretchBlt->offBitsSrc);
hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc); if(pStretchBlt->offBmiSrc == 0) { /* Record is a PatBlt */
hBrushOld = SelectObject(hdcSrc, hBrush); PatBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top, pStretchBlt->dwRop);
pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left, } else { /* StretchBlt */
pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY); HDC hdcSrc = CreateCompatibleDC(hdc);
SelectObject(hdcSrc, hBrushOld); HBRUSH hBrush, hBrushOld;
DeleteObject(hBrush); HBITMAP hBmp = 0, hBmpOld = 0;
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pStretchBlt->offBmiSrc);
if (pStretchBlt->offBmiSrc) SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc);
{
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
(BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
hBmpOld = SelectObject(hdcSrc, hBmp);
}
StretchBlt(hdc, hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
pStretchBlt->xDest, hBrushOld = SelectObject(hdcSrc, hBrush);
pStretchBlt->yDest, PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
pStretchBlt->cxDest, pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
pStretchBlt->cyDest, pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
hdcSrc, SelectObject(hdcSrc, hBrushOld);
pStretchBlt->xSrc, DeleteObject(hBrush);
pStretchBlt->ySrc,
pStretchBlt->cxSrc,
pStretchBlt->cySrc,
pStretchBlt->dwRop);
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
(BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
hBmpOld = SelectObject(hdcSrc, hBmp);
if (pStretchBlt->offBmiSrc) StretchBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
{ hdcSrc, pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc,
SelectObject(hdcSrc, hBmpOld); pStretchBlt->dwRop);
DeleteObject(hBmp);
}
DeleteDC(hdcSrc); SelectObject(hdcSrc, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hdcSrc);
}
break; break;
} }
@ -1884,6 +2020,7 @@ BOOL WINAPI EnumEnhMetaFile(
SIZE vp_size, win_size; SIZE vp_size, win_size;
POINT vp_org, win_org; POINT vp_org, win_org;
INT mapMode = MM_TEXT; INT mapMode = MM_TEXT;
COLORREF old_text_color = 0, old_bk_color = 0;
if(!lpRect) if(!lpRect)
{ {
@ -1933,6 +2070,9 @@ BOOL WINAPI EnumEnhMetaFile(
hPen = GetCurrentObject(hdc, OBJ_PEN); hPen = GetCurrentObject(hdc, OBJ_PEN);
hBrush = GetCurrentObject(hdc, OBJ_BRUSH); hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
hFont = GetCurrentObject(hdc, OBJ_FONT); hFont = GetCurrentObject(hdc, OBJ_FONT);
old_text_color = SetTextColor(hdc, RGB(0,0,0));
old_bk_color = SetBkColor(hdc, RGB(0xff, 0xff, 0xff));
} }
info->mode = MM_TEXT; info->mode = MM_TEXT;
@ -2004,13 +2144,16 @@ BOOL WINAPI EnumEnhMetaFile(
while(ret && offset < emh->nBytes) while(ret && offset < emh->nBytes)
{ {
emr = (ENHMETARECORD *)((char *)emh + offset); emr = (ENHMETARECORD *)((char *)emh + offset);
TRACE("Calling EnumFunc with record type %ld, size %ld\n", emr->iType, emr->nSize); TRACE("Calling EnumFunc with record %s, size %ld\n", get_emr_name(emr->iType), emr->nSize);
ret = (*callback)(hdc, ht, emr, emh->nHandles, (LPARAM)data); ret = (*callback)(hdc, ht, emr, emh->nHandles, (LPARAM)data);
offset += emr->nSize; offset += emr->nSize;
} }
if (hdc) if (hdc)
{ {
SetBkColor(hdc, old_bk_color);
SetTextColor(hdc, old_text_color);
/* restore pen, brush and font */ /* restore pen, brush and font */
SelectObject(hdc, hBrush); SelectObject(hdc, hBrush);
SelectObject(hdc, hPen); SelectObject(hdc, hPen);