From 53f2e61e37c62edd742d124833cfc4968c72123a Mon Sep 17 00:00:00 2001 From: Dave Belanger <dave.belanger@cimmetry.com> Date: Wed, 15 Oct 2003 02:33:15 +0000 Subject: [PATCH] Implemented BitBlt, StretchBlt and SetDIBitsToDevice EMF driver callbacks. Cleaned up redundant code in EMFDRV_StretchDIBits. --- dlls/gdi/enhmfdrv/bitblt.c | 216 ++++++++++++++++++++++++++++++------- dlls/gdi/enhmfdrv/init.c | 6 +- 2 files changed, 181 insertions(+), 41 deletions(-) diff --git a/dlls/gdi/enhmfdrv/bitblt.c b/dlls/gdi/enhmfdrv/bitblt.c index a0ed92d5e0a..7759c621c89 100644 --- a/dlls/gdi/enhmfdrv/bitblt.c +++ b/dlls/gdi/enhmfdrv/bitblt.c @@ -26,6 +26,7 @@ #include "wingdi.h" #include "gdi.h" #include "enhmetafiledrv.h" +#include "bitmap.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); @@ -68,6 +69,130 @@ BOOL EMFDRV_PatBlt( PHYSDEV dev, INT left, INT top, return ret; } +/* Utilitarian function used by EMFDRV_BitBlt and EMFDRV_StretchBlt */ + +static BOOL EMFDRV_BitBlockTransfer( + PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst, + PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop, + DWORD emrType) +{ + BOOL ret; + PEMRBITBLT pEMR; + UINT emrSize; + UINT bmiSize; + UINT bitsSize; + UINT size; + BITMAP BM; + WORD nBPP; + LPBITMAPINFOHEADER lpBmiH; + EMFDRV_PDEVICE* physDevSrc = (EMFDRV_PDEVICE*)devSrc; + DC* dcSrc = physDevSrc->dc; + + if (emrType == EMR_BITBLT) + emrSize = sizeof(EMRBITBLT); + else if (emrType == EMR_STRETCHBLT) + emrSize = sizeof(EMRSTRETCHBLT); + else + return FALSE; + + GetObjectA(dcSrc->hBitmap, sizeof(BITMAP), &BM); + + nBPP = BM.bmPlanes * BM.bmBitsPixel; + if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ + + bitsSize = DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * BM.bmHeight; + bmiSize = sizeof(BITMAPINFOHEADER) + + (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); + size = emrSize + bmiSize + bitsSize; + + pEMR = HeapAlloc(GetProcessHeap(), 0, size); + if (!pEMR) return FALSE; + + /* Initialize EMR */ + pEMR->emr.iType = emrType; + pEMR->emr.nSize = size; + pEMR->rclBounds.left = xDst; + pEMR->rclBounds.top = yDst; + pEMR->rclBounds.right = xDst + widthDst - 1; + pEMR->rclBounds.bottom = yDst + heightDst - 1; + pEMR->xDest = xDst; + pEMR->yDest = yDst; + pEMR->cxDest = widthDst; + pEMR->cyDest = heightDst; + pEMR->dwRop = rop; + pEMR->xSrc = xSrc; + pEMR->ySrc = ySrc; + pEMR->xformSrc.eM11 = 1.0; /** FIXME: */ + pEMR->xformSrc.eM12 = 0.0; /** Setting default */ + pEMR->xformSrc.eM21 = 0.0; /** value. */ + pEMR->xformSrc.eM22 = 1.0; /** Where should we */ + pEMR->xformSrc.eDx = 0.0; /** get that info */ + pEMR->xformSrc.eDy = 0.0; /** ???? */ + pEMR->crBkColorSrc = dcSrc->backgroundColor; + pEMR->iUsageSrc = DIB_RGB_COLORS; + pEMR->offBmiSrc = emrSize; + pEMR->cbBmiSrc = bmiSize; + pEMR->offBitsSrc = emrSize + bmiSize; + pEMR->cbBitsSrc = bitsSize; + if (emrType == EMR_STRETCHBLT) + { + PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; + pEMRStretch->cxSrc = widthSrc; + pEMRStretch->cySrc = heightSrc; + } + + /* Initialize BITMAPINFO structure */ + lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); + + lpBmiH->biSize = sizeof(BITMAPINFOHEADER); + lpBmiH->biWidth = BM.bmWidth; + lpBmiH->biHeight = BM.bmHeight; + lpBmiH->biPlanes = BM.bmPlanes; + lpBmiH->biBitCount = nBPP; + /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ + lpBmiH->biCompression = BI_RGB; + lpBmiH->biSizeImage = bitsSize; + lpBmiH->biYPelsPerMeter = /* 1 meter = 39.37 inch */ + MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100); + lpBmiH->biXPelsPerMeter = + MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100); + lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; + /* Set biClrImportant to 0, indicating that all of the + device colors are important. */ + lpBmiH->biClrImportant = 0; + + /* Initiliaze bitmap bits */ + if (GetDIBits(dcSrc->hSelf, dcSrc->hBitmap, 0, (UINT)lpBmiH->biHeight, + (BYTE*)pEMR + pEMR->offBitsSrc, + (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) + { + ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); + if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); + } + else + ret = FALSE; + + HeapFree( GetProcessHeap(), 0, pEMR); + return ret; +} + +BOOL EMFDRV_BitBlt( + PHYSDEV devDst, INT xDst, INT yDst, INT width, INT height, + PHYSDEV devSrc, INT xSrc, INT ySrc, DWORD rop) +{ + return EMFDRV_BitBlockTransfer( devDst, xDst, yDst, width, height, + devSrc, xSrc, ySrc, width, height, + rop, EMR_BITBLT ); +} + +BOOL EMFDRV_StretchBlt( + PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst, + PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop ) +{ + return EMFDRV_BitBlockTransfer( devDst, xDst, yDst, widthDst, heightDst, + devSrc, xSrc, ySrc, widthSrc, heightSrc, + rop, EMR_STRETCHBLT ); +} INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, INT xSrc, INT ySrc, @@ -78,48 +203,17 @@ INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, EMRSTRETCHDIBITS *emr; BOOL ret; UINT bmi_size=0, bits_size, emr_size; - UINT width_bytes; - - /* calculate the size of the bits we need to store */ - switch(info->bmiHeader.biBitCount) - { - case 1: - width_bytes = (info->bmiHeader.biWidth+7)/8; - break; - case 4: - width_bytes = (info->bmiHeader.biWidth+1)/2; - break; - case 8: - width_bytes = info->bmiHeader.biWidth; - break; - case 16: - width_bytes = info->bmiHeader.biWidth*2; - break; - case 24: - width_bytes = info->bmiHeader.biWidth*3; - break; - case 32: - width_bytes = info->bmiHeader.biWidth*4; - break; - default: - FIXME("bi.biCount has and unknown value (%d)\n", info->bmiHeader.biBitCount); - return FALSE; - } - width_bytes = ((width_bytes+3)/4) << 2; - bits_size = width_bytes * info->bmiHeader.biHeight; + + bits_size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth, + info->bmiHeader.biHeight, + info->bmiHeader.biBitCount); /* calculate the size of the colour table */ - bmi_size = sizeof (BITMAPINFO); - if ( info->bmiHeader.biBitCount <= 8 ) - { - UINT num_colors = info->bmiHeader.biClrUsed; - if ( num_colors == 0 ) - num_colors = (1<<info->bmiHeader.biBitCount); - bmi_size += num_colors*sizeof(RGBQUAD); - } + bmi_size = DIB_BitmapInfoSize(info, wUsage); emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + bits_size; emr = HeapAlloc(GetProcessHeap(), 0, emr_size ); + if (!emr) return 0; /* write a bitmap info header (with colours) to the record */ memcpy( &emr[1], info, bmi_size); @@ -139,7 +233,7 @@ INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, emr->xSrc = xSrc; /* FIXME: only save the piece of the bitmap needed */ emr->ySrc = ySrc; - emr->iUsageSrc = DIB_RGB_COLORS; + emr->iUsageSrc = wUsage; emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); emr->cbBmiSrc = bmi_size; emr->offBitsSrc = emr->offBmiSrc + bmi_size; @@ -162,3 +256,49 @@ INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, return ret; } + +INT EMFDRV_SetDIBitsToDevice( + PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height, + INT xSrc, INT ySrc, UINT startscan, UINT lines, + LPCVOID bits, const BITMAPINFO *info, UINT wUsage ) +{ + EMRSETDIBITSTODEVICE* pEMR; + DWORD size, bmiSize, bitsSize; + + bmiSize = DIB_BitmapInfoSize(info, wUsage); + bitsSize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth, + info->bmiHeader.biHeight, + info->bmiHeader.biBitCount ); + size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + bitsSize; + + pEMR = HeapAlloc(GetProcessHeap(), 0, size); + if (!pEMR) return 0; + + pEMR->emr.iType = EMR_SETDIBITSTODEVICE; + pEMR->emr.nSize = size; + pEMR->rclBounds.left = xDst; + pEMR->rclBounds.top = yDst; + pEMR->rclBounds.right = xDst + width - 1; + pEMR->rclBounds.bottom = yDst + height - 1; + pEMR->xDest = xDst; + pEMR->yDest = yDst; + pEMR->xSrc = xSrc; + pEMR->ySrc = ySrc; + pEMR->cxSrc = width; + pEMR->cySrc = height; + pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); + pEMR->cbBmiSrc = bmiSize; + pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; + pEMR->cbBitsSrc = bitsSize; + pEMR->iUsageSrc = wUsage; + pEMR->iStartScan = startscan; + pEMR->cScans = lines; + memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); + memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, bitsSize); + + if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) + EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); + + HeapFree( GetProcessHeap(), 0, pEMR); + return lines; +} diff --git a/dlls/gdi/enhmfdrv/init.c b/dlls/gdi/enhmfdrv/init.c index d9ad2320c1f..715552a83bc 100644 --- a/dlls/gdi/enhmfdrv/init.c +++ b/dlls/gdi/enhmfdrv/init.c @@ -38,7 +38,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = EMFDRV_Arc, /* pArc */ NULL, /* pArcTo */ EMFDRV_BeginPath, /* pBeginPath */ - NULL, /* pBitBlt */ + EMFDRV_BitBlt, /* pBitBlt */ NULL, /* pChoosePixelFormat */ EMFDRV_Chord, /* pChord */ EMFDRV_CloseFigure, /* pCloseFigure */ @@ -119,7 +119,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = NULL, /* pSetDCOrg */ NULL, /* pSetDIBColorTable */ NULL, /* pSetDIBits */ - NULL, /* pSetDIBitsToDevice */ + EMFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */ NULL, /* pSetDeviceClipping */ NULL, /* pSetDeviceGammaRamp */ EMFDRV_SetMapMode, /* pSetMapMode */ @@ -141,7 +141,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = EMFDRV_SetWorldTransform, /* pSetWorldTransform */ NULL, /* pStartDoc */ NULL, /* pStartPage */ - NULL, /* pStretchBlt */ + EMFDRV_StretchBlt, /* pStretchBlt */ EMFDRV_StretchDIBits, /* pStretchDIBits */ EMFDRV_StrokeAndFillPath, /* pStrokeAndFillPath */ EMFDRV_StrokePath, /* pStrokePath */ -- GitLab