[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / arc.c
index 3138e25..e2ffeb5 100644 (file)
@@ -1,4 +1,4 @@
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -7,30 +7,31 @@
  * a couple macros to fill a single pixel or a line
  */
 #define PUTPIXEL(x,y,BrushInst)        \
-  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
-       dc->CombinedClip,                         \
+  ret = ret && IntEngLineTo(&psurf->SurfObj, \
+       dc->rosdc.CombinedClip,                         \
        &BrushInst.BrushObject,                   \
        x, y, (x)+1, y,                           \
        &RectBounds,                              \
-       ROP2_TO_MIX(Dc_Attr->jROP2));
+       ROP2_TO_MIX(pdcattr->jROP2));
 
 #define PUTLINE(x1,y1,x2,y2,BrushInst) \
-  ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
-       dc->CombinedClip,                         \
+  ret = ret && IntEngLineTo(&psurf->SurfObj, \
+       dc->rosdc.CombinedClip,                         \
        &BrushInst.BrushObject,                   \
        x1, y1, x2, y2,                           \
        &RectBounds,                              \
-       ROP2_TO_MIX(Dc_Attr->jROP2));
+       ROP2_TO_MIX(pdcattr->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 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);
 
 static
 BOOL
 FASTCALL
-IntArc( DC *dc, 
+IntArc( DC *dc,
         int  Left,
         int  Top,
         int  Right,
@@ -41,28 +42,16 @@ IntArc( DC *dc,
         int  YRadialEnd,
         ARCTYPE arctype)
 {
-    PDC_ATTR Dc_Attr;
-    RECTL RectBounds;
-    PGDIBRUSHOBJ PenBrushObj;
-    GDIBRUSHINST PenBrushInst;
-    BITMAPOBJ *BitmapObj;
+    PDC_ATTR pdcattr;
+    RECTL RectBounds, RectSEpts;
+    PBRUSH pbrushPen;
+    SURFACE *psurf;
     BOOL ret = TRUE;
     LONG PenWidth, PenOrigWidth;
     double AngleStart, AngleEnd;
     LONG RadiusX, RadiusY, CenterX, CenterY;
     LONG SfCx, SfCy, EfCx, EfCy;
 
-/*                  top
-            ___________________
-          +|                   |
-           |                   |
-           |                   |
-      left |                   | right
-           |                   |
-           |                   |
-          0|___________________|
-            0     bottom       +
- */
     if (Right < Left)
     {
        INT tmp = Right; Right = Left; Left = tmp;
@@ -78,32 +67,20 @@ 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;
+    pdcattr = dc->pdcattr;
 
-    PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-    if (NULL == PenBrushObj)
+    pbrushPen = PEN_LockPen(pdcattr->hpen);
+    if (!pbrushPen)
     {
         DPRINT1("Arc Fail 1\n");
         SetLastWin32Error(ERROR_INTERNAL_ERROR);
         return FALSE;
     }
 
-    PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
-    if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
+    PenOrigWidth = PenWidth = pbrushPen->ptPenWidth.x;
+    if (pbrushPen->ulPenStyle == PS_NULL) PenWidth = 0;
 
-    if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
+    if (pbrushPen->ulPenStyle == PS_INSIDEFRAME)
     {
        if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
        if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
@@ -114,34 +91,43 @@ 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;
-
-    DPRINT1("1: StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
-               XRadialStart,YRadialStart,XRadialEnd,YRadialEnd);
+    pbrushPen->ptPenWidth.x = PenWidth;
 
     RectBounds.left   = Left;
     RectBounds.right  = Right;
     RectBounds.top    = Top;
     RectBounds.bottom = Bottom;
-    DPRINT1("1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
+
+    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);
 
-    RadiusX = (RectBounds.right - RectBounds.left) / 2;
-    RadiusY = (RectBounds.bottom - RectBounds.top) / 2;
+    RadiusX = max((RectBounds.right - RectBounds.left) / 2, 1);
+    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);
@@ -151,90 +137,45 @@ IntArc( DC *dc,
     if ((arctype == GdiTypePie) || (arctype == GdiTypeChord))
     {
         ret = IntFillArc( dc,
-             RectBounds.left,
+              RectBounds.left,
               RectBounds.top,
-             fabs(RectBounds.right-RectBounds.left), // Width
-             fabs(RectBounds.bottom-RectBounds.top), // Height
-                  AngleStart,
-                    AngleEnd,
-                     arctype);
+              abs(RectBounds.right-RectBounds.left), // Width
+              abs(RectBounds.bottom-RectBounds.top), // Height
+              AngleStart,
+              AngleEnd,
+              arctype);
     }
 
-    BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-    if (NULL == BitmapObj)
+    ret = IntDrawArc( dc,
+              RectBounds.left,
+              RectBounds.top,
+              abs(RectBounds.right-RectBounds.left), // Width
+              abs(RectBounds.bottom-RectBounds.top), // Height
+              AngleStart,
+              AngleEnd,
+              arctype,
+              pbrushPen);
+
+    psurf = dc->dclevel.pSurface;
+    if (NULL == psurf)
     {
         DPRINT1("Arc Fail 2\n");
-        PENOBJ_UnlockPen(PenBrushObj);
+        PEN_UnlockPen(pbrushPen);
         SetLastWin32Error(ERROR_INTERNAL_ERROR);
         return FALSE;
     }
 
-    IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-
     if (arctype == GdiTypePie)
     {
-       PUTLINE(CenterX, CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
-    }
-    {
-       double AngS = AngleStart, AngT = AngleEnd,
-       Factor = fabs(RadiusX) < 25 ? 1.0 : (25/fabs(RadiusX));
-       int x,y, ox = 0, oy = 0;
-       BOOL Start = TRUE;
-
-       if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
-       {
-          DPRINT1("Arc CW\n");
-          for (; AngS < AngT; AngS += Factor)
-          {
-              x = (RadiusX * Rcos(AngS));
-              y = (RadiusY * Rsin(AngS));
-
-              DPRINT("Arc CW -> %d, X: %d Y: %d\n",(INT)AngS,x,y);
-              if (Start)
-              {
-                 PUTPIXEL(x + CenterX, y + CenterY, PenBrushInst);
-                 ox = x;
-                 oy = y;
-                 Start = FALSE;
-                 continue;
-              }
-              PUTLINE(ox + CenterX, oy + CenterY, x + CenterX, y + CenterY, PenBrushInst);
-              ox = x;
-              oy = y;      
-          }
-       }
-       else
-       {
-          DPRINT1("Arc CCW\n");
-          for (; AngT < AngS; AngS -= Factor)
-          {
-              x = (RadiusX * Rcos(AngS));
-              y = (RadiusY * Rsin(AngS));
-
-              DPRINT("Arc CCW -> %d, X: %d Y: %d\n",(INT)AngS,x,y);
-              if (Start)
-              {
-                 PUTPIXEL(x + CenterX, y + CenterY, PenBrushInst);
-                 ox = x;
-                 oy = y;
-                 Start = FALSE;
-                 continue;
-              }
-              PUTLINE(ox + CenterX, oy + CenterY, x + CenterX, y + CenterY, PenBrushInst);
-              ox = x;
-              oy = y;
-          }        
-       }
+       PUTLINE(CenterX, CenterY, SfCx + CenterX, SfCy + CenterY, dc->eboLine);
+       PUTLINE(EfCx + CenterX, EfCy + CenterY, CenterX, CenterY, dc->eboLine);
     }
-    if (arctype == GdiTypePie)
-       PUTLINE(EfCx + CenterX, EfCy + CenterY, CenterX, CenterY, PenBrushInst);
     if (arctype == GdiTypeChord)
-       PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
+        PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, dc->eboLine);
 
-    PenBrushObj->ptPenWidth.x = PenOrigWidth;
-    BITMAPOBJ_UnlockBitmap(BitmapObj);
-    PENOBJ_UnlockPen(PenBrushObj);
-    DPRINT1("IntArc Exit.\n");
+    pbrushPen->ptPenWidth.x = PenOrigWidth;
+    PEN_UnlockPen(pbrushPen);
+    DPRINT("IntArc Exit.\n");
     return ret;
 }
 
@@ -253,14 +194,16 @@ IntGdiArcInternal(
           int YEndArc)
 {
   BOOL Ret;
-  RECT rc, rc1;
+  PDC_ATTR pdcattr;
 
-  DPRINT1("StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
+  DPRINT("StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
            XStartArc,YStartArc,XEndArc,YEndArc);
-  DPRINT1("Left: %d, Top: %d, Right: %d, Bottom: %d\n",
+  DPRINT("Left: %d, Top: %d, Right: %d, Bottom: %d\n",
            LeftRect,TopRect,RightRect,BottomRect);
 
-  if (PATH_IsPathOpen(dc->DcLevel))
+  if ((LeftRect == RightRect) || (TopRect == BottomRect)) return TRUE;
+
+  if (PATH_IsPathOpen(dc->dclevel))
   {
      return PATH_Arc( dc,
                 LeftRect,
@@ -274,38 +217,33 @@ IntGdiArcInternal(
                  arctype);
   }
 
+  pdcattr = dc->pdcattr;
+
   if (arctype == GdiTypeArcTo)
   {
-    if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
+    if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
        IntGdiLineTo(dc, XEndArc, YEndArc);
     else
        IntGdiLineTo(dc, XStartArc, YStartArc);
   }
 
-  IntGdiSetRect(&rc, LeftRect, TopRect, RightRect, BottomRect);
-  IntGdiSetRect(&rc1, XStartArc, YStartArc, XEndArc, YEndArc);
-
-//  IntLPtoDP(dc, (LPPOINT)&rc, 2);
-//  IntLPtoDP(dc, (LPPOINT)&rc1, 2);
-
-
   Ret = IntArc( dc,
-           rc.left,
-            rc.top,
-          rc.right,
-         rc.bottom,
-          rc1.left,
-           rc1.top,
-         rc1.right,
-        rc1.bottom,
+          LeftRect,
+           TopRect,
+         RightRect,
+        BottomRect,
+         XStartArc,
+         YStartArc,
+           XEndArc,
+           YEndArc,
            arctype);
 
   if (arctype == GdiTypeArcTo)
   {
-     if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
-       IntGdiMoveToEx(dc, XStartArc, YStartArc, NULL);
+     if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
+       IntGdiMoveToEx(dc, XStartArc, YStartArc, NULL, TRUE);
      else
-       IntGdiMoveToEx(dc, XEndArc, YEndArc, NULL);
+       IntGdiMoveToEx(dc, XEndArc, YEndArc, NULL, TRUE);
   }
   return Ret;
 }
@@ -329,11 +267,11 @@ IntGdiAngleArc( PDC pDC,
   x1 = x + (INT)(cos((eStartAngle/360)*(M_PI*2)) * dwRadius);
   y1 = y - (INT)(sin((eStartAngle/360)*(M_PI*2)) * dwRadius);
 
-  arcdir = pDC->DcLevel.flPath & DCPATH_CLOCKWISE;
+  arcdir = pDC->dclevel.flPath & DCPATH_CLOCKWISE;
   if (eSweepAngle >= 0)
-     pDC->DcLevel.flPath &= ~DCPATH_CLOCKWISE;
+     pDC->dclevel.flPath &= ~DCPATH_CLOCKWISE;
   else
-     pDC->DcLevel.flPath |= DCPATH_CLOCKWISE;
+     pDC->dclevel.flPath |= DCPATH_CLOCKWISE;
 
   result = IntGdiArcInternal( GdiTypeArcTo,
                                        pDC,
@@ -346,11 +284,11 @@ IntGdiAngleArc( PDC pDC,
                                         x2,
                                         y2 );
 
-  pDC->DcLevel.flPath |= (arcdir & DCPATH_CLOCKWISE);
+  pDC->dclevel.flPath |= (arcdir & DCPATH_CLOCKWISE);
 
   if (result)
   {
-     IntGdiMoveToEx(pDC, x2, y2, NULL); // Dont forget Path.
+     IntGdiMoveToEx(pDC, x2, y2, NULL, TRUE);
   }
   return result;
 }
@@ -377,7 +315,7 @@ NtGdiAngleArc(
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return FALSE;
   }
-  if (pDC->DC_Type == DC_TYPE_INFO)
+  if (pDC->dctype == DC_TYPE_INFO)
   {
     DC_UnlockDc(pDC);
     /* Yes, Windows really returns TRUE in this case */
@@ -385,13 +323,20 @@ NtGdiAngleArc(
   }
   worker.l  = dwStartAngle;
   worker1.l = dwSweepAngle;
+  DC_vPrepareDCsForBlit(pDC, pDC->rosdc.CombinedClip->rclBounds,
+                           NULL, pDC->rosdc.CombinedClip->rclBounds);
+  if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+    DC_vUpdateFillBrush(pDC);
+  if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+    DC_vUpdateLineBrush(pDC);
   Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
+  DC_vFinishBlit(pDC, NULL);
   DC_UnlockDc( pDC );
   return Ret;
 }
 
 BOOL
-STDCALL
+APIENTRY
 NtGdiArcInternal(
         ARCTYPE arctype,
         HDC  hDC,
@@ -413,13 +358,22 @@ NtGdiArcInternal(
     SetLastWin32Error(ERROR_INVALID_HANDLE);
     return FALSE;
   }
-  if (dc->DC_Type == DC_TYPE_INFO)
+  if (dc->dctype == DC_TYPE_INFO)
   {
     DC_UnlockDc(dc);
     /* Yes, Windows really returns TRUE in this case */
     return TRUE;
   }
 
+  DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                            NULL, dc->rosdc.CombinedClip->rclBounds);
+
+  if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+    DC_vUpdateFillBrush(dc);
+
+  if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+    DC_vUpdateLineBrush(dc);
+
   Ret = IntGdiArcInternal(
                   arctype,
                   dc,
@@ -432,6 +386,7 @@ NtGdiArcInternal(
                   XEndArc,
                   YEndArc);
 
+  DC_vFinishBlit(dc, NULL);
   DC_UnlockDc( dc );
   return Ret;
 }