Implement Get/Set EMFTransform

Warren_Baird at cimmetry.com Warren_Baird at cimmetry.com
Thu Feb 6 08:52:49 CST 2003



ChangeLog:

     1. Implementation of GetEMFTransform and SetEMFTransform Windows API
functions.
     2. Fix EnumEnhMetaFile so it renders properly inside the limits
     of the given rectangle input parameter.

Description:

     1. GetEMFTransform and SetEMFTransform have been implemented by storing an
     additional XFORM inside the DC structure to map an EMF to a destination
     rectangle.

     2. Fixing EnumEnhMetaFile relies on the previous GetEMFTransform and
     SetEMFTransform functions. The EMF mapping transformation is combined
     to the Wnd2VPort transformation.

Warren Baird : Warren_Baird at cimmetry.com
Xavier Servettaz

diff -ur clean/wine/include/wingdi.h wine/include/wingdi.h
--- clean/wine/include/wingdi.h    Wed Jan 29 15:31:07 2003
+++ wine/include/wingdi.h     Mon Feb  3 18:54:12 2003
@@ -3255,6 +3255,7 @@
 COLORREF  WINAPI GetDCPenColor(HDC);
 UINT      WINAPI GetDIBColorTable(HDC,UINT,UINT,RGBQUAD*);
 INT       WINAPI GetDIBits(HDC,HBITMAP,UINT,UINT,LPVOID,LPBITMAPINFO,UINT);
+BOOL      WINAPI GetEMFTransform(HDC, LPXFORM);
 HENHMETAFILE WINAPI GetEnhMetaFileA(LPCSTR);
 HENHMETAFILE WINAPI GetEnhMetaFileW(LPCWSTR);
 #define     GetEnhMetaFile WINELIB_NAME_AW(GetEnhMetaFile)
@@ -3413,6 +3414,7 @@
 INT       WINAPI SetDIBits(HDC,HBITMAP,UINT,UINT,LPCVOID,const
BITMAPINFO*,UINT);
 INT       WINAPI SetDIBitsToDevice(HDC,INT,INT,DWORD,DWORD,INT,
                          INT,UINT,UINT,LPCVOID,const BITMAPINFO*,UINT);
+BOOL      WINAPI SetEMFTransform(HDC, const XFORM *);
 HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT,const BYTE *);
 INT         WINAPI SetGraphicsMode(HDC,INT);
 INT         WINAPI SetICMMode(HDC,INT);

diff -ur clean/wine/include/gdi.h wine/include/gdi.h
--- clean/wine/include/gdi.h  Wed Jan 29 15:31:05 2003
+++ wine/include/gdi.h   Mon Feb  3 10:55:03 2003
@@ -159,6 +159,7 @@
     XFORM         xformWorld2Wnd;    /* World-to-window transformation */
     XFORM         xformWorld2Vport;  /* World-to-viewport transformation */
     XFORM         xformVport2World;  /* Inverse of the above transformation */
+     XFORM         xformEMFmapping;   /* Map an EMF to destination rectangle*/
     BOOL          vport2WorldValid;  /* Is xformVport2World valid? */
 } DC;

diff -ur clean/wine/objects/dc.c wine/objects/dc.c
--- clean/wine/objects/dc.c   Wed Jan 29 15:31:13 2003
+++ wine/objects/dc.c    Mon Feb  3 10:33:17 2003
@@ -119,6 +119,7 @@
     dc->xformWorld2Wnd.eDy  = 0.0f;
     dc->xformWorld2Vport    = dc->xformWorld2Wnd;
     dc->xformVport2World    = dc->xformWorld2Wnd;
+    dc->xformEMFmapping     = dc->xformWorld2Wnd;
     dc->vport2WorldValid    = TRUE;
     PATH_InitGdiPath(&dc->path);
     return dc;
@@ -256,9 +257,14 @@
     xformWnd2Vport.eDy  = (FLOAT)dc->vportOrgY -
         scaleY * (FLOAT)dc->wndOrgY;

+    XFORM additionalTransform;
     /* Combine with the world transformation */
-    CombineTransform( &dc->xformWorld2Vport, &dc->xformWorld2Wnd,
-        &xformWnd2Vport );
+    CombineTransform(&additionalTransform,
+                         &dc->xformWorld2Wnd,
+                         &xformWnd2Vport );
+    CombineTransform(&dc->xformWorld2Vport,
+                         &additionalTransform,
+                         &dc->xformEMFmapping );

     /* Create inverse of world-to-viewport transformation */
     dc->vport2WorldValid = DC_InvertXform( &dc->xformWorld2Vport,
@@ -314,6 +320,7 @@
     newdc->xformWorld2Wnd   = dc->xformWorld2Wnd;
     newdc->xformWorld2Vport = dc->xformWorld2Vport;
     newdc->xformVport2World = dc->xformVport2World;
+    newdc->xformEMFmapping  = dc->xformEMFmapping;
     newdc->vport2WorldValid = dc->vport2WorldValid;
     newdc->wndOrgX          = dc->wndOrgX;
     newdc->wndOrgY          = dc->wndOrgY;
@@ -402,6 +409,7 @@
     dc->xformWorld2Wnd   = dcs->xformWorld2Wnd;
     dc->xformWorld2Vport = dcs->xformWorld2Vport;
     dc->xformVport2World = dcs->xformVport2World;
+    dc->xformEMFmapping  = dcs->xformEMFmapping;
     dc->vport2WorldValid = dcs->vport2WorldValid;

     dc->wndOrgX          = dcs->wndOrgX;
@@ -976,6 +984,35 @@
     return nOldDirection;
 }

+/***********************************************************************
+ *           GetEMFTransform    (GDI32.@)
+ */
+BOOL WINAPI GetEMFTransform( HDC hdc, LPXFORM xform )
+{
+    DC * dc;
+    if (!xform) return FALSE;
+    if (!(dc = DC_GetDCPtr( hdc ))) return FALSE;
+    *xform = dc->xformEMFmapping;
+    GDI_ReleaseObj( hdc );
+    return TRUE;
+}
+
+/***********************************************************************
+ *           SetEMFTransform    (GDI32.@)
+ */
+BOOL WINAPI SetEMFTransform( HDC hdc, const XFORM *xform )
+{
+    BOOL ret = FALSE;
+    DC *dc = DC_GetDCPtr( hdc );
+    if (!dc) { return FALSE;}
+    if (xform) {
+         dc->xformEMFmapping = *xform;
+         DC_UpdateXforms( dc );
+         ret = TRUE;
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
+}

 /***********************************************************************
  *           GetWorldTransform    (GDI32.@)

diff -ur clean/wine/objects/enhmetafile.c wine/objects/enhmetafile.c
--- clean/wine/objects/enhmetafile.c     Mon Feb  3 19:07:49 2003
+++ wine/objects/enhmetafile.c     Mon Feb  3 19:15:45 2003
@@ -418,18 +418,12 @@
       }
     case EMR_SETWINDOWORGEX:
       {
-         XFORM xform;
-         PEMRSETWINDOWORGEX pSetWindowOrgEx = (PEMRSETWINDOWORGEX) mr;
-
-         xform.eM11 = 1;
-         xform.eM12 = 0;
-         xform.eM21 = 0;
-         xform.eM22 = 1;
-         xform.eDx = -pSetWindowOrgEx->ptlOrigin.x;
-         xform.eDy = -pSetWindowOrgEx->ptlOrigin.y;
-
-         ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
-         break;
+          PEMRSETWINDOWORGEX pSetWindowOrgEx = (PEMRSETWINDOWORGEX) mr;
+           SetWindowOrgEx(hdc,
+                              pSetWindowOrgEx->ptlOrigin.x,
+                              pSetWindowOrgEx->ptlOrigin.y,
+                              NULL);
+           break;
       }
     case EMR_SETWINDOWEXTEX:
       {
@@ -1608,11 +1602,15 @@
     HANDLETABLE *ht;
     INT savedMode = 0;
     FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale;
-    XFORM savedXform, xform;
+    XFORM savedXform, xform, savedEMFXform;
     HPEN hPen = NULL;
     HBRUSH hBrush = NULL;
     HFONT hFont = NULL;
     POINT pt[2];
+    INT   oldvportExtX = 0;
+    INT   oldvportExtY = 0;
+    INT   oldvportOrgX = 0;
+    INT   oldvportOrgY = 0;

     if(!lpRect)
     {
@@ -1660,10 +1658,59 @@

     savedMode = SetGraphicsMode(hdc, GM_ADVANCED);
     GetWorldTransform(hdc, &savedXform);
+    GetEMFTransform(hdc, &savedEMFXform);

-    if (!ModifyWorldTransform(hdc, &xform, MWT_RIGHTMULTIPLY)) {
-        ERR("World transform failed!\n");
+    /* here we combine "out-of-EMF" Wnd2Vport transformation with
+       the one mapping to the selected output rectangle.
+       Since they both will be included in the additionalTransform, we ensure
+       Identity is set to xformWnd2Vport before playing the EMF
+
+       rem: "out-of-EMF" means any transform that is already set for this DC.
+    */
+
+    DC *dc = DC_GetDCPtr (hdc);
+    if (!dc) {
+         FIXME ("ERROR failed to get DC ptr while playing enhmetafile!/n");
+         return FALSE;
     }
+
+    XFORM xformWnd2Vport;
+    XFORM additionalTransform;
+    FLOAT scaleX, scaleY;
+
+    /* Construct a transformation to do the window-to-viewport conversion */
+    scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
+    scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
+    xformWnd2Vport.eM11 = scaleX;
+    xformWnd2Vport.eM12 = 0.0;
+    xformWnd2Vport.eM21 = 0.0;
+    xformWnd2Vport.eM22 = scaleY;
+    xformWnd2Vport.eDx  = (FLOAT)dc->vportOrgX -
+        scaleX * (FLOAT)dc->wndOrgX;
+    xformWnd2Vport.eDy  = (FLOAT)dc->vportOrgY -
+        scaleY * (FLOAT)dc->wndOrgY;
+
+    /* save old values */
+    oldvportExtX = dc->vportExtX;
+    oldvportExtY = dc->vportExtY;
+    oldvportOrgX = dc->vportOrgX;
+    oldvportOrgY = dc->vportOrgY;
+
+    /* set identity */
+    dc->vportExtX = dc->wndExtX;
+    dc->vportExtY = dc->wndExtY;
+    dc->vportOrgX = dc->wndOrgX;
+    dc->vportOrgY = dc->wndOrgY;
+
+    /* release DC */
+    GDI_ReleaseObj(hdc);
+
+    /* combine transformations */
+    CombineTransform(&additionalTransform,
+                         &xform,
+                         &xformWnd2Vport);
+
+    SetEMFTransform(hdc, &additionalTransform);

     /* save the current pen, brush and font */
     hPen = GetCurrentObject(hdc, OBJ_PEN);
@@ -1696,7 +1743,22 @@
     SelectObject(hdc, hPen);
     SelectObject(hdc, hFont);

+    /* reset vport values */
+    DC *dc = DC_GetDCPtr (hdc);
+    if (!dc) {
+        FIXME ("ERROR failed to get DC ptr while playing enhmetafile!/n");
+        return FALSE;
+    }
+    dc->vportExtX = oldvportExtX;
+    dc->vportExtY = oldvportExtY;
+    dc->vportOrgX = oldvportOrgX;
+    dc->vportOrgY = oldvportOrgY;
+    /* release DC */
+    GDI_ReleaseObj(hdc);
+
     SetWorldTransform(hdc, &savedXform);
+    SetEMFTransform(hdc, &savedEMFXform);
+
     if (savedMode)
         SetGraphicsMode(hdc, savedMode);
     }





More information about the wine-patches mailing list