[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / objects / bitmaps.c
index 2fe310a..f974625 100644 (file)
@@ -82,8 +82,6 @@ GreCreateBitmapEx(
     PSURFACE psurf;
     SURFOBJ *pso;
     HBITMAP hbmp;
-    PVOID pvCompressedBits;
-    SIZEL sizl;
 
     /* Verify format */
     if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
@@ -103,22 +101,38 @@ GreCreateBitmapEx(
     /* The infamous RLE hack */
     if (iFormat == BMF_4RLE || iFormat == BMF_8RLE)
     {
+        PVOID pvCompressedBits;
+        SIZEL sizl;
+        LONG lDelta;
+
         sizl.cx = nWidth;
         sizl.cy = nHeight;
+        lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]);
+
         pvCompressedBits = pvBits;
-        pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
-        DecompressBitmap(sizl, pvCompressedBits, pvBits, pso->lDelta, iFormat);
+        pvBits = EngAllocMem(FL_ZERO_MEMORY, lDelta * nHeight, TAG_DIB);
+        if (!pvBits)
+        {
+            EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            SURFACE_FreeSurfaceByHandle(hbmp);
+            return NULL;
+        }
+        DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat);
         fjBitmap |= BMF_RLE_HACK;
+        
+        iFormat = iFormat == BMF_4RLE ? BMF_4BPP : BMF_8BPP;
+        psurf->SurfObj.iBitmapFormat = iFormat;
     }
 
-       /* Mark as API bitmap */
-       psurf->flags |= (flags | API_BITMAP);
+    /* Mark as API bitmap */
+    psurf->flags |= (flags | API_BITMAP);
 
     /* Set the bitmap bits */
     if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
     {
         /* Bail out if that failed */
         DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
         SURFACE_FreeSurfaceByHandle(hbmp);
         return NULL;
     }
@@ -219,116 +233,111 @@ IntCreateCompatibleBitmap(
     /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
     if (0 == Width || 0 == Height)
     {
-        Bmp = NtGdiGetStockObject(DEFAULT_BITMAP);
+        return NtGdiGetStockObject(DEFAULT_BITMAP);
+    }
+
+    if (Dc->dctype != DC_TYPE_MEMORY)
+    {
+        PSURFACE psurf;
+
+        Bmp = GreCreateBitmap(abs(Width),
+                              abs(Height),
+                              1,
+                              Dc->ppdev->gdiinfo.cBitsPixel,
+                              NULL);
+        psurf = SURFACE_ShareLockSurface(Bmp);
+        ASSERT(psurf);
+        /* Set palette */
+        psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+        /* Set flags */
+        psurf->flags = API_BITMAP;
+        psurf->hdc = NULL; // Fixme
+        SURFACE_ShareUnlockSurface(psurf);
     }
     else
     {
-        if (Dc->dctype != DC_TYPE_MEMORY)
+        DIBSECTION dibs;
+        INT Count;
+        PSURFACE psurf = Dc->dclevel.pSurface;
+        Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
+
+        if (Count == sizeof(BITMAP))
         {
-            PSURFACE psurf;
+            PSURFACE psurfBmp;
 
             Bmp = GreCreateBitmap(abs(Width),
-                                  abs(Height),
-                                  1,
-                                  Dc->ppdev->gdiinfo.cBitsPixel,
-                                  NULL);
-            psurf = SURFACE_LockSurface(Bmp);
-            ASSERT(psurf);
-            /* Set palette */
-            psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+                          abs(Height),
+                          1,
+                          dibs.dsBm.bmBitsPixel,
+                          NULL);
+            psurfBmp = SURFACE_LockSurface(Bmp);
+            ASSERT(psurfBmp);
+            /* Assign palette */
+            psurfBmp->ppal = psurf->ppal;
+            GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
             /* Set flags */
-            psurf->flags = API_BITMAP;
-            psurf->hdc = NULL; // Fixme
-            SURFACE_UnlockSurface(psurf);
+            psurfBmp->flags = API_BITMAP;
+            psurfBmp->hdc = NULL; // Fixme
+            SURFACE_UnlockSurface(psurfBmp);
         }
-        else
+        else if (Count == sizeof(DIBSECTION))
         {
-            DIBSECTION dibs;
-            INT Count;
-            PSURFACE psurf = Dc->dclevel.pSurface;
-            Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
-
-            if (Count)
+            /* A DIB section is selected in the DC */
+            BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
+            PVOID Bits;
+            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)
             {
-                if (Count == sizeof(BITMAP))
+                /* Copy the color masks */
+                RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
+            }
+            else if (bi->bmiHeader.biBitCount <= 8)
+            {
+                /* Copy the color table */
+                UINT Index;
+                PPALETTE PalGDI;
+
+                if (!psurf->ppal)
                 {
-                    PSURFACE psurfBmp;
-
-                    Bmp = GreCreateBitmap(abs(Width),
-                                  abs(Height),
-                                  1,
-                                  dibs.dsBm.bmBitsPixel,
-                                  NULL);
-                    psurfBmp = SURFACE_LockSurface(Bmp);
-                    ASSERT(psurfBmp);
-                    /* Assign palette */
-                    psurfBmp->ppal = psurf->ppal;
-                    GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
-                    /* Set flags */
-                    psurfBmp->flags = API_BITMAP;
-                    psurfBmp->hdc = NULL; // Fixme
-                    SURFACE_UnlockSurface(psurfBmp);
+                    EngSetLastError(ERROR_INVALID_HANDLE);
+                    return 0;
                 }
-                else
+
+                PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+
+                for (Index = 0;
+                        Index < 256 && Index < PalGDI->NumColors;
+                        Index++)
                 {
-                    /* A DIB section is selected in the DC */
-                                       BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
-                    PVOID Bits;
-                                       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)
-                    {
-                        /* Copy the color table */
-                        UINT Index;
-                        PPALETTE PalGDI;
-
-                        if (!psurf->ppal)
-                        {
-                            EngSetLastError(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);
-
-                        Bmp = DIB_CreateDIBSection(Dc,
-                                                   bi,
-                                                   DIB_RGB_COLORS,
-                                                   &Bits,
-                                                   NULL,
-                                                   0,
-                                                   0);
-                        return Bmp;
-                    }
+                    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,
+                                       DIB_RGB_COLORS,
+                                       &Bits,
+                                       NULL,
+                                       0,
+                                       0);
+            return Bmp;
         }
     }
     return Bmp;
@@ -431,7 +440,8 @@ NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
 
     XPos += dc->ptlDCOrig.x;
     YPos += dc->ptlDCOrig.y;
-    if (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos))
+    if ((dc->rosdc.CombinedClip == NULL) ||
+        (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos)))
     {
         bInRect = TRUE;
         psurf = dc->dclevel.pSurface;
@@ -834,7 +844,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
         return 0;
     }
 
-    Bitmap = SURFACE_LockSurface(hBitmap);
+    Bitmap = SURFACE_ShareLockSurface(hBitmap);
     if (Bitmap == NULL)
     {
         return 0;
@@ -859,11 +869,14 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
 
     if (res)
     {
-        resBitmap = SURFACE_LockSurface(res);
+        resBitmap = SURFACE_ShareLockSurface(res);
         if (resBitmap)
         {
             IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
-                       SURFACE_UnlockSurface(resBitmap);
+            GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject);
+            GDIOBJ_ShareUnlockObjByPtr(&resBitmap->ppal->BaseObject);
+            resBitmap->ppal = Bitmap->ppal;
+            SURFACE_ShareUnlockSurface(resBitmap);
         }
         else
         {
@@ -872,7 +885,7 @@ BITMAP_CopyBitmap(HBITMAP hBitmap)
         }
     }
 
-    SURFACE_UnlockSurface(Bitmap);
+    SURFACE_ShareUnlockSurface(Bitmap);
 
     return  res;
 }
@@ -912,36 +925,47 @@ 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;
-                       if(psurf->ppal->flFlags & 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;
-                               }
-                       }
+
+            switch (psurf->SurfObj.iBitmapFormat)
+            {
+                case BMF_1BPP:
+                case BMF_4BPP:
+                case BMF_8BPP:
+                   pds->dsBmih.biCompression = BI_RGB;
+                   break;
+
+                case BMF_16BPP:
+                    if (psurf->ppal->flFlags & PAL_RGB16_555)
+                        pds->dsBmih.biCompression = BI_RGB;
+                    else
+                        pds->dsBmih.biCompression = BI_BITFIELDS;
+                    break;
+
+                case BMF_24BPP:
+                case BMF_32BPP:
+                    /* 24/32bpp BI_RGB is actually BGR format */
+                    if (psurf->ppal->flFlags & PAL_BGR)
+                        pds->dsBmih.biCompression = BI_RGB;
+                    else
+                        pds->dsBmih.biCompression = BI_BITFIELDS;
+                    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;
+                default:
+                    ASSERT(FALSE); /* this shouldn't happen */
+            }
+
             pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
             pds->dsBmih.biXPelsPerMeter = 0;
             pds->dsBmih.biYPelsPerMeter = 0;