[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dcobjs.c
index ec45654..6975b60 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS kernel
  * PURPOSE:           Functions for creation and destruction of DCs
@@ -6,72 +6,17 @@
  * PROGRAMER:         Timo Kreuzer (timo.kreuzer@rectos.org)
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
-// HACK!
-static
-BOOLEAN
-IntUpdateBrushXlate(PDC pdc, XLATEOBJ **ppxlo, BRUSH *pbrush)
-{
-    SURFACE * psurf;
-    XLATEOBJ *pxlo = NULL;
-    HPALETTE hPalette = NULL;
-
-    psurf = pdc->dclevel.pSurface;
-    if (psurf)
-    {
-        hPalette = psurf->hDIBPalette;
-    }
-    if (!hPalette) hPalette = pPrimarySurface->DevInfo.hpalDefault;
-
-    if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
-    {
-        pxlo = NULL;
-    }
-    else if (pbrush->flAttrs & GDIBRUSH_IS_SOLID)
-    {
-        pxlo = IntEngCreateXlate(0, PAL_RGB, hPalette, NULL);
-    }
-    else
-    {
-        SURFACE *psurfPattern = SURFACE_LockSurface(pbrush->hbmPattern);
-        if (psurfPattern == NULL)
-            return FALSE;
-
-        /* Special case: 1bpp pattern */
-        if (psurfPattern->SurfObj.iBitmapFormat == BMF_1BPP)
-        {
-            if (pdc->rosdc.bitsPerPixel != 1)
-                pxlo = IntEngCreateSrcMonoXlate(hPalette,
-                                                pdc->pdcattr->crBackgroundClr,
-                                                pbrush->BrushAttr.lbColor);
-        }
-        else if (pbrush->flAttrs & GDIBRUSH_IS_DIB)
-        {
-            pxlo = IntEngCreateXlate(0, 0, hPalette, psurfPattern->hDIBPalette);
-        }
-
-        SURFACE_UnlockSurface(psurfPattern);
-    }
-
-    if (*ppxlo != NULL)
-        EngDeleteXlate(*ppxlo);
-
-    *ppxlo = pxlo;
-    return TRUE;
-}
-
-
 VOID
 FASTCALL
 DC_vUpdateFillBrush(PDC pdc)
 {
     PDC_ATTR pdcattr = pdc->pdcattr;
     PBRUSH pbrFill;
-    XLATEOBJ *pxlo = NULL;
 
     /* Check if the brush handle has changed */
     if (pdcattr->hbrush != pdc->dclevel.pbrFill->BaseObject.hHmgr)
@@ -97,23 +42,16 @@ DC_vUpdateFillBrush(PDC pdc)
     /* Check if the EBRUSHOBJ needs update */
     if (pdcattr->ulDirty_ & DIRTY_FILL)
     {
-        pbrFill = pdc->dclevel.pbrFill;
-
-        /* ROS HACK, should use surf xlate */
-        IntUpdateBrushXlate(pdc, &pdc->rosdc.XlateBrush, pbrFill);
-
-        /* Update eboFill, realizing it, if needed */
-        EBRUSHOBJ_vUpdate(&pdc->eboFill, pbrFill, pdc->rosdc.XlateBrush);
+        /* Update eboFill */
+        EBRUSHOBJ_vUpdate(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
     }
 
     /* Check for DC brush */
     if (pdcattr->hbrush == StockObjects[DC_BRUSH])
     {
         /* ROS HACK, should use surf xlate */
-        pxlo = pdc->rosdc.XlateBrush;
-
         /* Update the eboFill's solid color */
-        EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, pdcattr->crPenClr, pxlo);
+        EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboFill, pdcattr->crPenClr);
     }
 
     /* Clear flags */
@@ -126,7 +64,6 @@ DC_vUpdateLineBrush(PDC pdc)
 {
     PDC_ATTR pdcattr = pdc->pdcattr;
     PBRUSH pbrLine;
-    XLATEOBJ *pxlo;
 
     /* Check if the pen handle has changed */
     if (pdcattr->hpen != pdc->dclevel.pbrLine->BaseObject.hHmgr)
@@ -152,23 +89,15 @@ DC_vUpdateLineBrush(PDC pdc)
     /* Check if the EBRUSHOBJ needs update */
     if (pdcattr->ulDirty_ & DIRTY_LINE)
     {
-        pbrLine = pdc->dclevel.pbrLine;
-
-        /* ROS HACK, should use surf xlate */
-        IntUpdateBrushXlate(pdc, &pdc->rosdc.XlatePen, pbrLine);
-
-        /* Update eboLine, realizing it, if needed */
-        EBRUSHOBJ_vUpdate(&pdc->eboLine, pbrLine, pdc->rosdc.XlatePen);
+        /* Update eboLine */
+        EBRUSHOBJ_vUpdate(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
     }
 
     /* Check for DC pen */
     if (pdcattr->hpen == StockObjects[DC_PEN])
     {
-        /* ROS HACK, should use surf xlate */
-        pxlo = pdc->rosdc.XlatePen;
-
         /* Update the eboLine's solid color */
-        EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, pdcattr->crPenClr, pxlo);
+        EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboLine, pdcattr->crPenClr);
     }
 
     /* Clear flags */
@@ -180,25 +109,14 @@ FASTCALL
 DC_vUpdateTextBrush(PDC pdc)
 {
     PDC_ATTR pdcattr = pdc->pdcattr;
-    XLATEOBJ *pxlo = NULL;
-    SURFACE *psurf;
-    HPALETTE hpal;
 
-    psurf = pdc->dclevel.pSurface;
-    if (psurf)
-    {
-        hpal = psurf->hDIBPalette;
-        if (!hpal) hpal = pPrimarySurface->DevInfo.hpalDefault;
-        pxlo = IntEngCreateXlate(0, PAL_RGB, hpal, NULL);
-    }
+    /* Timo : The text brush should never be changed.
+     * Jérôme : Yeah, but its palette must be updated anyway! */
+    if(pdcattr->ulDirty_ & DIRTY_TEXT)
+        EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
 
     /* Update the eboText's solid color */
-    EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr, pxlo);
-
-    if (pxlo)
-    {
-        EngDeleteXlate(pxlo);
-    }
+    EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
 
     /* Clear flag */
     pdcattr->ulDirty_ &= ~DIRTY_TEXT;
@@ -209,32 +127,19 @@ FASTCALL
 DC_vUpdateBackgroundBrush(PDC pdc)
 {
     PDC_ATTR pdcattr = pdc->pdcattr;
-    XLATEOBJ *pxlo = NULL;
-    SURFACE *psurf;
-    HPALETTE hpal;
 
-    psurf = pdc->dclevel.pSurface;
-    if (psurf)
-    {
-        hpal = psurf->hDIBPalette;
-        if (!hpal) hpal = pPrimarySurface->DevInfo.hpalDefault;
-        pxlo = IntEngCreateXlate(0, PAL_RGB, hpal, NULL);
-    }
+    if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+        EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
 
     /* Update the eboBackground's solid color */
-    EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr, pxlo);
-
-    if (pxlo)
-    {
-        EngDeleteXlate(pxlo);
-    }
+    EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
 
     /* Clear flag */
     pdcattr->ulDirty_ &= ~DIRTY_BACKGROUND;
 }
 
-HPALETTE 
-FASTCALL 
+HPALETTE
+FASTCALL
 GdiSelectPalette(
     HDC hDC,
     HPALETTE hpal,
@@ -252,28 +157,29 @@ GdiSelectPalette(
     }
 
     /* Check if this is a valid palette handle */
-    ppal = PALETTE_LockPalette(hpal);
+    ppal = PALETTE_ShareLockPalette(hpal);
     if (!ppal)
     {
         DC_UnlockDc(pdc);
         return NULL;
     }
 
-    // FIXME: This looks wrong
     /* Is this a valid palette for this depth? */
-    if ((pdc->rosdc.bitsPerPixel <= 8 && ppal->Mode == PAL_INDEXED) ||
-        (pdc->rosdc.bitsPerPixel > 8))
+       if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
+                                       && (ppal->flFlags & PAL_INDEXED)) ||
+                       (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
     {
         /* Get old palette, set new one */
         oldPal = pdc->dclevel.hpal;
         pdc->dclevel.hpal = hpal;
+        DC_vSelectPalette(pdc, ppal);
 
         /* Mark the brushes invalid */
         pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE |
                                   DIRTY_BACKGROUND | DIRTY_TEXT;
     }
 
-    PALETTE_UnlockPalette(ppal);
+    PALETTE_ShareUnlockPalette(ppal);
     DC_UnlockDc(pdc);
 
     return oldPal;
@@ -345,81 +251,119 @@ NtGdiSelectPen(
 HBITMAP
 APIENTRY
 NtGdiSelectBitmap(
-    IN HDC hDC,
-    IN HBITMAP hBmp)
+    IN HDC hdc,
+    IN HBITMAP hbmp)
 {
-    PDC pDC;
+    PDC pdc;
     PDC_ATTR pdcattr;
-    HBITMAP hOrgBmp;
-    PSURFACE psurfBmp, psurfOld;
+    HBITMAP hbmpOld;
+    PSURFACE psurfNew;
     HRGN hVisRgn;
+    SIZEL sizlBitmap = {1, 1};
+    HDC hdcOld;
+    ASSERT_NOGDILOCKS();
 
-    if (hDC == NULL || hBmp == NULL) return NULL;
+    /* Verify parameters */
+    if (hdc == NULL || hbmp == NULL) return NULL;
 
-    pDC = DC_LockDc(hDC);
-    if (!pDC)
+    /* First lock the DC */
+    pdc = DC_LockDc(hdc);
+    if (!pdc)
     {
         return NULL;
     }
-    pdcattr = pDC->pdcattr;
+    pdcattr = pdc->pdcattr;
 
-    /* must be memory dc to select bitmap */
-    if (pDC->dctype != DC_TYPE_MEMORY)
+    /* Must be a memory dc to select a bitmap */
+    if (pdc->dctype != DC_TYPE_MEMORY)
     {
-        DC_UnlockDc(pDC);
+        DC_UnlockDc(pdc);
         return NULL;
     }
 
-    psurfBmp = SURFACE_LockSurface(hBmp);
-    if (!psurfBmp)
+    /* Check if there was a bitmap selected before */
+    if (pdc->dclevel.pSurface)
     {
-        DC_UnlockDc(pDC);
-        return NULL;
+        /* Return its handle */
+        hbmpOld = pdc->dclevel.pSurface->BaseObject.hHmgr;
+    }
+    else
+    {
+        /* Return default bitmap */
+        hbmpOld = StockObjects[DEFAULT_BITMAP];
     }
 
-    /* Get the handle for the old bitmap */
-    psurfOld = pDC->dclevel.pSurface;
-    hOrgBmp = psurfOld ? psurfOld->BaseObject.hHmgr : NULL;
-
-    /* Release the old bitmap, reference the new */
-    DC_vSelectSurface(pDC, psurfBmp);
-
-    // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
-    psurfBmp->hDC = hDC;
-
-    // if we're working with a DIB, get the palette 
-    // [fixme: only create if the selected palette is null]
-    if (psurfBmp->hSecure)
+    /* Check if the default bitmap was passed */
+    if (hbmp == StockObjects[DEFAULT_BITMAP])
     {
-//        pDC->rosdc.bitsPerPixel = psurfBmp->dib->dsBmih.biBitCount; ???
-        pDC->rosdc.bitsPerPixel = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
+        psurfNew = NULL;
+
+        // HACK
+        psurfNew = SURFACE_ShareLockSurface(hbmp);
     }
     else
     {
-        pDC->rosdc.bitsPerPixel = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
+        /* Reference the new bitmap and check if it's valid */
+        psurfNew = SURFACE_ShareLockSurface(hbmp);
+        if (!psurfNew)
+        {
+            DC_UnlockDc(pdc);
+            return NULL;
+        }
+
+        /* Set the bitmp's hdc */
+        hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0);
+        if (hdcOld != NULL && hdcOld != hdc)
+        {
+            /* The bitmap is already selected, fail */
+            SURFACE_ShareUnlockSurface(psurfNew);
+            DC_UnlockDc(pdc);
+            return NULL;
+        }
+
+        /* Get the bitmap size */
+        sizlBitmap = psurfNew->SurfObj.sizlBitmap;
+
+        /* Check if the bitmap is a dibsection */
+        if(psurfNew->hSecure)
+        {
+            /* Set DIBSECTION attribute */
+            pdcattr->ulDirty_ |= DC_DIBSECTION;
+        }
+        else
+        {
+            pdcattr->ulDirty_ &= ~DC_DIBSECTION;
+        }
     }
 
-    /* FIXME; improve by using a region without a handle and selecting it */
-    hVisRgn = NtGdiCreateRectRgn(0,
-                                 0,
-                                 psurfBmp->SurfObj.sizlBitmap.cx,
-                                 psurfBmp->SurfObj.sizlBitmap.cy);
+    /* Select the new surface, release the old */
+    DC_vSelectSurface(pdc, psurfNew);
+
+    /* Set the new size */
+    pdc->dclevel.sizl = sizlBitmap;
 
-    /* Release the exclusive lock */
-    SURFACE_UnlockSurface(psurfBmp);
+    /* Release one reference we added */
+    SURFACE_ShareUnlockSurface(psurfNew);
 
-    /* Mark the brushes invalid */
+    /* Mark the dc brushes invalid */
     pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
 
-    DC_UnlockDc(pDC);
+    /* Unlock the DC */
+    DC_UnlockDc(pdc);
 
+    /* FIXME; improve by using a region without a handle and selecting it */
+    hVisRgn = IntSysCreateRectRgn( 0,
+                                   0,
+                                   sizlBitmap.cx,
+                                   sizlBitmap.cy);
     if (hVisRgn)
     {
-        GdiSelectVisRgn(hDC, hVisRgn);
-        GreDeleteObject(hVisRgn);
+        GdiSelectVisRgn(hdc, hVisRgn);
+        REGION_FreeRgnByHandle(hVisRgn);
     }
 
-    return hOrgBmp;
+    /* Return the old bitmp handle */
+    return hbmpOld;
 }
 
 
@@ -434,11 +378,11 @@ NtGdiSelectClipPath(
     BOOL  success = FALSE;
     PDC_ATTR pdcattr;
     PDC pdc;
-    
+
     pdc = DC_LockDc(hDC);
     if (!pdc)
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
     pdcattr = pdc->pdcattr;
@@ -453,7 +397,8 @@ NtGdiSelectClipPath(
     /* Check that path is closed */
     if (pPath->state != PATH_Closed)
     {
-        SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+        EngSetLastError(ERROR_CAN_NOT_COMPLETE);
+        DC_UnlockDc(pdc);
         return FALSE;
     }
 
@@ -489,7 +434,7 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType)
 
     if(!(pdc = DC_LockDc(hDC)))
     {
-        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        EngSetLastError(ERROR_INVALID_HANDLE);
         return NULL;
     }
     pdcattr = pdc->pdcattr;
@@ -534,7 +479,7 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType)
 
         default:
             SelObject = NULL;
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             break;
     }
 
@@ -542,6 +487,79 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType)
     return SelObject;
 }
 
+/* See wine, msdn, osr and  Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw
+
+   1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
+
+   The intersection of the clip with the meta region is not Rao it's API!
+   Go back and read 7.2 Clipping pages 418-19:
+   Rao = API & Vis:
+   1) The Rao region is the intersection of the API region and the system region,
+      named after the Microsoft engineer who initially proposed it.
+   2) The Rao region can be calculated from the API region and the system region.
+
+   API:
+      API region is the intersection of the meta region and the clipping region,
+      clearly named after the fact that it is controlled by GDI API calls.
+*/
+INT
+APIENTRY
+NtGdiGetRandomRgn(
+    HDC hdc,
+    HRGN hrgnDest,
+    INT iCode)
+{
+    INT ret = 0;
+    PDC pdc;
+    HRGN hrgnSrc = NULL;
+    POINTL ptlOrg;
+
+    pdc = DC_LockDc(hdc);
+    if (!pdc)
+    {
+        EngSetLastError(ERROR_INVALID_HANDLE);
+        return -1;
+    }
+
+    switch (iCode)
+    {
+        case CLIPRGN:
+            hrgnSrc = pdc->rosdc.hClipRgn;
+//            if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
+            break;
+        case METARGN:
+            if (pdc->dclevel.prgnMeta)
+                hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr;
+            break;
+        case APIRGN:
+            if (pdc->prgnAPI) hrgnSrc = pdc->prgnAPI->BaseObject.hHmgr;
+//            else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr;
+            else if (pdc->rosdc.hClipRgn) hrgnSrc = pdc->rosdc.hClipRgn;
+            else if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr;
+            break;
+        case SYSRGN:
+            if (pdc->prgnVis) hrgnSrc = pdc->prgnVis->BaseObject.hHmgr;
+            break;
+        default:
+            hrgnSrc = NULL;
+    }
+
+    if (hrgnSrc)
+    {
+        ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1;
+    }
+
+    if (iCode == SYSRGN)
+    {
+        ptlOrg = pdc->ptlDCOrig;
+        NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y );
+    }
+
+    DC_UnlockDc(pdc);
+
+    return ret;
+}
+
 ULONG
 APIENTRY
 NtGdiEnumObjects(