mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 22:52:58 +00:00
- Rewritten NtGdiEllipse with improved and optimized algorithm. Now it works also for non-circles, but unfortuently it still looks a bit choppy.
svn path=/trunk/; revision=8030
This commit is contained in:
parent
75a008acf6
commit
f599776b65
1 changed files with 167 additions and 139 deletions
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: fillshap.c,v 1.38 2003/12/13 13:05:30 weiden Exp $ */
|
/* $Id: fillshap.c,v 1.39 2004/02/04 22:10:00 navaraf Exp $ */
|
||||||
|
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -205,164 +205,192 @@ NtGdiChord(HDC hDC,
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
/*
|
||||||
STDCALL
|
* NtGdiEllipse
|
||||||
NtGdiEllipse(HDC hDC,
|
*
|
||||||
int Left,
|
* Author
|
||||||
int Top,
|
* Filip Navara
|
||||||
int Right,
|
*
|
||||||
int Bottom)
|
* Remarks
|
||||||
{
|
* This function uses optimized Bresenham's ellipse algorithm. It draws
|
||||||
PDC dc;
|
* four lines of the ellipse in one pass.
|
||||||
int X, X18, X27, X36, X45;
|
*
|
||||||
int Y, Y14, Y23, Y58, Y67;
|
* Todo
|
||||||
int d, Radius;
|
* Make it look like a Windows ellipse.
|
||||||
RECTL RectBounds;
|
*/
|
||||||
PSURFOBJ SurfObj;
|
|
||||||
BRUSHOBJ PenBrushObj;
|
|
||||||
PBRUSHOBJ FillBrushObj;
|
|
||||||
BOOL Even;
|
|
||||||
BOOL ret = TRUE;
|
|
||||||
|
|
||||||
if (Right <= Left || Bottom <= Top)
|
BOOL STDCALL
|
||||||
|
NtGdiEllipse(
|
||||||
|
HDC hDC,
|
||||||
|
int nLeftRect,
|
||||||
|
int nTopRect,
|
||||||
|
int nRightRect,
|
||||||
|
int nBottomRect)
|
||||||
|
{
|
||||||
|
int ix, iy;
|
||||||
|
int A, B, C, D;
|
||||||
|
int da, db;
|
||||||
|
int NewA, NewB, NewC, NewD;
|
||||||
|
int nx, ny;
|
||||||
|
int CenterX, CenterY;
|
||||||
|
int RadiusX, RadiusY;
|
||||||
|
int Temp;
|
||||||
|
BRUSHOBJ PenBrush;
|
||||||
|
PBRUSHOBJ FillBrush;
|
||||||
|
PSURFOBJ SurfObj;
|
||||||
|
RECTL RectBounds;
|
||||||
|
PDC dc;
|
||||||
|
BOOL ret = TRUE, Cond1, Cond2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nRightRect <= nLeftRect || nBottomRect <= nTopRect)
|
||||||
{
|
{
|
||||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Right - Left != Bottom - Top)
|
/*
|
||||||
{
|
* Get pointers to all necessary GDI objects.
|
||||||
UNIMPLEMENTED;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
dc = DC_LockDc ( hDC );
|
dc = DC_LockDc(hDC);
|
||||||
if (NULL == dc)
|
if (dc == NULL)
|
||||||
{
|
{
|
||||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
|
FillBrush = BRUSHOBJ_LockBrush(dc->w.hBrush);
|
||||||
if (NULL == FillBrushObj)
|
if (NULL == FillBrush)
|
||||||
{
|
{
|
||||||
DC_UnlockDc(hDC);
|
DC_UnlockDc(hDC);
|
||||||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Even = (0 == (Right - Left) % 2);
|
SurfObj = (PSURFOBJ)AccessUserObject((ULONG)dc->Surface);
|
||||||
|
HPenToBrushObj(&PenBrush, dc->w.hPen);
|
||||||
|
|
||||||
Left += dc->w.DCOrgX;
|
nLeftRect += dc->w.DCOrgX;
|
||||||
Right += dc->w.DCOrgX - 1;
|
nRightRect += dc->w.DCOrgX;
|
||||||
Top += dc->w.DCOrgY;
|
nTopRect += dc->w.DCOrgY;
|
||||||
Bottom += dc->w.DCOrgY - 1;
|
nBottomRect += dc->w.DCOrgY;
|
||||||
|
|
||||||
RectBounds.left = Left;
|
RadiusX = max((nRightRect - nLeftRect) >> 1, 1);
|
||||||
RectBounds.right = Right;
|
RadiusY = max((nBottomRect - nTopRect) >> 1, 1);
|
||||||
RectBounds.top = Top;
|
CenterX = nLeftRect + RadiusX;
|
||||||
RectBounds.bottom = Bottom;
|
CenterY = nTopRect + RadiusY;
|
||||||
|
|
||||||
SurfObj = (PSURFOBJ) AccessUserObject((ULONG)dc->Surface);
|
RectBounds.left = nLeftRect;
|
||||||
HPenToBrushObj(&PenBrushObj, dc->w.hPen);
|
RectBounds.right = nRightRect;
|
||||||
|
RectBounds.top = nTopRect;
|
||||||
|
RectBounds.bottom = nBottomRect;
|
||||||
|
|
||||||
if (Left == Right)
|
if (RadiusX > RadiusY)
|
||||||
{
|
{
|
||||||
PUTPIXEL(Left, Top, &PenBrushObj);
|
nx = RadiusX;
|
||||||
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
|
ny = RadiusY;
|
||||||
DC_UnlockDc(hDC);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Radius = (Right - Left) / 2;
|
|
||||||
if (Even)
|
|
||||||
{
|
|
||||||
X = 0;
|
|
||||||
Y = Radius;
|
|
||||||
d = 2 - Radius;
|
|
||||||
X18 = Right;
|
|
||||||
X27 = (Left + Right) / 2 + 1;
|
|
||||||
X36 = (Left + Right) / 2;
|
|
||||||
X45 = Left;
|
|
||||||
Y14 = Top + Radius;
|
|
||||||
Y23 = Top;
|
|
||||||
Y58 = Top + Radius + 1;
|
|
||||||
Y67 = Top + (Right - Left);
|
|
||||||
PUTLINE(X45 + 1, Y14, X18, Y14, FillBrushObj);
|
|
||||||
PUTLINE(X45 + 1, Y58, X18, Y58, FillBrushObj);
|
|
||||||
PUTPIXEL(X27, Y23, &PenBrushObj);
|
|
||||||
PUTPIXEL(X36, Y23, &PenBrushObj);
|
|
||||||
PUTPIXEL(X18, Y14, &PenBrushObj);
|
|
||||||
PUTPIXEL(X45, Y14, &PenBrushObj);
|
|
||||||
PUTPIXEL(X18, Y58, &PenBrushObj);
|
|
||||||
PUTPIXEL(X45, Y58, &PenBrushObj);
|
|
||||||
PUTPIXEL(X27, Y67, &PenBrushObj);
|
|
||||||
PUTPIXEL(X36, Y67, &PenBrushObj);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
X = 0;
|
nx = RadiusY;
|
||||||
Y = Radius;
|
ny = RadiusX;
|
||||||
d = 1 - Radius;
|
|
||||||
X18 = Right;
|
|
||||||
X27 = (Left + Right) / 2;
|
|
||||||
X36 = (Left + Right) / 2;
|
|
||||||
X45 = Left;
|
|
||||||
Y14 = Top + Radius;
|
|
||||||
Y23 = Top;
|
|
||||||
Y58 = Top + Radius;
|
|
||||||
Y67 = Top + (Right - Left);
|
|
||||||
PUTLINE(X45 + 1, Y14, X18, Y58, FillBrushObj);
|
|
||||||
PUTPIXEL(X27, Y23, &PenBrushObj);
|
|
||||||
PUTPIXEL(X45, Y14, &PenBrushObj);
|
|
||||||
PUTPIXEL(X18, Y58, &PenBrushObj);
|
|
||||||
PUTPIXEL(X27, Y67, &PenBrushObj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (X < Y)
|
da = -1;
|
||||||
{
|
db = 0xFFFF;
|
||||||
if (d < 0)
|
ix = 0;
|
||||||
{
|
iy = nx * 64;
|
||||||
d += 2 * X + (Even ? 4 : 3);
|
NewA = 0;
|
||||||
|
NewB = (iy + 32) >> 6;
|
||||||
|
NewC = 0;
|
||||||
|
NewD = (NewB * ny) / nx;
|
||||||
|
|
||||||
X27++;
|
do {
|
||||||
X36--;
|
A = NewA;
|
||||||
Y14--;
|
B = NewB;
|
||||||
Y58++;
|
C = NewC;
|
||||||
|
D = NewD;
|
||||||
|
|
||||||
|
ix += iy / nx;
|
||||||
|
iy -= ix / nx;
|
||||||
|
NewA = (ix + 32) >> 6;
|
||||||
|
NewB = (iy + 32) >> 6;
|
||||||
|
NewC = (NewA * ny) / nx;
|
||||||
|
NewD = (NewB * ny) / nx;
|
||||||
|
|
||||||
|
if (RadiusX > RadiusY)
|
||||||
|
{
|
||||||
|
Temp = A; A = C; C = Temp;
|
||||||
|
Temp = B; B = D; D = Temp;
|
||||||
|
Cond1 = ((C != NewA) || (B != NewD)) && (NewC <= NewD);
|
||||||
|
Cond2 = ((D != NewB) || (A != NewC)) && (NewC <= B);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
d += 2 * (X - Y) + 5;
|
Cond1 = ((C != NewC) || (B != NewB)) && (NewA <= NewB);
|
||||||
Y--;
|
Cond2 = ((D != NewD) || (A != NewA)) && (NewA <= B);
|
||||||
|
|
||||||
Y23++;
|
|
||||||
Y67--;
|
|
||||||
X18--;
|
|
||||||
X45++;
|
|
||||||
X27++;
|
|
||||||
X36--;
|
|
||||||
Y14--;
|
|
||||||
Y58++;
|
|
||||||
PUTLINE(X36 + 1, Y23, X27, Y23, FillBrushObj);
|
|
||||||
PUTLINE(X36 + 1, Y67, X27, Y67, FillBrushObj);
|
|
||||||
}
|
}
|
||||||
X++;
|
|
||||||
|
|
||||||
if (Y23 < Y14)
|
/*
|
||||||
|
* Draw the lines going from inner to outer (+ mirrored).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((A > da) && (A < db))
|
||||||
{
|
{
|
||||||
PUTLINE(X45 + 1, Y14, X18, Y14, FillBrushObj);
|
PUTLINE(CenterX - D, CenterY + A, CenterX + D, CenterY + A, FillBrush);
|
||||||
PUTLINE(X45 + 1, Y58, X18, Y58, FillBrushObj);
|
if (A)
|
||||||
|
{
|
||||||
|
PUTLINE(CenterX - D, CenterY - A, CenterX + D, CenterY - A, FillBrush);
|
||||||
}
|
}
|
||||||
PUTPIXEL(X27, Y23, &PenBrushObj);
|
da = A;
|
||||||
PUTPIXEL(X36, Y23, &PenBrushObj);
|
|
||||||
PUTPIXEL(X18, Y14, &PenBrushObj);
|
|
||||||
PUTPIXEL(X45, Y14, &PenBrushObj);
|
|
||||||
PUTPIXEL(X18, Y58, &PenBrushObj);
|
|
||||||
PUTPIXEL(X45, Y58, &PenBrushObj);
|
|
||||||
PUTPIXEL(X27, Y67, &PenBrushObj);
|
|
||||||
PUTPIXEL(X36, Y67, &PenBrushObj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw the lines going from outer to inner (+ mirrored).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((B < db) && (B > da))
|
||||||
|
{
|
||||||
|
PUTLINE(CenterX - C, CenterY + B, CenterX + C, CenterY + B, FillBrush);
|
||||||
|
PUTLINE(CenterX - C, CenterY - B, CenterX + C, CenterY - B, FillBrush);
|
||||||
|
db = B;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Draw the pixels on the margin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Cond1)
|
||||||
|
{
|
||||||
|
PUTPIXEL(CenterX + C, CenterY + B, &PenBrush);
|
||||||
|
if (C)
|
||||||
|
PUTPIXEL(CenterX - C, CenterY + B, &PenBrush);
|
||||||
|
if (B)
|
||||||
|
{
|
||||||
|
PUTPIXEL(CenterX + C, CenterY - B, &PenBrush);
|
||||||
|
if (C)
|
||||||
|
PUTPIXEL(CenterX - C, CenterY - B, &PenBrush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cond2)
|
||||||
|
{
|
||||||
|
PUTPIXEL(CenterX + D, CenterY + A, &PenBrush);
|
||||||
|
if (D)
|
||||||
|
PUTPIXEL(CenterX - D, CenterY + A, &PenBrush);
|
||||||
|
if (A)
|
||||||
|
{
|
||||||
|
PUTPIXEL(CenterX + D, CenterY - A, &PenBrush);
|
||||||
|
if (D)
|
||||||
|
PUTPIXEL(CenterX - D, CenterY - A, &PenBrush);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (B > A);
|
||||||
|
|
||||||
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
|
BRUSHOBJ_UnlockBrush(dc->w.hBrush);
|
||||||
DC_UnlockDc(hDC);
|
DC_UnlockDc(hDC);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue