[WIN32K] Sync bezier.c with Wine Staging 1.7.37. CORE-9246

svn path=/trunk/; revision=67957
This commit is contained in:
Amine Khaldi 2015-05-29 20:57:23 +00:00
parent 604dacb5af
commit af907575d7
3 changed files with 129 additions and 139 deletions

View file

@ -331,5 +331,8 @@ secur32 -
reactos/dll/win32/secur32/thunks.c # Synced to WineStaging-1.7.37 reactos/dll/win32/secur32/thunks.c # Synced to WineStaging-1.7.37
reactos/dll/win32/secur32/wrapper.c # Synced to WineStaging-1.7.37 reactos/dll/win32/secur32/wrapper.c # Synced to WineStaging-1.7.37
win32k -
win32ss/gdi/ntgdi/bezier.c # Synced to WineStaging-1.7.37
ws2_32 - ws2_32 -
reactos/dll/win32/ws2_32/misc/async.c # Synced to Wine-1.5.4 reactos/dll/win32/ws2_32/misc/async.c # Synced to Wine-1.5.4

View file

@ -1,9 +1,6 @@
/* /*
* COPYRIGHT: GNU GPL, See COPYING in the top level directory * COPYRIGHT: GNU LGPL
* PROJECT: ReactOS kernel * PURPOSE: Bezier functions
* PURPOSE: Bezier functions
* FILE: subsys/win32k/objects/bezier.c
* PROGRAMER: Unknown
*/ */
#include <win32k.h> #include <win32k.h>
@ -11,12 +8,14 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/* Based on Wine Staging 1.7.37 - dlls/gdi32/painting.c */
/****************************************************************** /******************************************************************
* *
* *Very* simple bezier drawing code, * *Very* simple bezier drawing code,
* *
* It uses a recursive algorithm to divide the curve in a series * It uses a recursive algorithm to divide the curve in a series
* of straight line segements. Not ideal but for me sufficient. * of straight line segments. Not ideal but sufficient for me.
* If you are in need for something better look for some incremental * If you are in need for something better look for some incremental
* algorithm. * algorithm.
* *
@ -24,14 +23,14 @@
*/ */
/* /*
* Some macro definitions for bezier drawing. * some macro definitions for bezier drawing
* *
* To avoid trucation errors the coordinates are * to avoid truncation errors the coordinates are
* shifted upwards. When used in drawing they are * shifted upwards. When used in drawing they are
* shifted down again, including correct rounding * shifted down again, including correct rounding
* and avoiding floating point arithmatic * and avoiding floating point arithmetic
* 4 bits should allow 27 bits coordinates which I saw * 4 bits should allow 27 bits coordinates which I saw
* somewere in the win32 doc's * somewhere in the win32 doc's
* *
*/ */
@ -39,20 +38,20 @@
#define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS) #define BEZIERSHIFTUP(x) ((x)<<BEZIERSHIFTBITS)
#define BEZIERPIXEL BEZIERSHIFTUP(1) #define BEZIERPIXEL BEZIERSHIFTUP(1)
#define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS) #define BEZIERSHIFTDOWN(x) (((x)+(1<<(BEZIERSHIFTBITS-1)))>>BEZIERSHIFTBITS)
/* Maximum depth of recursion */ /* maximum depth of recursion */
#define BEZIERMAXDEPTH 8 #define BEZIERMAXDEPTH 8
/* Size of array to store points on */ /* size of array to store points on */
/* enough for one curve */ /* enough for one curve */
#define BEZIER_INITBUFSIZE (150) #define BEZIER_INITBUFSIZE (150)
/* Calculate Bezier average, in this case the middle /* calculate Bezier average, in this case the middle
* correctly rounded... * correctly rounded...
* */ * */
#define BEZIERMIDDLE(Mid, P1, P2) \ #define BEZIERMIDDLE(Mid, P1, P2) \
(Mid).x=((P1).x+(P2).x + 1) >> 1;\ (Mid).x=((P1).x+(P2).x + 1)/2;\
(Mid).y=((P1).y+(P2).y + 1) >> 1; (Mid).y=((P1).y+(P2).y + 1)/2;
/********************************************************** /**********************************************************
* BezierCheck helper function to check * BezierCheck helper function to check
@ -60,120 +59,109 @@
* Points[0] and Points[3] are begin and endpoint * Points[0] and Points[3] are begin and endpoint
* Points[1] and Points[2] are control points * Points[1] and Points[2] are control points
* level is the recursion depth * level is the recursion depth
* returns true if the recusion can be terminated * returns true if the recursion can be terminated
*/ */
static BOOL FASTCALL BezierCheck( int level, POINT *Points) static BOOL BezierCheck( int level, POINT *Points)
{ {
INT dx, dy; INT dx, dy;
dx=Points[3].x-Points[0].x;
dx=Points[3].x-Points[0].x; dy=Points[3].y-Points[0].y;
dy=Points[3].y-Points[0].y; if(abs(dy)<=abs(dx)){/* shallow line */
if ( abs(dy) <= abs(dx) ) /* Shallow line */ /* check that control points are between begin and end */
{ if(Points[1].x < Points[0].x){
/* Check that control points are between begin and end */ if(Points[1].x < Points[3].x)
if ( Points[1].x < Points[0].x ) return FALSE;
{ }else
if ( Points[1].x < Points[3].x ) if(Points[1].x > Points[3].x)
return FALSE; return FALSE;
} if(Points[2].x < Points[0].x){
else if ( Points[1].x > Points[3].x ) if(Points[2].x < Points[3].x)
return FALSE; return FALSE;
if ( Points[2].x < Points[0].x) }else
{ if(Points[2].x > Points[3].x)
if ( Points[2].x < Points[3].x ) return FALSE;
return FALSE; dx=BEZIERSHIFTDOWN(dx);
} if(!dx) return TRUE;
else if ( Points[2].x > Points[3].x ) if(abs(Points[1].y-Points[0].y-(dy/dx)*
return FALSE; BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL ||
dx = BEZIERSHIFTDOWN(dx); abs(Points[2].y-Points[0].y-(dy/dx)*
if ( !dx ) BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL )
return TRUE; return FALSE;
if ( abs(Points[1].y-Points[0].y-(dy/dx)* else
BEZIERSHIFTDOWN(Points[1].x-Points[0].x)) > BEZIERPIXEL || return TRUE;
abs(Points[2].y-Points[0].y-(dy/dx)* }else{ /* steep line */
BEZIERSHIFTDOWN(Points[2].x-Points[0].x)) > BEZIERPIXEL /* check that control points are between begin and end */
) if(Points[1].y < Points[0].y){
return FALSE; if(Points[1].y < Points[3].y)
else return FALSE;
return TRUE; }else
} if(Points[1].y > Points[3].y)
else return FALSE;
{ if(Points[2].y < Points[0].y){
/* Steep line */ if(Points[2].y < Points[3].y)
/* Check that control points are between begin and end */ return FALSE;
if(Points[1].y < Points[0].y) }else
{ if(Points[2].y > Points[3].y)
if(Points[1].y < Points[3].y) return FALSE;
return FALSE; dy=BEZIERSHIFTDOWN(dy);
} if(!dy) return TRUE;
else if(Points[1].y > Points[3].y) if(abs(Points[1].x-Points[0].x-(dx/dy)*
return FALSE; BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL ||
if ( Points[2].y < Points[0].y ) abs(Points[2].x-Points[0].x-(dx/dy)*
{ BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL )
if ( Points[2].y < Points[3].y ) return FALSE;
return FALSE; else
} return TRUE;
else if ( Points[2].y > Points[3].y )
return FALSE;
dy = BEZIERSHIFTDOWN(dy);
if ( !dy )
return TRUE;
if ( abs(Points[1].x-Points[0].x-(dx/dy)*
BEZIERSHIFTDOWN(Points[1].y-Points[0].y)) > BEZIERPIXEL ||
abs(Points[2].x-Points[0].x-(dx/dy)*
BEZIERSHIFTDOWN(Points[2].y-Points[0].y)) > BEZIERPIXEL
)
return FALSE;
else
return TRUE;
} }
} }
/* Helper for GDI_Bezier. /* Helper for GDI_Bezier.
* Just handles one Bezier, so Points should point to four POINTs * Just handles one Bezier, so Points should point to four POINTs
*/ */
static void APIENTRY GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut, static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut,
INT *nPtsOut, INT level ) INT *nPtsOut, INT level )
{ {
if(*nPtsOut == *dwOut) { if(*nPtsOut == *dwOut) {
*dwOut *= 2; *dwOut *= 2;
*PtsOut = ExAllocatePoolWithTag(PagedPool, *dwOut * sizeof(POINT), TAG_BEZIER); *PtsOut = ExAllocatePoolWithTag(PagedPool, *dwOut * sizeof(POINT), TAG_BEZIER);
if (*PtsOut == NULL) if (*PtsOut == NULL)
{ {
/// \todo FIXME! /// \todo FIXME!
NT_ASSERT(FALSE); NT_ASSERT(FALSE);
return; return;
}
} }
}
if(!level || BezierCheck(level, Points)) { if(!level || BezierCheck(level, Points)) {
if(*nPtsOut == 0) { if(*nPtsOut == 0) {
(*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x); (*PtsOut)[0].x = BEZIERSHIFTDOWN(Points[0].x);
(*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y); (*PtsOut)[0].y = BEZIERSHIFTDOWN(Points[0].y);
*nPtsOut = 1; *nPtsOut = 1;
}
(*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x);
(*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y);
(*nPtsOut) ++;
} else {
POINT Points2[4]; /* for the second recursive call */
Points2[3]=Points[3];
BEZIERMIDDLE(Points2[2], Points[2], Points[3]);
BEZIERMIDDLE(Points2[0], Points[1], Points[2]);
BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]);
BEZIERMIDDLE(Points[1], Points[0], Points[1]);
BEZIERMIDDLE(Points[2], Points[1], Points2[0]);
BEZIERMIDDLE(Points[3], Points[2], Points2[1]);
Points2[0]=Points[3];
/* do the two halves */
GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1);
GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1);
} }
(*PtsOut)[*nPtsOut].x = BEZIERSHIFTDOWN(Points[3].x);
(*PtsOut)[*nPtsOut].y = BEZIERSHIFTDOWN(Points[3].y);
(*nPtsOut) ++;
} else {
POINT Points2[4]; /* For the second recursive call */
Points2[3]=Points[3];
BEZIERMIDDLE(Points2[2], Points[2], Points[3]);
BEZIERMIDDLE(Points2[0], Points[1], Points[2]);
BEZIERMIDDLE(Points2[1],Points2[0],Points2[2]);
BEZIERMIDDLE(Points[1], Points[0], Points[1]);
BEZIERMIDDLE(Points[2], Points[1], Points2[0]);
BEZIERMIDDLE(Points[3], Points[2], Points2[1]);
Points2[0]=Points[3];
/* Do the two halves */
GDI_InternalBezier(Points, PtsOut, dwOut, nPtsOut, level-1);
GDI_InternalBezier(Points2, PtsOut, dwOut, nPtsOut, level-1);
}
} }
/*********************************************************************** /***********************************************************************
* GDI_Bezier [INTERNAL] * GDI_Bezier [INTERNAL]
* Calculate line segments that approximate -what microsoft calls- a bezier * Calculate line segments that approximate -what microsoft calls- a bezier
@ -191,38 +179,37 @@ static void APIENTRY GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwO
* *
* RETURNS * RETURNS
* *
* Ptr to an array of POINTs that contain the lines that approximinate the * Ptr to an array of POINTs that contain the lines that approximate the
* Beziers. The array is allocated on the process heap and it is the caller's * Beziers. The array is allocated on the process heap and it is the caller's
* responsibility to HeapFree it. [this is not a particularly nice interface * responsibility to HeapFree it. [this is not a particularly nice interface
* but since we can't know in advance how many points will generate, the * but since we can't know in advance how many points we will generate, the
* alternative would be to call the function twice, once to determine the size * alternative would be to call the function twice, once to determine the size
* and a second time to do the work - I decided this was too much of a pain]. * and a second time to do the work - I decided this was too much of a pain].
*/ */
POINT * FASTCALL GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut ) POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
{ {
POINT *out; POINT *out;
INT Bezier, dwOut = BEZIER_INITBUFSIZE, i; INT Bezier, dwOut = BEZIER_INITBUFSIZE, i;
if((count - 1) % 3 != 0) { if (count == 1 || (count - 1) % 3 != 0) {
return NULL; DPRINT1("Invalid no. of points %d\n", count);
} return NULL;
*nPtsOut = 0;
out = ExAllocatePoolWithTag(PagedPool, dwOut * sizeof(POINT), TAG_BEZIER);
if(!out) {
return NULL;
}
for(Bezier = 0; Bezier < (count-1)/3; Bezier++) {
POINT ptBuf[4];
memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4);
for(i = 0; i < 4; i++) {
ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x);
ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y);
} }
GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH ); *nPtsOut = 0;
}
return out; out = ExAllocatePoolWithTag(PagedPool, dwOut * sizeof(POINT), TAG_BEZIER);
if (!out) return NULL;
for(Bezier = 0; Bezier < (count-1)/3; Bezier++) {
POINT ptBuf[4];
memcpy(ptBuf, Points + Bezier * 3, sizeof(POINT) * 4);
for(i = 0; i < 4; i++) {
ptBuf[i].x = BEZIERSHIFTUP(ptBuf[i].x);
ptBuf[i].y = BEZIERSHIFTUP(ptBuf[i].y);
}
GDI_InternalBezier( ptBuf, &out, &dwOut, nPtsOut, BEZIERMAXDEPTH );
}
DPRINT("Produced %d points\n", *nPtsOut);
return out;
} }
/* EOF */ /* EOF */

View file

@ -124,7 +124,7 @@ IntGetSystemPaletteEntries(HDC hDC,
VOID FASTCALL CreateStockObjects (VOID); VOID FASTCALL CreateStockObjects (VOID);
VOID FASTCALL CreateSysColorObjects (VOID); VOID FASTCALL CreateSysColorObjects (VOID);
PPOINT FASTCALL GDI_Bezier (const POINT *Points, INT count, PINT nPtsOut); PPOINT GDI_Bezier (const POINT *Points, INT count, PINT nPtsOut);
BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype); BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype);
BOOL FASTCALL IntDrawArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PBRUSH pbrush); BOOL FASTCALL IntDrawArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PBRUSH pbrush);