[win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / dibobj.c
index 9bc9ea2..cc2a16e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * ReactOS W32 Subsystem
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
  *
@@ -14,9 +12,9 @@
  * 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>
@@ -151,7 +149,7 @@ IntGetDIBColorTable(
     PDC dc;
     PSURFACE psurf;
     PPALETTE PalGDI;
-    UINT Index;
+    UINT Index, Count = 0;
     ULONG biBitCount;
 
     if (!(dc = DC_LockDc(hDC))) return 0;
@@ -199,15 +197,14 @@ IntGetDIBColorTable(
             Colors[Index - StartIndex].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
             Colors[Index - StartIndex].rgbBlue = PalGDI->IndexedColors[Index].peBlue;
             Colors[Index - StartIndex].rgbReserved = 0;
+            Count++;
         }
         PALETTE_UnlockPalette(PalGDI);
     }
-    else
-        Entries = 0;
 
     DC_UnlockDc(dc);
 
-    return Entries;
+    return Count;
 }
 
 // Converts a DIB to a device-dependent bitmap
@@ -230,11 +227,11 @@ IntSetDIBits(
     SIZEL       SourceSize;
     POINTL      ZeroPoint;
     RECTL       DestRect;
-    XLATEOBJ   *XlateObj;
-    PPALETTE     hDCPalette;
+    EXLATEOBJ   exlo;
+    PPALETTE    ppalDDB, ppalDIB;
     //RGBQUAD    *lpRGB;
     HPALETTE    DDB_Palette, DIB_Palette;
-    ULONG       DDB_Palette_Type, DIB_Palette_Type;
+    ULONG       DIB_Palette_Type;
     INT         DIBWidth;
 
     // Check parameters
@@ -287,11 +284,11 @@ IntSetDIBits(
     else
     {
         // Destination palette obtained from the hDC
-        DDB_Palette = DC->ppdev->DevInfo.hpalDefault;
+        DDB_Palette = DC->ppdev->devinfo.hpalDefault;
     }
 
-    hDCPalette = PALETTE_LockPalette(DDB_Palette);
-    if (NULL == hDCPalette)
+    ppalDDB = PALETTE_LockPalette(DDB_Palette);
+    if (NULL == ppalDDB)
     {
         EngUnlockSurface(SourceSurf);
         EngDeleteSurface((HSURF)SourceBitmap);
@@ -299,8 +296,6 @@ IntSetDIBits(
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         return 0;
     }
-    DDB_Palette_Type = hDCPalette->Mode;
-    PALETTE_UnlockPalette(hDCPalette);
 
     // Source palette obtained from the BITMAPINFO
     DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type);
@@ -313,17 +308,10 @@ IntSetDIBits(
         return 0;
     }
 
-    // Determine XLATEOBJ for color translation
-    XlateObj = IntEngCreateXlate(0, 0, DDB_Palette, DIB_Palette);
-    if (NULL == XlateObj)
-    {
-        PALETTE_FreePaletteByHandle(DIB_Palette);
-        EngUnlockSurface(SourceSurf);
-        EngDeleteSurface((HSURF)SourceBitmap);
-        SURFACE_UnlockSurface(bitmap);
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        return 0;
-    }
+    ppalDIB = PALETTE_LockPalette(DIB_Palette);
+
+    /* Initialize XLATEOBJ for color translation */
+    EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
 
     // Zero point
     ZeroPoint.x = 0;
@@ -335,7 +323,7 @@ IntSetDIBits(
     DestRect.right     = SourceSize.cx;
     DestRect.bottom    = DestRect.top + ScanLines;
 
-    copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, XlateObj, &DestRect, &ZeroPoint);
+    copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
 
     // If it succeeded, return number of scanlines copies
     if (copyBitsResult == TRUE)
@@ -346,7 +334,9 @@ IntSetDIBits(
     }
 
     // Clean up
-    EngDeleteXlate(XlateObj);
+    EXLATEOBJ_vCleanup(&exlo);
+    PALETTE_UnlockPalette(ppalDIB);
+    PALETTE_UnlockPalette(ppalDDB);
     PALETTE_FreePaletteByHandle(DIB_Palette);
     EngUnlockSurface(SourceSurf);
     EngDeleteSurface((HSURF)SourceBitmap);
@@ -449,10 +439,10 @@ NtGdiSetDIBitsToDeviceInternal(
     POINTL ptSource;
     INT DIBWidth;
     SIZEL SourceSize;
-    XLATEOBJ *XlateObj = NULL;
-    PPALETTE pDCPalette;
-    HPALETTE DDBPalette, DIBPalette = NULL;
-    ULONG DDBPaletteType, DIBPaletteType;
+    EXLATEOBJ exlo;
+    PPALETTE ppalDDB = NULL, ppalDIB = NULL;
+    HPALETTE hpalDDB, hpalDIB = NULL;
+    ULONG DIBPaletteType;
 
     if (!Bits) return 0;
 
@@ -485,17 +475,19 @@ NtGdiSetDIBitsToDeviceInternal(
     }
 
     /* Use destination palette obtained from the DC by default */
-    DDBPalette = pDC->ppdev->DevInfo.hpalDefault;
+    hpalDDB = pDC->ppdev->devinfo.hpalDefault;
 
     /* Try to use hDIBPalette if it exists */
     pSurf = pDC->dclevel.pSurface;
     if (pSurf && pSurf->hDIBPalette)
     {
-        DDBPalette = pSurf->hDIBPalette;
+        hpalDDB = pSurf->hDIBPalette;
     }
 
     pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
 
+    ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
+
     rcDest.left = XDest;
     rcDest.top = YDest;
     if (bTransformCoordinates)
@@ -506,11 +498,14 @@ NtGdiSetDIBitsToDeviceInternal(
     rcDest.top += pDC->ptlDCOrig.y;
     rcDest.right = rcDest.left + Width;
     rcDest.bottom = rcDest.top + Height;
+    rcDest.top += StartScan;
+
     ptSource.x = XSrc;
     ptSource.y = YSrc;
 
     SourceSize.cx = bmi->bmiHeader.biWidth;
-    SourceSize.cy = ScanLines; // this one --> abs(bmi->bmiHeader.biHeight) - StartScan
+    SourceSize.cy = ScanLines;
+
     DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
 
     hSourceBitmap = EngCreateBitmap(SourceSize,
@@ -533,57 +528,66 @@ NtGdiSetDIBitsToDeviceInternal(
     }
 
     /* Obtain destination palette */
-    pDCPalette = PALETTE_LockPalette(DDBPalette);
-    if (!pDCPalette)
+    ppalDDB = PALETTE_LockPalette(hpalDDB);
+    if (!ppalDDB)
     {
         SetLastWin32Error(ERROR_INVALID_HANDLE);
         Status = STATUS_UNSUCCESSFUL;
         goto Exit;
     }
 
-    DDBPaletteType = pDCPalette->Mode;
-    PALETTE_UnlockPalette(pDCPalette);
-
-    DIBPalette = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
-    if (!DIBPalette)
+    /* Create a palette for the DIB */
+    hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
+    if (!hpalDIB)
     {
         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
         Status = STATUS_NO_MEMORY;
         goto Exit;
     }
 
-    /* Determine XlateObj */
-    XlateObj = IntEngCreateXlate(DDBPaletteType, DIBPaletteType, DDBPalette, DIBPalette);
-    if (!XlateObj)
+    /* Lock the DIB palette */
+    ppalDIB = PALETTE_LockPalette(hpalDIB);
+    if (!ppalDDB)
     {
-        SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-        Status = STATUS_NO_MEMORY;
+        SetLastWin32Error(ERROR_INVALID_HANDLE);
+        Status = STATUS_UNSUCCESSFUL;
         goto Exit;
     }
 
+    /* Initialize EXLATEOBJ */
+    EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+
     /* Copy the bits */
+    DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n", 
+        rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
+        ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
     Status = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
                           NULL,
                           pDC->rosdc.CombinedClip,
-                          XlateObj,
+                          &exlo.xlo,
                           &rcDest,
                           &ptSource,
                           NULL,
                           NULL,
                           NULL,
                           ROP3_TO_ROP4(SRCCOPY));
+
+    /* Cleanup EXLATEOBJ */
+    EXLATEOBJ_vCleanup(&exlo);
+
 Exit:
     if (NT_SUCCESS(Status))
     {
-        /* FIXME: Should probably be only the number of lines actually copied */
-        ret = ScanLines; // this one --> abs(Info->bmiHeader.biHeight) - StartScan;
+        ret = ScanLines;
     }
 
+    if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
+    if (ppalDDB) PALETTE_UnlockPalette(ppalDDB);
+
     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
-    if (XlateObj) EngDeleteXlate(XlateObj);
-    if (DIBPalette) PALETTE_FreePaletteByHandle(DIBPalette);
+    if (hpalDIB) PALETTE_FreePaletteByHandle(hpalDIB);
     DC_UnlockDc(pDC);
 
     return ret;
@@ -609,15 +613,14 @@ NtGdiGetDIBitsInternal(
     HBITMAP hDestBitmap = NULL;
     HPALETTE hSourcePalette = NULL;
     HPALETTE hDestPalette = NULL;
-    PPALETTE SourcePalette = NULL;
-    PPALETTE DestPalette = NULL;
+    PPALETTE ppalSrc = NULL;
+    PPALETTE ppalDst = NULL;
     NTSTATUS Status = STATUS_SUCCESS;
     ULONG Result = 0;
     BOOL bPaletteMatch = FALSE;
     PBYTE ChkBits = Bits;
     PVOID ColorPtr;
     RGBQUAD *rgbQuads;
-    ULONG SourcePaletteType = 0;
     ULONG DestPaletteType;
     ULONG Index;
 
@@ -632,6 +635,8 @@ NtGdiGetDIBitsInternal(
 
     _SEH2_TRY
     {
+        ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1);
+        
         ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core.
         if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
     }
@@ -663,7 +668,7 @@ NtGdiGetDIBitsInternal(
     hSourcePalette = psurf->hDIBPalette;
     if (!hSourcePalette)
     {
-        hSourcePalette = pPrimarySurface->DevInfo.hpalDefault;
+        hSourcePalette = pPrimarySurface->devinfo.hpalDefault;
     }
 
     ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize);
@@ -671,8 +676,9 @@ NtGdiGetDIBitsInternal(
 
     /* Copy palette information
      * Always create a palette for 15 & 16 bit. */
-    if (Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
-        Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16)
+    if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
+         Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) ||
+         !ChkBits)
     {
         hDestPalette = hSourcePalette;
         bPaletteMatch = TRUE;
@@ -680,23 +686,20 @@ NtGdiGetDIBitsInternal(
     else
         hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
 
-    SourcePalette = PALETTE_LockPalette(hSourcePalette);
-    /* FIXME - SourcePalette can be NULL!!! Don't assert here! */
-    ASSERT(SourcePalette);
-    SourcePaletteType = SourcePalette->Mode;
-    PALETTE_UnlockPalette(SourcePalette);
+    ppalSrc = PALETTE_LockPalette(hSourcePalette);
+    /* FIXME - ppalSrc can be NULL!!! Don't assert here! */
+    ASSERT(ppalSrc);
 
-    if (bPaletteMatch)
+    if (!bPaletteMatch)
     {
-        DestPalette = PALETTE_LockPalette(hDestPalette);
-        /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
-        DPRINT("DestPalette : %p\n", DestPalette);
-        ASSERT(DestPalette);
-        DestPaletteType = DestPalette->Mode;
+        ppalDst = PALETTE_LockPalette(hDestPalette);
+        /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */
+        DPRINT("ppalDst : %p\n", ppalDst);
+        ASSERT(ppalDst);
     }
     else
     {
-        DestPalette = SourcePalette;
+        ppalDst = ppalSrc;
     }
 
     /* Copy palette. */
@@ -712,15 +715,15 @@ NtGdiGetDIBitsInternal(
             {
                 if (Usage == DIB_RGB_COLORS)
                 {
-                    if (DestPalette->NumColors != 1 << Info->bmiHeader.biBitCount)
-                        Info->bmiHeader.biClrUsed = DestPalette->NumColors;
+                    if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount)
+                        Info->bmiHeader.biClrUsed = ppalDst->NumColors;
                     for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount) && Index < DestPalette->NumColors;
+                         Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
                          Index++)
                     {
-                        rgbQuads[Index].rgbRed   = DestPalette->IndexedColors[Index].peRed;
-                        rgbQuads[Index].rgbGreen = DestPalette->IndexedColors[Index].peGreen;
-                        rgbQuads[Index].rgbBlue  = DestPalette->IndexedColors[Index].peBlue;
+                        rgbQuads[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
+                        rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
+                        rgbQuads[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
                         rgbQuads[Index].rgbReserved = 0;
                     }
                 }
@@ -750,12 +753,12 @@ NtGdiGetDIBitsInternal(
                 else if (Info->bmiHeader.biBitCount > 1  && bPaletteMatch)
                 {
                     for (Index = 0;
-                         Index < (1 << Info->bmiHeader.biBitCount) && Index < DestPalette->NumColors;
+                         Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
                          Index++)
                     {
-                        Info->bmiColors[Index].rgbRed   = DestPalette->IndexedColors[Index].peRed;
-                        Info->bmiColors[Index].rgbGreen = DestPalette->IndexedColors[Index].peGreen;
-                        Info->bmiColors[Index].rgbBlue  = DestPalette->IndexedColors[Index].peBlue;
+                        Info->bmiColors[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
+                        Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
+                        Info->bmiColors[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
                         Info->bmiColors[Index].rgbReserved = 0;
                     }
                 }
@@ -825,8 +828,8 @@ NtGdiGetDIBitsInternal(
             break;
     }
 
-    if (bPaletteMatch)
-        PALETTE_UnlockPalette(DestPalette);
+    if (!bPaletteMatch)
+        PALETTE_UnlockPalette(ppalDst);
 
     /* fill out the BITMAPINFO struct */
     if (!ChkBits)
@@ -934,14 +937,11 @@ NtGdiGetDIBitsInternal(
 
         if (NT_SUCCESS(Status))
         {
-            XLATEOBJ *XlateObj;
+            EXLATEOBJ exlo;
             SURFOBJ *DestSurfObj;
             RECTL DestRect;
 
-            XlateObj = IntEngCreateXlate(DestPaletteType,
-                                         SourcePaletteType,
-                                         hDestPalette,
-                                         hSourcePalette);
+            EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0);
 
             SourcePoint.x = 0;
             SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
@@ -957,7 +957,7 @@ NtGdiGetDIBitsInternal(
             if (IntEngCopyBits(DestSurfObj,
                                &psurf->SurfObj,
                                NULL,
-                               XlateObj,
+                               &exlo.xlo,
                                &DestRect,
                                &SourcePoint))
             {
@@ -965,11 +965,13 @@ NtGdiGetDIBitsInternal(
                 Result = ScanLines;
             }
 
-            EngDeleteXlate(XlateObj);
+            EXLATEOBJ_vCleanup(&exlo);
             EngUnlockSurface(DestSurfObj);
         }
     }
 cleanup:
+    PALETTE_UnlockPalette(ppalSrc);
+
     if (hDestBitmap != NULL)
         EngDeleteSurface((HSURF)hDestBitmap);
 
@@ -1356,6 +1358,7 @@ DIB_CreateDIBSection(
     RGBQUAD *lpRGB;
     HANDLE hSecure;
     DWORD dsBitfields[3] = {0};
+    ULONG ColorCount;
 
     DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
            bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
@@ -1437,9 +1440,19 @@ DIB_CreateDIBSection(
     hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
 
     if (usage == DIB_PAL_COLORS)
+    {
         lpRGB = DIB_MapPaletteColors(dc, bmi);
+        ColorCount = bi->biClrUsed;
+        if (ColorCount == 0)
+        {
+            ColorCount = 1 << bi->biBitCount;
+        }
+    }
     else
+    {
         lpRGB = bmi->bmiColors;
+        ColorCount = 1 << bi->biBitCount;
+    }
 
     /* Set dsBitfields values */
     if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
@@ -1506,17 +1519,14 @@ DIB_CreateDIBSection(
                   table between the DIB and the X physical device. Obviously,
                   this is left out of the ReactOS implementation. Instead,
                   we call NtGdiSetDIBColorTable. */
-    bi->biClrUsed = 0;
-    /* set number of entries in bmi.bmiColors table */
-    if (bi->biBitCount == 1) {
-        bi->biClrUsed = 2;
-    } else
-        if (bi->biBitCount == 4) {
-            bi->biClrUsed = 16;
-        } else
-            if (bi->biBitCount == 8) {
-                bi->biClrUsed = 256;
-            }
+    if (bi->biBitCount <= 8)
+    {
+        bi->biClrUsed = 1 << bi->biBitCount;
+    }
+    else
+    {
+        bi->biClrUsed = 0;
+    }
 
     bmp->hDIBSection = section;
     bmp->hSecure = hSecure;
@@ -1529,12 +1539,16 @@ DIB_CreateDIBSection(
     bmp->biClrImportant = bi->biClrImportant;
 
     if (bi->biClrUsed != 0)
-        bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(bi->biClrUsed, lpRGB);
+    {
+        bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
+    }
     else
+    {
         bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
                                                 dsBitfields[0],
                                                 dsBitfields[1],
                                                 dsBitfields[2]);
+    }
 
     // Clean up in case of errors
     if (!res || !bmp || !bm.bmBits)
@@ -1579,7 +1593,7 @@ DIB_CreateDIBSection(
         *bits = bm.bmBits;
     }
 
-//  if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
+    if (res) pdcattr->ulDirty_ |= DC_DIBSECTION;
 
     return res;
 }
@@ -1672,9 +1686,18 @@ DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
 
     for (i = 0; i < nNumColors; i++)
     {
-        lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
-        lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
-        lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+        if (*lpIndex < palGDI->NumColors)
+        {
+            lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
+            lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
+            lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+        }
+        else
+        {
+            lpRGB[i].rgbRed = 0;
+            lpRGB[i].rgbGreen = 0;
+            lpRGB[i].rgbBlue = 0;
+        }
         lpRGB[i].rgbReserved = 0;
         lpIndex++;
     }