[ros-diffs] [jimtabor] 34233: 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.

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Tue Jul 1 15:30:45 CEST 2008


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/objects/arc.c?rev=34233&r1=34232&r2=34233&view=diff
==============================================================================
--- 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/objects/drawing.c?rev=34233&r1=34232&r2=34233&view=diff
==============================================================================
--- 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/objects/fillshap.c?rev=34233&r1=34232&r2=34233&view=diff
==============================================================================
--- 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;
 }
 



More information about the Ros-diffs mailing list