Sync with trunk (r48545)
[reactos.git] / subsystems / win32 / win32k / objects / bitmaps.c
index 4fc4388..3c9f0e2 100644 (file)
@@ -76,14 +76,14 @@ GreCreateBitmapEx(
     IN ULONG iFormat,
     IN USHORT fjBitmap,
     IN ULONG cjSizeImage,
-    IN OPTIONAL PVOID pvBits)
+    IN OPTIONAL PVOID pvBits,
+       IN FLONG flags)
 {
     PSURFACE psurf;
     SURFOBJ *pso;
     HBITMAP hbmp;
     PVOID pvCompressedBits;
     SIZEL sizl;
-    FLONG fl = 0;
 
     /* Verify format */
     if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
@@ -107,7 +107,7 @@ GreCreateBitmapEx(
         pvCompressedBits = pvBits;
         pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
         Decompress4bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
-        fl |= BMF_RLE_HACK;
+        fjBitmap |= BMF_RLE_HACK;
     }
     else if (iFormat == BMF_8RLE)
     {
@@ -115,9 +115,12 @@ GreCreateBitmapEx(
         pvCompressedBits = pvBits;
         pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
         Decompress8bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
-        fl |= BMF_RLE_HACK;
+        fjBitmap |= BMF_RLE_HACK;
     }
 
+       /* Mark as API bitmap */
+       psurf->flags |= (flags | API_BITMAP);
+
     /* Set the bitmap bits */
     if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
     {
@@ -127,14 +130,14 @@ GreCreateBitmapEx(
         return NULL;
     }
 
-    /* Mark as API bitmap */
-    psurf->flags |= API_BITMAP;
-
     /* Unlock the surface and return */
     SURFACE_UnlockSurface(psurf);
     return hbmp;
 }
 
+/* Creates a DDB surface,
+ * as in CreateCompatibleBitmap or CreateBitmap.
+ */
 HBITMAP
 APIENTRY
 GreCreateBitmap(
@@ -151,7 +154,8 @@ GreCreateBitmap(
                              BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
                              0, /* no bitmap flags */
                              0, /* auto size */
-                             pvBits);
+                             pvBits,
+                                                        DDB_SURFACE /* DDB */);
 }
 
 HBITMAP
@@ -163,10 +167,7 @@ NtGdiCreateBitmap(
     IN UINT cBitsPixel,
     IN OPTIONAL LPBYTE pUnsafeBits)
 {
-    PSURFACE psurf;
-    SURFOBJ *pso;
     HBITMAP hbmp;
-    FLONG fl = 0;
     ULONG cjWidthBytes, iFormat;
 
     /* NOTE: Windows also doesn't store nr. of planes separately! */
@@ -185,7 +186,7 @@ NtGdiCreateBitmap(
     }
 
     /* Make sure that cjBits will not overflow */
-    cjWidthBytes = DIB_GetDIBWidthBytes(nWidth, cBitsPixel);
+    cjWidthBytes = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
     if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
     {
         DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
@@ -194,30 +195,12 @@ NtGdiCreateBitmap(
         return NULL;
     }
 
-    /* Allocate a surface */
-    psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
-    if (!psurf)
-    {
-        DPRINT1("SURFACE_AllocSurface failed.\n");
-        EngSetLastError(ERROR_OUTOFMEMORY);
-        return NULL;
-    }
-
-    /* Get the handle for the bitmap and the surfobj */
-    hbmp = (HBITMAP)psurf->SurfObj.hsurf;
-    pso = &psurf->SurfObj;
+       /* cBitsPixel = cBitsPixel * cPlanes now! */
+       hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
 
-    /* Allocate the bitmap bits */
-    if (!SURFACE_bSetBitmapBits(psurf, fl, 0, NULL))
-    {
-        /* Bail out if that failed */
-        DPRINT1("SURFACE_bSetBitmapBits failed.\n");
-        SURFACE_FreeSurfaceByHandle(hbmp);
-        return NULL;
-    }
-    
     if (pUnsafeBits)
     {
+               PSURFACE psurf = SURFACE_LockSurface(hbmp);
         _SEH2_TRY
         {
             ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
@@ -225,17 +208,15 @@ NtGdiCreateBitmap(
         }
         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
         {
+                       SURFACE_UnlockSurface(psurf);
             SURFACE_FreeSurfaceByHandle(hbmp);
             _SEH2_YIELD(return NULL;)
         }
         _SEH2_END
-    }
 
-    /* Mark as API bitmap */
-    psurf->flags |= API_BITMAP;
+               SURFACE_UnlockSurface(psurf);
+    }
 
-    /* Unlock the surface and return */
-    SURFACE_UnlockSurface(psurf);
     return hbmp;
 }
 
@@ -291,7 +272,7 @@ IntCreateCompatibleBitmap(
                     PSURFACE psurfBmp;
                     size.cx = abs(Width);
                     size.cy = abs(Height);
-            Bmp = GreCreateBitmap(abs(Width),
+                                       Bmp = GreCreateBitmap(abs(Width),
                                   abs(Height),
                                   1,
                                   dibs.dsBm.bmBitsPixel,
@@ -309,63 +290,51 @@ IntCreateCompatibleBitmap(
                 else
                 {
                     /* A DIB section is selected in the DC */
-                    BITMAPINFO *bi;
+                                       BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
                     PVOID Bits;
-
-                    /* Allocate memory for a BITMAPINFOHEADER structure and a
-                       color table. The maximum number of colors in a color table
-                       is 256 which corresponds to a bitmap with depth 8.
-                       Bitmaps with higher depths don't have color tables. */
-                    bi = ExAllocatePoolWithTag(PagedPool,
-                                               sizeof(BITMAPINFOHEADER) +
-                                                   256 * sizeof(RGBQUAD),
-                                               TAG_TEMP);
-
-                    if (bi)
+                                       BITMAPINFO* bi = (BITMAPINFO*)buf;
+
+                    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+                    bi->bmiHeader.biWidth         = Width;
+                    bi->bmiHeader.biHeight        = Height;
+                    bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
+                    bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
+                    bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
+                    bi->bmiHeader.biSizeImage     = 0;
+                    bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
+                    bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
+                    bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
+                    bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
+
+                    if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                    {
+                        /* Copy the color masks */
+                        RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
+                    }
+                    else if (bi->bmiHeader.biBitCount <= 8)
                     {
-                        bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
-                        bi->bmiHeader.biWidth         = Width;
-                        bi->bmiHeader.biHeight        = Height;
-                        bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
-                        bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
-                        bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
-                        bi->bmiHeader.biSizeImage     = 0;
-                        bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
-                        bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
-                        bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
-                        bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
-
-                        if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                        /* Copy the color table */
+                        UINT Index;
+                        PPALETTE PalGDI;
+
+                        if (!psurf->ppal)
                         {
-                            /* Copy the color masks */
-                            RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3 * sizeof(DWORD));
+                            SetLastWin32Error(ERROR_INVALID_HANDLE);
+                            return 0;
                         }
-                        else if (bi->bmiHeader.biBitCount <= 8)
+
+                        PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
+                        for (Index = 0;
+                                Index < 256 && Index < PalGDI->NumColors;
+                                Index++)
                         {
-                            /* Copy the color table */
-                            UINT Index;
-                            PPALETTE PalGDI;
-
-                            if (!psurf->ppal)
-                            {
-                                ExFreePoolWithTag(bi, TAG_TEMP);
-                                SetLastWin32Error(ERROR_INVALID_HANDLE);
-                                return 0;
-                            }
-
-                            PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
-
-                            for (Index = 0;
-                                    Index < 256 && Index < PalGDI->NumColors;
-                                    Index++)
-                            {
-                                bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
-                                bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
-                                bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
-                                bi->bmiColors[Index].rgbReserved = 0;
-                            }
-                            PALETTE_UnlockPalette(PalGDI);
+                            bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
+                            bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
+                            bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
+                            bi->bmiColors[Index].rgbReserved = 0;
                         }
+                        PALETTE_UnlockPalette(PalGDI);
 
                         Bmp = DIB_CreateDIBSection(Dc,
                                                    bi,
@@ -374,8 +343,6 @@ IntCreateCompatibleBitmap(
                                                    NULL,
                                                    0,
                                                    0);
-
-                        ExFreePoolWithTag(bi, TAG_TEMP);
                         return Bmp;
                     }
                 }
@@ -614,6 +581,36 @@ IntGetBitmapBits(
     return ret;
 }
 
+VOID
+FASTCALL
+UnsafeGetBitmapBits(
+    PSURFACE psurf,
+       DWORD Bytes,
+       OUT PBYTE pvBits)
+{
+       PUCHAR pjDst, pjSrc;
+    LONG lDeltaDst, lDeltaSrc;
+    ULONG nWidth, nHeight, cBitsPixel;
+
+    nWidth = psurf->SurfObj.sizlBitmap.cx;
+    nHeight = psurf->SurfObj.sizlBitmap.cy;
+    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+
+    /* Get pointers */
+    pjSrc = psurf->SurfObj.pvScan0;
+    pjDst = pvBits;
+    lDeltaSrc = psurf->SurfObj.lDelta;
+    lDeltaDst = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
+
+    while (nHeight--)
+    {
+        /* Copy one line */
+        RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
+        pjSrc += lDeltaSrc;
+        pjDst += lDeltaDst;
+    }
+}
+
 LONG APIENTRY
 NtGdiGetBitmapBits(
     HBITMAP hBitmap,
@@ -653,7 +650,8 @@ NtGdiGetBitmapBits(
     _SEH2_TRY
     {
         ProbeForWrite(pUnsafeBits, Bytes, 1);
-        ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits);
+        UnsafeGetBitmapBits(psurf, Bytes, pUnsafeBits);
+               ret = Bytes;
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -926,7 +924,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
         return 0;
     }
 
-    Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
+    Bitmap = SURFACE_LockSurface(hBitmap);
     if (Bitmap == NULL)
     {
         return 0;
@@ -939,40 +937,25 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
 
     Size.cx = abs(bm.bmWidth);
     Size.cy = abs(bm.bmHeight);
-            res = GreCreateBitmap(abs(bm.bmWidth),
-                                  abs(bm.bmHeight),
-                                  1,
-                                  bm.bmBitsPixel,
-                                  NULL);
+    res = GreCreateBitmapEx(Size.cx,
+                                                       Size.cy,
+                                                       bm.bmWidthBytes,
+                                                       Bitmap->SurfObj.iBitmapFormat,
+                                                       Bitmap->SurfObj.fjBitmap,
+                                                       Bitmap->SurfObj.cjBits,
+                                                       NULL,
+                                                       Bitmap->flags);
+
 
     if (res)
     {
-        PBYTE buf;
-
-        resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
+        resBitmap = SURFACE_LockSurface(res);
         if (resBitmap)
         {
-            buf = ExAllocatePoolWithTag(PagedPool,
-                                        bm.bmWidthBytes * abs(bm.bmHeight),
-                                        TAG_BITMAP);
-            if (buf == NULL)
-            {
-                GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
-                GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
-                GreDeleteObject(res);
-                return 0;
-            }
-            IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
-            IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
-            ExFreePoolWithTag(buf,TAG_BITMAP);
-            resBitmap->flags = Bitmap->flags;
-            /* Copy palette */
-            if (Bitmap->ppal)
-            {
-                resBitmap->ppal = Bitmap->ppal ;
-                GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject);
-            }
-            GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
+            IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
+            resBitmap->ppal = Bitmap->ppal;
+            GDIOBJ_IncrementShareCount((POBJ)Bitmap->ppal);
+                       SURFACE_UnlockSurface(resBitmap);
         }
         else
         {
@@ -981,7 +964,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
         }
     }
 
-    GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
+    SURFACE_UnlockSurface(Bitmap);
 
     return  res;
 }
@@ -999,15 +982,17 @@ BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
     pBitmap->bmType = 0;
     pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
     pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
-    pBitmap->bmWidthBytes = abs(psurf->SurfObj.lDelta);
     pBitmap->bmPlanes = 1;
     pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+       pBitmap->bmWidthBytes = BITMAP_GetWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
 
     /* Check for DIB section */
     if (psurf->hSecure)
     {
         /* Set bmBits in this case */
         pBitmap->bmBits = psurf->SurfObj.pvBits;
+               /* DIBs data are 32 bits aligned */
+               pBitmap->bmWidthBytes = DIB_GetDIBWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
 
         if (Count >= sizeof(DIBSECTION))
         {
@@ -1019,38 +1004,44 @@ BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
             pds->dsBmih.biHeight = pds->dsBm.bmHeight;
             pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
             pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
-            switch (psurf->SurfObj.iBitmapFormat)
-            {
-                /* FIXME: What about BI_BITFIELDS? */
-                case BMF_1BPP:
-                case BMF_4BPP:
-                case BMF_8BPP:
-                case BMF_16BPP:
-                case BMF_24BPP:
-                case BMF_32BPP:
-                   pds->dsBmih.biCompression = BI_RGB;
-                   break;
-                case BMF_4RLE:
-                   pds->dsBmih.biCompression = BI_RLE4;
-                   break;
-                case BMF_8RLE:
-                   pds->dsBmih.biCompression = BI_RLE8;
-                   break;
-                case BMF_JPEG:
-                   pds->dsBmih.biCompression = BI_JPEG;
-                   break;
-                case BMF_PNG:
-                   pds->dsBmih.biCompression = BI_PNG;
-                   break;
-            }
+                       if(psurf->ppal->Mode & PAL_BITFIELDS)
+                       {
+                               pds->dsBmih.biCompression = BI_BITFIELDS;
+                       }
+                       else
+                       {
+                               switch (psurf->SurfObj.iBitmapFormat)
+                               {
+                                       case BMF_1BPP:
+                                       case BMF_4BPP:
+                                       case BMF_8BPP:
+                                       case BMF_16BPP:
+                                       case BMF_24BPP:
+                                       case BMF_32BPP:
+                                          pds->dsBmih.biCompression = BI_RGB;
+                                          break;
+                                       case BMF_4RLE:
+                                          pds->dsBmih.biCompression = BI_RLE4;
+                                          break;
+                                       case BMF_8RLE:
+                                          pds->dsBmih.biCompression = BI_RLE8;
+                                          break;
+                                       case BMF_JPEG:
+                                          pds->dsBmih.biCompression = BI_JPEG;
+                                          break;
+                                       case BMF_PNG:
+                                          pds->dsBmih.biCompression = BI_PNG;
+                                          break;
+                               }
+                       }
             pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
             pds->dsBmih.biXPelsPerMeter = 0;
             pds->dsBmih.biYPelsPerMeter = 0;
-            pds->dsBmih.biClrUsed = psurf->biClrUsed;
+            pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
             pds->dsBmih.biClrImportant = psurf->biClrImportant;
-            pds->dsBitfields[0] = psurf->dsBitfields[0];
-            pds->dsBitfields[1] = psurf->dsBitfields[1];
-            pds->dsBitfields[2] = psurf->dsBitfields[2];
+            pds->dsBitfields[0] = psurf->ppal->RedMask;
+            pds->dsBitfields[1] = psurf->ppal->GreenMask;
+            pds->dsBitfields[2] = psurf->ppal->BlueMask;
             pds->dshSection = psurf->hDIBSection;
             pds->dsOffset = psurf->dwOffset;
 
@@ -1084,4 +1075,5 @@ NtGdiGetDCforBitmap(
     return hdc;
 }
 
+
 /* EOF */