emf: bitblt, colours and debugging

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Nov 10 11:17:38 CST 2003


        Huw Davies <huw at codeweavers.com>
	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.
-- 
Huw Davies
huw at codeweavers.com
Index: objects/enhmetafile.c
===================================================================
RCS file: /home/wine/wine/objects/enhmetafile.c,v
retrieving revision 1.71
diff -u -r1.71 enhmetafile.c
--- objects/enhmetafile.c	5 Sep 2003 23:15:42 -0000	1.71
+++ objects/enhmetafile.c	10 Nov 2003 17:12:12 -0000
@@ -54,6 +54,146 @@
     BOOL           on_disk;   /* true if metafile is on disk */
 } 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
@@ -500,7 +640,7 @@
   if ( IS_WIN9X() && emr_produces_output(type) )
      EMF_Update_MF_Xform(hdc, info);
 
-  TRACE(" type=%d\n", type);
+  TRACE("record %s\n", get_emr_name(type));
   switch(type)
     {
     case EMR_HEADER:
@@ -574,14 +714,18 @@
     case EMR_RESTOREDC:
       {
 	PEMRRESTOREDC pRestoreDC = (PEMRRESTOREDC) mr;
+        TRACE("EMR_RESTORE: %ld\n", pRestoreDC->iRelative);
 	RestoreDC(hdc, pRestoreDC->iRelative);
 	break;
       }
     case EMR_INTERSECTCLIPRECT:
       {
 	PEMRINTERSECTCLIPRECT pClipRect = (PEMRINTERSECTCLIPRECT) mr;
-	IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top,
-			  pClipRect->rclClip.right, pClipRect->rclClip.bottom);
+        TRACE("EMR_INTERSECTCLIPRECT: rect %ld,%ld - %ld, %ld\n",
+              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;
       }
     case EMR_SELECTOBJECT:
@@ -861,6 +1005,10 @@
 	rc.top = pExtTextOutW->emrtext.rcl.top;
 	rc.right = pExtTextOutW->emrtext.rcl.right;
 	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,
 	    pExtTextOutW->emrtext.fOptions, &rc,
 	    (LPWSTR)((BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars,
@@ -1446,92 +1594,80 @@
     case EMR_BITBLT:
     {
 	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);
 
-	hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
-	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)
-	{
-		hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
-					  (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
-		hBmpOld = SelectObject(hdcSrc, hBmp);
-	}
-
-	BitBlt(hdc,
-	       pBitBlt->xDest,
-	       pBitBlt->yDest,
-	       pBitBlt->cxDest,
-	       pBitBlt->cyDest,
-	       hdcSrc,
-	       pBitBlt->xSrc,
-	       pBitBlt->ySrc,
-	       pBitBlt->dwRop);
-
-	if (pBitBlt->offBmiSrc > 0)
-	{
-		SelectObject(hdcSrc, hBmpOld);
-		DeleteObject(hBmp);
-	}
-	DeleteDC(hdcSrc);
+        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);
+
+            SetWorldTransform(hdcSrc, &pBitBlt->xformSrc);
+
+            hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc);
+            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);
+
+            hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+                                  (BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
+            hBmpOld = SelectObject(hdcSrc, hBmp);
+
+            BitBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest,
+                   hdcSrc, pBitBlt->xSrc, pBitBlt->ySrc, pBitBlt->dwRop);
+
+            SelectObject(hdcSrc, hBmpOld);
+            DeleteObject(hBmp);
+            DeleteDC(hdcSrc);
+        }
 	break;
     }
 
     case EMR_STRETCHBLT:
     {
 	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);
-
-	hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
-	hBrushOld = SelectObject(hdcSrc, hBrush);
-	PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
-	       pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
-	       pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
-	SelectObject(hdcSrc, hBrushOld);
-	DeleteObject(hBrush);
-
-	if (pStretchBlt->offBmiSrc)
-	{
-		hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
-					  (BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
-		hBmpOld = SelectObject(hdcSrc, hBmp);
-	}
 
-	StretchBlt(hdc,
-	       pStretchBlt->xDest,
-	       pStretchBlt->yDest,
-	       pStretchBlt->cxDest,
-	       pStretchBlt->cyDest,
-	       hdcSrc,
-	       pStretchBlt->xSrc,
-	       pStretchBlt->ySrc,
-	       pStretchBlt->cxSrc,
-	       pStretchBlt->cySrc,
-	       pStretchBlt->dwRop);
-
-
-	if (pStretchBlt->offBmiSrc)
-	{
-		SelectObject(hdcSrc, hBmpOld);
-		DeleteObject(hBmp);
-	}
-
-	DeleteDC(hdcSrc);
+        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);
+
+        if(pStretchBlt->offBmiSrc == 0) { /* Record is a PatBlt */
+            PatBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
+                   pStretchBlt->dwRop);
+        } else { /* StretchBlt */
+            HDC hdcSrc = CreateCompatibleDC(hdc);
+            HBRUSH hBrush, hBrushOld;
+            HBITMAP hBmp = 0, hBmpOld = 0;
+            BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pStretchBlt->offBmiSrc);
+
+            SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc);
+
+            hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc);
+            hBrushOld = SelectObject(hdcSrc, hBrush);
+            PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top,
+                   pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left,
+                   pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY);
+            SelectObject(hdcSrc, hBrushOld);
+            DeleteObject(hBrush);
+
+            hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
+                                  (BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
+            hBmpOld = SelectObject(hdcSrc, hBmp);
+
+            StretchBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest,
+                       hdcSrc, pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc,
+                       pStretchBlt->dwRop);
+
+            SelectObject(hdcSrc, hBmpOld);
+            DeleteObject(hBmp);
+            DeleteDC(hdcSrc);
+        }
 	break;
     }
 
@@ -1884,6 +2020,7 @@
     SIZE vp_size, win_size;
     POINT vp_org, win_org;
     INT mapMode = MM_TEXT;
+    COLORREF old_text_color = 0, old_bk_color = 0;
 
     if(!lpRect)
     {
@@ -1933,6 +2070,9 @@
 	hPen = GetCurrentObject(hdc, OBJ_PEN);
 	hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
 	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;
@@ -2004,13 +2144,16 @@
     while(ret && offset < emh->nBytes)
     {
 	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);
 	offset += emr->nSize;
     }
 
     if (hdc)
     {
+        SetBkColor(hdc, old_bk_color);
+        SetTextColor(hdc, old_text_color);
+
 	/* restore pen, brush and font */
 	SelectObject(hdc, hBrush);
 	SelectObject(hdc, hPen);



More information about the wine-patches mailing list