Author: jimtabor
Date: Tue Jul 1 08:30:44 2008
New Revision: 34233
URL:
http://svn.reactos.org/svn/reactos?rev=34233&view=rev
Log:
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.
Modified:
trunk/reactos/subsystems/win32/win32k/objects/arc.c
trunk/reactos/subsystems/win32/win32k/objects/drawing.c
trunk/reactos/subsystems/win32/win32k/objects/fillshap.c
Modified: trunk/reactos/subsystems/win32/win32k/objects/arc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/arc.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/arc.c [iso-8859-1] Tue Jul 1 08:30:44
2008
@@ -42,7 +42,7 @@
ARCTYPE arctype)
{
PDC_ATTR Dc_Attr;
- RECTL RectBounds;
+ RECTL RectBounds, RectSEpts;
PGDIBRUSHOBJ PenBrushObj;
GDIBRUSHINST PenBrushInst;
BITMAPOBJ *BitmapObj;
@@ -67,17 +67,6 @@
(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 @@
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 @@
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 @@
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 @@
}
else
{
- DPRINT("Arc CCW\n");
+ DPRINT1("Arc CCW\n");
for (; AngT < AngS; AngS -= Factor)
{
x = (RadiusX * Rcos(AngS));
Modified: trunk/reactos/subsystems/win32/win32k/objects/drawing.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/drawing.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/drawing.c [iso-8859-1] Tue Jul 1
08:30:44 2008
@@ -81,12 +81,11 @@
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 @@
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 @@
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 @@
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,11 +167,299 @@
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;
}
/*
@@ -652,14 +948,11 @@
/* 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 @@
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 @@
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;
+}
Modified: trunk/reactos/subsystems/win32/win32k/objects/fillshap.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] Tue Jul 1
08:30:44 2008
@@ -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 @@
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 @@
{
if (PATH_IsPathOpen(dc->DcLevel))
return PATH_PolyPolygon ( dc, Points, PolyCounts, Count);
+
while (--Count >=0)
{
if (!IntGdiPolygon ( dc, Points, *PolyCounts ))
@@ -179,247 +186,124 @@
* 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);
-
- if ((nLeftRect == nRightRect) || (nTopRect == nBottomRect)) return TRUE;
-
- /*
- * Get pointers to all necessary GDI objects.
- */
+ RECTL RectBounds;
+ PGDIBRUSHOBJ PenBrushObj;
+ BOOL ret = TRUE;
+ LONG PenWidth, PenOrigWidth;
+ LONG RadiusX, RadiusY, CenterX, CenterY;
+
+ 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;
+ }
+
+ if (PATH_IsPathOpen(dc->DcLevel))
+ {
+ ret = PATH_Ellipse(dc, Left, Top, Right, Bottom);
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;
- }
-
- if (nRightRect < nLeftRect)
- {
- INT tmp = nRightRect; nRightRect = nLeftRect; nLeftRect = tmp;
- }
- if (nBottomRect < nTopRect)
- {
- INT tmp = nBottomRect; nBottomRect = nTopRect; nTopRect = tmp;
+ return ret;
+ }
+
+ if (Right < Left)
+ {
+ INT tmp = Right; Right = Left; Left = tmp;
+ }
+ if (Bottom < Top)
+ {
+ 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)
- {
- BRUSHOBJ_UnlockBrush(FillBrush);
- DC_UnlockDc(dc);
- SetLastWin32Error(ERROR_INTERNAL_ERROR);
- return FALSE;
- }
-
- 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;
-
+ PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
+ if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
+
+ if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
+ {
+ 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;
+ }
+
+ 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);
-
- 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;
-
- 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);
+ DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n",
+ CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
+
+ 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);
+
+ PenBrushObj->ptPenWidth.x = PenOrigWidth;
+ PENOBJ_UnlockPen(PenBrushObj);
DC_UnlockDc(dc);
- DPRINT("NtGdiEllipse exit \n");
+ DPRINT("Ellipse Exit.\n");
return ret;
}