Release 980201
Sun Feb 1 13:24:54 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [files/drive.c]
Added Device= parameter to drive configuration.
* [if1632/relay.c]
Throw() and Catch() now use the correct CATCHBUF layout (untested).
* [tools/build.c] [include/stackframe.h] [loader/task.c]
Moved 16-bit stack pointer into thread database.
Save current %fs while running 16-bit code.
Fri Jan 30 09:25:49 1998 Martin Boehme <boehme@informatik.mu-luebeck.de>
* [graphics/mapping.c]
Made DPtoLP32 and LPtoDP32 respect world transforms.
* [graphics/path.c] [graphics/painting.c] [if1632/gdi.spec]
[include/path.h]
More path support.
* [include/gdi.h] [include/windows.h] [objects/dc.c]
[relay/gdi32.spec]
Support for Get/SetArcDirection and Get/SetWorldTransform
* [windows/hook.c]
Fixed a bug in HOOK_Map16To32Common.
Thu Jan 29 23:43:18 1998 Douglas Ridgway <ridgway@taiga.gmcl.com>
* [graphics/metafiledrv/init.c] [objects/metafile.c]
Documentation for metafile related API calls. Fixed a bug to avoid
documenting it.
* [include/windows.h]
Declaration for LoadImage.
Thu Jan 29 21:44:45 1998 Huw D M Davies <h.davies1@physics.oxford.ac.uk>
* [graphics/win16drv/*]
Changes to printing code to enable use of printer fonts with the
win3.1 postscript driver. Remember to add printer=on to [wine]
section of wine.conf . You will also need to disable truetype
fonts from control panel. Winword 6.0 and Write seem to be happy
with this...
* [include/bitmap.h]
Fix Widthbytes for 15bpp displays.
Tue Jan 27 20:54:08 1998 Kristian Nielsen <kristian.nielsen@risoe.dk>
* [tsx11/*] [include/ts*] [tools/make_X11wrappers]
Implemented thread-safe X11 wrappers.
Tue Jan 27 13:54:09 1998 Constantine Sapuntzakis <csapuntz@tma-1.lcs.mit.edu>
* [windows/queue.c]
Forgot to convert thdb to thread_id.
* [misc/registry.c]
Sped up Windows 95 registry reading. Changed code to traverse
registry as a tree rather than read in all possible keys
(including dead ones).
Tue Jan 27 12:46:09 1998 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [loader/pe_image.c][Makefile.in][scheduler/thread.c]
[libtest/hello5.c]
Don't exit() on failed to load referenced dlls.
Fixed static tls allocation for multiple threads.
WINELIB should now be able to load PE dlls. A sample
winelib program, that dynamically loads a internal dll
is included.
* [graphics/ddraw.c][include/ddraw.h][include/d3d.h]
Cleaned up and enhanced further. Added several DirectX5
interface definitions and DirectSurface3 implementation.
Stubs for D3D (NOT coming soon, just there so it fails safely).
* [multimedia/dsound.c][include/dsound.h]
Actually works now for a lot of cases. Some DirectX5 stuff
added. Still lacking several features.
* [windows/dinput.c][include/dinput.h]
Started implementing DirectInput. Doesn't work yet, don't
know why.
* [if1632/thunk.c][misc/callbacks.c]
[win32/kernel.c][include/callbacks.h]
Added WOWCallback16Ex, WOWHandle32.
* [misc/cpu.c]
Fixed GetSystemInfo, IsProcessorFeaturePresent.
* [multimedia/joystick.c][multimedia/time.c]
Several fixes. Small hack to get timerevents in timeGetTime() loops.
Tue Jan 20 11:26:27 1998 Slaven Rezic <eserte@cs.tu-berlin.de>
* [configure.in]
Fixed check for union semun on FreeBSD systems.
Sun Jan 18 23:05:04 1998 Karl Backström <karl_b@geocities.com>
* [misc/ole2nls.c] [programs/progman/Sw.rc] [programs/winhelp/Sw.rc]
[resources/sysres_Sw.rc]
Added/updated Swedish language support.
Sun Jan 18 18:49:01 1998 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [misc/winsock.c] [misc/winsock_dns.c] [windows/event.c]
[windows/win.c] [windows/dce.c] [windows/winpos.c]
Bug fixes.
Sun Jan 18 12:45:23 1997 Andreas Mohr <100.30936@germany.net>
* [msdos/int25.c] [msdos/int26.c]
Implemented "native" absolute disk read/write access.
* [msdos/int13.c] [msdos/ioports.c]
Enhanced GET DRIVE PARAMETERS (int13 AH=08).
* [graphics/win16drv/prtdrv.c] [if1632/gdi.spec]
Fixed typos, implemented dmEnumDFonts,
Started implementation of dmRealizeObject.
* [if1632/compobj.spec] [ole/compobj.c] [relay32/ole32.spec]
Stubs CoCreateInstance, CoFreeUnusedLibraries, implemented
CoFileTimeNow.
* [if1632/kernel.spec] [include/windows.h] [memory/global.c]
[memory/string.c] [misc/kernel.c] [misc/Makefile.in]
[misc/toolhelp.c] [msdos/int21.c]
Implemented GlobalHandleNoRIP, GetFreeMemInfo, DebugFillBuffer,
stubs GetSetKernelDOSProc, DiagQuery, DiagOutput, ToolHelpHook
(Undocumented Windows).
* [if1632/user.spec] [if1632/win32s16.spec] [misc/win32s16.c]
Misc stubs.
* [if1632/winaspi.spec] [misc/aspi.c]
Implemented GetASPIDLLVersion.
* [if1632/wprocs.spec] [msdos/int20.c] [msdos/Makefile.in]
Added handler for Int 0x20 (terminate program, _very_ old-fashioned).
* [misc/w32scomb.c]
Implemented Get16DLLAddress() partially
(big thanks to Marcus and Alexandre).
* [relay32/Makefile.in] [relay32/builtin32.c] [relay32/dplay.spec]
Added built-in DPLAY.DLL.
* [relay32/winmm.spec] [multimedia/joystick.c]
Added joySetThreshold.
* [misc/windebug.c]
Added WinNotify.
* [win32/console.c]
Stubs CreateConsoleScreenBuffer, SetConsoleActiveScreenBuffer,
WriteConsoleOutput32A.
* [windows/user.c]
Stub SetEventHook.
Sat Jan 17 19:30:35 1998 Matthew Toseland <Paul.Toseland@btinternet.com>
* [windows/painting.c]
Fixed broken restore-to-maximized.
Mon Jan 12 21:25:32 1998 Perceval - Marc Huguet Puig <mhp@tinet.fut.es>
* [documentation/wine.man] [include/options.h]
[misc/main.c] [ole/ole2nls.c] [resources/sysres.c]
[resources/sysres_Ca.rc] [resources/Makefile.in]
Added language catalan. (Afegit l'idioma catalĂ ).
diff --git a/graphics/path.c b/graphics/path.c
index e4e4013..d53acd9 100644
--- a/graphics/path.c
+++ b/graphics/path.c
@@ -1,11 +1,12 @@
/*
* Graphics paths (BeginPath, EndPath etc.)
*
- * Copyright 1997 Martin Boehme
+ * Copyright 1997, 1998 Martin Boehme
*/
#include <assert.h>
#include <malloc.h>
+#include <math.h>
#include "windows.h"
#include "winerror.h"
@@ -64,6 +65,22 @@
static BOOL32 PATH_AddEntry(GdiPath *pPath, POINT32 point, BYTE flags);
static BOOL32 PATH_ReserveEntries(GdiPath *pPath, INT32 numEntries);
static BOOL32 PATH_GetPathFromHDC(HDC32 hdc, GdiPath **ppPath);
+static BOOL32 PATH_DoArcPart(GdiPath *pPath, POINT32 corners[],
+ double angleStart, double angleEnd, BOOL32 addMoveTo);
+static void PATH_ScaleNormalizedPoint(POINT32 corners[], double x, double y,
+ POINT32 *pPoint);
+static void PATH_NormalizePoint(POINT32 corners[], const POINT32 *pPoint,
+ double *pX, double *pY);
+
+
+/***********************************************************************
+ * BeginPath16 (GDI.512)
+ */
+BOOL16 WINAPI BeginPath16(HDC16 hdc)
+{
+ return (BOOL16)BeginPath32((HDC32)hdc);
+}
+
/***********************************************************************
* BeginPath32 (GDI32.9)
@@ -95,6 +112,15 @@
/***********************************************************************
+ * EndPath16 (GDI.514)
+ */
+BOOL16 WINAPI EndPath16(HDC16 hdc)
+{
+ return (BOOL16)EndPath32((HDC32)hdc);
+}
+
+
+/***********************************************************************
* EndPath32 (GDI32.78)
*/
BOOL32 WINAPI EndPath32(HDC32 hdc)
@@ -123,6 +149,15 @@
/***********************************************************************
+ * AbortPath16 (GDI.511)
+ */
+BOOL16 WINAPI AbortPath16(HDC16 hdc)
+{
+ return (BOOL16)AbortPath32((HDC32)hdc);
+}
+
+
+/***********************************************************************
* AbortPath32 (GDI32.1)
*/
BOOL32 WINAPI AbortPath32(HDC32 hdc)
@@ -145,6 +180,15 @@
/***********************************************************************
+ * CloseFigure16 (GDI.513)
+ */
+BOOL16 WINAPI CloseFigure16(HDC16 hdc)
+{
+ return (BOOL16)CloseFigure32((HDC32)hdc);
+}
+
+
+/***********************************************************************
* CloseFigure32 (GDI32.16)
*/
BOOL32 WINAPI CloseFigure32(HDC32 hdc)
@@ -178,13 +222,25 @@
/***********************************************************************
+ * GetPath16 (GDI.517)
+ */
+INT16 WINAPI GetPath16(HDC16 hdc, LPPOINT16 pPoints, LPBYTE pTypes,
+ INT16 nSize)
+{
+ /* FIXME: Not implemented */
+ fprintf(stdnimp, "GetPath16: Unimplemented stub\n");
+
+ return 0;
+}
+
+
+/***********************************************************************
* GetPath32 (GDI32.210)
*/
INT32 WINAPI GetPath32(HDC32 hdc, LPPOINT32 pPoints, LPBYTE pTypes,
INT32 nSize)
{
GdiPath *pPath;
- BOOL32 temp_flag;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
@@ -213,10 +269,12 @@
memcpy(pTypes, pPath->pFlags, sizeof(BYTE)*pPath->numEntriesUsed);
/* Convert the points to logical coordinates */
- temp_flag=DPtoLP32(hdc, pPoints, pPath->numEntriesUsed);
-
- /* Since hdc is valid, conversion should never fail */
- assert(temp_flag);
+ if(!DPtoLP32(hdc, pPoints, pPath->numEntriesUsed))
+ {
+ /* FIXME: Is this the correct value? */
+ SetLastError(ERROR_CAN_NOT_COMPLETE);
+ return -1;
+ }
return pPath->numEntriesUsed;
}
@@ -266,8 +324,9 @@
/* FIXME: Check that SetLastError is being called correctly */
{
GdiPath *pPath;
- INT32 mapMode;
+ INT32 mapMode, graphicsMode;
POINT32 ptViewportExt, ptViewportOrg, ptWindowExt, ptWindowOrg;
+ XFORM xform;
HRGN32 hrgn;
/* Get pointer to path */
@@ -290,6 +349,9 @@
/* Since PaintRgn interprets the region as being in logical coordinates
* but the points we store for the path are already in device
* coordinates, we have to set the mapping mode to MM_TEXT temporarily.
+ * Using SaveDC to save information about the mapping mode / world
+ * transform would be easier but would require more overhead, especially
+ * now that SaveDC saves the current path.
*/
/* Save the information about the old mapping mode */
@@ -299,13 +361,14 @@
GetWindowExtEx32(hdc, &ptWindowExt);
GetWindowOrgEx32(hdc, &ptWindowOrg);
- /* FIXME: Once world transforms become available, we will have to do
- * a GetWorldTransform, too (along with a SetWorldTransform later on).
- * Moral: Perhaps I should have used SaveDC right away. The reason why
- * I didn't is that I wanted to avoid the overhead of a full SaveDC
- * (especially since SaveDC now saves the current path as well).
+ /* Save world transform
+ * NB: The Windows documentation on world transforms would lead one to
+ * believe that this has to be done only in GM_ADVANCED; however, my
+ * tests show that resetting the graphics mode to GM_COMPATIBLE does
+ * not reset the world transform.
*/
-
+ GetWorldTransform(hdc, &xform);
+
/* Set MM_TEXT */
SetMapMode32(hdc, MM_TEXT);
@@ -319,6 +382,12 @@
SetWindowExtEx32(hdc, ptWindowExt.x, ptWindowExt.y, NULL);
SetWindowOrgEx32(hdc, ptWindowOrg.x, ptWindowOrg.y, NULL);
+ /* Go to GM_ADVANCED temporarily to restore the world transform */
+ graphicsMode=GetGraphicsMode(hdc);
+ SetGraphicsMode(hdc, GM_ADVANCED);
+ SetWorldTransform(hdc, &xform);
+ SetGraphicsMode(hdc, graphicsMode);
+
/* Empty the path */
PATH_EmptyPath(pPath);
return TRUE;
@@ -335,12 +404,12 @@
/***********************************************************************
* SelectClipPath32 (GDI32.296)
*/
-BOOL32 WINAPI SelectClipPath32(HDC32 hdc, int iMode)
+BOOL32 WINAPI SelectClipPath32(HDC32 hdc, INT32 iMode)
/* FIXME: Check that SetLastError is being called correctly */
{
GdiPath *pPath;
HRGN32 hrgnPath, hrgnClip;
- BOOL32 success = FALSE;
+ BOOL32 success;
/* Get pointer to path */
if(!PATH_GetPathFromHDC(hdc, &pPath))
@@ -360,7 +429,9 @@
if(PATH_PathToRegion(pPath, GetPolyFillMode32(hdc), &hrgnPath))
{
hrgnClip=CreateRectRgn32(0, 0, 0, 0);
- if(hrgnClip!=NULL)
+ if(hrgnClip==NULL)
+ success=FALSE;
+ else
{
success=(GetClipRgn32(hdc, hrgnClip)!=-1) &&
(CombineRgn32(hrgnClip, hrgnClip, hrgnPath, iMode)!=ERROR) &&
@@ -510,6 +581,152 @@
return PATH_AddEntry(pPath, point, PT_LINETO);
}
+/* PATH_Ellipse
+ *
+ * Should be called when a call to Ellipse is performed on a DC that has
+ * an open path. This adds four Bezier splines representing the ellipse
+ * to the path. Returns TRUE if successful, else FALSE.
+ */
+BOOL32 PATH_Ellipse(HDC32 hdc, INT32 x1, INT32 y1, INT32 x2, INT32 y2)
+{
+ return PATH_Arc(hdc, x1, y1, x2, y2, x1, 0, x1, 0);
+}
+
+/* PATH_Arc
+ *
+ * Should be called when a call to Arc is performed on a DC that has
+ * an open path. This adds up to five Bezier splines representing the arc
+ * to the path. Returns TRUE if successful, else FALSE.
+ */
+BOOL32 PATH_Arc(HDC32 hdc, INT32 x1, INT32 y1, INT32 x2, INT32 y2,
+ INT32 xStart, INT32 yStart, INT32 xEnd, INT32 yEnd)
+{
+ GdiPath *pPath;
+ double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
+ /* Initialize angleEndQuadrant to silence gcc's warning */
+ double x, y;
+ POINT32 corners[2], pointStart, pointEnd;
+ BOOL32 start, end;
+ INT32 temp;
+
+ /* FIXME: This function should check for all possible error returns */
+
+ /* Get pointer to path */
+ if(!PATH_GetPathFromHDC(hdc, &pPath))
+ return FALSE;
+
+ /* Check that path is open */
+ if(pPath->state!=PATH_Open)
+ return FALSE;
+
+ /* Check for zero height / width */
+ /* FIXME: Should we do this before or after LPtoDP? */
+ if(x1==x2 || y1==y2)
+ return TRUE;
+
+ /* In GM_COMPATIBLE, don't include bottom and right edges */
+ if(GetGraphicsMode(hdc)==GM_COMPATIBLE)
+ {
+ /* FIXME: Should we do this before or after LPtoDP? */
+ x2--;
+ y2--;
+ }
+
+ /* Convert points to device coordinates */
+ corners[0].x=x1;
+ corners[0].y=y1;
+ corners[1].x=x2;
+ corners[1].y=y2;
+ pointStart.x=xStart;
+ pointStart.y=yStart;
+ pointEnd.x=xEnd;
+ pointEnd.y=yEnd;
+ if(!LPtoDP32(hdc, corners, 2) || !LPtoDP32(hdc, &pointStart, 1) ||
+ !LPtoDP32(hdc, &pointEnd, 1))
+ return FALSE;
+
+ /* Make sure first corner is top left and right corner is bottom right */
+ /* FIXME: Should we do this before or after LPtoDP? */
+ if(corners[0].x>corners[1].x)
+ {
+ temp=corners[0].x;
+ corners[0].x=corners[1].x;
+ corners[1].x=temp;
+ }
+ if(corners[0].y>corners[1].y)
+ {
+ temp=corners[0].y;
+ corners[0].y=corners[1].y;
+ corners[1].y=temp;
+ }
+
+ /* Compute start and end angle */
+ PATH_NormalizePoint(corners, &pointStart, &x, &y);
+ angleStart=atan2(y, x);
+ PATH_NormalizePoint(corners, &pointEnd, &x, &y);
+ angleEnd=atan2(y, x);
+
+ /* Make sure the end angle is "on the right side" of the start angle */
+ if(GetArcDirection32(hdc)==AD_CLOCKWISE)
+ {
+ if(angleEnd<=angleStart)
+ {
+ angleEnd+=2*M_PI;
+ assert(angleEnd>=angleStart);
+ }
+ }
+ else
+ {
+ if(angleEnd>=angleStart)
+ {
+ angleEnd-=2*M_PI;
+ assert(angleEnd<=angleStart);
+ }
+ }
+
+ /* Add the arc to the path with one Bezier spline per quadrant that the
+ * arc spans */
+ start=TRUE;
+ end=FALSE;
+ do
+ {
+ /* Determine the start and end angles for this quadrant */
+ if(start)
+ {
+ angleStartQuadrant=angleStart;
+ if(GetArcDirection32(hdc)==AD_CLOCKWISE)
+ angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2;
+ else
+ angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2;
+ }
+ else
+ {
+ angleStartQuadrant=angleEndQuadrant;
+ if(GetArcDirection32(hdc)==AD_CLOCKWISE)
+ angleEndQuadrant+=M_PI_2;
+ else
+ angleEndQuadrant-=M_PI_2;
+ }
+
+ /* Have we reached the last part of the arc? */
+ if((GetArcDirection32(hdc)==AD_CLOCKWISE &&
+ angleEnd<=angleEndQuadrant) ||
+ (GetArcDirection32(hdc)==AD_COUNTERCLOCKWISE &&
+ angleEnd>=angleEndQuadrant))
+ {
+ /* Adjust the end angle for this quadrant */
+ angleEndQuadrant=angleEnd;
+ end=TRUE;
+ }
+
+ /* Add the Bezier spline to the path */
+ PATH_DoArcPart(pPath, corners, angleStartQuadrant, angleEndQuadrant,
+ start);
+ start=FALSE;
+ } while(!end);
+
+ return TRUE;
+}
/***********************************************************************
* Internal functions
@@ -702,3 +919,85 @@
else
return FALSE;
}
+
+/* PATH_DoArcPart
+ *
+ * Creates a Bezier spline that corresponds to part of an arc and appends the
+ * corresponding points to the path. The start and end angles are passed in
+ * "angleStart" and "angleEnd"; these angles should span a quarter circle
+ * at most. If "addMoveTo" is true, a PT_MOVETO entry for the first control
+ * point is added to the path; otherwise, it is assumed that the current
+ * position is equal to the first control point.
+ */
+static BOOL32 PATH_DoArcPart(GdiPath *pPath, POINT32 corners[],
+ double angleStart, double angleEnd, BOOL32 addMoveTo)
+{
+ double halfAngle, a;
+ double xNorm[4], yNorm[4];
+ POINT32 point;
+ int i;
+
+ assert(fabs(angleEnd-angleStart)<=M_PI_2);
+
+ /* FIXME: Is there an easier way of computing this? */
+
+ /* Compute control points */
+ halfAngle=(angleEnd-angleStart)/2.0;
+ a=4.0/3.0*(1-cos(halfAngle))/sin(halfAngle);
+ xNorm[0]=cos(angleStart);
+ yNorm[0]=sin(angleStart);
+ xNorm[1]=xNorm[0] - a*yNorm[0];
+ yNorm[1]=yNorm[0] + a*xNorm[0];
+ xNorm[3]=cos(angleEnd);
+ yNorm[3]=sin(angleEnd);
+ xNorm[2]=xNorm[3] + a*yNorm[3];
+ yNorm[2]=yNorm[3] - a*xNorm[3];
+
+ /* Add starting point to path if desired */
+ if(addMoveTo)
+ {
+ PATH_ScaleNormalizedPoint(corners, xNorm[0], yNorm[0], &point);
+ if(!PATH_AddEntry(pPath, point, PT_MOVETO))
+ return FALSE;
+ }
+
+ /* Add remaining control points */
+ for(i=1; i<4; i++)
+ {
+ PATH_ScaleNormalizedPoint(corners, xNorm[i], yNorm[i], &point);
+ if(!PATH_AddEntry(pPath, point, PT_BEZIERTO))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* PATH_ScaleNormalizedPoint
+ *
+ * Scales a normalized point (x, y) with respect to the box whose corners are
+ * passed in "corners". The point is stored in "*pPoint". The normalized
+ * coordinates (-1.0, -1.0) correspond to corners[0], the coordinates
+ * (1.0, 1.0) correspond to corners[1].
+ */
+static void PATH_ScaleNormalizedPoint(POINT32 corners[], double x, double y,
+ POINT32 *pPoint)
+{
+ pPoint->x=(INT32)floor( (double)corners[0].x +
+ (double)(corners[1].x-corners[0].x)*0.5*(x+1.0) );
+ pPoint->y=(INT32)floor( (double)corners[0].y +
+ (double)(corners[1].y-corners[0].y)*0.5*(y+1.0) );
+}
+
+/* PATH_NormalizePoint
+ *
+ * Normalizes a point with respect to the box whose corners are passed in
+ * "corners". The normalized coordinates are stored in "*pX" and "*pY".
+ */
+static void PATH_NormalizePoint(POINT32 corners[], const POINT32 *pPoint,
+ double *pX, double *pY)
+{
+ *pX=(double)(pPoint->x-corners[0].x)/(double)(corners[1].x-corners[0].x) *
+ 2.0 - 1.0;
+ *pY=(double)(pPoint->y-corners[0].y)/(double)(corners[1].y-corners[0].y) *
+ 2.0 - 1.0;
+}