Alexandre Julliard : winex11: Add an implementation for the GetImage entry point.

Alexandre Julliard julliard at winehq.org
Thu Jul 14 13:08:12 CDT 2011


Module: wine
Branch: master
Commit: e6fcbc543ee5fdae32d662731d782cd0bce661c6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e6fcbc543ee5fdae32d662731d782cd0bce661c6

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jul 14 12:37:04 2011 +0200

winex11: Add an implementation for the GetImage entry point.

---

 dlls/winex11.drv/bitblt.c |  172 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/winex11.drv/init.c   |    2 +-
 dlls/winex11.drv/x11drv.h |    2 +
 3 files changed, 174 insertions(+), 2 deletions(-)

diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c
index 54e635a..14f90ef 100644
--- a/dlls/winex11.drv/bitblt.c
+++ b/dlls/winex11.drv/bitblt.c
@@ -1,7 +1,7 @@
 /*
  * GDI bit-blit operations
  *
- * Copyright 1993, 1994  Alexandre Julliard
+ * Copyright 1993, 1994, 2011 Alexandre Julliard
  * Copyright 2006 Damjan Jovanovic
  *
  * This library is free software; you can redistribute it and/or
@@ -1547,3 +1547,173 @@ BOOL X11DRV_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
 
     return XRender_AlphaBlend( physDevDst, dst, physDevSrc, src, blendfn );
 }
+
+
+static void free_heap_bits( struct gdi_image_bits *bits )
+{
+    HeapFree( GetProcessHeap(), 0, bits->ptr );
+}
+
+static void free_ximage_bits( struct gdi_image_bits *bits )
+{
+    wine_tsx11_lock();
+    XFree( bits->ptr );
+    wine_tsx11_unlock();
+}
+
+/* store the palette or color mask data in the bitmap info structure */
+static void set_color_info( const ColorShifts *color_shifts, BITMAPINFO *info )
+{
+    DWORD *colors = (DWORD *)((char *)info + info->bmiHeader.biSize);
+
+    switch (info->bmiHeader.biBitCount)
+    {
+    case 1:
+    case 4:
+    case 8:
+        info->bmiHeader.biCompression = BI_RGB;
+        /* FIXME: set color palette */
+        break;
+    case 16:
+    case 32:
+        info->bmiHeader.biCompression = BI_BITFIELDS;
+        colors[0] = color_shifts->logicalRed.max << color_shifts->logicalRed.shift;
+        colors[1] = color_shifts->logicalGreen.max << color_shifts->logicalGreen.shift;
+        colors[2] = color_shifts->logicalBlue.max << color_shifts->logicalBlue.shift;
+        break;
+    case 24:
+        info->bmiHeader.biCompression = BI_RGB;
+        break;
+    }
+}
+
+/***********************************************************************
+ *           X11DRV_GetImage
+ */
+DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
+                       struct gdi_image_bits *bits, const RECT *rect )
+{
+    X11DRV_PDEVICE *physdev;
+    X_PHYSBITMAP *bitmap;
+    DWORD ret = ERROR_SUCCESS;
+    XImage *image;
+    UINT i, align, x, y, width, height;
+    int depth;
+    const XPixmapFormatValues *format;
+    const ColorShifts *color_shifts;
+
+    if (hbitmap)
+    {
+        if (!(bitmap = X11DRV_get_phys_bitmap( hbitmap ))) return ERROR_INVALID_HANDLE;
+        physdev = NULL;
+        depth = bitmap->pixmap_depth;
+        color_shifts = &bitmap->pixmap_color_shifts;
+    }
+    else
+    {
+        physdev = get_x11drv_dev( dev );
+        bitmap = NULL;
+        depth = physdev->depth;
+        color_shifts = physdev->color_shifts;
+    }
+    format = pixmap_formats[depth];
+
+    /* align start and width to 32-bit boundary */
+    switch (format->bits_per_pixel)
+    {
+    case 1:  align = 32; break;
+    case 4:  align = 8;  break;
+    case 8:  align = 4;  break;
+    case 16: align = 2;  break;
+    case 24: align = 4;  break;
+    case 32: align = 1;  break;
+    default:
+        FIXME( "depth %u bpp %u not supported yet\n", depth, format->bits_per_pixel );
+        return ERROR_BAD_FORMAT;
+    }
+    bits->offset = rect->left & (align - 1);
+    x = rect->left - bits->offset;
+    y = rect->top;
+    width = rect->right - x;
+    height = rect->bottom - rect->top;
+    if (format->scanline_pad != 32) width = (width + (align - 1)) & ~(align - 1);
+
+    if (bitmap)
+    {
+        BITMAP bm;
+        GetObjectW( hbitmap, sizeof(bm), &bm );
+        width = min( width, bm.bmWidth - x );
+        height = min( height, bm.bmHeight - y );
+        wine_tsx11_lock();
+        image = XGetImage( gdi_display, bitmap->pixmap, x, y, width, height, AllPlanes, ZPixmap );
+        wine_tsx11_unlock();
+    }
+    else if (GetObjectType( dev->hdc ) == OBJ_MEMDC)
+    {
+        X11DRV_LockDIBSection( physdev, DIB_Status_GdiMod );
+        width = min( width, physdev->dc_rect.right - physdev->dc_rect.left - x );
+        height = min( height, physdev->dc_rect.bottom - physdev->dc_rect.top - y );
+        wine_tsx11_lock();
+        image = XGetImage( gdi_display, physdev->drawable,
+                           physdev->dc_rect.left + x, physdev->dc_rect.top + y,
+                           width, height, AllPlanes, ZPixmap );
+        wine_tsx11_unlock();
+        X11DRV_UnlockDIBSection( physdev, FALSE );
+    }
+    else
+    {
+        Pixmap pixmap;
+
+        wine_tsx11_lock();
+        /* use a temporary pixmap to avoid BadMatch errors */
+        pixmap = XCreatePixmap( gdi_display, root_window, width, height, depth );
+        XCopyArea( gdi_display, physdev->drawable, pixmap, get_bitmap_gc(depth),
+                   physdev->dc_rect.left + x, physdev->dc_rect.top + y, width, height, 0, 0 );
+        image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap );
+        XFreePixmap( gdi_display, pixmap );
+        wine_tsx11_unlock();
+    }
+    if (!image) return ERROR_OUTOFMEMORY;
+
+    info->bmiHeader.biSize          = sizeof(info->bmiHeader);
+    info->bmiHeader.biWidth         = width;
+    info->bmiHeader.biHeight        = -height;
+    info->bmiHeader.biPlanes        = 1;
+    info->bmiHeader.biBitCount      = image->bits_per_pixel;
+    info->bmiHeader.biSizeImage     = height * image->bytes_per_line;
+    info->bmiHeader.biXPelsPerMeter = 0;
+    info->bmiHeader.biYPelsPerMeter = 0;
+    info->bmiHeader.biClrUsed       = 0;
+    info->bmiHeader.biClrImportant  = 0;
+    set_color_info( color_shifts, info );
+
+    /* check if we need to copy the bits */
+    if (image->bytes_per_line & 3)
+    {
+        UINT width_bytes = (image->bytes_per_line + 3) & ~3;
+        info->bmiHeader.biSizeImage = height * width_bytes;
+        if ((bits->ptr = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage )))
+        {
+            bits->is_copy = TRUE;
+            bits->free = free_heap_bits;
+            for (i = 0; i < height; i++)
+                memcpy( (char *)bits->ptr + i * width_bytes,
+                        (char *)image->data + i * image->bytes_per_line,
+                        image->bytes_per_line );
+            /* FIXME: byte swapping */
+        }
+        else ret = ERROR_OUTOFMEMORY;
+    }
+    else
+    {
+        bits->ptr = image->data;
+        bits->is_copy = TRUE;
+        bits->free = free_ximage_bits;
+        image->data = NULL;
+    }
+
+    wine_tsx11_lock();
+    XDestroyImage( image );
+    wine_tsx11_unlock();
+    return ret;
+}
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index d1800d4..f78e20e 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -486,7 +486,7 @@ static const struct gdi_dc_funcs x11drv_funcs =
     X11DRV_GetDeviceCaps,               /* pGetDeviceCaps */
     X11DRV_GetDeviceGammaRamp,          /* pGetDeviceGammaRamp */
     X11DRV_GetICMProfile,               /* pGetICMProfile */
-    NULL,                               /* pGetImage */
+    X11DRV_GetImage,                    /* pGetImage */
     X11DRV_GetNearestColor,             /* pGetNearestColor */
     X11DRV_GetPixel,                    /* pGetPixel */
     X11DRV_GetPixelFormat,              /* pGetPixelFormat */
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 5575b89..ecf608e 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -204,6 +204,8 @@ extern BOOL X11DRV_GetDeviceGammaRamp( PHYSDEV dev, LPVOID ramp ) DECLSPEC_HIDDE
 extern INT X11DRV_GetDIBits( PHYSDEV dev, HBITMAP hbitmap, UINT startscan, UINT lines,
                              LPVOID bits, BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN;
 extern BOOL X11DRV_GetICMProfile( PHYSDEV dev, LPDWORD size, LPWSTR filename ) DECLSPEC_HIDDEN;
+extern DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
+                              struct gdi_image_bits *bits, const RECT *rect ) DECLSPEC_HIDDEN;
 extern COLORREF X11DRV_GetNearestColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN;
 extern COLORREF X11DRV_GetPixel( PHYSDEV dev, INT x, INT y) DECLSPEC_HIDDEN;
 extern UINT X11DRV_GetSystemPaletteEntries( PHYSDEV dev, UINT start, UINT count, LPPALETTEENTRY entries ) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list