Implement TransparentBlt

Warren_Baird at cimmetry.com Warren_Baird at cimmetry.com
Wed Feb 5 17:22:37 CST 2003



ChangeLog:

     Implementation of TransparentBlt.

Description:

     It performs a bit-block transfer of the color data corresponding
     to a rectangle of pixels from the specified source device context
     into a destination device context.

Warren Baird : Warren_Baird at cimmetry.com
Xavier Servettaz


diff -ur clean/wine/dlls/msimg32/msimg32_main.c wine/dlls/msimg32/msimg32_main.c
--- clean/wine/dlls/msimg32/msimg32_main.c    16 Dec 2002 19:39:01 -0000
1.1.1.2
+++ wine/dlls/msimg32/msimg32_main.c     29 Jan 2003 16:41:58 -0000
@@ -20,6 +20,9 @@
 #include "wingdi.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "winuser.h"
+#include <stdlib.h>
+

 WINE_DEFAULT_DEBUG_CHANNEL(msimg32);

@@ -56,9 +59,191 @@
                             HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int
heightSrc,
                             UINT crTransparent )
 {
-    FIXME("stub: TransparentBlt from %p to %p\n", hdcSrc, hdcDest );
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    BOOL      result = FALSE;
+    RECT      dstDevRect, srcDevRect;
+    int            dstDCID   = 0, srcDCID     = 0;
+    HDC            hdcBack   = 0, hdcObject   = 0, hdcMem   = 0, hdcSave   = 0;
+    HBITMAP        bmAndBack = 0, bmAndObject = 0, bmAndMem = 0, bmSave    = 0;
+    HBITMAP        bmBackOld = 0, bmObjectOld = 0, bmMemOld = 0, bmSaveOld = 0;
+    COLORREF  color;
+    LONG dstWidth  = 0;
+    LONG dstHeight = 0;
+    LONG srcWidth  = 0;
+    LONG srcHeight = 0;
+    LONG maxWidth  = 0;
+    LONG maxHeight = 0;
+    /* Create some DCs to hold temporary data. */
+    hdcBack   = CreateCompatibleDC(hdcDest);
+    hdcObject = CreateCompatibleDC(hdcDest);
+    hdcMem    = CreateCompatibleDC(hdcDest);
+    hdcSave   = CreateCompatibleDC(hdcDest);
+
+    if (hdcBack == 0 || hdcObject == 0 || hdcMem == 0 || hdcSave == 0) {
+         goto exit;
+    }
+
+    /* Convert destination logical coordinates to device coordinates. */
+    SetRect(&dstDevRect, xDest, yDest, xDest + widthDest, yDest + heightDst);
+    LPtoDP(hdcDest, (LPPOINT) &dstDevRect, 2);
+    dstWidth  = dstDevRect.right - dstDevRect.left;
+    dstHeight = dstDevRect.bottom - dstDevRect.top;
+
+    /* Convert source logical coordinates to device coordinates. */
+    SetRect(&srcDevRect, xSrc, ySrc, xSrc + widthSrc, ySrc + heightSrc);
+    LPtoDP(hdcSrc, (LPPOINT) &srcDevRect, 2);
+    srcWidth  = srcDevRect.right - srcDevRect.left;
+    srcHeight = srcDevRect.bottom - srcDevRect.top;
+
+    /*********************************************
+     * Perform transparency operation on the
+     * largest DC to avoid rouding issues resulting
+     * in images too dark
+     ********************************************/
+
+    /* calculate max extends */
+    maxWidth = max(abs(srcWidth), abs(dstWidth));
+    maxHeight = max(abs(srcHeight), abs(dstHeight));
+
+    /* Save and reset destination and source DC settings. */
+    dstDCID = SaveDC(hdcDest);
+    SetBkMode(hdcDest, OPAQUE);
+    SetBkColor(hdcDest, RGB(255, 255, 255));
+    SetMapMode(hdcDest, MM_TEXT);
+    SetViewportOrgEx(hdcDest, 0, 0, NULL);
+    SetWindowOrgEx(hdcDest, 0, 0, NULL);
+
+    srcDCID = SaveDC(hdcSrc);
+    SetBkMode(hdcSrc, OPAQUE);
+    SetBkColor(hdcSrc, RGB(255, 255, 255));
+    SetMapMode(hdcSrc, MM_TEXT);
+    SetViewportOrgEx(hdcSrc, 0, 0, NULL);
+    SetWindowOrgEx(hdcSrc, 0, 0, NULL);
+
+    /* Create a bitmap for each DC. */
+    bmAndBack   = CreateBitmap(maxWidth , maxHeight, 1, 1, 0);
+    bmAndObject = CreateBitmap(maxWidth , maxHeight, 1, 1, 0);
+    bmAndMem    = CreateCompatibleBitmap(hdcDest, maxWidth, maxHeight);
+    bmSave      = CreateCompatibleBitmap(hdcDest, srcWidth, srcHeight);
+
+    if (bmAndBack == 0 || bmAndObject == 0 || bmAndMem == 0 || bmSave == 0) {
+         goto exit;
+    }
+
+    /* Each DC must select a bitmap object to store pixel data. */
+    bmBackOld   = (HBITMAP)SelectObject(hdcBack,   bmAndBack);
+    bmObjectOld = (HBITMAP)SelectObject(hdcObject, bmAndObject);
+    bmMemOld  = (HBITMAP)SelectObject(hdcMem,    bmAndMem);
+    bmSaveOld   = (HBITMAP)SelectObject(hdcSave,   bmSave);
+
+    if (bmBackOld == 0 || bmObjectOld == 0 || bmMemOld == 0 || bmSaveOld == 0)
{
+         goto exit;
+    }
+
+    /* Save the given bitmap because it will be overwritten. */
+    if (!BitBlt(hdcSave, 0, 0, srcWidth, srcHeight, hdcSrc, srcDevRect.left,
srcDevRect.top, SRCCOPY)) {
+         goto exit;
+    }
+
+    /* Set the background color of the source DC
+       to the color contained in the parts of the bitmap that should be
transparent. */
+    color = SetBkColor(hdcSrc, crTransparent);
+
+    /* Create the object mask for the bitmap
+       by performing a BitBlt() from the source bitmap to a monochrome bitmap.
*/
+    if (!StretchBlt(hdcObject, 0, 0, maxWidth, maxHeight, hdcSrc,
srcDevRect.left, srcDevRect.top, srcWidth , srcHeight , SRCCOPY)) {
+         goto exit;
+    }
+
+    /* Set the background color of the source DC back to the original color. */
+    SetBkColor(hdcSrc, color);
+
+    /* Create the inverse of the object mask. */
+    if (!BitBlt(hdcBack, 0, 0, maxWidth, maxHeight, hdcObject, 0, 0,
NOTSRCCOPY)) {
+         goto exit;
+    }
+
+    /* Copy the background of the main DC to the destination. */
+    if (!StretchBlt(hdcMem, 0, 0, maxWidth , maxHeight, hdcDest,
dstDevRect.left, dstDevRect.top, dstWidth , dstHeight , SRCCOPY)) {{
+         goto exit;
+    }
+
+    /* Mask out the places where the bitmap will be placed. */
+    if (!BitBlt(hdcMem, 0, 0, maxWidth, maxHeight, hdcObject, 0, 0, SRCAND)) {
+         goto exit;
+    }
+
+    /* Mask out the transparent colored pixels on the bitmap. */
+    if (!StretchBlt(hdcSrc, srcDevRect.left, srcDevRect.top, srcWidth,
srcHeight , hdcBack, 0, 0, maxWidth, maxHeight, SRCAND)) {
+         goto exit;
+    }
+
+    /* XOR the bitmap with the background on the destination DC. */
+    if (!StretchBlt(hdcMem, 0, 0, maxWidth , maxHeight, hdcSrc,
srcDevRect.left, srcDevRect.top, srcWidth , srcHeight , SRCPAINT)) {{
+         goto exit;
+    }
+
+    /* Copy the destination to the screen. */
+    if (!StretchBlt(hdcDest, dstDevRect.left, dstDevRect.top, dstWidth,
dstHeight , hdcMem, 0, 0, maxWidth , maxHeight, SRCCOPY)) {{{
+         goto exit;
+    }
+
+    /* Place the original bitmap back into the given bitmap. */
+    if (!BitBlt(hdcSrc, srcDevRect.left, srcDevRect.top, srcWidth, srcHeight,
hdcSave, 0, 0, SRCCOPY)) {
+         goto exit;
+    }
+
+    result = TRUE;
+
+  exit:
+    /* Restore destination and source DC settings. */
+    if (dstDCID)
+         RestoreDC(hdcDest, dstDCID);
+    if (srcDCID)
+         RestoreDC(hdcSrc, srcDCID);
+
+    /* Select old bitmaps. */
+    if (bmSaveOld != 0) {
+         SelectObject(hdcSave, bmSaveOld);
+    }
+    if (bmMemOld != 0) {
+         SelectObject(hdcMem, bmMemOld);
+    }
+    if (bmObjectOld != 0) {
+         SelectObject(hdcObject, bmObjectOld);
+    }
+    if (bmBackOld != 0) {
+         SelectObject(hdcBack, bmBackOld);
+    }
+
+    /* Delete bitmaps. */
+    if (bmSave != 0) {
+         DeleteObject(bmSave);
+    }
+    if (bmAndMem != 0) {
+         DeleteObject(bmAndMem);
+    }
+    if (bmAndObject != 0) {
+         DeleteObject(bmAndObject);
+    }
+    if (bmAndBack != 0) {
+         DeleteObject(bmAndBack);
+    }
+
+    /* Delete DCs. */
+    if (hdcSave != 0) {
+         DeleteDC(hdcSave);
+    }
+    if (hdcMem != 0) {
+         DeleteDC(hdcMem);
+    }
+    if (hdcObject != 0) {
+         DeleteDC(hdcObject);
+    }
+    if (hdcBack != 0) {
+         DeleteDC(hdcBack);
+    }
+
+    return result;
 }







More information about the wine-patches mailing list