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:
@@ -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 )))
|
||||
1601
app-emulation/wine/files/0002-dib-engine-initial-pass-throug.patch
Normal file
1601
app-emulation/wine/files/0002-dib-engine-initial-pass-throug.patch
Normal file
File diff suppressed because it is too large
Load Diff
1858
app-emulation/wine/files/0003-dib-engine-fork-ddb-dib-behavi.patch
Normal file
1858
app-emulation/wine/files/0003-dib-engine-fork-ddb-dib-behavi.patch
Normal file
File diff suppressed because it is too large
Load Diff
9088
app-emulation/wine/files/0004-dib-engine-implement-most-engi.patch
Normal file
9088
app-emulation/wine/files/0004-dib-engine-implement-most-engi.patch
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
@@ -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 */
|
||||
463
app-emulation/wine/files/0007-dib-engine-implement-polygon.patch
Normal file
463
app-emulation/wine/files/0007-dib-engine-implement-polygon.patch
Normal 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;
|
||||
}
|
||||
1804
app-emulation/wine/files/0008-dib-engine-fixes-clipping-text.patch
Normal file
1804
app-emulation/wine/files/0008-dib-engine-fixes-clipping-text.patch
Normal file
File diff suppressed because it is too large
Load Diff
1695
app-emulation/wine/files/0009-dib-engine-fixes-against-wine-.patch
Normal file
1695
app-emulation/wine/files/0009-dib-engine-fixes-against-wine-.patch
Normal file
File diff suppressed because it is too large
Load Diff
2103
app-emulation/wine/files/0010-dib-engine-introduction-of-bit.patch
Normal file
2103
app-emulation/wine/files/0010-dib-engine-introduction-of-bit.patch
Normal file
File diff suppressed because it is too large
Load Diff
42
app-emulation/wine/files/ddraw-1.1.24.diff
Normal file
42
app-emulation/wine/files/ddraw-1.1.24.diff
Normal 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)
|
||||
5
app-emulation/wine/files/hack.reg
Normal file
5
app-emulation/wine/files/hack.reg
Normal file
@@ -0,0 +1,5 @@
|
||||
REGEDIT4
|
||||
|
||||
[HKEY_CURRENT_USER\Software\Wine\Direct3D]
|
||||
"DirectDrawDesktopHack"="true"
|
||||
|
||||
Reference in New Issue
Block a user