[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / line.c
index 5ea83b6..28ff28a 100644 (file)
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -30,32 +30,34 @@ BOOL FASTCALL
 IntGdiMoveToEx(DC      *dc,
                int     X,
                int     Y,
-               LPPOINT Point)
+               LPPOINT Point,
+               BOOL    BypassPath)
 {
     BOOL  PathIsOpen;
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
     if ( Point )
     {
-        if ( Dc_Attr->ulDirty_ & DIRTY_PTLCURRENT ) // Double hit!
+        if ( pdcattr->ulDirty_ & DIRTY_PTLCURRENT ) // Double hit!
         {
-            Point->x = Dc_Attr->ptfxCurrent.x; // ret prev before change.
-            Point->y = Dc_Attr->ptfxCurrent.y;
+            Point->x = pdcattr->ptfxCurrent.x; // ret prev before change.
+            Point->y = pdcattr->ptfxCurrent.y;
             IntDPtoLP ( dc, Point, 1);         // reconvert back.
         }
         else
         {
-            Point->x = Dc_Attr->ptlCurrent.x;
-            Point->y = Dc_Attr->ptlCurrent.y;
+            Point->x = pdcattr->ptlCurrent.x;
+            Point->y = pdcattr->ptlCurrent.y;
         }
     }
-    Dc_Attr->ptlCurrent.x = X;
-    Dc_Attr->ptlCurrent.y = Y;
-    Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-    CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-    Dc_Attr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+    pdcattr->ptlCurrent.x = X;
+    pdcattr->ptlCurrent.y = Y;
+    pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+    CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+    pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
 
-    PathIsOpen = PATH_IsPathOpen(dc->DcLevel);
+    if (BypassPath) return TRUE;
+
+    PathIsOpen = PATH_IsPathOpen(dc->dclevel);
 
     if ( PathIsOpen )
         return PATH_MoveTo ( dc );
@@ -68,19 +70,18 @@ IntGdiMoveToEx(DC      *dc,
 VOID FASTCALL
 IntGetCurrentPositionEx(PDC dc, LPPOINT pt)
 {
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
     if ( pt )
     {
-        if (Dc_Attr->ulDirty_ & DIRTY_PTFXCURRENT)
+        if (pdcattr->ulDirty_ & DIRTY_PTFXCURRENT)
         {
-            Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-            CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-            Dc_Attr->ulDirty_ &= ~(DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+            pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+            CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+            pdcattr->ulDirty_ &= ~(DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
         }
-        pt->x = Dc_Attr->ptlCurrent.x;
-        pt->y = Dc_Attr->ptlCurrent.y;
+        pt->x = pdcattr->ptlCurrent.x;
+        pt->y = pdcattr->ptlCurrent.y;
     }
 }
 
@@ -89,47 +90,38 @@ IntGdiLineTo(DC  *dc,
              int XEnd,
              int YEnd)
 {
-    BITMAPOBJ *BitmapObj;
+    SURFACE *psurf;
     BOOL      Ret = TRUE;
-    PGDIBRUSHOBJ PenBrushObj;
-    GDIBRUSHINST PenBrushInst;
+    PBRUSH pbrLine;
     RECTL     Bounds;
     POINT     Points[2];
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
-
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
     {
         Ret = PATH_LineTo(dc, XEnd, YEnd);
         if (Ret)
         {
             // FIXME - PATH_LineTo should maybe do this? No
-            Dc_Attr->ptlCurrent.x = XEnd;
-            Dc_Attr->ptlCurrent.y = YEnd;
-            Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-            CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-            Dc_Attr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+            pdcattr->ptlCurrent.x = XEnd;
+            pdcattr->ptlCurrent.y = YEnd;
+            pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+            CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+            pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
         }
         return Ret;
     }
     else
     {
-       if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY)
-          IntGdiSelectBrush(dc,Dc_Attr->hbrush);
-
-       if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY)
-          IntGdiSelectPen(dc,Dc_Attr->hpen);
-
-        BitmapObj = BITMAPOBJ_LockBitmap ( dc->w.hBitmap );
-        if (NULL == BitmapObj)
+        psurf = dc->dclevel.pSurface;
+        if (NULL == psurf)
         {
             SetLastWin32Error(ERROR_INVALID_HANDLE);
             return FALSE;
         }
 
-        Points[0].x = Dc_Attr->ptlCurrent.x;
-        Points[0].y = Dc_Attr->ptlCurrent.y;
+        Points[0].x = pdcattr->ptlCurrent.x;
+        Points[0].y = pdcattr->ptlCurrent.y;
         Points[1].x = XEnd;
         Points[1].y = YEnd;
 
@@ -146,38 +138,30 @@ IntGdiLineTo(DC  *dc,
         Bounds.right = max(Points[0].x, Points[1].x);
         Bounds.bottom = max(Points[0].y, Points[1].y);
 
-        /* get BRUSHOBJ from current pen. */
-        PenBrushObj = PENOBJ_LockPen( Dc_Attr->hpen );
-        if (!PenBrushObj)
-        {
-            /* default to BLACK_PEN */
-            PenBrushObj = PENOBJ_LockPen(NtGdiGetStockObject(BLACK_PEN));
-            ASSERT(PenBrushObj);
-        }
+        /* get BRUSH from current pen. */
+        pbrLine = dc->dclevel.pbrLine;
+        ASSERT(pbrLine);
 
-        if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+        if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
         {
-            IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-            Ret = IntEngLineTo(&BitmapObj->SurfObj,
-                               dc->CombinedClip,
-                               &PenBrushInst.BrushObject,
+            Ret = IntEngLineTo(&psurf->SurfObj,
+                               dc->rosdc.CombinedClip,
+                               &dc->eboLine.BrushObject,
                                Points[0].x, Points[0].y,
                                Points[1].x, Points[1].y,
                                &Bounds,
-                               ROP2_TO_MIX(Dc_Attr->jROP2));
+                               ROP2_TO_MIX(pdcattr->jROP2));
         }
 
-        BITMAPOBJ_UnlockBitmap ( BitmapObj );
-        PENOBJ_UnlockPen( PenBrushObj );
     }
 
     if (Ret)
     {
-        Dc_Attr->ptlCurrent.x = XEnd;
-        Dc_Attr->ptlCurrent.y = YEnd;
-        Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-        CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-        Dc_Attr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+        pdcattr->ptlCurrent.x = XEnd;
+        pdcattr->ptlCurrent.y = YEnd;
+        pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+        CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+        pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
     }
 
     return Ret;
@@ -190,7 +174,7 @@ IntGdiPolyBezier(DC      *dc,
 {
     BOOL ret = FALSE; // default to FAILURE
 
-    if ( PATH_IsPathOpen(dc->DcLevel) )
+    if ( PATH_IsPathOpen(dc->dclevel) )
     {
         return PATH_PolyBezier ( dc, pt, Count );
     }
@@ -217,10 +201,9 @@ IntGdiPolyBezierTo(DC      *dc,
                    DWORD  Count)
 {
     BOOL ret = FALSE; // default to failure
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    if ( PATH_IsPathOpen(dc->DcLevel) )
+    if ( PATH_IsPathOpen(dc->dclevel) )
         ret = PATH_PolyBezierTo ( dc, pt, Count );
     else /* We'll do it using PolyBezier */
     {
@@ -230,8 +213,8 @@ IntGdiPolyBezierTo(DC      *dc,
                                     TAG_BEZIER);
         if ( npt )
         {
-            npt[0].x = Dc_Attr->ptlCurrent.x;
-            npt[0].y = Dc_Attr->ptlCurrent.y;
+            npt[0].x = pdcattr->ptlCurrent.x;
+            npt[0].y = pdcattr->ptlCurrent.y;
             memcpy(npt + 1, pt, sizeof(POINT) * Count);
             ret = IntGdiPolyBezier(dc, npt, Count+1);
             ExFreePoolWithTag(npt, TAG_BEZIER);
@@ -239,11 +222,11 @@ IntGdiPolyBezierTo(DC      *dc,
     }
     if ( ret )
     {
-        Dc_Attr->ptlCurrent.x = pt[Count-1].x;
-        Dc_Attr->ptlCurrent.y = pt[Count-1].y;
-        Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-        CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-        Dc_Attr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+        pdcattr->ptlCurrent.x = pt[Count-1].x;
+        pdcattr->ptlCurrent.y = pt[Count-1].y;
+        pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+        CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+        pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
     }
 
     return ret;
@@ -254,59 +237,56 @@ IntGdiPolyline(DC      *dc,
                LPPOINT pt,
                int     Count)
 {
-    BITMAPOBJ *BitmapObj;
-    GDIBRUSHOBJ *PenBrushObj;
-    GDIBRUSHINST PenBrushInst;
+    SURFACE *psurf;
+    BRUSH *pbrLine;
     LPPOINT Points;
     BOOL Ret = TRUE;
     LONG i;
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
-
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
         return PATH_Polyline(dc, pt, Count);
 
-    if (Dc_Attr->ulDirty_ & DC_BRUSH_DIRTY)
-       IntGdiSelectBrush(dc,Dc_Attr->hbrush);
+    DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                            NULL, dc->rosdc.CombinedClip->rclBounds);
 
-    if (Dc_Attr->ulDirty_ & DC_PEN_DIRTY)
-       IntGdiSelectPen(dc,Dc_Attr->hpen);
+    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+        DC_vUpdateFillBrush(dc);
+
+    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
 
     /* Get BRUSHOBJ from current pen. */
-    PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
-    /* FIXME - PenBrushObj can be NULL! Don't assert here! */
-    ASSERT(PenBrushObj);
+    pbrLine = dc->dclevel.pbrLine;
+    ASSERT(pbrLine);
 
-    if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
+    if (!(pbrLine->flAttrs & GDIBRUSH_IS_NULL))
     {
         Points = EngAllocMem(0, Count * sizeof(POINT), TAG_COORD);
         if (Points != NULL)
         {
-            BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-            /* FIXME - BitmapObj can be NULL!!!!
+            psurf = dc->dclevel.pSurface;
+            /* FIXME - psurf can be NULL!!!!
                Don't assert but handle this case gracefully! */
-            ASSERT(BitmapObj);
+            ASSERT(psurf);
 
             RtlCopyMemory(Points, pt, Count * sizeof(POINT));
             IntLPtoDP(dc, Points, Count);
 
-            /* Offset the array of point by the dc->w.DCOrg */
+            /* Offset the array of points by the DC origin */
             for (i = 0; i < Count; i++)
             {
                 Points[i].x += dc->ptlDCOrig.x;
                 Points[i].y += dc->ptlDCOrig.y;
             }
 
-            IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
-            Ret = IntEngPolyline(&BitmapObj->SurfObj,
-                                 dc->CombinedClip,
-                                 &PenBrushInst.BrushObject,
+            Ret = IntEngPolyline(&psurf->SurfObj,
+                                 dc->rosdc.CombinedClip,
+                                 &dc->eboLine.BrushObject,
                                  Points,
                                  Count,
-                                 ROP2_TO_MIX(Dc_Attr->jROP2));
+                                 ROP2_TO_MIX(pdcattr->jROP2));
 
-            BITMAPOBJ_UnlockBitmap(BitmapObj);
             EngFreeMem(Points);
         }
         else
@@ -315,7 +295,7 @@ IntGdiPolyline(DC      *dc,
         }
     }
 
-    PENOBJ_UnlockPen(PenBrushObj);
+    DC_vFinishBlit(dc, NULL);
 
     return Ret;
 }
@@ -326,10 +306,9 @@ IntGdiPolylineTo(DC      *dc,
                  DWORD   Count)
 {
     BOOL ret = FALSE; // default to failure
-    PDC_ATTR Dc_Attr = dc->pDc_Attr;
+    PDC_ATTR pdcattr = dc->pdcattr;
 
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
     {
         ret = PATH_PolylineTo(dc, pt, Count);
     }
@@ -340,8 +319,8 @@ IntGdiPolylineTo(DC      *dc,
                                            TAG_SHAPE);
         if ( pts )
         {
-            pts[0].x = Dc_Attr->ptlCurrent.x;
-            pts[0].y = Dc_Attr->ptlCurrent.y;
+            pts[0].x = pdcattr->ptlCurrent.x;
+            pts[0].y = pdcattr->ptlCurrent.y;
             memcpy( pts + 1, pt, sizeof(POINT) * Count);
             ret = IntGdiPolyline(dc, pts, Count + 1);
             ExFreePoolWithTag(pts, TAG_SHAPE);
@@ -349,11 +328,11 @@ IntGdiPolylineTo(DC      *dc,
     }
     if ( ret )
     {
-        Dc_Attr->ptlCurrent.x = pt[Count-1].x;
-        Dc_Attr->ptlCurrent.y = pt[Count-1].y;
-        Dc_Attr->ptfxCurrent = Dc_Attr->ptlCurrent;
-        CoordLPtoDP(dc, &Dc_Attr->ptfxCurrent); // Update fx
-        Dc_Attr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
+        pdcattr->ptlCurrent.x = pt[Count-1].x;
+        pdcattr->ptlCurrent.y = pt[Count-1].y;
+        pdcattr->ptfxCurrent = pdcattr->ptlCurrent;
+        CoordLPtoDP(dc, &pdcattr->ptfxCurrent); // Update fx
+        pdcattr->ulDirty_ &= ~(DIRTY_PTLCURRENT|DIRTY_PTFXCURRENT|DIRTY_STYLESTATE);
     }
 
     return ret;
@@ -373,7 +352,7 @@ IntGdiPolyPolyline(DC      *dc,
     pts = pt;
     pc = PolyPoints;
 
-    if (PATH_IsPathOpen(dc->DcLevel))
+    if (PATH_IsPathOpen(dc->dclevel))
         return PATH_PolyPolyline( dc, pt, PolyPoints, Count );
 
     for (i = 0; i < Count; i++)
@@ -399,6 +378,7 @@ NtGdiLineTo(HDC  hDC,
 {
     DC *dc;
     BOOL Ret;
+    RECT rcLockRect ;
 
     dc = DC_LockDc(hDC);
     if (!dc)
@@ -406,15 +386,35 @@ NtGdiLineTo(HDC  hDC,
         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;
     }
 
+    rcLockRect.left = dc->pdcattr->ptlCurrent.x;
+    rcLockRect.top = dc->pdcattr->ptlCurrent.y;
+    rcLockRect.right = XEnd;
+    rcLockRect.bottom = YEnd;
+
+    IntLPtoDP(dc, &rcLockRect, 2);
+
+    /* The DCOrg is in device coordinates */
+    rcLockRect.left += dc->ptlDCOrig.x;
+    rcLockRect.top += dc->ptlDCOrig.y;
+    rcLockRect.right += dc->ptlDCOrig.x;
+    rcLockRect.bottom += dc->ptlDCOrig.y;
+
+    DC_vPrepareDCsForBlit(dc, rcLockRect, NULL, rcLockRect);
+
+    if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+        DC_vUpdateLineBrush(dc);
+
     Ret = IntGdiLineTo(dc, XEnd, YEnd);
 
+    DC_vFinishBlit(dc, NULL);
+
     DC_UnlockDc(dc);
     return Ret;
 }
@@ -432,12 +432,11 @@ NtGdiPolyDraw(
     BOOL result = FALSE;
     POINT lastmove;
     unsigned int i;
-    PDC_ATTR Dc_Attr = NULL;
+    PDC_ATTR pdcattr;
 
     dc = DC_LockDc(hdc);
     if (!dc) return FALSE;
-    Dc_Attr = dc->pDc_Attr;
-    if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
+    pdcattr = dc->pdcattr;
 
     _SEH2_TRY
     {
@@ -456,25 +455,25 @@ NtGdiPolyDraw(
         }
 
         /* if no moveto occurs, we will close the figure here */
-        lastmove.x = Dc_Attr->ptlCurrent.x;
-        lastmove.y = Dc_Attr->ptlCurrent.y;
+        lastmove.x = pdcattr->ptlCurrent.x;
+        lastmove.y = pdcattr->ptlCurrent.y;
 
         /* now let's draw */
         for ( i = 0; i < cCount; i++ )
         {
             if ( lpbTypes[i] == PT_MOVETO )
             {
-                IntGdiMoveToEx( dc, lppt[i].x, lppt[i].y, NULL );
-                lastmove.x = Dc_Attr->ptlCurrent.x;
-                lastmove.y = Dc_Attr->ptlCurrent.y;
+                IntGdiMoveToEx( dc, lppt[i].x, lppt[i].y, NULL, FALSE );
+                lastmove.x = pdcattr->ptlCurrent.x;
+                lastmove.y = pdcattr->ptlCurrent.y;
             }
             else if ( lpbTypes[i] & PT_LINETO )
                 IntGdiLineTo( dc, lppt[i].x, lppt[i].y );
             else if ( lpbTypes[i] & PT_BEZIERTO )
             {
                 POINT pts[4];
-                pts[0].x = Dc_Attr->ptlCurrent.x;
-                pts[0].y = Dc_Attr->ptlCurrent.y;
+                pts[0].x = pdcattr->ptlCurrent.x;
+                pts[0].y = pdcattr->ptlCurrent.y;
                 RtlCopyMemory(pts + 1, &lppt[i], sizeof(POINT) * 3);
                 IntGdiPolyBezier(dc, pts, 4);
                 i += 2;
@@ -483,9 +482,9 @@ NtGdiPolyDraw(
 
             if ( lpbTypes[i] & PT_CLOSEFIGURE )
             {
-                if ( PATH_IsPathOpen(dc->DcLevel) )
+                if ( PATH_IsPathOpen(dc->dclevel) )
                 {
-                    pPath = PATH_LockPath( dc->DcLevel.hPath );
+                    pPath = PATH_LockPath( dc->dclevel.hPath );
                     if (pPath)
                     {
                        IntGdiCloseFigure( pPath );