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