Fixed some bitblt issues.
authorArmin Novak <armin.novak@thincast.com>
Tue, 2 Aug 2016 08:03:18 +0000 (10:03 +0200)
committerArmin Novak <armin.novak@thincast.com>
Thu, 6 Oct 2016 11:43:05 +0000 (13:43 +0200)
include/freerdp/codec/color.h
libfreerdp/gdi/bitmap.c

index 43ea247..f47349f 100644 (file)
@@ -677,6 +677,8 @@ static INLINE UINT32 ReadColor(const BYTE* src, UINT32 format)
                        break;
 
                case 8:
+               case 4:
+               case 1:
                        color = *src;
                        break;
 
index 7105528..63fd449 100644 (file)
@@ -468,11 +468,674 @@ static BOOL BitBlt_DSPDxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        return TRUE;
 }
 
+static BOOL BitBlt_DPno(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = ~colorB | color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               dstColor = ~colorB | colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DPo(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                       UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                       UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_Pn(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                      UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                      UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor = ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 color = ReadColor(patp, hdcDest->format);
+                                               dstColor = ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DPon(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | ~colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DPan(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB & ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB & ~colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_SDno(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       for (y = 0; y < nHeight; y++)
+       {
+               for (x = 0; x < nWidth; x++)
+               {
+                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                              hdcSrc, nXSrc + x, nYSrc + y);
+                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                        hdcDest, nXDest + x, nYDest + y);
+
+                       if (srcp && dstp)
+                       {
+                               UINT32 dstColor;
+                               UINT32 colorA = ReadColor(srcp, hdcDest->format);
+                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                     hdcDest->format, palette);
+                               dstColor = ~colorA | colorB;
+                               WriteColor(dstp, hdcDest->format, dstColor);
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DPna(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = ~colorB & color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = ~colorB & colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_PDno(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB | ~colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_PDna(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB & ~color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (patp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               dstColor = colorB & ~colorA;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
 static BOOL BitBlt_DSPDxox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                            UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
                            UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
 {
-       UINT32 x, y, color;
+       UINT32 x, y, color;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->textColor;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               dstColor = (colorA ^ colorB) | (color ^ colorB);
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp && patp)
+                                       {
+                                               UINT32 color;
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               UINT32 colorC = ReadColor(patp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = (colorA ^ colorB) | (colorB ^ colorC);
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_PSDPxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                           UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                           UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y, colorC;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       colorC = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 color;
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = (colorA ^ colorC) & (colorB ^ colorC);
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 color;
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                                               UINT32 colorC = ReadColor(patp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = (colorA ^ colorC) & (colorB ^ colorC);
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_PSDnox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                          UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                          UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y, colorA;
 
        if (!hdcDest || !hdcSrc)
                return FALSE;
@@ -480,7 +1143,7 @@ static BOOL BitBlt_DSPDxox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        switch (gdi_GetBrushStyle(hdcDest))
        {
                case GDI_BS_SOLID:
-                       color = hdcDest->textColor;
+                       colorA = hdcDest->brush->color;
 
                        for (y = 0; y < nHeight; y++)
                        {
@@ -493,13 +1156,13 @@ static BOOL BitBlt_DSPDxox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
 
                                        if (srcp && dstp)
                                        {
-                                               UINT32 dstColor;
-                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
-                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
-                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                               UINT32 color;
+                                               UINT32 colorB = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorC = ReadColor(dstp, hdcDest->format);
+                                               colorB = ConvertColor(colorB, hdcSrc->format,
                                                                      hdcDest->format, palette);
-                                               dstColor = (colorA ^ colorB) | (color ^ colorB);
-                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                               color = (~colorA | colorB) ^ colorC;
+                                               WriteColor(dstp, hdcDest->format, color);
                                        }
                                }
                        }
@@ -518,15 +1181,15 @@ static BOOL BitBlt_DSPDxox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                                        BYTE* dstp = gdi_get_bitmap_pointer(
                                                         hdcDest, nXDest + x, nYDest + y);
 
-                                       if (srcp && dstp)
+                                       if (srcp && dstp && patp)
                                        {
                                                UINT32 color;
-                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
-                                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
-                                               UINT32 colorC = ReadColor(patp, hdcDest->format);
-                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                               UINT32 colorB = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorC = ReadColor(dstp, hdcDest->format);
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               colorB = ConvertColor(colorB, hdcSrc->format,
                                                                      hdcDest->format, palette);
-                                               color = (colorA ^ colorB) | (colorB ^ colorC);
+                                               color = (~colorA | colorB) ^ colorC;
                                                WriteColor(dstp, hdcDest->format, color);
                                        }
                                }
@@ -538,11 +1201,11 @@ static BOOL BitBlt_DSPDxox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        return TRUE;
 }
 
-static BOOL BitBlt_PSDPxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
-                           UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
-                           UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+static BOOL BitBlt_PDSona(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                          UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                          UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
 {
-       UINT32 x, y, colorC;
+       UINT32 x, y, colorA;
 
        if (!hdcDest || !hdcSrc)
                return FALSE;
@@ -550,7 +1213,7 @@ static BOOL BitBlt_PSDPxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        switch (gdi_GetBrushStyle(hdcDest))
        {
                case GDI_BS_SOLID:
-                       colorC = hdcDest->brush->color;
+                       colorA = hdcDest->brush->color;
 
                        for (y = 0; y < nHeight; y++)
                        {
@@ -564,11 +1227,11 @@ static BOOL BitBlt_PSDPxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                                        if (srcp && dstp)
                                        {
                                                UINT32 color;
-                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorC = ReadColor(srcp, hdcSrc->format);
                                                UINT32 colorB = ReadColor(dstp, hdcDest->format);
-                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                               colorC = ConvertColor(colorC, hdcSrc->format,
                                                                      hdcDest->format, palette);
-                                               color = (colorA ^ colorC) & (colorB ^ colorC);
+                                               color = (colorA | ~colorB) & colorC;
                                                WriteColor(dstp, hdcDest->format, color);
                                        }
                                }
@@ -588,15 +1251,85 @@ static BOOL BitBlt_PSDPxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                                        BYTE* dstp = gdi_get_bitmap_pointer(
                                                         hdcDest, nXDest + x, nYDest + y);
 
-                                       if (srcp && dstp)
+                                       if (srcp && dstp && patp)
                                        {
                                                UINT32 color;
-                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorC = ReadColor(srcp, hdcSrc->format);
                                                UINT32 colorB = ReadColor(dstp, hdcDest->format);
-                                               UINT32 colorC = ReadColor(patp, hdcDest->format);
-                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                               UINT32 colorA = ReadColor(patp, hdcDest->format);
+                                               colorC = ConvertColor(colorC, hdcSrc->format,
                                                                      hdcDest->format, palette);
-                                               color = (colorA ^ colorC) & (colorB ^ colorC);
+                                               color = (colorA | ~colorB) & colorC;
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DPSDonox(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                            UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                            UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y, colorB;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       colorB = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 color;
+                                               UINT32 colorC = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorA = ReadColor(dstp, hdcDest->format);
+                                               colorC = ConvertColor(colorC, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = (colorA | ~colorB | colorC) ^ colorA;
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp && patp)
+                                       {
+                                               UINT32 color;
+                                               UINT32 colorC = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorA = ReadColor(dstp, hdcDest->format);
+                                               UINT32 colorB = ReadColor(patp, hdcDest->format);
+                                               colorC = ConvertColor(colorC, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = (colorA | ~colorB | colorC) ^ colorA;
                                                WriteColor(dstp, hdcDest->format, color);
                                        }
                                }
@@ -659,7 +1392,7 @@ static BOOL BitBlt_SPDSxax(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                                        BYTE* dstp = gdi_get_bitmap_pointer(
                                                         hdcDest, nXDest + x, nYDest + y);
 
-                                       if (srcp && dstp)
+                                       if (srcp && dstp && patp)
                                        {
                                                UINT32 colorD;
                                                UINT32 colorA = ReadColor(srcp, hdcSrc->format);
@@ -777,15 +1510,46 @@ static BOOL BitBlt_DSna(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        return TRUE;
 }
 
+static BOOL BitBlt_DSxn(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
 
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
 
-static BOOL BitBlt_MERGECOPY(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
-                             UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
-                             UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+       for (y = 0; y < nHeight; y++)
+       {
+               for (x = 0; x < nWidth; x++)
+               {
+                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                              hdcSrc, nXSrc + x, nYSrc + y);
+                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                        hdcDest, nXDest + x, nYDest + y);
+
+                       if (srcp && dstp)
+                       {
+                               UINT32 color;
+                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
+                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                     hdcDest->format, palette);
+                               color = ~colorA ^ colorB;
+                               WriteColor(dstp, hdcDest->format, color);
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_DSan(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                        UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                        UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
 {
        UINT32 x, y;
 
-       /* PSa */
        if (!hdcDest || !hdcSrc)
                return FALSE;
 
@@ -795,19 +1559,46 @@ static BOOL BitBlt_MERGECOPY(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                {
                        const BYTE* srcp = gdi_get_bitmap_pointer(
                                               hdcSrc, nXSrc + x, nYSrc + y);
-                       const BYTE* patp = gdi_get_brush_pointer(
-                                              hdcDest, nXDest + x, nYDest + y);
                        BYTE* dstp = gdi_get_bitmap_pointer(
                                         hdcDest, nXDest + x, nYDest + y);
 
-                       if (srcp && patp && dstp)
+                       if (srcp && dstp)
                        {
                                UINT32 color;
                                UINT32 colorA = ReadColor(srcp, hdcSrc->format);
-                               UINT32 colorB = ReadColor(patp, hdcDest->format);
+                               UINT32 colorB = ReadColor(dstp, hdcDest->format);
                                colorA = ConvertColor(colorA, hdcSrc->format,
                                                      hdcDest->format, palette);
-                               color = colorA & colorB;
+                               color = ~colorA & colorB;
+                               WriteColor(dstp, hdcDest->format, color);
+                       }
+               }
+       }
+
+       return TRUE;
+}
+
+static BOOL BitBlt_D(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                     UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                     UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       for (y = 0; y < nHeight; y++)
+       {
+               for (x = 0; x < nWidth; x++)
+               {
+                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                              hdcDest, nXSrc + x, nYSrc + y);
+                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                        hdcDest, nXDest + x, nYDest + y);
+
+                       if (srcp && dstp)
+                       {
+                               UINT32 color = ReadColor(srcp, hdcSrc->format);
                                WriteColor(dstp, hdcDest->format, color);
                        }
                }
@@ -816,6 +1607,75 @@ static BOOL BitBlt_MERGECOPY(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
        return TRUE;
 }
 
+static BOOL BitBlt_MERGECOPY(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
+                             UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
+                             UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
+{
+       UINT32 x, y;
+       UINT32 color;
+
+       /* PSa */
+       if (!hdcDest || !hdcSrc)
+               return FALSE;
+
+       switch (gdi_GetBrushStyle(hdcDest))
+       {
+               case GDI_BS_SOLID:
+                       color = hdcDest->brush->color;
+
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && dstp)
+                                       {
+                                               UINT32 dstColor;
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               dstColor = color = colorA & color;
+                                               WriteColor(dstp, hdcDest->format, dstColor);
+                                       }
+                               }
+                       }
+
+                       break;
+
+               default:
+                       for (y = 0; y < nHeight; y++)
+                       {
+                               for (x = 0; x < nWidth; x++)
+                               {
+                                       const BYTE* srcp = gdi_get_bitmap_pointer(
+                                                              hdcSrc, nXSrc + x, nYSrc + y);
+                                       const BYTE* patp = gdi_get_brush_pointer(
+                                                              hdcDest, nXDest + x, nYDest + y);
+                                       BYTE* dstp = gdi_get_bitmap_pointer(
+                                                        hdcDest, nXDest + x, nYDest + y);
+
+                                       if (srcp && patp && dstp)
+                                       {
+                                               UINT32 colorA = ReadColor(srcp, hdcSrc->format);
+                                               UINT32 colorB = ReadColor(patp, hdcDest->format);
+                                               colorA = ConvertColor(colorA, hdcSrc->format,
+                                                                     hdcDest->format, palette);
+                                               color = colorA & colorB;
+                                               WriteColor(dstp, hdcDest->format, color);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return TRUE;
+}
+
 static BOOL BitBlt_MERGEPAINT(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                               UINT32 nWidth, UINT32 nHeight, HGDI_DC hdcSrc,
                               UINT32 nXSrc, UINT32 nYSrc, const gdiPalette* palette)
@@ -951,8 +1811,68 @@ BOOL gdi_BitBlt(HGDI_DC hdcDest, UINT32 nXDest, UINT32 nYDest,
                        return BitBlt_MERGEPAINT(hdcDest, nXDest, nYDest, nWidth, nHeight,
                                                 hdcSrc, nXSrc, nYSrc, palette);
 
+               case GDI_DPno:
+                       return BitBlt_DPno(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DPna:
+                       return BitBlt_DPna(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_SDno:
+                       return BitBlt_SDno(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_PDno:
+                       return BitBlt_PDno(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_PDna:
+                       return BitBlt_PDna(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DPo:
+                       return BitBlt_DPo(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                         hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_Pn:
+                       return BitBlt_Pn(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                        hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DPon:
+                       return BitBlt_DPon(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DPan:
+                       return BitBlt_DPan(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DSxn:
+                       return BitBlt_DSxn(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DSan:
+                       return BitBlt_DSan(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                          hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_PSDnox:
+                       return BitBlt_PSDnox(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                            hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_PDSona:
+                       return BitBlt_PDSona(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                            hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_DPSDonox:
+                       return BitBlt_DPSDonox(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                              hdcSrc, nXSrc, nYSrc, palette);
+
+               case GDI_D:
+                       return BitBlt_D(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                       hdcSrc, nXSrc, nYSrc, palette);
+
                default:
-                       WLog_ERR(TAG,  "BitBlt: unknown rop: 0x%08X", rop);
+                       WLog_ERR(TAG,  "BitBlt: unknown rop: %s", gdi_rop_to_string(rop));
                        return FALSE;
        }
 }