Handle conserving patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hi,


This patch attempts to conserve handles when generating enhanced metafiles. It was originally written by Huw Davies, however I have modified it to not use extra space in the GDI heap, as per Alexandre's objections.

The same thing needs to be done for old format metafiles too, but I'll wait until this patch is accepted first.

Mike


ChangeLog: <huw@codeweavers.com> <mike@codeweavers.com> * elimate duplication of handles when generating EMFs


Index: dlls/gdi/enhmfdrv/enhmetafiledrv.h
===================================================================
RCS file: /home/wine/wine/dlls/gdi/enhmfdrv/enhmetafiledrv.h,v
retrieving revision 1.11
diff -u -r1.11 enhmetafiledrv.h
--- dlls/gdi/enhmfdrv/enhmetafiledrv.h	23 Jun 2003 19:46:56 -0000	1.11
+++ dlls/gdi/enhmfdrv/enhmetafiledrv.h	27 Jul 2003 08:12:38 -0000
@@ -27,12 +27,20 @@
 
 /* Enhanced Metafile driver physical DC */
 
+typedef struct _EMFDRV_handle_info
+{
+    DWORD     type;
+    DWORD     size;
+    BYTE      data[1];
+} EMFDRV_handle_info;
+
 typedef struct
 {
     HDC             hdc;
     DC             *dc;
     ENHMETAHEADER  *emh;           /* Pointer to enhanced metafile header */
-    UINT       nextHandle;         /* Next handle number */
+    UINT       handles_size, cur_handles;
+    EMFDRV_handle_info **handle_info;
     HANDLE     hFile;              /* Handle for disk based MetaFile */
     INT        horzres, vertres;
     INT        horzsize, vertsize;
@@ -46,10 +54,11 @@
 
 
 extern BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr );
-extern int EMFDRV_AddHandleDC( PHYSDEV dev );
 extern void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect );
 extern DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush );
 
+#define HANDLE_LIST_INC 20
+
 /* Metafile driver functions */
 extern BOOL     EMFDRV_AbortPath( PHYSDEV dev );
 extern BOOL     EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right,
@@ -63,6 +72,7 @@
                               INT bottom, INT xstart, INT ystart, INT xend,
                               INT yend );
 extern BOOL     EMFDRV_CloseFigure( PHYSDEV dev );
+extern BOOL     EMFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj );
 extern BOOL     EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top,
                                 INT right, INT bottom );
 extern BOOL     EMFDRV_EndPath( PHYSDEV dev );
Index: dlls/gdi/enhmfdrv/init.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/enhmfdrv/init.c,v
retrieving revision 1.19
diff -u -r1.19 init.c
--- dlls/gdi/enhmfdrv/init.c	23 Jun 2003 19:46:56 -0000	1.19
+++ dlls/gdi/enhmfdrv/init.c	27 Jul 2003 08:12:39 -0000
@@ -154,8 +154,13 @@
 {
     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
     DC *dc = physDev->dc;
+    UINT index;
 
     if (physDev->emh) HeapFree( GetProcessHeap(), 0, physDev->emh );
+    for(index = 0; index < physDev->handles_size; index++)
+        if( physDev->handle_info[index] )
+            HeapFree( GetProcessHeap(), 0,  physDev->handle_info[index] );
+    HeapFree( GetProcessHeap(), 0, physDev->handle_info );
     HeapFree( GetProcessHeap(), 0, physDev );
     dc->physDev = NULL;
     GDI_FreeObject( dc->hSelf, dc );
@@ -212,20 +217,6 @@
     return;
 }
 
-/******************************************************************
- *         EMFDRV_AddHandleDC
- *
- * Note: this function assumes that we never delete objects.
- * If we do someday, we'll need to maintain a table to re-use deleted
- * handles.
- */
-int EMFDRV_AddHandleDC( PHYSDEV dev )
-{
-    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
-    physDev->emh->nHandles++;
-    return physDev->nextHandle++;
-}
-
 
 /**********************************************************************
  *          CreateEnhMetaFileA   (GDI32.@)
@@ -312,7 +303,10 @@
         return 0;
     }
 
-    physDev->nextHandle = 1;
+    physDev->handle_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
+                             HANDLE_LIST_INC * sizeof(physDev->handle_info[0]));
+    physDev->handles_size = HANDLE_LIST_INC;
+    physDev->cur_handles = 1;
     physDev->hFile = 0;
 
     physDev->horzres = GetDeviceCaps(hRefDC, HORZRES);
Index: dlls/gdi/enhmfdrv/objects.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/enhmfdrv/objects.c,v
retrieving revision 1.7
diff -u -r1.7 objects.c
--- dlls/gdi/enhmfdrv/objects.c	21 May 2003 18:28:49 -0000	1.7
+++ dlls/gdi/enhmfdrv/objects.c	27 Jul 2003 08:12:39 -0000
@@ -28,6 +28,127 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);
 
+
+/******************************************************************
+ *         EMFDRV_AddHandle
+ */
+static UINT EMFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+    UINT index, type, size;
+    EMFDRV_handle_info *info;
+
+    type = GetObjectType( obj );
+    if( !type )
+        return 0;
+    size = GetObjectW( obj, 0, NULL );
+    if( !size )
+        return 0;
+
+    for(index = 0; index < physDev->handles_size; index++)
+        if(physDev->handle_info[index] == NULL) break;
+    if(index == physDev->handles_size)
+    {
+        UINT len = physDev->handles_size + HANDLE_LIST_INC;
+        EMFDRV_handle_info **temp = physDev->handle_info;
+
+	temp = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                            temp, len * sizeof temp[0]);
+        if( !temp )
+            return 0;
+        physDev->handle_info = temp;
+        physDev->handles_size = len;
+    }
+
+    info = HeapAlloc( GetProcessHeap(), 0,
+                      sizeof (EMFDRV_handle_info) + size );
+    if( !info )
+        return 0;
+
+    info->type = type;
+    info->size = size;
+    if( size != GetObjectW( obj, size, info->data ))
+        return 0;
+
+    physDev->handle_info[index] = info;
+
+    physDev->cur_handles++;
+    if(physDev->cur_handles > physDev->emh->nHandles)
+        physDev->emh->nHandles++;
+
+    return index + 1; /* index 0 is reserved for the hmf, so we increment everything by 1 */
+}
+
+
+/******************************************************************
+ *         EMFDRV_FindObject
+ */
+static UINT EMFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
+    UINT index, type, size;
+    EMFDRV_handle_info *info, *x;
+
+    type = GetObjectType( obj );
+    if( !type )
+        return 0;
+    size = GetObjectW( obj, 0, NULL );
+    if( !size )
+        return 0;
+
+    for(index = 0; index < physDev->handles_size; index++)
+    {
+        x = physDev->handle_info[index];
+        if( !x )
+            continue;
+        if( type != x->type )
+            continue;
+        if( size != x->size )
+            continue;
+        info = HeapAlloc( GetProcessHeap(), 0, size );
+        if( info )
+        {
+            BOOL ok = TRUE;
+
+            if( ok && ( size != GetObjectW( obj, size, info ) ) )
+                ok = FALSE;
+            if( ok && memcmp( info, x->data, size ) )
+                ok = FALSE;
+        
+            HeapFree( GetProcessHeap(), 0, info );
+            if( ok )
+                break;
+        }
+    }
+
+    if(index == physDev->handles_size) return 0;
+
+    return index + 1;
+}
+
+
+/******************************************************************
+ *         EMFDRV_DeleteObject
+ */
+BOOL EMFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMRDELETEOBJECT emr;
+    UINT index;
+    BOOL ret = TRUE;
+
+    if(!(index = EMFDRV_FindObject(dev, obj))) return 0;
+
+    emr.emr.iType = EMR_DELETEOBJECT;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihObject = index;
+
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        ret = FALSE;
+
+    return ret;
+}
+
+  
 /***********************************************************************
  *           EMFDRV_SelectBitmap
  */
@@ -55,7 +176,7 @@
 	EMRCREATEBRUSHINDIRECT emr;
 	emr.emr.iType = EMR_CREATEBRUSHINDIRECT;
 	emr.emr.nSize = sizeof(emr);
-	emr.ihBrush = index = EMFDRV_AddHandleDC( dev );
+	emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush );
 	emr.lb = logbrush;
 
 	if(!EMFDRV_WriteRecord( dev, &emr.emr ))
@@ -80,7 +201,7 @@
 	if(!emr) break;
 	emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT;
 	emr->emr.nSize = size;
-	emr->ihBrush = index = EMFDRV_AddHandleDC( dev );
+	emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush );
 	emr->iUsage = LOWORD(logbrush.lbColor);
 	emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT);
 	emr->cbBmi = biSize;
@@ -130,6 +251,9 @@
             goto found;
         }
     }
+    if((index = EMFDRV_FindObject(dev, hBrush)) != 0)
+        goto found;
+
     if (!(index = EMFDRV_CreateBrushIndirect(dev, hBrush ))) return 0;
 
  found:
@@ -153,7 +277,7 @@
 
     emr.emr.iType = EMR_EXTCREATEFONTINDIRECTW;
     emr.emr.nSize = (sizeof(emr) + 3) / 4 * 4;
-    emr.ihFont = index = EMFDRV_AddHandleDC( dev );
+    emr.ihFont = index = EMFDRV_AddHandle( dev, hFont );
     emr.elfw.elfFullName[0] = '\0';
     emr.elfw.elfStyle[0]    = '\0';
     emr.elfw.elfVersion     = 0;
@@ -203,7 +327,12 @@
             goto found;
         }
     }
+
+    if((index = EMFDRV_FindObject(dev, hFont)) != 0)
+        goto found;
+
     if (!(index = EMFDRV_CreateFontIndirect(dev, hFont ))) return HGDI_ERROR;
+
  found:
     emr.emr.iType = EMR_SELECTOBJECT;
     emr.emr.nSize = sizeof(emr);
@@ -227,7 +356,7 @@
 
     emr.emr.iType = EMR_CREATEPEN;
     emr.emr.nSize = sizeof(emr);
-    emr.ihPen = index = EMFDRV_AddHandleDC( dev );
+    emr.ihPen = index = EMFDRV_AddHandle( dev, hPen );
 
     if(!EMFDRV_WriteRecord( dev, &emr.emr ))
         index = 0;
@@ -257,7 +386,11 @@
             goto found;
         }
     }
+    if((index = EMFDRV_FindObject(dev, hPen)) != 0)
+        goto found;
+
     if (!(index = (DWORD)EMFDRV_CreatePenIndirect(dev, hPen ))) return 0;
+
  found:
     emr.emr.iType = EMR_SELECTOBJECT;
     emr.emr.nSize = sizeof(emr);

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux