app-emulation/wine: add direct draw hack and the dib engine

git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/linamh@1438 6952d904-891a-0410-993b-d76249ca496b
This commit is contained in:
geos_one 2009-08-01 09:30:00 +00:00
parent 1b2a80cabc
commit 23245f3322
15 changed files with 19955 additions and 2 deletions

View File

@ -2,6 +2,20 @@
# Copyright 1999-2009 Gentoo Foundation; Distributed under the GPL v2
# $Header: /var/cvsroot/gentoo-x86/app-emulation/wine/ChangeLog,v 1.268 2009/07/18 22:15:36 vapier Exp $
01 Aug 2009; Mario Fetka <mario.fetka@gmail.com>
+files/0001-dib-engine-hook-the-engine-bet.patch,
+files/0002-dib-engine-initial-pass-throug.patch,
+files/0003-dib-engine-fork-ddb-dib-behavi.patch, wine-1.1.26.ebuild,
+files/0004-dib-engine-implement-most-engi.patch,
+files/0005-dib-engine-implement-alphablen.patch,
+files/0006-dib-engine-add-clipping-on-xxx.patch,
+files/0007-dib-engine-implement-polygon.patch,
+files/0008-dib-engine-fixes-clipping-text.patch,
+files/0010-dib-engine-introduction-of-bit.patch,
+files/ddraw-1.1.24.diff,
+files/0009-dib-engine-fixes-against-wine-.patch, +files/hack.reg:
add direct draw hack and the dib engine
*wine-1.1.26 (18 Jul 2009)
18 Jul 2009; Mike Frysinger <vapier@gentoo.org> +wine-1.1.26.ebuild:

View File

@ -1,10 +1,22 @@
AUX 0001-dib-engine-hook-the-engine-bet.patch 5834 RMD160 706331c400aee2ed871101ab8b2718eba776fd29 SHA1 911ccd084668c992cd82c05ec54336330107c442 SHA256 9e624da5f55eb5c0f38868144dfe29f25defab101e5ad9c843bce0c54d98b38b
AUX 0002-dib-engine-initial-pass-throug.patch 58751 RMD160 6a9ffead85fc07222fc1b4f605177e8b5f11dfa4 SHA1 76a29e7f83afea41e28fff0764be0ff44f966065 SHA256 2049b7358d7fe8274d0ffc4248d49a90e7b5f909316a2765f8ce7cd809b38c27
AUX 0003-dib-engine-fork-ddb-dib-behavi.patch 71105 RMD160 240d9f7343f1d44cad683f523e7bc0b039da5c21 SHA1 6f2112e267e88d5f85fa1f48b1566edc424b03ce SHA256 0b9f9301165d6b2de352f9f24b512daef0a9f696561dbde91e11286b17f477b1
AUX 0004-dib-engine-implement-most-engi.patch 321458 RMD160 e8c19b55863eaff1325a3d468a7da7becacdfb19 SHA1 0c383eb74db081b09b7f2b4c6b432fce5f7dc850 SHA256 0de2d30595e71691b8b84df418a0f7102735defc5ebdfc52cc2db70a6b4b5c21
AUX 0005-dib-engine-implement-alphablen.patch 19263 RMD160 ab524654fbb2f1c449fc6d55ce94c59362822687 SHA1 d56d5ba2d2bb11296aba5e9c8c77ba8d30dd011c SHA256 50861a914db94eb00de2e202da22ea3e07ba612cf17856494c83251266fb7a16
AUX 0006-dib-engine-add-clipping-on-xxx.patch 21707 RMD160 dc04ac758bb8aaa33e823caf7201cada242b06d6 SHA1 02905f3913a8f6c28848cffe6fe896d5eac8e8bc SHA256 c2f98915b8f6e7c76ee1bce78b1179a1311925ffc3adcc0a3e9f2559d5cff00d
AUX 0007-dib-engine-implement-polygon.patch 13978 RMD160 8e030449a13a13206d9aacf0504d9e5b33830c18 SHA1 e72837cf2b8e964e67a40a8e35545d64d916b00e SHA256 9d517ce464b78350c9b6654cdb216b7f4ce7e895b6200ea3fef86176261d99f7
AUX 0008-dib-engine-fixes-clipping-text.patch 68553 RMD160 ac63728c2655b676c2fa5fb0eea3e02af07913a5 SHA1 69c4f4c4197102fd9c1e0f4c288b46124a7c1f34 SHA256 08b64f3679538ded626f5cafe0090a64936572bac3480497331ed2d124fe7abb
AUX 0009-dib-engine-fixes-against-wine-.patch 66734 RMD160 3008c58918e4412b87b2608d22e71ad4a6d52283 SHA1 399f3624a59d88ca847d09f68030d9f240d0014e SHA256 2345e604481c0781b61618656f3e5ee2c9efd16671a207dad5e4913a621705a1
AUX 0010-dib-engine-introduction-of-bit.patch 86639 RMD160 4df26b6b2c51b79f3d4a1d3d1dddac51d298e825 SHA1 f347761b2c64d67ff98d2407408673cc30cf760d SHA256 2fb6b2fceab6a2d383e992831f0323dbdec537231b744f457c90f396fbb7c6dd
AUX acceptex.patch 46857 RMD160 154c2f6ea1c32de52e99d640322d17512aad816a SHA1 49878e892c72c19f9ca12fd9c416dff9f23a235c SHA256 ccbd476a97b7c74956fe906723f029f0c3078768f434680869508dc6107bf31c
AUX ddraw-1.1.24.diff 1781 RMD160 ff268de228a0d9ede41e7e3c2ee6c3a0669e9b16 SHA1 8a00fe11adef8252bb94e689b63066754566dc6b SHA256 e7e66970a91dee220c598320fb838a62e4ef171c7454db7a26fc5b948e9c8c1d
AUX dinput.patch 3094 RMD160 05c8550c4a75a77dd4674635a29503c059f0b0fd SHA1 04570397eb182d68fc18b0badca5f9d52977c7df SHA256 b75c2b3e7db47d7221b2fc6065f4fb37807b9a8acf0903519e21d5ec1e1325f6
AUX hack.reg 87 RMD160 6240dce28bb01a7863e366bbb94be513480d34c2 SHA1 079a5bb9d8f71ad02cb9798fb1fd739ad80a95a6 SHA256 a5e6f4cf2ed92718d347c343762a9051dfabb0ca77c7f168ef67a7f65720ea6f
AUX revert-ntdll.patch 686 RMD160 ee2ebf8e0af7b7310e70b1f3652ad40f6576232e SHA1 7ba005f9bc22702e5461e22f6a4dc6a032237af1 SHA256 ceeb1e503e8cbe9804b31478997061ba54c77b4966e6407fcc9a49ada49616e8
AUX schannel.patch 4761 RMD160 191ef5eb1156262fd0bb3092a9214cb3ed04f548 SHA1 01adfd89c1fd7de75651fb7051ff79d10167d64d SHA256 41d1a34b69d6d1cdff80ab8e7e267385de3334af0fbff84393bc827a56ba632a
AUX wine-1.1.15-winegcc.patch 1550 RMD160 086fbdd7dbe5da98c3457f00cb30705150d58b1f SHA1 0aa5a9d0947e15af9fe103797a0c993cbb3eedab SHA256 fcf4a0578774d817b8de094abae85e370683a77805a59efe6c5f7b8b87935de9
DIST wine-1.1.26.tar.bz2 15666433 RMD160 7949d7abbb62ee1db23940e348a5f9dc4a74fd4d SHA1 d39314e002c540d1852d10124473513cfb857dfd SHA256 0285b346ca7af8def0773cece1e9b01f47e7340577d6c780cd38863c948a1f5a
DIST wine_gecko-0.9.1.cab 7806837 RMD160 8b16a4d065cd28d87a2e226400fa0a3ed600c2f1 SHA1 9a49fc691740596517e381b47096a4bdf19a87d8 SHA256 76345852b844c4b624a1beaf3f47f261ad956dbee97316ea26b3c587b363be84
EBUILD wine-1.1.26.ebuild 3590 RMD160 ab167fad7e4629dd5ba9eef16083070a977d2824 SHA1 60e31508a7e915064e3ce4270b084a4ae24be52e SHA256 df22d1d1c91fc5a200f1795b0eb607a0a72e9d141d7f26fde64b12b7af170e8e
MISC ChangeLog 46467 RMD160 898b3d7fa7f8d8e0f9268e3598112fbc21aacb97 SHA1 71a2cf14877b6713dfdcfe02fdf17c14a0b7049d SHA256 eafa6ca2d3d5c67dfbfc3f55dc6742a89ee853a1ccf51b4afbbe8ae008309940
EBUILD wine-1.1.26.ebuild 4268 RMD160 30e744d30dfb9d7e757cd1a8e870d825a3d8bb53 SHA1 9113a7324de4ae47d4daedd7d394f0cbc9fe13d4 SHA256 e4306e6d3f218e8f4c6ffea95b85b6c5113cefb4b46fa52cf46775096e5177a3
MISC ChangeLog 47144 RMD160 15a460c2eba5dc09d41d03ad653cb480794e9954 SHA1 d658603ffa767fec71df7e1816333416c38e0b25 SHA256 74be5474c9665e0655238603b8f4261bb5978d91af91a07e65e93dd19493a842
MISC metadata.xml 1123 RMD160 168b7d83724ac65a23a10ad8bbe04d4dee180f6f SHA1 f8bb8f4eb1e4dab230f9f8d8b87fe04c6e638334 SHA256 eeee6aabb900286b05e81427597d143fb5fe74cc9b503d58464abd2534eaa569

View File

@ -0,0 +1,185 @@
DIB Engine: Hook the engine between GDI32 and Display driver
From: Massimo Del Fedele <max@veneto.com>
---
dlls/gdi32/driver.c | 139 +++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 123 insertions(+), 16 deletions(-)
diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c
index 20d3f36..95a69c7 100644
--- a/dlls/gdi32/driver.c
+++ b/dlls/gdi32/driver.c
@@ -3,6 +3,7 @@
*
* Copyright 1994 Bob Amstadt
* Copyright 1996, 2001 Alexandre Julliard
+ * Copyright 2009 Massimo Del Fedele
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -25,6 +26,7 @@
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
@@ -220,6 +222,104 @@ static struct graphics_driver *create_driver( HMODULE module )
/**********************************************************************
+ * Load_Dib_Driver
+ *
+ * Check if we want the DIB engine and try to load it
+ */
+static HMODULE Load_Dib_Driver(void)
+{
+ HMODULE module;
+
+ static const char *winedib_drv = "winedib.drv";
+
+ /* we do want use DIB Engine ? */
+ BOOL driverRequired = TRUE;
+
+ /* already checked env/registry for DIB driver ? */
+ BOOL envChecked = FALSE;
+
+ char *winedib;
+ char buffer[10];
+
+ /* environment variable WINEDIB takes precedence */
+ if( (winedib = getenv("WINEDIB")) != NULL)
+ {
+ if(!strcasecmp(winedib, "ON") ||
+ !strcasecmp(winedib, "TRUE") ||
+ !strcasecmp(winedib, "ENABLE") ||
+ !strcasecmp(winedib, "ENABLED")
+ )
+ {
+ TRACE("DIB Engine enabled by environment\n");
+ envChecked = TRUE;
+ driverRequired = TRUE;
+ }
+ else if(!strcasecmp(winedib, "OFF") ||
+ !strcasecmp(winedib, "FALSE") ||
+ !strcasecmp(winedib, "DISABLE") ||
+ !strcasecmp(winedib, "DISABLED")
+ )
+ {
+ TRACE("DIB Engine disabled by environment\n");
+ envChecked = TRUE;
+ driverRequired = FALSE;
+ }
+ else
+ ERR("Bad WINEDIB environment variable\n");
+ }
+
+ /* no WINEDIB environment var found or wrong value, we check registry */
+ if(!envChecked)
+ {
+ HKEY hkey;
+ buffer[0] = 0;
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\DIB Engine", &hkey ))
+ {
+ DWORD type, count = sizeof(buffer);
+ RegQueryValueExA( hkey, "Enable", 0, &type, (LPBYTE) buffer, &count );
+ RegCloseKey( hkey );
+ }
+ if(*buffer)
+ {
+ /* registry value found, must be Y or y to enable driver, N or n to disable */
+ if(!strncasecmp(buffer, "Y", 1))
+ {
+ TRACE("DIB Engine enabled by registry\n");
+ envChecked = TRUE;
+ driverRequired = TRUE;
+ }
+ else if(!strncasecmp(buffer, "N", 1))
+ {
+ TRACE("DIB Engine disabled by registry\n");
+ envChecked = TRUE;
+ driverRequired = FALSE;
+ }
+ }
+ }
+
+ /* none of above, we assume we don't want to use engine */
+ if(!envChecked)
+ {
+ TRACE("DIB Engine disabled by default\n");
+ envChecked = TRUE;
+ driverRequired = FALSE;
+ }
+
+ /* if DIB Engine is required, try to load it
+ * otherwise just return NULL module */
+ if(driverRequired)
+ {
+ if( (module = LoadLibraryA( winedib_drv )) != 0)
+ TRACE("Succesfully loaded DIB Engine\n");
+ else
+ ERR("Couldn't load DIB Engine\n");
+ return module;
+ }
+ else
+ return 0;
+}
+
+/**********************************************************************
* load_display_driver
*
* Special case for loading the display driver: get the name from the config file
@@ -235,25 +335,32 @@ static struct graphics_driver *load_display_driver(void)
display_driver->count++;
return display_driver;
}
-
- strcpy( buffer, "x11" ); /* default value */
- /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
- if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
+
+ /* check at first if DIB engine is present and if we want
+ * to use it */
+ if( (module = Load_Dib_Driver()) == 0)
{
- DWORD type, count = sizeof(buffer);
- RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
- RegCloseKey( hkey );
- }
+ /* no DIB Engine loaded, just load normal display driver */
+
+ strcpy( buffer, "x11" ); /* default value */
+ /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
+ {
+ DWORD type, count = sizeof(buffer);
+ RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
+ RegCloseKey( hkey );
+ }
- name = buffer;
- while (name)
- {
- next = strchr( name, ',' );
- if (next) *next++ = 0;
+ name = buffer;
+ while (name)
+ {
+ next = strchr( name, ',' );
+ if (next) *next++ = 0;
- snprintf( libname, sizeof(libname), "wine%s.drv", name );
- if ((module = LoadLibraryA( libname )) != 0) break;
- name = next;
+ snprintf( libname, sizeof(libname), "wine%s.drv", name );
+ if ((module = LoadLibraryA( libname )) != 0) break;
+ name = next;
+ }
}
if (!(display_driver = create_driver( module )))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,512 @@
DIB Engine: implement AlphaBlend
From: Massimo Del Fedele <max@veneto.com>
---
dlls/winedib.drv/bitblt.c | 88 ++++++++--
dlls/winedib.drv/dibdrv.h | 2
dlls/winedib.drv/primitives.c | 12 +
dlls/winedib.drv/primitives_bitblt.c | 287 ++++++++++++++++++++++++++++++++++
4 files changed, 370 insertions(+), 19 deletions(-)
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index 20cdcaa..c0227a0 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -150,34 +150,84 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
xDst, yDst, widthDst, heightDst,
physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
xSrc, ySrc, widthSrc, heightSrc));
+
- if(physDevDst->hasDIB && physDevSrc->hasDIB)
+ /* if sizes are null or negative, returns false */
+ if(widthSrc <= 0 || heightSrc <= 0 || widthDst <= 0 || heightDst <= 0)
{
- /* DIB section selected in both source and dest DC, use DIB Engine */
- ONCE(FIXME("STUB\n"));
- res = TRUE;
+ res = FALSE;
+ goto fin;
}
- else if(!physDevDst->hasDIB && !physDevSrc->hasDIB)
+
+ /* source sould be a 32 bit DIB */
+ if(!physDevSrc)
{
- /* DDB selected in noth source and dest DC, use X11 driver */
- res = _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
- physDevSrc->X11PhysDev, xSrc, ySrc, widthSrc, heightSrc,
- blendfn);
+ FIXME("Null source bitmap -- shouldn't happen\n");
+ res = FALSE;
+ goto fin;
}
- else if(physDevSrc->hasDIB)
+ else if(!physDevSrc->hasDIB)
{
- /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
- ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
- res = _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
- physDevSrc->X11PhysDev, xSrc, ySrc, widthSrc, heightSrc,
- blendfn);
+ FIXME("DDB source bitmap -- shouldn't happen\n");
+ res = FALSE;
+ goto fin;
}
- else /* if(physDevDst->hasDIB) */
+
+ if(physDevDst->hasDIB)
{
- /* DDB on source, DIB on dest -- must convert source DDB to DIB and use the engine for blit */
- ONCE(FIXME("STUB\n"));
- res = TRUE;
+ /* DIB section selected in dest DC, use DIB Engine */
+ MAYBE(TRACE("Blending DIB->DIB\n"));
+ res = physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
+ physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
+ }
+ else
+ {
+ /* DDB selected on dest DC -- must double-convert */
+ HBITMAP tmpDIB, stock;
+ HDC tmpDC;
+ MAYBE(TRACE("Blending DIB->DDB\n"));
+
+ /* converts dest DDB onto a temporary DIB -- just the needed part */
+ tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst);
+ if(!tmpDIB)
+ {
+ ERR("Couldn't convert dest DDB to DIB\n");
+ res = FALSE;
+ goto fin;
+ }
+
+ /* selects the temporary DIB into a temporary DC */
+ tmpDC = CreateCompatibleDC(physDevDst->hdc);
+ if(!tmpDC)
+ {
+ ERR("Couldn't create temporary DC\n");
+ DeleteObject(tmpDIB);
+ res = FALSE;
+ goto fin;
+ }
+ stock = SelectObject(tmpDC, tmpDIB);
+ if(!stock)
+ {
+ ERR("Couldn't select temporary DIB into temporary DC\n");
+ DeleteDC(tmpDC);
+ DeleteObject(tmpDIB);
+ res = FALSE;
+ goto fin;
+ }
+
+ /* blends source DIB onto temp DIB and re-blits onto dest DC */
+ res = GdiAlphaBlend(tmpDC, 0, 0, widthDst, heightDst, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
+ if(!res)
+ MAYBE(TRACE("AlphaBlend failed\n"));
+ else
+ res = BitBlt(physDevDst->hdc, xDst, yDst, widthDst, heightDst, tmpDC, 0, 0, SRCCOPY);
+
+ /* frees resources */
+ SelectObject(tmpDC, stock);
+ DeleteDC(tmpDC);
+ DeleteObject(tmpDIB);
}
+fin:
return res;
}
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index 773941e..c801d96 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -94,6 +94,8 @@ typedef struct _DIBDRV_PRIMITIVE_FUNCS
BOOL (* PutLine) ( struct _DIBDRVBITMAP *bmp, int line, int startx, int width, void *buf);
/* BitBlt primitives */
+ BOOL (* AlphaBlend) ( struct _DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, int widthDst, int heightDst,
+ const struct _DIBDRVPHYSDEV *physDevSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFn );
BOOL (* BitBlt) ( struct _DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, int width, int height,
const struct _DIBDRVPHYSDEV *physDevSrc, int xSrc, int ySrc, DWORD rop );
BOOL (* StretchBlt) ( struct _DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, int widthDst, int heightDst,
diff --git a/dlls/winedib.drv/primitives.c b/dlls/winedib.drv/primitives.c
index cbad239..a2fa04a 100644
--- a/dlls/winedib.drv/primitives.c
+++ b/dlls/winedib.drv/primitives.c
@@ -133,6 +133,10 @@ BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
INT widthDst, INT heightDst, const DIBDRVPHYSDEV *physDevSrc,
INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop);
+BOOL _DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV *physDevDst, int xDst, int yDst,
+ int widthDst, int heightDst, const DIBDRVPHYSDEV *physDevSrc,
+ int xSrc, int ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFn );
+
/* ------------------------------------------------------------*/
/* FREETYPE FONT BITMAP BLITTING */
void _DIBDRV_freetype_blit_8888 (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
@@ -156,6 +160,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_RGB =
_DIBDRV_SolidVLine32,
_DIBDRV_GetLine32_RGB,
_DIBDRV_PutLine32_RGB,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_32_RGB
@@ -172,6 +177,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_BITFIELDS =
_DIBDRV_SolidVLine32,
_DIBDRV_GetLine32_BITFIELDS,
_DIBDRV_PutLine32_BITFIELDS,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_32_BITFIELDS
@@ -188,6 +194,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB24 =
_DIBDRV_SolidVLine24,
_DIBDRV_GetLine24,
_DIBDRV_PutLine24,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_24
@@ -204,6 +211,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_RGB =
_DIBDRV_SolidVLine16,
_DIBDRV_GetLine16_RGB,
_DIBDRV_PutLine16_RGB,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_16_RGB
@@ -220,6 +228,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_BITFIELDS =
_DIBDRV_SolidVLine16,
_DIBDRV_GetLine16_BITFIELDS,
_DIBDRV_PutLine16_BITFIELDS,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_16_BITFIELDS
@@ -236,6 +245,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB8 =
_DIBDRV_SolidVLine8,
_DIBDRV_GetLine8,
_DIBDRV_PutLine8,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_8
@@ -252,6 +262,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB4 =
_DIBDRV_SolidVLine4,
_DIBDRV_GetLine4,
_DIBDRV_PutLine4,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_4
@@ -268,6 +279,7 @@ DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB1 =
_DIBDRV_SolidVLine1,
_DIBDRV_GetLine1,
_DIBDRV_PutLine1,
+ _DIBDRV_AlphaBlend_generic,
_DIBDRV_BitBlt_generic,
_DIBDRV_StretchBlt_generic,
_DIBDRV_freetype_blit_1
diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c
index da48352..7540dad 100644
--- a/dlls/winedib.drv/primitives_bitblt.c
+++ b/dlls/winedib.drv/primitives_bitblt.c
@@ -80,6 +80,293 @@ static void StretchLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth)
memcpy(dst, src, 4 * srcWidth);
}
+/* premultiply alpha channel on a line by a constant alpha
+ note : it seems that pixels are already premultiplied
+ by alpha channel content */
+static void PemultiplyLine(DWORD *dst, int width, BYTE constAlpha)
+{
+ int i = width;
+ BYTE *alphaPnt = (BYTE *)dst + 3;
+
+ /* small optimization for 0 and 255 values of constAlpha */
+
+ /* fully transparent -- just sets all pix to 0 */
+ if(constAlpha == 0)
+ {
+ while(i--)
+ *dst++ = 0;
+ return;
+ }
+
+ /* fully opaque, just do nothing */
+ if(constAlpha == 255)
+ return;
+
+ /* intermediate -- premultiply alpha values */
+ while(i--)
+ {
+ *alphaPnt = MulDiv(*alphaPnt, constAlpha, 255);
+ alphaPnt += 4;
+ }
+ return;
+
+}
+
+/* alpha blends a source line onto a destination line
+ preconditions :
+ 1) source and dest widths must be the same
+ 2) source line should be already premultiplied by constant alpha */
+static void BlendLine(DWORD *dst, DWORD *src, int width)
+{
+ int i = width;
+ BYTE *blueDst = (BYTE *)dst;
+ BYTE *greenDst = blueDst + 1;
+ BYTE *redDst = greenDst + 1;
+ BYTE *blueSrc = (BYTE *)src;
+ BYTE *greenSrc = blueSrc + 1;
+ BYTE *redSrc = greenSrc + 1;
+ BYTE *alphaSrc = redSrc + 1;
+ BYTE alpha;
+
+ /* still don't know if it must take in account an eventual dest
+ alpha channel..... */
+ while(i--)
+ {
+ alpha = 255 - *alphaSrc;
+
+ *blueDst = *blueSrc + MulDiv(*blueDst, alpha, 255);
+ *greenDst = *greenSrc + MulDiv(*greenDst, alpha, 255);
+ *redDst = *redSrc + MulDiv(*redDst, alpha, 255);
+
+ blueSrc += 4;
+ greenSrc += 4;
+ redSrc += 4;
+ alphaSrc += 4;
+ blueDst += 4;
+ greenDst += 4;
+ redDst += 4;
+ }
+
+}
+
+/* ------------------------------------------------------------*/
+/* ALPHABLEND PRIMITIVES */
+BOOL _DIBDRV_AlphaBlend_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+ INT widthDst, INT heightDst, const DIBDRVPHYSDEV *physDevSrc,
+ INT xSrc, INT ySrc, int widthSrc, int heightSrc, BLENDFUNCTION blendFn)
+{
+ /* flags indicating wether source should be stretched */
+ BOOL horStretch = (widthSrc != widthDst);
+ BOOL verStretch = (heightSrc != heightDst);
+
+ /* constant alpha value */
+ BYTE constAlpha = blendFn.SourceConstantAlpha;
+
+ /* source and dest bitmaps */
+ const DIBDRVBITMAP *srcBmp = &physDevSrc->physBitmap;
+ DIBDRVBITMAP *dstBmp = &physDevDst->physBitmap;
+
+ /* source and destination line buffers */
+ DWORD *sBuf = HeapAlloc(GetProcessHeap(), 0, abs(srcBmp->stride));
+ DWORD *dBuf = HeapAlloc(GetProcessHeap(), 0, abs(dstBmp->stride));
+
+ int ys = ySrc;
+ int yd = yDst;
+ int iLine;
+ int delta;
+
+ /* in order to optimize a bit, we divide the routine in 4 parts,
+ depending on stretching modes */
+ if(!horStretch && !verStretch)
+ {
+ /* simplest case, no stretching needed */
+ MAYBE(TRACE("No stretching\n"));
+ for(iLine = 0; iLine < heightSrc; iLine++, ys++, yd++)
+ {
+ /* load source and dest lines */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(sBuf, widthSrc, constAlpha);
+
+ /* blends source on dest */
+ BlendLine(dBuf, sBuf, widthSrc);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+ }
+ }
+ else if (horStretch && !verStretch)
+ {
+ /* just horizontal stretching needed */
+ DWORD *strBuf = HeapAlloc(GetProcessHeap(), 0, abs(dstBmp->stride));
+ MAYBE(TRACE("Horizontal stretching\n"));
+
+ for(iLine = 0; iLine < heightSrc; iLine++, ys++, yd++)
+ {
+ /* load source and dest lines */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* stretch source line to match dest one */
+ StretchLine(strBuf, widthDst, sBuf, widthSrc);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(strBuf, widthDst, constAlpha);
+
+ /* blends source on dest */
+ BlendLine(dBuf, sBuf, widthDst);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+ }
+ HeapFree(GetProcessHeap(), 0, strBuf);
+ }
+ else if (!horStretch && verStretch)
+ {
+ /* just vertical stretching needed */
+ MAYBE(TRACE("Vertical stretching\n"));
+
+ if(heightSrc > heightDst)
+ {
+ iLine = 0;
+ delta = 0;
+ while(iLine < heightDst)
+ {
+ /* load source and dest lines */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(sBuf, widthSrc, constAlpha);
+
+ /* blends source on dest */
+ BlendLine(dBuf, sBuf, widthDst);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ while(delta < heightSrc)
+ {
+ ys++;
+ delta += heightDst;
+ }
+ delta -= heightSrc;
+ yd++;
+ iLine++;
+ }
+ }
+ else if(heightSrc < heightDst)
+ {
+ iLine = 0;
+ delta = 0;
+ while(iLine < heightSrc)
+ {
+ /* load source line */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(sBuf, widthSrc, constAlpha);
+
+ while(delta < heightDst)
+ {
+ /* load dest line */
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* blends source on dest */
+ BlendLine(dBuf, sBuf, widthDst);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+ yd++;
+ delta += heightSrc;
+ }
+ delta -= heightDst;
+ ys++;
+ iLine++;
+ }
+ }
+ }
+ else
+ {
+ DWORD *strBuf = HeapAlloc(GetProcessHeap(), 0, abs(dstBmp->stride));
+ /* both stretching needed -- generic case */
+ MAYBE(TRACE("Horizontal and vertical stretching\n"));
+
+ if(heightSrc > heightDst)
+ {
+ iLine = 0;
+ delta = 0;
+ while(iLine < heightDst)
+ {
+ /* load source and dest lines */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* stretch source line to match dest one */
+ StretchLine(strBuf, widthDst, sBuf, widthSrc);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(strBuf, widthDst, constAlpha);
+
+ /* blends source on dest */
+ BlendLine(dBuf, strBuf, widthDst);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ while(delta < heightSrc)
+ {
+ ys++;
+ delta += heightDst;
+ }
+ delta -= heightSrc;
+ yd++;
+ iLine++;
+ }
+ }
+ else if(heightSrc < heightDst)
+ {
+ iLine = 0;
+ delta = 0;
+ while(iLine < heightSrc)
+ {
+ /* load source line */
+ srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBuf);
+
+ /* stretch source line to match dest one */
+ StretchLine(strBuf, widthDst, sBuf, widthSrc);
+
+ /* premultiply source by constant and pixel alpha */
+ PemultiplyLine(strBuf, widthDst, constAlpha);
+
+ while(delta < heightDst)
+ {
+ /* load dest line */
+ dstBmp->funcs->GetLine(dstBmp, yd, xDst, widthDst, dBuf);
+
+ /* blends source on dest */
+ BlendLine(dBuf, strBuf, widthDst);
+
+ /* puts dest line back */
+ dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+ yd++;
+ delta += heightSrc;
+ }
+ delta -= heightDst;
+ ys++;
+ iLine++;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, strBuf);
+ }
+
+ HeapFree(GetProcessHeap(), 0, sBuf);
+ HeapFree(GetProcessHeap(), 0, dBuf);
+ return TRUE;
+}
+
/* ------------------------------------------------------------*/
/* BLITTING PRIMITIVES */
BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,

View File

@ -0,0 +1,560 @@
DIB Engine: Add clipping on xxxBlt and AlphaBlend
From: Massimo Del Fedele <max@veneto.com>
---
dlls/winedib.drv/bitblt.c | 332 +++++++++++++++++++++++++++++++++++++------
dlls/winedib.drv/clipping.c | 42 +++++
dlls/winedib.drv/dc.c | 14 ++
dlls/winedib.drv/dibdrv.h | 6 +
4 files changed, 341 insertions(+), 53 deletions(-)
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index c0227a0..05c9392 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -33,6 +33,26 @@ static inline void intSwap(int *a, int *b)
*b = tmp;
}
+static inline void setRect(RECT *r, int x1, int y1, int x2, int y2)
+{
+ r->left = x1;
+ r->top = y1;
+ r->right = x2;
+ r->bottom = y2;
+}
+
+static inline void setPoint(POINT *p, int x, int y)
+{
+ p->x = x;
+ p->y = y;
+}
+
+static inline void setSize(SIZE *sz, int cx, int cy)
+{
+ sz->cx = cx;
+ sz->cy = cy;
+}
+
/* clips a source and destination areas to their respective clip rectangles
returning both source and dest modified; result is TRUE if clipping
leads to a non null rectangle, FALSE otherwise */
@@ -130,13 +150,158 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
leads to a non null rectangle, FALSE otherwise */
static BOOL StretchBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *szSrc, SIZE *szDst, RECT*srcClip, RECT*dstClip)
{
- ONCE(FIXME("TO DO\n"));
+ int xs1, ys1, xs2, ys2;
+ int xsc1, ysc1, xsc2, ysc2;
+ int xd1, yd1, xd2, yd2;
+ int xdc1, ydc1, xdc2, ydc2;
+ int ws, hs, wd, hd, dx, dy;
+ int mulh, divh, mulv, divv;
+
+ /* extract sizes */
+ ws = szSrc->cx; hs = szSrc->cy;
+ wd = szDst->cx; hd = szDst->cy;
+
+ /* if sizes null or negative, just return false */
+ /* FIXME : add support for mirror stretch */
+ if(ws <= 0 || hs <= 0 || wd <= 0 || hd <= 0)
+ return FALSE;
+
+ /* stores scaling factors from source rect to dest one */
+ mulh = wd; divh = ws;
+ mulv = hd; divv = hs;
+
+ /* extract dest area data */
+ xd1 = pd->x;
+ yd1 = pd->y;
+ xd2 = xd1 + wd;
+ yd2 = yd1 + hd;
+
+ /* extract source data */
+ xs1 = ps->x;
+ ys1 = ps->y;
+ xs2 = xs1 + ws;
+ ys2 = ys1 + hs;
+
+ /* if source clip area is not null, do first clipping on it */
+ if(srcClip)
+ {
+ /* extract source clipping area */
+ xsc1 = srcClip->left;
+ ysc1 = srcClip->top;
+ xsc2 = srcClip->right;
+ ysc2 = srcClip->bottom;
+
+ /* order clip area rectangle points */
+ if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
+ if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
+
+ /* clip on source clipping start point */
+ if(xs1 < xsc1) { dx = xsc1 - xs1; ws -= dx; xd1 += MulDiv(dx, mulh, divh); xs1 = xsc1; }
+ if(ys1 < ysc1) { dy = ysc1 - ys1; hs -= dy; yd1 += MulDiv(dy, mulv, divv); ys1 = ysc1; }
+
+ /* clip on source clipping end point */
+ if(xs2 > xsc2) { dx = xs2 - xsc2; ws -= dx; xd2 -= MulDiv(dx, mulh, divh); xs2 = xsc2; }
+ if(ys2 > ysc2) { dy = ys2 - ysc2; hs -= dy; yd2 -= MulDiv(dy, mulv, divv); ys2 = ysc2; }
+
+ /* if already zero area, return false */
+ if(ws <= 0 || hs <= 0)
+ return FALSE;
+ wd = xd2 - xd1;
+ hd = yd2 - yd1;
+ }
+ /* now do clipping on destination area */
+ if(dstClip)
+ {
+ /* extract destination clipping area */
+ xdc1 = dstClip->left;
+ ydc1 = dstClip->top;
+ xdc2 = dstClip->right;
+ ydc2 = dstClip->bottom;
+
+ /* order clip area rectangle points */
+ if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
+ if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
+
+ /* clip on dest clipping start point */
+ if(xd1 < xdc1) { dx = xdc1 - xd1; wd -= dx; xs1 += MulDiv(dx, divh, mulh); xd1 = xdc1; }
+ if(yd1 < ydc1) { dy = ydc1 - yd1; hd -= dy; ys1 += MulDiv(dy, divv, mulv); yd1 = ydc1; }
+
+ /* clip on dest clipping end point */
+ if(xd2 > xdc2) { dx = xd2 - xdc2; wd -= dx; xs2 -= MulDiv(dx, divh, mulh); xd2 = xdc2; }
+ if(yd2 > ydc2) { dy = yd2 - ydc2; hd -= dy; ys2 -= MulDiv(dy, divv, mulv); yd2 = ydc2; }
+
+ /* if already zero area, return false */
+ if(wd <= 0 || hd <= 0)
+ return FALSE;
+
+ ws = xs2 - xs1;
+ hs = ys2 - ys1;
+ }
+
+ /* sets clipped/translated points and sizes and returns TRUE */
+ ps->x = xs1; ps->y = ys1;
+ pd->x = xd1; pd->y = yd1;
+ szSrc->cx = ws; szSrc->cy = hs;
+ szDst->cx = wd; szDst->cy = hd;
+
return TRUE;
}
/***********************************************************************
+ * _DIBDRV_InternalAlphaBlend
+ */
+BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
+ DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
+ BLENDFUNCTION blendfn)
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE szSrc, szDst;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
+ }
+ else
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ widthDst = szDst.cx; heightDst = szDst.cy;
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, blendfn))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
* DIBDRV_AlphaBlend
*/
BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
@@ -145,6 +310,11 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
{
BOOL res;
+ POINT pd = {xDst, yDst};
+ POINT ps = {xSrc, ySrc};
+ SIZE szDst = {widthDst, heightDst};
+ SIZE szSrc = {widthSrc, heightSrc};
+
MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
xDst, yDst, widthDst, heightDst,
@@ -177,16 +347,24 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
{
/* DIB section selected in dest DC, use DIB Engine */
MAYBE(TRACE("Blending DIB->DIB\n"));
- res = physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
- physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
+ res = _DIBDRV_InternalAlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
+ physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
}
else
{
/* DDB selected on dest DC -- must double-convert */
HBITMAP tmpDIB, stock;
HDC tmpDC;
+ RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
MAYBE(TRACE("Blending DIB->DDB\n"));
+ /* clip blit area */
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
+ if(!res)
+ goto fin;
+ xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
+ xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
/* converts dest DDB onto a temporary DIB -- just the needed part */
tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst);
if(!tmpDIB)
@@ -232,8 +410,55 @@ fin:
}
/***********************************************************************
- * DIBDRV_BitBlt
+ * _DIBDRV_InternalBitBlt
*/
+BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+ INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
+ INT xSrc, INT ySrc, DWORD rop )
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE sz;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&sz, width, height);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
+ }
+ else
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ width = sz.cx; height = sz.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&sz, width, height);
+ if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
+ * DIBDRV_BitBlt */
BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
INT xSrc, INT ySrc, DWORD rop )
@@ -254,26 +479,13 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
if(physDevDst->hasDIB)
{
/* DIB section selected in dest DC, use DIB Engine */
-
/* clip blit area */
RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
if(!physDevSrc || physDevSrc->hasDIB)
{
- /* clip blit area */
- if(physDevSrc)
- {
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
- res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
- }
- else
- res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
-
/* source is null or has a DIB, no need to convert anyting */
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
}
else
{
@@ -309,8 +521,7 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
goto noBlt1;
}
SelectObject(physDevSrc->hdc, dib);
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height,
- physDevSrc, xSrc, 0, rop);
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, 0, rop);
SelectObject(physDevSrc->hdc, ddb);
DeleteObject(dib);
noBlt1:
@@ -410,6 +621,58 @@ noBlt3:
}
/***********************************************************************
+ * _DIBDRV_InternalStretchBlt
+ */
+BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+ INT widthDst, INT heightDst, DIBDRVPHYSDEV *physDevSrc,
+ INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop )
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE szSrc, szDst;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
+ }
+ else
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ widthDst = szDst.cx; heightDst = szDst.cy;
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, rop))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
* DIBDRV_StretchBlt
*/
BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
@@ -439,38 +702,15 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
{
/* DIB section selected in dest DC, use DIB Engine */
- /* clip blit area */
- RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
-
if(!physDevSrc || physDevSrc->hasDIB)
{
- /* clip blit area */
- if(physDevSrc)
- {
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
- }
- else
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
-
/* source is null or has a DIB, no need to convert anyting */
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
}
else
{
/* source is a DDB, must convert it to DIB */
- /* don't clip on source */
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
-
/* we must differentiate from 2 cases :
1) source DC is a memory DC
2) source DC is a device DC */
@@ -495,8 +735,8 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
goto noBlt1;
}
SelectObject(physDevSrc->hdc, dib);
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
- physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
+ physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
SelectObject(physDevSrc->hdc, ddb);
DeleteObject(dib);
noBlt1:
diff --git a/dlls/winedib.drv/clipping.c b/dlls/winedib.drv/clipping.c
index 81dec25..ed10b92 100644
--- a/dlls/winedib.drv/clipping.c
+++ b/dlls/winedib.drv/clipping.c
@@ -25,22 +25,50 @@
WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
-
/***********************************************************************
* DIBDRV_SetDeviceClipping
*/
void DIBDRV_SetDeviceClipping( DIBDRVPHYSDEV *physDev, HRGN vis_rgn, HRGN clip_rgn )
{
+ RGNDATA *data;
+ DWORD size;
+ int iRect;
+
MAYBE(TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn));
- if(physDev->hasDIB)
+ /* sets the region for X11 driver anyways... we may change bitmap later on */
+ _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
+
+ /* then we set the region for DIB engine, same reason */
+
+ CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY );
+
+ /* get region rectangles */
+ if(!(size = GetRegionData(physDev->region, 0, NULL)))
+ return;
+ data = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!GetRegionData(physDev->region, size, data))
{
- /* DIB section selected in, use DIB Engine */
- ONCE(FIXME("STUB\n"));
+ HeapFree( GetProcessHeap(), 0, data );
+ return;
}
- else
+
+ /* frees any previous regions rectangles in DC */
+ if(physDev->regionData)
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
+
+ /* sets the rectangles on physDev */
+ physDev->regionData = data;
+ physDev->regionRects = (RECT *)data->Buffer;
+ physDev->regionRectCount = data->rdh.nCount;
+
+ if(TRACE_ON(dibdrv))
{
- /* DDB selected in, use X11 driver */
- _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
+ TRACE("Region dump : %d rectangles\n", physDev->regionRectCount);
+ for(iRect = 0; iRect < physDev->regionRectCount; iRect++)
+ {
+ RECT *r = physDev->regionRects + iRect;
+ TRACE("Rect #%03d, x1:%4d, y1:%4d, x2:%4d, y2:%4d\n", iRect, r->left, r->top, r->right, r->bottom);
+ }
}
}
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
index 6184677..8212d42 100644
--- a/dlls/winedib.drv/dc.c
+++ b/dlls/winedib.drv/dc.c
@@ -165,6 +165,12 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
/* clears pen and brush */
physDev->rop2 = R2_COPYPEN;
+
+ /* clipping region */
+ physDev->region = CreateRectRgn( 0, 0, 0, 0 );
+ physDev->regionData = NULL;
+ physDev->regionRects = NULL;
+ physDev->regionRectCount = 0;
physDev->backgroundColor = 0;
_DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor);
@@ -228,6 +234,14 @@ BOOL DIBDRV_DeleteDC( DIBDRVPHYSDEV *physDev )
physDev->brushAnds = NULL;
physDev->brushXors = NULL;
+ /* frees clipping region */
+ DeleteObject(physDev->region);
+ if(physDev->regionData)
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
+ physDev->regionData = NULL;
+ physDev->regionRects = NULL;
+ physDev->regionRectCount = 0;
+
/* frees DIB Engine device */
HeapFree(GetProcessHeap(), 0, physDev);
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index c801d96..b0f128e 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -204,6 +204,12 @@ typedef struct _DIBDRVPHYSDEV
/* active ROP2 */
INT rop2;
+
+ /* clipping region and its rectangles */
+ HRGN region;
+ RGNDATA *regionData;
+ RECT *regionRects;
+ int regionRectCount;
/* background color and active ROP2 precalculated
AND and XOR values for it */

View File

@ -0,0 +1,463 @@
DIB Engine: Implement Polygon
From: Massimo Del Fedele <max@veneto.com>
---
dlls/winedib.drv/graphics.c | 405 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 395 insertions(+), 10 deletions(-)
diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c
index 8dda082..e416488 100644
--- a/dlls/winedib.drv/graphics.c
+++ b/dlls/winedib.drv/graphics.c
@@ -36,6 +36,281 @@ static inline void OrderInt(int *i1, int *i2)
}
}
+#define LEFT_SIDE 1
+#define TOP_SIDE 2
+#define RIGHT_SIDE 4
+#define BOTTOM_SIDE 8
+
+/* clips a line segment by a rectangular window */
+static inline BYTE outCodes(const POINT *p, const RECT *r)
+{
+ BYTE Code = 0;
+
+ if(p->y < r->top)
+ Code |= TOP_SIDE;
+ else if(p->y >= r->bottom)
+ Code |= BOTTOM_SIDE;
+ if(p->x >= r->right)
+ Code |= RIGHT_SIDE;
+ else if(p->x < r->left)
+ Code |= LEFT_SIDE;
+ return Code;
+}
+
+static BOOL ClipLine(const POINT *p1, const POINT *p2, const RECT *r, POINT *pc1, POINT *pc2)
+{
+ BYTE outCode1,outCode2;
+ int tmp;
+ BYTE tmpCode;
+
+ pc1->x = p1->x; pc1->y = p1->y;
+ pc2->x = p2->x; pc2->y = p2->y;
+ while(TRUE)
+ {
+ outCode1 = outCodes(pc1, r);
+ outCode2 = outCodes(pc2, r);
+ if(outCode1 & outCode2)
+ return FALSE;
+ if(!outCode1 && !outCode2)
+ return TRUE;
+ if(!outCode1)
+ {
+ tmp = pc1->x; pc1->x = pc2->x; pc2->x = tmp;
+ tmp = pc1->y; pc1->y = pc2->y; pc2->y = tmp;
+ tmpCode = outCode1; outCode1 = outCode2; outCode2 = tmpCode;
+ }
+ if(outCode1 & TOP_SIDE)
+ {
+ pc1->x += MulDiv(pc2->x - pc1->x, r->top - pc1->y, pc2->y - pc1->y);
+ pc1->y = r->top;
+ }
+ else if(outCode1 & BOTTOM_SIDE)
+ {
+ pc1->x += MulDiv(pc2->x - pc1->x, r->bottom - 1 - pc1->y, pc2->y - pc1->y);
+ pc1->y = r->bottom - 1;
+ }
+ else if(outCode1 & RIGHT_SIDE)
+ {
+ pc1->y += MulDiv(pc2->y - pc1->y, r->right - 1 - pc1->x, pc2->x - pc1->x);
+ pc1->x = r->right - 1;
+ }
+ else if(outCode1 & LEFT_SIDE)
+ {
+ pc1->y += MulDiv(pc2->y - pc1->y, r->left - pc1->x, pc2->x - pc1->x);
+ pc1->x = r->left;
+ }
+ }
+}
+
+/* Clips a polygon by an horizontal/vertical line
+ which indicates the side :
+*/
+static inline BOOL PointInside(const POINT *p, const RECT *r, BYTE side)
+{
+ switch(side)
+ {
+ case 1: /* left */
+ return p->x >= r->left;
+ case 2: /* top */
+ return p->y >= r->top;
+ case 4: /* right */
+ return p->x < r->right;
+ case 8: /* bottom */
+ return p->y < r->bottom;
+ default:
+ return FALSE;
+ }
+}
+
+static inline void SideIntersect(const POINT *p1, const POINT *p2, const RECT *r, BYTE side, POINT *inters)
+{
+ switch( side )
+ {
+ case LEFT_SIDE: /* left */
+ inters->x = r->left;
+ inters->y = MulDiv(p2->y - p1->y, r->left - p1->x, p2->x - p1->x) + p1->y;
+ break;
+ case TOP_SIDE: /* top */
+ inters->x = MulDiv(p2->x - p1->x, r->top - p1->y, p2->y - p1->y) + p1->x;
+ inters->y = r->bottom;
+ break;
+ case RIGHT_SIDE: /* right */
+ inters->x = r->right - 1;
+ inters->y = MulDiv(p2->y - p1->y, r->right - 1 - p1->x, p2->x - p1->x) + p1->y;
+ break;
+ case BOTTOM_SIDE: /* bottom */
+ inters->x = MulDiv(p2->x - p1->x, r->bottom - 1 - p1->y, p2->y - p1->y) + p1->x;
+ inters->y = r->bottom - 1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+static BOOL ClipPolygonBySide(const POINT *pt, int count, const RECT *r, BYTE side, POINT **clipped, int *clippedCount)
+{
+ int iPoint;
+ const POINT *p1, *p2;
+ POINT *pOut;
+
+ if(!(*clipped = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count * 2)))
+ return FALSE;
+ pOut = *clipped;
+ *clippedCount = 0;
+
+ p1 = pt + count - 1;
+ p2 = pt;
+ for(iPoint = 0 ; iPoint < count ; iPoint++)
+ {
+ if(PointInside(p2, r, side))
+ {
+ /* point p is "inside" */
+ if(!PointInside(p1, r, side))
+ {
+ /* p is "inside" and s is "outside" */
+ SideIntersect(p2, p1, r, side, pOut++);
+ (*clippedCount)++;
+ }
+ pOut->x = p2->x;
+ pOut->y = p2->y;
+ pOut++;
+ (*clippedCount)++;
+ }
+ else if(PointInside( p1, r, side ))
+ {
+ /* s is "inside" and p is "outside" */
+ SideIntersect(p1, p2, r, side, pOut++);
+ (*clippedCount)++;
+ }
+ p1 = p2++;
+ }
+ return *clippedCount;
+}
+
+
+/* Clips a polygon by a rectangular window - returns a new polygon */
+static BOOL ClipPolygon(const POINT* pt, int count, const RECT *r, POINT **newPt, int *newCount)
+{
+ POINT *pc1, *pc2;
+ int count1, count2;
+ BOOL res;
+
+ if(!ClipPolygonBySide(pt, count, r, LEFT_SIDE, &pc1, &count1))
+ return FALSE;
+ res = ClipPolygonBySide(pc1, count1, r, TOP_SIDE, &pc2, &count2);
+ HeapFree(GetProcessHeap(), 0, pc1);
+ if(!res)
+ return FALSE;
+ res = ClipPolygonBySide(pc2, count2, r, RIGHT_SIDE, &pc1, &count1);
+ HeapFree(GetProcessHeap(), 0, pc2);
+ if(!res)
+ return FALSE;
+ res = ClipPolygonBySide(pc1, count1, r, BOTTOM_SIDE, &pc2, &count2);
+ HeapFree(GetProcessHeap(), 0, pc1);
+ if(!res)
+ return FALSE;
+
+ *newPt = pc2;
+ *newCount = count2;
+ return TRUE;
+}
+
+/* Intersects a line given by 2 points with an horizontal scan line at height y */
+static BOOL ScanLine(const POINT *p1, const POINT *p2, int ys, POINT *pRes)
+{
+ if(!pRes)
+ return FALSE;
+
+ /* if line lies completely over or under scan line, no intersection */
+ if((p1->y < ys && p2->y < ys) || (p1->y > ys && p2->y > ys))
+ return FALSE;
+
+ /* if line is parallel to x axis, we consider it not intersecting */
+ if(p1->y == p2->y)
+ return FALSE;
+
+ pRes->x = MulDiv(p2->x - p1->x, ys - p1->y, p2->y - p1->y) + p1->x;
+ pRes->y = ys;
+ return TRUE;
+}
+
+/* Gets an x-ordered list of intersection points of a scanline at position y
+ with a polygon/polyline */
+static BOOL ScanPolygon(const POINT *pt, int count, int ys, POINT **scans, int *scanCount)
+{
+ const POINT *p1, *p2;
+ POINT *pDest;
+ int iPoint;
+ POINT *ps1, *ps2;
+ int i, j, tmp;
+
+ /* if not at least 2 points, nothing to return */
+ if(count < 2)
+ return FALSE;
+
+ /* intersections count is AT MOST 'count'; we don't care to
+ allocate exact memory needed */
+ *scans = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT)*count);
+ if(!*scans)
+ return FALSE;
+
+ /* builds unordered intersections */
+ pDest = *scans;
+ *scanCount = 0;
+ p2 = pt;
+ for(iPoint = 0; iPoint < count-1; iPoint++)
+ {
+ p1 = p2;
+ p2++;
+ if(ScanLine(p1, p2, ys, pDest))
+ {
+ pDest++;
+ (*scanCount)++;
+ }
+ }
+ p1 = p2;
+ p2 = pt;
+ if(ScanLine(p1, p2, ys, pDest))
+ {
+ pDest++;
+ (*scanCount)++;
+ }
+
+ /* now we sort the list -- duped point are left into
+ as they're needed for the scanline fill algorithm */
+ for(i = 0, ps1 = *scans; i < *scanCount -1; i++, ps1++)
+ for(j = i+1, ps2 = ps1+1; j < *scanCount; j++, ps2++)
+ if(ps2->x < ps1->x)
+ {
+ tmp = ps2->x;
+ ps2->x = ps1->x;
+ ps1->x = tmp;
+ tmp = ps2->y;
+ ps2->y = ps1->y;
+ ps1->y = tmp;
+ }
+
+ return TRUE;
+}
+
+/* gets bounding box of a polygon */
+void PolygonBoundingBox(const POINT *pt, int count, RECT *bBox)
+{
+ const POINT *p;
+ int iPoint;
+
+ bBox->left = MAXLONG; bBox->right = -MAXLONG;
+ bBox->top = MAXLONG; bBox->bottom = -MAXLONG;
+ for(p = pt, iPoint = 0; iPoint < count; iPoint++, p++)
+ {
+ if(p->x < bBox->left ) bBox->left = p->x;
+ if(p->x > bBox->right ) bBox->right = p->x;
+ if(p->y < bBox->top ) bBox->top = p->y;
+ if(p->y > bBox->bottom) bBox->bottom = p->y;
+ }
+}
+
/***********************************************************************
* DIBDRV_Arc
*/
@@ -291,45 +566,155 @@ BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, int left, int top, int right, int botto
/**********************************************************************
* DIBDRV_Polygon
*/
-BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* pt, int count )
+BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
{
BOOL res;
+ POINT *pt;
+ RECT *r;
+ int iRec;
+ POINT *clipped;
+ int clippedCount;
+ RECT bBox;
+ int ys;
+ POINT *scans;
+ int scanCount, iScan;
+ const POINT *p1, *p2;
+ int iPoint;
+ POINT pc1, pc2;
- MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count));
+ MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
if(physDev->hasDIB)
{
/* DIB section selected in, use DIB Engine */
- ONCE(FIXME("STUB\n"));
- res = TRUE;
+
+ res = FALSE;
+
+ /* first converts all points to device coords */
+ if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
+ goto fin;
+ memcpy(pt, ptw, sizeof(POINT) * count);
+ LPtoDP(physDev->hdc, pt, count);
+
+ /* cycle on all current clipping rectangles */
+ r = physDev->regionRects;
+ for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
+ {
+ /* filled area */
+ if(ClipPolygon(pt, count, r, &clipped, &clippedCount))
+ {
+ /* gets polygon bounding box -- for ytop and ybottom */
+ PolygonBoundingBox(clipped, clippedCount, &bBox);
+
+ /* gets all ordered intersections of polygon with
+ current scanline */
+ for(ys = bBox.top; ys < bBox.bottom; ys++)
+ {
+ if(ScanPolygon(clipped, clippedCount, ys, &scans, &scanCount))
+ {
+ if(scanCount >= 2)
+ {
+ res = TRUE;
+ p1 = scans;
+ p2 = p1+1;
+ iScan = 0;
+ while(iScan < scanCount - 1)
+ {
+ physDev->brushHLine(physDev, p1->x, p2->x, ys);
+ p1 +=2;
+ p2 +=2;
+ iScan +=2;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, scans);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, clipped);
+ }
+
+ /* perimeter -- don't use PolyLine for speed */
+ p2 = pt;
+ for(iPoint = 0; iPoint < count -1; iPoint++)
+ {
+ p1 = p2++;
+ if(ClipLine(p1, p2, r, &pc1, &pc2))
+ {
+ res = TRUE;
+ physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
+ }
+ }
+ p1 = p2;
+ p2 = pt;
+ if(ClipLine(p1, p2, r, &pc1, &pc2))
+ {
+ res = TRUE;
+ physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, pt);
+
}
else
{
/* DDB selected in, use X11 driver */
- res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, pt, count);
+ res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, ptw, count);
}
+fin:
return res;
}
/**********************************************************************
* DIBDRV_Polyline
*/
-BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* pt, int count )
+BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
{
BOOL res;
- MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count));
+ MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, ptw, count));
if(physDev->hasDIB)
{
/* DIB section selected in, use DIB Engine */
- ONCE(FIXME("STUB\n"));
- res = TRUE;
+ POINT *pt;
+ RECT *r;
+ POINT pc1, pc2;
+ int iRec, iPoint;
+
+ if(count < 2)
+ return FALSE;
+ res = FALSE;
+
+ /* first converts all points to device coords */
+ if(!(pt = HeapAlloc(GetProcessHeap(), 0, sizeof(POINT) * count)))
+ return FALSE;
+ memcpy(pt, ptw, sizeof(POINT) * count);
+ LPtoDP(physDev->hdc, pt, count);
+
+ r = physDev->regionRects;
+ for(iRec = 0; iRec < physDev->regionRectCount; iRec++)
+ {
+ const POINT *p2 = pt, *p1;
+ for(iPoint = 0; iPoint < count -1; iPoint++)
+ {
+ p1 = p2++;
+ if(ClipLine(p1, p2, r, &pc1, &pc2))
+ {
+ res = TRUE;
+ physDev->penLine(physDev, pc1.x, pc1.y, pc2.x, pc2.y);
+ }
+ }
+ r++;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pt);
+
+ return res;
}
else
{
/* DDB selected in, use X11 driver */
- res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, pt, count);
+ res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, ptw, count);
}
return res;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
diff -urN wine-1.1.24.orig/dlls/ddraw/ddraw.c wine-1.1.24/dlls/ddraw/ddraw.c
--- wine-1.1.24.orig/dlls/ddraw/ddraw.c 2009-03-27 18:31:22.000000000 +0000
+++ wine-1.1.24/dlls/ddraw/ddraw.c 2009-04-05 19:06:28.000000000 +0100
@@ -35,6 +35,7 @@
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
+#include "winreg.h"
#include "wine/exception.h"
#include "ddraw.h"
@@ -45,6 +46,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
+#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
+
static BOOL IDirectDrawImpl_DDSD_Match(const DDSURFACEDESC2* requested, const DDSURFACEDESC2* provided);
static HRESULT IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This, IDirectDrawSurfaceImpl *primary);
static HRESULT IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD, IDirectDrawSurfaceImpl **ppSurf, UINT level);
@@ -476,7 +479,20 @@
!(This->devicewindow) &&
(hwnd != window) )
{
- This->dest_window = hwnd;
+ BYTE buffer[32];
+ DWORD size = sizeof(buffer);
+ HKEY hkey = 0;
+ HWND drawwin = hwnd;
+ /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey)) {
+ if (!RegQueryValueExA( hkey, "DirectDrawDesktopHack", 0, NULL, buffer, &size)) {
+ if ( IS_OPTION_TRUE( buffer[0] ) ) {
+ TRACE("Enabling DirectDrawDesktopHack hack\n");
+ drawwin = GetDesktopWindow();
+ }
+ }
+ }
+ This->dest_window = drawwin;
}
}
else if(cooplevel & DDSCL_EXCLUSIVE)

View File

@ -0,0 +1,5 @@
REGEDIT4
[HKEY_CURRENT_USER\Software\Wine\Direct3D]
"DirectDrawDesktopHack"="true"

View File

@ -91,6 +91,17 @@ src_prepare() {
epatch "${FILESDIR}"/dinput.patch
epatch "${FILESDIR}"/schannel.patch
epatch "${FILESDIR}"/revert-ntdll.patch
epatch "${FILESDIR}"/ddraw-1.1.24.diff
epatch "${FILESDIR}"/0001-dib-engine-hook-the-engine-bet.patch
epatch "${FILESDIR}"/0002-dib-engine-initial-pass-throug.patch
epatch "${FILESDIR}"/0003-dib-engine-fork-ddb-dib-behavi.patch
epatch "${FILESDIR}"/0004-dib-engine-implement-most-engi.patch
epatch "${FILESDIR}"/0005-dib-engine-implement-alphablen.patch
epatch "${FILESDIR}"/0006-dib-engine-add-clipping-on-xxx.patch
epatch "${FILESDIR}"/0007-dib-engine-implement-polygon.patch
epatch "${FILESDIR}"/0008-dib-engine-fixes-clipping-text.patch
epatch "${FILESDIR}"/0009-dib-engine-fixes-against-wine-.patch
epatch "${FILESDIR}"/0010-dib-engine-introduction-of-bit.patch
sed -i '/^UPDATE_DESKTOP_DATABASE/s:=.*:=true:' tools/Makefile.in || die
sed -i '/^MimeType/d' tools/wine.desktop || die #117785
}