[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / dibobj.c
index e391290..2dc749e 100644 (file)
@@ -32,27 +32,6 @@ static const RGBQUAD EGAColorsQuads[16] =
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
-static const RGBTRIPLE EGAColorsTriples[16] =
-{
-    /* rgbBlue, rgbGreen, rgbRed */
-    { 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x80 },
-    { 0x00, 0x80, 0x00 },
-    { 0x00, 0x80, 0x80 },
-    { 0x80, 0x00, 0x00 },
-    { 0x80, 0x00, 0x80 },
-    { 0x80, 0x80, 0x00 },
-    { 0x80, 0x80, 0x80 },
-    { 0xc0, 0xc0, 0xc0 },
-    { 0x00, 0x00, 0xff },
-    { 0x00, 0xff, 0x00 },
-    { 0x00, 0xff, 0xff },
-    { 0xff, 0x00, 0x00 },
-    { 0xff, 0x00, 0xff },
-    { 0xff, 0xff, 0x00 },
-    { 0xff, 0xff, 0xff }
-};
-
 static const RGBQUAD DefLogPaletteQuads[20] =   /* Copy of Default Logical Palette */
 {
     /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
@@ -78,31 +57,6 @@ static const RGBQUAD DefLogPaletteQuads[20] =   /* Copy of Default Logical Palet
     { 0xff, 0xff, 0xff, 0x00 }
 };
 
-static const RGBQUAD DefLogPaletteTriples[20] =   /* Copy of Default Logical Palette */
-{
-    /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
-    { 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0x80 },
-    { 0x00, 0x80, 0x00 },
-    { 0x00, 0x80, 0x80 },
-    { 0x80, 0x00, 0x00 },
-    { 0x80, 0x00, 0x80 },
-    { 0x80, 0x80, 0x00 },
-    { 0xc0, 0xc0, 0xc0 },
-    { 0xc0, 0xdc, 0xc0 },
-    { 0xf0, 0xca, 0xa6 },
-    { 0xf0, 0xfb, 0xff },
-    { 0xa4, 0xa0, 0xa0 },
-    { 0x80, 0x80, 0x80 },
-    { 0x00, 0x00, 0xf0 },
-    { 0x00, 0xff, 0x00 },
-    { 0x00, 0xff, 0xff },
-    { 0xff, 0x00, 0x00 },
-    { 0xff, 0x00, 0xff },
-    { 0xff, 0xff, 0x00 },
-    { 0xff, 0xff, 0xff }
-};
-
 PPALETTE
 NTAPI
 CreateDIBPalette(
@@ -375,6 +329,115 @@ cleanup:
     return result;
 }
 
+static
+HBITMAP
+IntGdiCreateMaskFromRLE(
+    DWORD Width,
+    DWORD Height,
+    ULONG Compression,
+    const BYTE* Bits,
+    DWORD BitsSize)
+{
+    HBITMAP Mask;
+    DWORD x, y;
+    SURFOBJ* SurfObj;
+    UINT i = 0;
+    BYTE Data, NumPixels, ToSkip;
+
+    ASSERT((Compression == BI_RLE8) || (Compression == BI_RLE4));
+
+    /* Create the bitmap */
+    Mask = GreCreateBitmapEx(Width, Height, 0, BMF_1BPP, 0, 0, NULL, 0);
+    if (!Mask)
+        return NULL;
+
+    SurfObj = EngLockSurface((HSURF)Mask);
+    if (!SurfObj)
+    {
+        GreDeleteObject(Mask);
+        return NULL;
+    }
+    ASSERT(SurfObj->pvBits != NULL);
+
+    x = y = 0;
+
+    while (i < BitsSize)
+    {
+        NumPixels = Bits[i];
+        Data = Bits[i + 1];
+        i += 2;
+
+        if (NumPixels != 0)
+        {
+            if ((x + NumPixels) > Width)
+                NumPixels = Width - x;
+
+            if (NumPixels == 0)
+                continue;
+
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+            continue;
+        }
+
+        if (Data < 3)
+        {
+            switch (Data)
+            {
+                case 0:
+                    /* End of line */
+                    y++;
+                    if (y == Height)
+                        goto done;
+                    x = 0;
+                    break;
+                case 1:
+                    /* End of file */
+                    goto done;
+                case 2:
+                    /* Jump */
+                    if (i >= (BitsSize - 1))
+                        goto done;
+                    x += Bits[i];
+                    if (x > Width)
+                        x = Width;
+                    y += Bits[i + 1];
+                    if (y >= Height)
+                        goto done;
+                    i += 2;
+                    break;
+            }
+            /* Done for this run */
+            continue;
+        }
+
+        /* Embedded data into the RLE */
+        NumPixels = Data;
+        if (Compression == BI_RLE8)
+            ToSkip = NumPixels;
+        else
+            ToSkip = (NumPixels / 2) + (NumPixels & 1);
+
+        if ((i + ToSkip) > BitsSize)
+            goto done;
+        ToSkip = (ToSkip + 1) & ~1;
+
+        if ((x + NumPixels) > Width)
+            NumPixels = Width - x;
+
+        if (NumPixels != 0)
+        {
+            DIB_1BPP_HLine(SurfObj, x, x + NumPixels, y, 1);
+            x += NumPixels;
+        }
+        i += ToSkip;
+    }
+
+done:
+    EngUnlockSurface(SurfObj);
+    return Mask;
+}
+
 W32KAPI
 INT
 APIENTRY
@@ -399,8 +462,8 @@ NtGdiSetDIBitsToDeviceInternal(
     INT ret = 0;
     NTSTATUS Status = STATUS_SUCCESS;
     PDC pDC;
-    HBITMAP hSourceBitmap = NULL;
-    SURFOBJ *pDestSurf, *pSourceSurf = NULL;
+    HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
+    SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
     SURFACE *pSurf;
     RECTL rcDest;
     POINTL ptSource;
@@ -492,6 +555,28 @@ NtGdiSetDIBitsToDeviceInternal(
         goto Exit;
     }
 
+    /* HACK: If this is a RLE bitmap, only the relevant pixels must be set. */
+    if ((bmi->bmiHeader.biCompression == BI_RLE8) || (bmi->bmiHeader.biCompression == BI_RLE4))
+    {
+        hMaskBitmap = IntGdiCreateMaskFromRLE(bmi->bmiHeader.biWidth,
+            ScanLines,
+            bmi->bmiHeader.biCompression,
+            Bits,
+            cjMaxBits);
+        if (!hMaskBitmap)
+        {
+            EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
+            Status = STATUS_NO_MEMORY;
+            goto Exit;
+        }
+        pMaskSurf = EngLockSurface((HSURF)hMaskBitmap);
+        if (!pMaskSurf)
+        {
+            Status = STATUS_UNSUCCESSFUL;
+            goto Exit;
+        }
+    }
+
     /* Create a palette for the DIB */
     ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
     if (!ppalDIB)
@@ -529,15 +614,15 @@ NtGdiSetDIBitsToDeviceInternal(
            ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
     Status = IntEngBitBlt(pDestSurf,
                           pSourceSurf,
-                          NULL,
+                          pMaskSurf,
                           &pDC->co.ClipObj,
                           &exlo.xlo,
                           &rcDest,
                           &ptSource,
+                          pMaskSurf ? &ptSource : NULL,
                           NULL,
                           NULL,
-                          NULL,
-                          ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
+                          pMaskSurf ? ROP4_MASK : ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY));
 
     /* Cleanup EXLATEOBJ */
     EXLATEOBJ_vCleanup(&exlo);
@@ -555,6 +640,8 @@ Exit:
 
     if (pSourceSurf) EngUnlockSurface(pSourceSurf);
     if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
+    if (pMaskSurf) EngUnlockSurface(pMaskSurf);
+    if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
     DC_UnlockDc(pDC);
 Exit2:
     ExFreePoolWithTag(pbmiSafe, 'pmTG');
@@ -1250,7 +1337,7 @@ IntCreateDIBitmap(
         DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
 
         // Check if the first color of the colormap is black
-        if ((col == RGB(0, 0, 0)))
+        if (col == RGB(0, 0, 0))
         {
             rgb++;
             col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);