[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dcobjs.c
index 0bafaad..6975b60 100644 (file)
@@ -110,8 +110,10 @@ DC_vUpdateTextBrush(PDC pdc)
 {
     PDC_ATTR pdcattr = pdc->pdcattr;
 
+    /* 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, pdc->eboText.pbrush, pdc);
+        EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
 
     /* Update the eboText's solid color */
     EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
@@ -127,7 +129,7 @@ DC_vUpdateBackgroundBrush(PDC pdc)
     PDC_ATTR pdcattr = pdc->pdcattr;
 
     if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
-        EBRUSHOBJ_vUpdate(&pdc->eboBackground, pdc->eboBackground.pbrush, pdc);
+        EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
 
     /* Update the eboBackground's solid color */
     EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
@@ -162,10 +164,10 @@ GdiSelectPalette(
         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;
@@ -249,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 = IntSysCreateRectRgn( 0,
-                                   0,
-                                   psurfBmp->SurfObj.sizlBitmap.cx,
-                                   psurfBmp->SurfObj.sizlBitmap.cy);
+    /* Select the new surface, release the old */
+    DC_vSelectSurface(pdc, psurfNew);
 
-    /* Release the exclusive lock */
-    SURFACE_UnlockSurface(psurfBmp);
+    /* Set the new size */
+    pdc->dclevel.sizl = sizlBitmap;
 
-    /* Mark the brushes invalid */
+    /* Release one reference we added */
+    SURFACE_ShareUnlockSurface(psurfNew);
+
+    /* 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);
+        GdiSelectVisRgn(hdc, hVisRgn);
         REGION_FreeRgnByHandle(hVisRgn);
     }
 
-    return hOrgBmp;
+    /* Return the old bitmp handle */
+    return hbmpOld;
 }
 
 
@@ -342,7 +382,7 @@ NtGdiSelectClipPath(
     pdc = DC_LockDc(hDC);
     if (!pdc)
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
     pdcattr = pdc->pdcattr;
@@ -357,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;
     }
 
@@ -393,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;
@@ -438,7 +479,7 @@ NtGdiGetDCObject(HDC hDC, INT ObjectType)
 
         default:
             SelObject = NULL;
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             break;
     }
 
@@ -446,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(