+                /* This might not work for values of "dwRop" much
different than "SRCCOPY".
+                 * Further testing is required.
+                 * mkosch (2008/09/22)
+                 */

Add a test case for this if it is possible and test it, if possible. 
Then you will know if it works/does not work.

James McKenzie

From da2f416c33348ef059e0c3958392d5231b6fd774 Mon Sep 17 00:00:00 2001
From: Mathias Kosch <[EMAIL PROTECTED]>
Date: Tue, 23 Sep 2008 01:36:34 +0200
Subject: gdi32: "StretchDIBits" with value of zero for "xSrc" and "ySrc"

This patch fixes Bug#13344.

The function "StretchDIBits" behaves odd in case of "top-down" bitmaps with 
values of zero for "xSrc" and "ySrc".
Tests using Windows Server 2003 shew that in this particular case the source 
rectangle is selected starting at the upper left corner of the bitmap. In all 
other cases the rectangle is aligned to the bottom of the bitmap.

I provided a test case which tests several combinations, especially those with 
some of the values set to zero. (Some additional cosmetic corrections have been 
applied to the test case.)
It passes under "Windows Server 2003 R2 SP2" and Wine 1.1.5 (only) with this 
path applied.
---
 dlls/gdi32/dib.c             |   20 +++-
 dlls/gdi32/tests/Makefile.in |    1 +
 dlls/gdi32/tests/dib.c       |  238 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 257 insertions(+), 2 deletions(-)
 create mode 100644 dlls/gdi32/tests/dib.c

diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 440857d..a59a02e 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -212,6 +212,7 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT 
widthDst,
         DWORD compr, size;
         HBITMAP hBitmap;
         BOOL fastpath = FALSE;
+        int ySrcAdjusted;
 
         release_dc_ptr( dc );
 
@@ -227,6 +228,16 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT 
widthDst,
             return 0;
         }
 
+        /* Computation of source coordinates behaves different in case of "top 
down"
+           bitmaps and values of zero for "xSrc" and "ySrc": */
+        if (height < 0)
+        {
+            height = -height;  /* Positive from now on. */
+            ySrcAdjusted = ((xSrc) || (ySrc)) ? height - heightSrc - ySrc : 0;
+        }
+        else
+            ySrcAdjusted = height - heightSrc - ySrc;
+
         hBitmap = GetCurrentObject(hdc, OBJ_BITMAP);
 
         if (xDst == 0 && yDst == 0 && xSrc == 0 && ySrc == 0 &&
@@ -286,8 +297,13 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT 
widthDst,
                  * ericP (2000/09/09)
                  */
 
+                /* This might not work for values of "dwRop" much different 
than "SRCCOPY".
+                 * Further testing is required.
+                 * mkosch (2008/09/22)
+                 */
+
                 /* copy existing bitmap from destination dc */
-                StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc,
+                StretchBlt( hdcMem, xSrc, ySrcAdjusted,
                             widthSrc, heightSrc, hdc, xDst, yDst, widthDst, 
heightDst,
                             dwRop );
             }
@@ -297,7 +313,7 @@ INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT 
widthDst,
             /* Origin for DIBitmap may be bottom left (positive biHeight) or 
top
                left (negative biHeight) */
             if (ret) StretchBlt( hdc, xDst, yDst, widthDst, heightDst,
-                                 hdcMem, xSrc, abs(height) - heightSrc - ySrc,
+                                 hdcMem, xSrc, ySrcAdjusted,
                                  widthSrc, heightSrc, dwRop );
             if(hpal)
                 SelectPalette(hdcMem, hpal, FALSE);
diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in
index 866615c..86c931b 100644
--- a/dlls/gdi32/tests/Makefile.in
+++ b/dlls/gdi32/tests/Makefile.in
@@ -10,6 +10,7 @@ CTESTS = \
        brush.c \
        clipping.c \
        dc.c \
+       dib.c \
        font.c \
        gdiobj.c \
        generated.c \
diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c
new file mode 100644
index 0000000..130bf23
--- /dev/null
+++ b/dlls/gdi32/tests/dib.c
@@ -0,0 +1,238 @@
+/*
+ * Unit tests for dib functions
+ *
+ * Copyright (c) 2008 Mathias Kosch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+
+#include "wine/test.h"
+
+
+static void test_StretchDIBits_internal(int xSrc, int ySrc,
+        int xDest, int yDest, int nWidth, int nHeight, BOOL bTopDown)
+{
+    BOOL bMatching;
+    int x, y, nResult;
+    int nBitmapWidth, nBitmapHeight, nNewBitmapWidth, nNewBitmapHeight;
+    ULONG i, nSize;
+    RGBTRIPLE *pBitmapData, *pNewBitmapData, *pStartLine, *pNewStartLine;
+    BITMAPINFO bmi, bmiNew;
+    HANDLE hProcessHeap;
+    HDC hDC, hMemDC;
+    HBITMAP hBitmap, hOldBitmap;
+
+
+    hProcessHeap = GetProcessHeap();
+    assert(hProcessHeap != NULL);
+
+    /* Compute bitmap widths and heights. The should be multiples of 4. */
+    nBitmapWidth = ((nWidth+xSrc+37) | 3)+1;
+    nBitmapHeight = ((nHeight+ySrc+43) | 3)+1;
+    nNewBitmapWidth = ((nWidth+xDest+103) | 3)+1;
+    nNewBitmapHeight = ((nHeight+yDest+57) | 3)+1;
+
+    /* Creating bitmap structure for bitmap: */
+    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmi.bmiHeader.biWidth = nBitmapWidth;
+    bmi.bmiHeader.biHeight = nBitmapHeight;
+    bmi.bmiHeader.biPlanes = 1;
+    bmi.bmiHeader.biBitCount = 24;
+    bmi.bmiHeader.biCompression = BI_RGB;
+    bmi.bmiHeader.biSizeImage = 0;
+    bmi.bmiHeader.biXPelsPerMeter = 0;
+    bmi.bmiHeader.biYPelsPerMeter = 0;
+    bmi.bmiHeader.biClrUsed = 0;
+    bmi.bmiHeader.biClrImportant = 0;
+    if (bTopDown)
+        bmi.bmiHeader.biHeight = -bmi.bmiHeader.biHeight;
+
+    /* Creating bitmap structure for new bitmap: */
+    bmiNew.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmiNew.bmiHeader.biWidth = nNewBitmapWidth;
+    bmiNew.bmiHeader.biHeight = nNewBitmapHeight;
+    bmiNew.bmiHeader.biPlanes = 1;
+    bmiNew.bmiHeader.biBitCount = 24;
+    bmiNew.bmiHeader.biCompression = BI_RGB;
+    bmiNew.bmiHeader.biSizeImage = 0;
+    bmiNew.bmiHeader.biXPelsPerMeter = 0;
+    bmiNew.bmiHeader.biYPelsPerMeter = 0;
+    bmiNew.bmiHeader.biClrUsed = 0;
+    bmiNew.bmiHeader.biClrImportant = 0;
+    if (bTopDown)
+        bmiNew.bmiHeader.biHeight = -bmiNew.bmiHeader.biHeight;
+
+    /* Creating device context. */
+    hDC = GetDC(NULL);
+    assert(hDC != NULL);
+    hMemDC = CreateCompatibleDC(hDC);
+    assert(hMemDC != NULL);
+    hBitmap = CreateCompatibleBitmap(hDC, nNewBitmapWidth, nNewBitmapHeight);
+    assert(hBitmap != NULL);
+    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
+    assert(hOldBitmap != NULL);
+
+    /* Allocating storage for bitmap data */
+    pBitmapData = (RGBTRIPLE*)HeapAlloc(hProcessHeap, 0,
+            nBitmapWidth*nBitmapHeight*sizeof(RGBTRIPLE));
+    assert(pBitmapData != NULL);
+    pNewBitmapData = (RGBTRIPLE*)HeapAlloc(hProcessHeap, 0,
+            nNewBitmapWidth*nNewBitmapHeight*sizeof(RGBTRIPLE));
+    assert(pNewBitmapData != NULL);
+
+    /* Initializing bitmap with random color data: */
+    nSize = nBitmapWidth*nBitmapHeight;
+    for (i = 0; i < nSize; i++)
+    {
+        pBitmapData[i].rgbtBlue = rand();
+        pBitmapData[i].rgbtGreen = rand();
+        pBitmapData[i].rgbtRed = rand();
+    }
+
+    /* Drawing bitmap data as "bottom up" bitmap into first dc: */
+    nResult = StretchDIBits(hMemDC, xDest, yDest, nWidth, nHeight, xSrc, ySrc,
+            nWidth, nHeight, pBitmapData, &bmi, DIB_RGB_COLORS, SRCCOPY);
+    assert(nResult != 0);
+
+    /* Retrieving bitmap data: */
+    nResult = GetDIBits(hMemDC, hBitmap, 0, nNewBitmapHeight, pNewBitmapData,
+            &bmiNew, DIB_RGB_COLORS);
+    assert(nResult != 0);
+
+    /* Computing starting lines for comparision. "StretchDIBits"
+       seems to behave odd in case "xSrc" an "ySrc" is 0. */
+    if (bTopDown)
+    {
+        pStartLine = pBitmapData;
+        if ((xSrc) || (ySrc))
+            pStartLine += (nBitmapHeight-nHeight-ySrc)*nBitmapWidth;
+        pNewStartLine = pNewBitmapData + yDest*nNewBitmapWidth;
+    }
+    else
+    {
+        pStartLine = pBitmapData + (nHeight+ySrc-1)*nBitmapWidth;
+        pNewStartLine = pNewBitmapData +
+                (nNewBitmapHeight-yDest-1)*nNewBitmapWidth;
+    }
+
+    /* Comparing bitmap data with supposed data. */
+    bMatching = TRUE;
+    for (y = 0; y < nHeight; y++)
+    {
+        for (x = 0; x < nWidth; x++)
+        {
+            if ((pStartLine[x+xSrc].rgbtBlue != 
pNewStartLine[x+xDest].rgbtBlue) ||
+                    (pStartLine[x+xSrc].rgbtGreen != 
pNewStartLine[x+xDest].rgbtGreen) ||
+                    (pStartLine[x+xSrc].rgbtRed != 
pNewStartLine[x+xDest].rgbtRed))
+            {
+                bMatching = FALSE;
+                break;
+            }
+        }
+
+        if (bTopDown)
+        {
+            pStartLine += nBitmapWidth;
+            pNewStartLine += nNewBitmapWidth;
+        }
+        else
+        {
+            pStartLine -= nBitmapWidth;
+            pNewStartLine -= nNewBitmapWidth;
+        }
+    }
+
+    ok(bMatching != FALSE, "Bitmap data not matching. [bTopDown=%s,"
+            " StretchDIBits(hMemDC, %d, %d, %d, %d, %d, %d, %d, %d,"
+            " pBitmapData, &bmi, DIB_RGB_COLORS, SRCCOPY)]\n",
+            (bTopDown) ? "true" : "false",
+            xDest, yDest, nWidth, nHeight, xSrc, ySrc, nWidth, nHeight);
+
+    SelectObject(hMemDC, hOldBitmap);
+    DeleteObject(hBitmap);
+    DeleteDC(hMemDC);
+    HeapFree(hProcessHeap, 0, pNewBitmapData);
+    HeapFree(hProcessHeap, 0, pBitmapData);
+}
+
+
+static void test_StretchDIBits()
+{
+    test_StretchDIBits_internal(33, 61, 103, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 61, 103, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 61, 103, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 61, 103, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 0, 103, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 0, 103, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 0, 103, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 0, 103, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 61, 0, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 61, 0, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 61, 0, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 61, 0, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 0, 0, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 0, 0, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 0, 0, 227, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 0, 0, 227, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 61, 103, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 61, 103, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 61, 103, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 61, 103, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 0, 103, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 0, 103, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 0, 103, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 0, 103, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 61, 0, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 61, 0, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 61, 0, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(0, 61, 0, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(33, 0, 0, 0, 663, 459, FALSE);
+    test_StretchDIBits_internal(33, 0, 0, 0, 663, 459, TRUE);
+
+    test_StretchDIBits_internal(0, 0, 0, 0, 663, 459, FALSE);
+    test_Str


Reply via email to