PATCH: PatBlt() with negative width or height draws in wrong place

Adam Gundy arg at cyberscience.com
Wed Mar 5 08:50:24 CST 2003


Hi. PatBlt() seems to behave differently with negative widths and height
to StretchBlt() - it does not invert the pattern etc. This caused 'lines'
drawn so that their ends touched (and appeared to be a single line) to have
gaps in them. Fixing this to behave like 'real' Windows caused the drawing
of window borders to break - they were (incorrectly) being drawn with negative 
widths and heights.

Cyberscience disclaims all copyright and responsibility... ;-)

Changelog:

        * graphics/x11drv/bitblt.c: Adam Gundy <arg at cyberscience.com>
        BITBLT_InternalStretchBlt() was adding 1 to the source or
        destination if the widths or heights were negative.
        This doesn't seem to match the way Windows behaves for operations
        without a source - it appears to re-order the points so that the
        width/height are positive. Code in graphics.c already does this
        re-ordering. Fixing this shows up a problem in window border drawing
        (see changelog entry for windows/nonclient.c below).

        * windows/nonclient.c: Adam Gundy <arg at cyberscience.com>
        NC_DrawFrame95() was passing negative widths and heights
        to PatBlt() for the right and bottom edges of the frame,
        causing them to draw in the wrong place. This was masked by
        the above bug in the X11 driver.

diff -u -r wine-20030219/graphics/x11drv/bitblt.c wine-20030219-new/graphics/x11drv/bitblt.c
--- wine-20030219/graphics/x11drv/bitblt.c      Thu Jan  9 05:59:47 2003
+++ wine-20030219-new/graphics/x11drv/bitblt.c  Wed Mar  5 14:42:34 2003
@@ -1228,16 +1228,6 @@
     DC *dcSrc = physDevSrc ? physDevSrc->dc : NULL;
     DC *dcDst = physDevDst->dc;
 
-    /* compensate for off-by-one shifting for negative widths and heights */
-    if (widthDst < 0)
-        ++xDst;
-    if (heightDst < 0)
-        ++yDst;
-    if (widthSrc < 0)
-        ++xSrc;
-    if (heightSrc < 0)
-        ++ySrc;
-
     usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
     useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
     useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
@@ -1245,11 +1235,36 @@
 
       /* Map the coordinates to device coords */
 
+    if ( useSrc )
+    {
+        /* compensate for off-by-one shifting for negative widths and heights */
+        if (widthDst < 0)
+            ++xDst;
+        if (heightDst < 0)
+            ++yDst;
+        if (widthSrc < 0)
+            ++xSrc;
+        if (heightSrc < 0)
+            ++ySrc;
+    }
+
     pts[0].x = xDst;
     pts[0].y = yDst;
     pts[1].x = xDst + widthDst;
     pts[1].y = yDst + heightDst;
     LPtoDP(physDevDst->hdc, pts, 2);
+
+    if ((pts[0].x == pts[1].x) || (pts[0].y == pts[1].y)) return TRUE;
+
+    if ( !useSrc )
+    {
+        /* OPs without a source use absolute width and height - make
+         * sure the width and height are positive
+         */
+        if (pts[1].x < pts[0].x) { INT tmp = pts[1].x; pts[1].x = pts[0].x; pts[0].x = tmp; }
+        if (pts[1].y < pts[0].y) { INT tmp = pts[1].y; pts[1].y = pts[0].y; pts[0].y = tmp; }
+    }
+
     xDst      = pts[0].x;
     yDst      = pts[0].y;
     widthDst  = pts[1].x - pts[0].x;
@@ -1271,6 +1286,7 @@
         pts[1].x = xSrc + widthSrc;
         pts[1].y = ySrc + heightSrc;
         LPtoDP(physDevSrc->hdc, pts, 2);
+
         xSrc      = pts[0].x;
         ySrc      = pts[0].y;
         widthSrc  = pts[1].x - pts[0].x;
diff -u -r wine-20030219/windows/nonclient.c wine-20030219-new/windows/nonclient.c
--- wine-20030219/windows/nonclient.c   Tue Feb 18 23:24:57 2003
+++ wine-20030219-new/windows/nonclient.c       Wed Mar  5 10:30:27 2003
@@ -1188,9 +1188,9 @@
         PatBlt( hdc, rect->left, rect->top,
                   width, rect->bottom - rect->top, PATCOPY );
         PatBlt( hdc, rect->left, rect->bottom - 1,
-                  rect->right - rect->left, -height, PATCOPY );
+                  rect->right - rect->left, height, PATCOPY );
         PatBlt( hdc, rect->right - 1, rect->top,
-                  -width, rect->bottom - rect->top, PATCOPY );
+                  width, rect->bottom - rect->top, PATCOPY );
 
         InflateRect( rect, -width, -height );
     }
@@ -1219,9 +1219,9 @@
         PatBlt( hdc, rect->left, rect->top,
                   width, rect->bottom - rect->top, PATCOPY );
         PatBlt( hdc, rect->left, rect->bottom - 1,
-                  rect->right - rect->left, -height, PATCOPY );
+                  rect->right - rect->left, height, PATCOPY );
         PatBlt( hdc, rect->right - 1, rect->top,
-                  -width, rect->bottom - rect->top, PATCOPY );
+                  width, rect->bottom - rect->top, PATCOPY );
 
         InflateRect( rect, -width, -height );
     }


Seeya,
 Adam
--
Real Programmers don't comment their code. If it was hard to write,
it should be hard to read, and even harder to modify.
These are all my own opinions.




More information about the wine-patches mailing list