mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
Arc, Ellipse:
- Converted over to use the new fill square algorithm for fill arcs and draw/fill ellipse. - Tested with (Area.exe) Yuan program. Chord work and the CW/CCW works as it should. - The pie angle still floats with aspect ratio of ellipse and not point fixed. Work in progress. svn path=/trunk/; revision=34233
This commit is contained in:
parent
fda8db4dd3
commit
9f5ede7adb
3 changed files with 452 additions and 247 deletions
|
@ -42,7 +42,7 @@ IntArc( DC *dc,
|
|||
ARCTYPE arctype)
|
||||
{
|
||||
PDC_ATTR Dc_Attr;
|
||||
RECTL RectBounds;
|
||||
RECTL RectBounds, RectSEpts;
|
||||
PGDIBRUSHOBJ PenBrushObj;
|
||||
GDIBRUSHINST PenBrushInst;
|
||||
BITMAPOBJ *BitmapObj;
|
||||
|
@ -67,17 +67,6 @@ IntArc( DC *dc,
|
|||
(Bottom - Top == 1))))
|
||||
return TRUE;
|
||||
|
||||
if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
|
||||
{
|
||||
INT X, Y;
|
||||
X = XRadialStart;
|
||||
Y = YRadialStart;
|
||||
XRadialStart = XRadialEnd;
|
||||
YRadialStart = YRadialEnd;
|
||||
XRadialEnd = X;
|
||||
YRadialEnd = Y;
|
||||
}
|
||||
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
||||
|
@ -105,25 +94,31 @@ IntArc( DC *dc,
|
|||
if (!PenWidth) PenWidth = 1;
|
||||
PenBrushObj->ptPenWidth.x = PenWidth;
|
||||
|
||||
Left += dc->ptlDCOrig.x;
|
||||
Right += dc->ptlDCOrig.x;
|
||||
Top += dc->ptlDCOrig.y;
|
||||
Bottom += dc->ptlDCOrig.y;
|
||||
|
||||
XRadialStart += dc->ptlDCOrig.x;
|
||||
YRadialStart += dc->ptlDCOrig.y;
|
||||
XRadialEnd += dc->ptlDCOrig.x;
|
||||
YRadialEnd += dc->ptlDCOrig.y;
|
||||
|
||||
DPRINT("1: StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
|
||||
XRadialStart,YRadialStart,XRadialEnd,YRadialEnd);
|
||||
|
||||
RectBounds.left = Left;
|
||||
RectBounds.right = Right;
|
||||
RectBounds.top = Top;
|
||||
RectBounds.bottom = Bottom;
|
||||
|
||||
RectSEpts.left = XRadialStart;
|
||||
RectSEpts.top = YRadialStart;
|
||||
RectSEpts.right = XRadialEnd;
|
||||
RectSEpts.bottom = YRadialEnd;
|
||||
|
||||
IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
|
||||
IntLPtoDP(dc, (LPPOINT)&RectSEpts, 2);
|
||||
|
||||
RectBounds.left += dc->ptlDCOrig.x;
|
||||
RectBounds.right += dc->ptlDCOrig.x;
|
||||
RectBounds.top += dc->ptlDCOrig.y;
|
||||
RectBounds.bottom += dc->ptlDCOrig.y;
|
||||
|
||||
RectSEpts.left += dc->ptlDCOrig.x;
|
||||
RectSEpts.top += dc->ptlDCOrig.y;
|
||||
RectSEpts.right += dc->ptlDCOrig.x;
|
||||
RectSEpts.bottom += dc->ptlDCOrig.y;
|
||||
|
||||
DPRINT("1: StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
|
||||
RectSEpts.left,RectSEpts.top,RectSEpts.right,RectSEpts.bottom);
|
||||
|
||||
DPRINT("1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
|
||||
RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
|
||||
|
@ -132,8 +127,8 @@ IntArc( DC *dc,
|
|||
RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 1);
|
||||
CenterX = (RectBounds.right + RectBounds.left) / 2;
|
||||
CenterY = (RectBounds.bottom + RectBounds.top) / 2;
|
||||
AngleEnd = atan2((YRadialEnd - CenterY), XRadialEnd - CenterX)*(360.0/(M_PI*2));
|
||||
AngleStart = atan2((YRadialStart - CenterY), XRadialStart - CenterX)*(360.0/(M_PI*2));
|
||||
AngleEnd = atan2((RectSEpts.bottom - CenterY), RectSEpts.right - CenterX)*(360.0/(M_PI*2));
|
||||
AngleStart = atan2((RectSEpts.top - CenterY), RectSEpts.left - CenterX)*(360.0/(M_PI*2));
|
||||
|
||||
SfCx = (Rcos(AngleStart) * RadiusX);
|
||||
SfCy = (Rsin(AngleStart) * RadiusY);
|
||||
|
@ -175,7 +170,7 @@ IntArc( DC *dc,
|
|||
|
||||
if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
|
||||
{
|
||||
DPRINT("Arc CW\n");
|
||||
DPRINT1("Arc CW\n");
|
||||
for (; AngS < AngT; AngS += Factor)
|
||||
{
|
||||
x = (RadiusX * Rcos(AngS));
|
||||
|
@ -197,7 +192,7 @@ IntArc( DC *dc,
|
|||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Arc CCW\n");
|
||||
DPRINT1("Arc CCW\n");
|
||||
for (; AngT < AngS; AngS -= Factor)
|
||||
{
|
||||
x = (RadiusX * Rcos(AngS));
|
||||
|
|
|
@ -81,12 +81,11 @@ INTERNAL_CALL
|
|||
rect(int x, int y, int width, int height)
|
||||
{
|
||||
Rect r;
|
||||
|
||||
r.x = x;
|
||||
r.y = y;
|
||||
r.width = width;
|
||||
r.height = height;
|
||||
return r;
|
||||
r.y = y;
|
||||
r.width = width;
|
||||
r.height = height;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
@ -107,11 +106,13 @@ int
|
|||
INTERNAL_CALL
|
||||
app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
|
||||
{
|
||||
DWORD ROP = PATCOPY;
|
||||
RECTL DestRect;
|
||||
BITMAPOBJ *BitmapObj;
|
||||
GDIBRUSHINST BrushInst;
|
||||
POINTL BrushOrigin;
|
||||
BOOL Ret = TRUE;
|
||||
PDC_ATTR Dc_Attr = NULL;
|
||||
|
||||
ASSERT(BrushObj);
|
||||
|
||||
|
@ -124,6 +125,8 @@ app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
|
|||
|
||||
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
|
||||
{
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
||||
/* fix negative spaces */
|
||||
if (r.width < 0)
|
||||
|
@ -146,6 +149,11 @@ app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
|
|||
BrushOrigin.x = BrushObj->ptOrigin.x;
|
||||
BrushOrigin.y = BrushObj->ptOrigin.y;
|
||||
|
||||
if (Dc_Attr->jROP2 == R2_XORPEN)
|
||||
ROP = PATINVERT;
|
||||
else
|
||||
ROP = PATCOPY;
|
||||
|
||||
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
|
||||
|
||||
Ret = IntEngBitBlt(
|
||||
|
@ -159,13 +167,301 @@ app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
|
|||
NULL,
|
||||
&BrushInst.BrushObject, // use pDC->eboFill
|
||||
&BrushOrigin,
|
||||
ROP3_TO_ROP4(PATCOPY));
|
||||
ROP3_TO_ROP4(ROP));
|
||||
}
|
||||
|
||||
BITMAPOBJ_UnlockBitmap(BitmapObj);
|
||||
return (int)Ret;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
INTERNAL_CALL
|
||||
app_fill_rect_pen(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
|
||||
{
|
||||
DWORD ROP = PATCOPY;
|
||||
RECTL DestRect;
|
||||
BITMAPOBJ *BitmapObj;
|
||||
GDIBRUSHINST BrushInst;
|
||||
POINTL BrushOrigin;
|
||||
BOOL Ret = TRUE;
|
||||
PDC_ATTR Dc_Attr = NULL;
|
||||
|
||||
ASSERT(BrushObj);
|
||||
|
||||
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
||||
if (BitmapObj == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
|
||||
{
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
||||
/* fix negative spaces */
|
||||
if (r.width < 0)
|
||||
{
|
||||
r.x += r.width;
|
||||
r.width = 0 - r.width;
|
||||
}
|
||||
if (r.height < 0)
|
||||
{
|
||||
r.y += r.height;
|
||||
r.height = 0 - r.height;
|
||||
}
|
||||
|
||||
DestRect.left = r.x;
|
||||
DestRect.right = r.x + r.width;
|
||||
|
||||
DestRect.top = r.y;
|
||||
DestRect.bottom = r.y + r.height;
|
||||
|
||||
BrushOrigin.x = BrushObj->ptOrigin.x;
|
||||
BrushOrigin.y = BrushObj->ptOrigin.y;
|
||||
|
||||
if (Dc_Attr->jROP2 == R2_XORPEN)
|
||||
ROP = PATINVERT;
|
||||
else
|
||||
ROP = PATCOPY;
|
||||
|
||||
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlatePen);
|
||||
|
||||
Ret = IntEngBitBlt(
|
||||
&BitmapObj->SurfObj,
|
||||
NULL,
|
||||
NULL,
|
||||
dc->CombinedClip,
|
||||
NULL,
|
||||
&DestRect,
|
||||
NULL,
|
||||
NULL,
|
||||
&BrushInst.BrushObject, // use pDC->eboFill
|
||||
&BrushOrigin,
|
||||
ROP3_TO_ROP4(ROP));
|
||||
}
|
||||
|
||||
BITMAPOBJ_UnlockBitmap(BitmapObj);
|
||||
return (int)Ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Drawing an ellipse with a certain line thickness.
|
||||
* Use an inner and and outer ellipse and fill the spaces between.
|
||||
* The inner ellipse uses all UPPERCASE letters, the outer lowercase.
|
||||
*
|
||||
* This algorithm is based on the fill_ellipse algorithm presented
|
||||
* above, but uses two ellipse calculations, and some fix-up code
|
||||
* to avoid pathological cases where the inner ellipse is almost
|
||||
* the same size as the outer (in which case the border of the
|
||||
* elliptical curve might otherwise have appeared broken).
|
||||
*/
|
||||
static
|
||||
int
|
||||
INTERNAL_CALL
|
||||
app_draw_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
|
||||
{
|
||||
/* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
|
||||
|
||||
int a = r.width / 2;
|
||||
int b = r.height / 2;
|
||||
int x = 0;
|
||||
int y = b;
|
||||
long a2 = a*a;
|
||||
long b2 = b*b;
|
||||
long xcrit = (3 * a2 / 4) + 1;
|
||||
long ycrit = (3 * b2 / 4) + 1;
|
||||
long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
|
||||
long dxt = b2*(3+x+x);
|
||||
long dyt = a2*(3-y-y);
|
||||
int d2xt = b2+b2;
|
||||
int d2yt = a2+a2;
|
||||
|
||||
int w = BrushObj->ptPenWidth.x;
|
||||
|
||||
/* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
|
||||
|
||||
int A = a-w > 0 ? a-w : 0;
|
||||
int B = b-w > 0 ? b-w : 0;
|
||||
int X = 0;
|
||||
int Y = B;
|
||||
long A2 = A*A;
|
||||
long B2 = B*B;
|
||||
long XCRIT = (3 * A2 / 4) + 1;
|
||||
long YCRIT = (3 * B2 / 4) + 1;
|
||||
long T = B2 + A2 - 2*A2*B; /* T = E(X+1,Y-1) */
|
||||
long DXT = B2*(3+X+X);
|
||||
long DYT = A2*(3-Y-Y);
|
||||
int D2XT = B2+B2;
|
||||
int D2YT = A2+A2;
|
||||
|
||||
int movedown, moveout;
|
||||
int innerX = 0, prevx, prevy, W;
|
||||
Rect r1, r2;
|
||||
int result = 1;
|
||||
|
||||
// START_DEBUG();
|
||||
|
||||
if ((r.width <= 2) || (r.height <= 2))
|
||||
return app_fill_rect_pen(g, r, BrushObj);
|
||||
|
||||
r1.x = r.x + a;
|
||||
r1.y = r.y;
|
||||
r1.width = r.width & 1; /* i.e. if width is odd */
|
||||
r1.height = 1;
|
||||
|
||||
r2 = r1;
|
||||
r2.y = r.y + r.height - 1;
|
||||
|
||||
prevx = r1.x;
|
||||
prevy = r1.y;
|
||||
|
||||
while (y > 0)
|
||||
{
|
||||
while (Y == y)
|
||||
{
|
||||
innerX = X;
|
||||
|
||||
if (T + A2*Y < XCRIT) /* E(X+1,Y-1/2) <= 0 */
|
||||
{
|
||||
/* move outwards to encounter edge */
|
||||
X += 1;
|
||||
T += DXT;
|
||||
DXT += D2XT;
|
||||
}
|
||||
else if (T - B2*X >= YCRIT) /* e(x+1/2,y-1) > 0 */
|
||||
{
|
||||
/* drop down one line */
|
||||
Y -= 1;
|
||||
T += DYT;
|
||||
DYT += D2YT;
|
||||
}
|
||||
else {
|
||||
/* drop diagonally down and out */
|
||||
X += 1;
|
||||
Y -= 1;
|
||||
T += DXT + DYT;
|
||||
DXT += D2XT;
|
||||
DYT += D2YT;
|
||||
}
|
||||
}
|
||||
|
||||
movedown = moveout = 0;
|
||||
|
||||
W = x - innerX;
|
||||
if (r1.x + W < prevx)
|
||||
W = prevx - r1.x;
|
||||
if (W < w)
|
||||
W = w;
|
||||
|
||||
if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
|
||||
{
|
||||
/* move outwards to encounter edge */
|
||||
x += 1;
|
||||
t += dxt;
|
||||
dxt += d2xt;
|
||||
|
||||
moveout = 1;
|
||||
}
|
||||
else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
|
||||
{
|
||||
/* drop down one line */
|
||||
y -= 1;
|
||||
t += dyt;
|
||||
dyt += d2yt;
|
||||
|
||||
movedown = 1;
|
||||
}
|
||||
else {
|
||||
/* drop diagonally down and out */
|
||||
x += 1;
|
||||
y -= 1;
|
||||
t += dxt + dyt;
|
||||
dxt += d2xt;
|
||||
dyt += d2yt;
|
||||
|
||||
movedown = 1;
|
||||
moveout = 1;
|
||||
}
|
||||
|
||||
if (movedown) {
|
||||
if (r1.width == 0) {
|
||||
r1.x -= 1; r1.width += 2;
|
||||
r2.x -= 1; r2.width += 2;
|
||||
moveout = 0;
|
||||
}
|
||||
|
||||
if (r1.x < r.x)
|
||||
r1.x = r2.x = r.x;
|
||||
if (r1.width > r.width)
|
||||
r1.width = r2.width = r.width;
|
||||
if (r1.y == r2.y-1) {
|
||||
r1.x = r2.x = r.x;
|
||||
r1.width = r2.width = r.width;
|
||||
}
|
||||
|
||||
if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W))
|
||||
{
|
||||
result &= app_fill_rect_pen(g, r1, BrushObj);
|
||||
result &= app_fill_rect_pen(g, r2, BrushObj);
|
||||
|
||||
prevx = r1.x;
|
||||
prevy = r1.y;
|
||||
}
|
||||
else if (r1.y+r1.height < r2.y)
|
||||
{
|
||||
/* draw distinct rectangles */
|
||||
result &= app_fill_rect_pen(g, rect(r1.x,r1.y,
|
||||
W,1), BrushObj);
|
||||
result &= app_fill_rect_pen(g, rect(
|
||||
r1.x+r1.width-W,r1.y,W,1), BrushObj);
|
||||
result &= app_fill_rect_pen(g, rect(r2.x,
|
||||
r2.y,W,1), BrushObj);
|
||||
result &= app_fill_rect_pen(g, rect(
|
||||
r2.x+r2.width-W,r2.y,W,1), BrushObj);
|
||||
|
||||
prevx = r1.x;
|
||||
prevy = r1.y;
|
||||
}
|
||||
|
||||
/* move down */
|
||||
r1.y += 1;
|
||||
r2.y -= 1;
|
||||
}
|
||||
|
||||
if (moveout) {
|
||||
/* move outwards */
|
||||
r1.x -= 1; r1.width += 2;
|
||||
r2.x -= 1; r2.width += 2;
|
||||
}
|
||||
}
|
||||
if ((x <= a) && (prevy < r2.y)) {
|
||||
/* draw final line */
|
||||
r1.height = r1.y+r1.height-r2.y;
|
||||
r1.y = r2.y;
|
||||
|
||||
W = w;
|
||||
if (r.x + W != prevx)
|
||||
W = prevx - r.x;
|
||||
if (W < w)
|
||||
W = w;
|
||||
|
||||
if (W+W >= r.width) {
|
||||
result &= app_fill_rect_pen(g, rect(r.x, r1.y,
|
||||
r.width, r1.height), BrushObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
result &= app_fill_rect_pen(g, rect(r.x, r1.y, W, r1.height), BrushObj);
|
||||
result &= app_fill_rect_pen(g, rect(r.x+r.width-W, r1.y,
|
||||
W, r1.height), BrushObj);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw an arc of an ellipse from start_angle anti-clockwise to
|
||||
* end_angle. If the angles coincide, draw nothing; if they
|
||||
|
@ -652,14 +948,11 @@ app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ BrushOb
|
|||
/* find arc wedge line end points */
|
||||
p1 = app_boundary_point(r, start_angle);
|
||||
p2 = app_boundary_point(r, end_angle);
|
||||
p0 = pt(r.x + r.width/2, r.y + r.height/2);
|
||||
if (Chord)
|
||||
{
|
||||
int zx, zy;
|
||||
zx = (p0.x-p1.x)/2;
|
||||
zy = (p2.y-p1.y)/2;
|
||||
p0 = pt(p1.x+zx,p0.y+zy);
|
||||
}
|
||||
p0 = pt((p1.x+p2.x)/2,(p1.y+p2.y)/2);
|
||||
else
|
||||
p0 = pt(r.x + r.width/2, r.y + r.height/2);
|
||||
|
||||
/* initialise rectangles to be drawn */
|
||||
r1.x = r.x + a;
|
||||
r1.y = r.y;
|
||||
|
@ -785,8 +1078,7 @@ IntFillArc( PDC dc,
|
|||
PGDIBRUSHOBJ FillBrushObj;
|
||||
int Start = ceill(StartArc);
|
||||
int End = ceill(EndArc);
|
||||
Rect r;
|
||||
BOOL Chord = (arctype == GdiTypeChord);
|
||||
BOOL Chord = (arctype == GdiTypeChord), ret;
|
||||
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
@ -798,18 +1090,52 @@ IntFillArc( PDC dc,
|
|||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
r.x = XLeft;
|
||||
r.y = YLeft;
|
||||
r.width = Width;
|
||||
r.height = Height;
|
||||
// Sort out alignment here.
|
||||
app_fill_arc(dc, r,
|
||||
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start,
|
||||
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
|
||||
FillBrushObj, Chord);
|
||||
|
||||
ret = app_fill_arc(dc, rect( XLeft, YLeft, Width, Height),
|
||||
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start,
|
||||
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
|
||||
FillBrushObj, Chord);
|
||||
|
||||
BRUSHOBJ_UnlockBrush(FillBrushObj);
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
IntDrawEllipse( PDC dc,
|
||||
INT XLeft,
|
||||
INT YLeft,
|
||||
INT Width,
|
||||
INT Height,
|
||||
PGDIBRUSHOBJ PenBrushObj)
|
||||
{
|
||||
return (BOOL)app_draw_ellipse(dc, rect( XLeft, YLeft, Width, Height), PenBrushObj);
|
||||
}
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
IntFillEllipse( PDC dc,
|
||||
INT XLeft,
|
||||
INT YLeft,
|
||||
INT Width,
|
||||
INT Height)
|
||||
{
|
||||
BOOL ret;
|
||||
PDC_ATTR Dc_Attr;
|
||||
PGDIBRUSHOBJ FillBrushObj;
|
||||
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
||||
FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
|
||||
if (NULL == FillBrushObj)
|
||||
{
|
||||
DPRINT1("FillEllipse Fail\n");
|
||||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
ret = (BOOL)app_fill_ellipse(dc, rect( XLeft, YLeft, Width, Height), FillBrushObj);
|
||||
|
||||
BRUSHOBJ_UnlockBrush(FillBrushObj);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@
|
|||
&RectBounds, \
|
||||
ROP2_TO_MIX(Dc_Attr->jROP2));
|
||||
|
||||
#define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
|
||||
#define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
|
||||
|
||||
BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height);
|
||||
BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ PenBrushObj);
|
||||
|
||||
BOOL FASTCALL
|
||||
IntGdiPolygon(PDC dc,
|
||||
PPOINT UnsafePoints,
|
||||
|
@ -133,9 +139,9 @@ IntGdiPolygon(PDC dc,
|
|||
ret = IntEngLineTo(&BitmapObj->SurfObj,
|
||||
dc->CombinedClip,
|
||||
&PenBrushInst.BrushObject,
|
||||
UnsafePoints[Count-1].x, /* From */
|
||||
UnsafePoints[Count-1].x, /* From */
|
||||
UnsafePoints[Count-1].y,
|
||||
UnsafePoints[0].x, /* To */
|
||||
UnsafePoints[0].x, /* To */
|
||||
UnsafePoints[0].y,
|
||||
&DestRect,
|
||||
ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
|
||||
|
@ -156,6 +162,7 @@ IntGdiPolyPolygon(DC *dc,
|
|||
{
|
||||
if (PATH_IsPathOpen(dc->DcLevel))
|
||||
return PATH_PolyPolygon ( dc, Points, PolyCounts, Count);
|
||||
|
||||
while (--Count >=0)
|
||||
{
|
||||
if (!IntGdiPolygon ( dc, Points, *PolyCounts ))
|
||||
|
@ -179,247 +186,124 @@ IntGdiPolyPolygon(DC *dc,
|
|||
* This function uses optimized Bresenham's ellipse algorithm. It draws
|
||||
* four lines of the ellipse in one pass.
|
||||
*
|
||||
* Todo
|
||||
* Make it look like a Windows ellipse.
|
||||
*/
|
||||
|
||||
BOOL STDCALL
|
||||
NtGdiEllipse(
|
||||
HDC hDC,
|
||||
int nLeftRect,
|
||||
int nTopRect,
|
||||
int nRightRect,
|
||||
int nBottomRect)
|
||||
int Left,
|
||||
int Top,
|
||||
int Right,
|
||||
int Bottom)
|
||||
{
|
||||
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;
|
||||
PGDIBRUSHOBJ FillBrush, PenBrush;
|
||||
GDIBRUSHINST FillBrushInst, PenBrushInst;
|
||||
BITMAPOBJ *BitmapObj;
|
||||
RECTL RectBounds;
|
||||
PDC dc;
|
||||
PDC_ATTR Dc_Attr;
|
||||
BOOL ret = TRUE, Cond1, Cond2;
|
||||
/* top
|
||||
___________________
|
||||
+| |
|
||||
| |
|
||||
| |
|
||||
left | | right
|
||||
| |
|
||||
| |
|
||||
0|___________________|
|
||||
0 bottom +
|
||||
*/
|
||||
/*
|
||||
* Check the parameters.
|
||||
*/
|
||||
DPRINT("nLeftRect: %d, nTopRect: %d, nRightRect: %d, nBottomRect: %d\n",nLeftRect,nTopRect,nRightRect,nBottomRect);
|
||||
RECTL RectBounds;
|
||||
PGDIBRUSHOBJ PenBrushObj;
|
||||
BOOL ret = TRUE;
|
||||
LONG PenWidth, PenOrigWidth;
|
||||
LONG RadiusX, RadiusY, CenterX, CenterY;
|
||||
|
||||
if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect)) return TRUE;
|
||||
|
||||
/*
|
||||
* Get pointers to all necessary GDI objects.
|
||||
*/
|
||||
if ((Left == Right) || (Top == Bottom)) return TRUE;
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if (dc == NULL)
|
||||
{
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
SetLastWin32Error(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dc->DC_Type == DC_TYPE_INFO)
|
||||
{
|
||||
DC_UnlockDc(dc);
|
||||
/* Yes, Windows really returns TRUE in this case */
|
||||
return TRUE;
|
||||
DC_UnlockDc(dc);
|
||||
/* Yes, Windows really returns TRUE in this case */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (PATH_IsPathOpen(dc->DcLevel))
|
||||
{
|
||||
ret = PATH_Ellipse(dc, nLeftRect, nTopRect, nRightRect, nBottomRect);
|
||||
DC_UnlockDc(dc);
|
||||
return ret;
|
||||
ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
|
||||
DC_UnlockDc(dc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nRightRect < nLeftRect)
|
||||
if (Right < Left)
|
||||
{
|
||||
INT tmp = nRightRect; nRightRect = nLeftRect; nLeftRect = tmp;
|
||||
INT tmp = Right; Right = Left; Left = tmp;
|
||||
}
|
||||
if (nBottomRect < nTopRect)
|
||||
if (Bottom < Top)
|
||||
{
|
||||
INT tmp = nBottomRect; nBottomRect = nTopRect; nTopRect = tmp;
|
||||
INT tmp = Bottom; Bottom = Top; Top = tmp;
|
||||
}
|
||||
|
||||
Dc_Attr = dc->pDc_Attr;
|
||||
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||
|
||||
FillBrush = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
|
||||
if (NULL == FillBrush)
|
||||
PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
|
||||
if (NULL == PenBrushObj)
|
||||
{
|
||||
DPRINT1("Ellipse Fail 1\n");
|
||||
DC_UnlockDc(dc);
|
||||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PenBrush = PENOBJ_LockPen(Dc_Attr->hpen);
|
||||
if (NULL == PenBrush)
|
||||
PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
|
||||
if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
|
||||
|
||||
if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
|
||||
{
|
||||
BRUSHOBJ_UnlockBrush(FillBrush);
|
||||
DC_UnlockDc(dc);
|
||||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||
return FALSE;
|
||||
if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
|
||||
if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
|
||||
Left += PenWidth / 2;
|
||||
Right -= (PenWidth - 1) / 2;
|
||||
Top += PenWidth / 2;
|
||||
Bottom -= (PenWidth - 1) / 2;
|
||||
}
|
||||
|
||||
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
||||
if (NULL == BitmapObj)
|
||||
{
|
||||
BRUSHOBJ_UnlockBrush(FillBrush);
|
||||
PENOBJ_UnlockPen(PenBrush);
|
||||
DC_UnlockDc(dc);
|
||||
SetLastWin32Error(ERROR_INTERNAL_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IntGdiInitBrushInstance(&FillBrushInst, FillBrush, dc->XlateBrush);
|
||||
IntGdiInitBrushInstance(&PenBrushInst, PenBrush, dc->XlatePen);
|
||||
|
||||
RectBounds.left = nLeftRect;
|
||||
RectBounds.right = nRightRect;
|
||||
RectBounds.top = nTopRect;
|
||||
RectBounds.bottom = nBottomRect;
|
||||
if (!PenWidth) PenWidth = 1;
|
||||
PenBrushObj->ptPenWidth.x = PenWidth;
|
||||
|
||||
RectBounds.left = Left;
|
||||
RectBounds.right = Right;
|
||||
RectBounds.top = Top;
|
||||
RectBounds.bottom = Bottom;
|
||||
|
||||
IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
|
||||
DPRINT("1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
|
||||
RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
|
||||
|
||||
|
||||
RectBounds.left += dc->ptlDCOrig.x;
|
||||
RectBounds.right += dc->ptlDCOrig.x;
|
||||
RectBounds.top += dc->ptlDCOrig.y;
|
||||
RectBounds.bottom += dc->ptlDCOrig.y;
|
||||
DPRINT("2: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
|
||||
|
||||
// Setup for dynamic width and height.
|
||||
RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room
|
||||
RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2);
|
||||
CenterX = (RectBounds.right + RectBounds.left) / 2;
|
||||
CenterY = (RectBounds.bottom + RectBounds.top) / 2;
|
||||
|
||||
DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
|
||||
RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
|
||||
|
||||
RadiusX = max((RectBounds.right - RectBounds.left) >> 1, 1);
|
||||
RadiusY = max((RectBounds.bottom - RectBounds.top) >> 1, 1);
|
||||
CenterX = RectBounds.left + RadiusX;
|
||||
CenterY = RectBounds.top + RadiusY;
|
||||
DPRINT("3: RadiusX: %d, RadiusY: %d, CenterX: %d, CenterY: %d\n",
|
||||
RadiusX,RadiusY,CenterX,CenterY);
|
||||
DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
|
||||
CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
|
||||
|
||||
if (RadiusX > RadiusY)
|
||||
{
|
||||
nx = RadiusX;
|
||||
ny = RadiusY;
|
||||
}
|
||||
else
|
||||
{
|
||||
nx = RadiusY;
|
||||
ny = RadiusX;
|
||||
}
|
||||
da = -1;
|
||||
db = 0xFFFF;
|
||||
ix = 0;
|
||||
iy = nx * 64;
|
||||
NewA = 0;
|
||||
NewB = (iy + 32) >> 6;
|
||||
NewC = 0;
|
||||
NewD = (NewB * ny) / nx;
|
||||
ret = IntFillEllipse( dc,
|
||||
CenterX - RadiusX,
|
||||
CenterY - RadiusY,
|
||||
RadiusX*2, // Width
|
||||
RadiusY*2); // Height
|
||||
if (ret)
|
||||
ret = IntDrawEllipse( dc,
|
||||
CenterX - RadiusX,
|
||||
CenterY - RadiusY,
|
||||
RadiusX*2, // Width
|
||||
RadiusY*2, // Height
|
||||
PenBrushObj);
|
||||
|
||||
do {
|
||||
A = NewA;
|
||||
B = NewB;
|
||||
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
|
||||
{
|
||||
Cond1 = ((C != NewC) || (B != NewB)) && (NewA <= NewB);
|
||||
Cond2 = ((D != NewD) || (A != NewA)) && (NewA <= B);
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the lines going from inner to outer (+ mirrored).
|
||||
*/
|
||||
|
||||
if ((A > da) && (A < db))
|
||||
{
|
||||
PUTLINE(CenterX - D, CenterY + A, CenterX + D, CenterY + A, FillBrushInst);
|
||||
if (A)
|
||||
{
|
||||
PUTLINE(CenterX - D, CenterY - A, CenterX + D, CenterY - A, FillBrushInst);
|
||||
}
|
||||
da = A;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the lines going from outer to inner (+ mirrored).
|
||||
*/
|
||||
|
||||
if ((B < db) && (B > da))
|
||||
{
|
||||
PUTLINE(CenterX - C, CenterY + B, CenterX + C, CenterY + B, FillBrushInst);
|
||||
PUTLINE(CenterX - C, CenterY - B, CenterX + C, CenterY - B, FillBrushInst);
|
||||
db = B;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the pixels on the margin.
|
||||
*/
|
||||
|
||||
if (Cond1)
|
||||
{
|
||||
PUTPIXEL(CenterX + C, CenterY + B, PenBrushInst);
|
||||
if (C)
|
||||
PUTPIXEL(CenterX - C, CenterY + B, PenBrushInst);
|
||||
if (B)
|
||||
{
|
||||
PUTPIXEL(CenterX + C, CenterY - B, PenBrushInst);
|
||||
if (C)
|
||||
PUTPIXEL(CenterX - C, CenterY - B, PenBrushInst);
|
||||
}
|
||||
}
|
||||
|
||||
if (Cond2)
|
||||
{
|
||||
PUTPIXEL(CenterX + D, CenterY + A, PenBrushInst);
|
||||
if (D)
|
||||
PUTPIXEL(CenterX - D, CenterY + A, PenBrushInst);
|
||||
if (A)
|
||||
{
|
||||
PUTPIXEL(CenterX + D, CenterY - A, PenBrushInst);
|
||||
if (D)
|
||||
PUTPIXEL(CenterX - D, CenterY - A, PenBrushInst);
|
||||
}
|
||||
}
|
||||
} while (B > A);
|
||||
|
||||
BITMAPOBJ_UnlockBitmap(BitmapObj);
|
||||
BRUSHOBJ_UnlockBrush(FillBrush);
|
||||
PENOBJ_UnlockPen(PenBrush);
|
||||
PenBrushObj->ptPenWidth.x = PenOrigWidth;
|
||||
PENOBJ_UnlockPen(PenBrushObj);
|
||||
DC_UnlockDc(dc);
|
||||
DPRINT("NtGdiEllipse exit \n");
|
||||
DPRINT("Ellipse Exit.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue