1 /* 2 * Enhanced MetaFile driver BitBlt functions 3 * 4 * Copyright 2002 Huw D M Davies for CodeWeavers 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <string.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wingdi.h" 27 #include "enhmetafiledrv.h" 28 #include "wine/debug.h" 29 30 BOOL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) 31 { 32 EMRBITBLT emr; 33 BOOL ret; 34 35 emr.emr.iType = EMR_BITBLT; 36 emr.emr.nSize = sizeof(emr); 37 emr.rclBounds.left = dst->log_x; 38 emr.rclBounds.top = dst->log_y; 39 emr.rclBounds.right = dst->log_x + dst->log_width - 1; 40 emr.rclBounds.bottom = dst->log_y + dst->log_height - 1; 41 emr.xDest = dst->log_x; 42 emr.yDest = dst->log_y; 43 emr.cxDest = dst->log_width; 44 emr.cyDest = dst->log_height; 45 emr.dwRop = rop; 46 emr.xSrc = 0; 47 emr.ySrc = 0; 48 emr.xformSrc.eM11 = 1.0; 49 emr.xformSrc.eM12 = 0.0; 50 emr.xformSrc.eM21 = 0.0; 51 emr.xformSrc.eM22 = 1.0; 52 emr.xformSrc.eDx = 0.0; 53 emr.xformSrc.eDy = 0.0; 54 emr.crBkColorSrc = 0; 55 emr.iUsageSrc = 0; 56 emr.offBmiSrc = 0; 57 emr.cbBmiSrc = 0; 58 emr.offBitsSrc = 0; 59 emr.cbBitsSrc = 0; 60 61 ret = EMFDRV_WriteRecord( dev, &emr.emr ); 62 if(ret) 63 EMFDRV_UpdateBBox( dev, &emr.rclBounds ); 64 return ret; 65 } 66 67 BOOL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, 68 PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) 69 { 70 BOOL ret; 71 PEMRBITBLT pEMR; 72 UINT emrSize; 73 UINT bmiSize; 74 UINT bitsSize; 75 UINT size; 76 BITMAP BM; 77 WORD nBPP = 0; 78 LPBITMAPINFOHEADER lpBmiH; 79 HBITMAP hBitmap = NULL; 80 DWORD emrType; 81 82 if (devSrc->funcs == devDst->funcs) return FALSE; /* can't use a metafile DC as source */ 83 84 if (src->log_width == dst->log_width && src->log_height == dst->log_height) 85 { 86 emrType = EMR_BITBLT; 87 emrSize = sizeof(EMRBITBLT); 88 } 89 else 90 { 91 emrType = EMR_STRETCHBLT; 92 emrSize = sizeof(EMRSTRETCHBLT); 93 } 94 95 hBitmap = GetCurrentObject(devSrc->hdc, OBJ_BITMAP); 96 97 if(sizeof(BITMAP) != GetObjectW(hBitmap, sizeof(BITMAP), &BM)) 98 return FALSE; 99 100 nBPP = BM.bmPlanes * BM.bmBitsPixel; 101 if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ 102 bitsSize = get_dib_stride( BM.bmWidth, nBPP ) * BM.bmHeight; 103 bmiSize = sizeof(BITMAPINFOHEADER) + 104 (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); 105 106 size = emrSize + bmiSize + bitsSize; 107 108 pEMR = HeapAlloc(GetProcessHeap(), 0, size); 109 if (!pEMR) return FALSE; 110 111 /* Initialize EMR */ 112 pEMR->emr.iType = emrType; 113 pEMR->emr.nSize = size; 114 pEMR->rclBounds.left = dst->log_x; 115 pEMR->rclBounds.top = dst->log_y; 116 pEMR->rclBounds.right = dst->log_x + dst->log_width - 1; 117 pEMR->rclBounds.bottom = dst->log_y + dst->log_height - 1; 118 pEMR->xDest = dst->log_x; 119 pEMR->yDest = dst->log_y; 120 pEMR->cxDest = dst->log_width; 121 pEMR->cyDest = dst->log_height; 122 pEMR->dwRop = rop; 123 pEMR->xSrc = src->log_x; 124 pEMR->ySrc = src->log_y; 125 #ifdef __REACTOS__ 126 NtGdiGetTransform(devSrc->hdc, GdiWorldSpaceToDeviceSpace, &pEMR->xformSrc); 127 #else 128 GetTransform(devSrc->hdc, 0x204, &pEMR->xformSrc); 129 #endif 130 pEMR->crBkColorSrc = GetBkColor(devSrc->hdc); 131 pEMR->iUsageSrc = DIB_RGB_COLORS; 132 pEMR->offBmiSrc = emrSize; 133 pEMR->offBitsSrc = emrSize + bmiSize; 134 pEMR->cbBmiSrc = bmiSize; 135 pEMR->cbBitsSrc = bitsSize; 136 if (emrType == EMR_STRETCHBLT) 137 { 138 PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; 139 pEMRStretch->cxSrc = src->log_width; 140 pEMRStretch->cySrc = src->log_height; 141 } 142 143 /* Initialize BITMAPINFO structure */ 144 lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); 145 146 lpBmiH->biSize = sizeof(BITMAPINFOHEADER); 147 lpBmiH->biWidth = BM.bmWidth; 148 lpBmiH->biHeight = BM.bmHeight; 149 lpBmiH->biPlanes = BM.bmPlanes; 150 lpBmiH->biBitCount = nBPP; 151 /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ 152 lpBmiH->biCompression = BI_RGB; 153 lpBmiH->biSizeImage = bitsSize; 154 lpBmiH->biYPelsPerMeter = 0; 155 lpBmiH->biXPelsPerMeter = 0; 156 lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; 157 /* Set biClrImportant to 0, indicating that all of the 158 device colors are important. */ 159 lpBmiH->biClrImportant = 0; 160 161 /* Initialize bitmap bits */ 162 if (GetDIBits(devSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight, 163 (BYTE*)pEMR + pEMR->offBitsSrc, 164 (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) 165 { 166 ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); 167 if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); 168 } 169 else 170 ret = FALSE; 171 172 HeapFree( GetProcessHeap(), 0, pEMR); 173 return ret; 174 } 175 176 INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, 177 INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits, 178 BITMAPINFO *info, UINT wUsage, DWORD dwRop ) 179 { 180 EMRSTRETCHDIBITS *emr; 181 BOOL ret; 182 UINT bmi_size, emr_size; 183 184 /* calculate the size of the colour table */ 185 bmi_size = get_dib_info_size(info, wUsage); 186 187 emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + info->bmiHeader.biSizeImage; 188 emr = HeapAlloc(GetProcessHeap(), 0, emr_size ); 189 if (!emr) return 0; 190 191 /* write a bitmap info header (with colours) to the record */ 192 memcpy( &emr[1], info, bmi_size); 193 194 /* write bitmap bits to the record */ 195 memcpy ( ( (BYTE *) (&emr[1]) ) + bmi_size, bits, info->bmiHeader.biSizeImage); 196 197 /* fill in the EMR header at the front of our piece of memory */ 198 emr->emr.iType = EMR_STRETCHDIBITS; 199 emr->emr.nSize = emr_size; 200 201 emr->xDest = xDst; 202 emr->yDest = yDst; 203 emr->cxDest = widthDst; 204 emr->cyDest = heightDst; 205 emr->dwRop = dwRop; 206 emr->xSrc = xSrc; /* FIXME: only save the piece of the bitmap needed */ 207 emr->ySrc = ySrc; 208 209 emr->iUsageSrc = wUsage; 210 emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); 211 emr->cbBmiSrc = bmi_size; 212 emr->offBitsSrc = emr->offBmiSrc + bmi_size; 213 emr->cbBitsSrc = info->bmiHeader.biSizeImage; 214 215 emr->cxSrc = widthSrc; 216 emr->cySrc = heightSrc; 217 218 emr->rclBounds.left = xDst; 219 emr->rclBounds.top = yDst; 220 emr->rclBounds.right = xDst + widthDst; 221 emr->rclBounds.bottom = yDst + heightDst; 222 223 /* save the record we just created */ 224 ret = EMFDRV_WriteRecord( dev, &emr->emr ); 225 if(ret) 226 EMFDRV_UpdateBBox( dev, &emr->rclBounds ); 227 228 HeapFree(GetProcessHeap(), 0, emr); 229 230 return ret ? heightSrc : GDI_ERROR; 231 } 232 233 INT EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height, 234 INT xSrc, INT ySrc, UINT startscan, UINT lines, 235 LPCVOID bits, BITMAPINFO *info, UINT wUsage ) 236 { 237 EMRSETDIBITSTODEVICE* pEMR; 238 DWORD bmiSize = get_dib_info_size(info, wUsage); 239 DWORD size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + info->bmiHeader.biSizeImage; 240 241 pEMR = HeapAlloc(GetProcessHeap(), 0, size); 242 if (!pEMR) return 0; 243 244 pEMR->emr.iType = EMR_SETDIBITSTODEVICE; 245 pEMR->emr.nSize = size; 246 pEMR->rclBounds.left = xDst; 247 pEMR->rclBounds.top = yDst; 248 pEMR->rclBounds.right = xDst + width - 1; 249 pEMR->rclBounds.bottom = yDst + height - 1; 250 pEMR->xDest = xDst; 251 pEMR->yDest = yDst; 252 pEMR->xSrc = xSrc; 253 pEMR->ySrc = ySrc; 254 pEMR->cxSrc = width; 255 pEMR->cySrc = height; 256 pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); 257 pEMR->cbBmiSrc = bmiSize; 258 pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; 259 pEMR->cbBitsSrc = info->bmiHeader.biSizeImage; 260 pEMR->iUsageSrc = wUsage; 261 pEMR->iStartScan = startscan; 262 pEMR->cScans = lines; 263 memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); 264 memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, info->bmiHeader.biSizeImage); 265 266 if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) 267 EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); 268 269 HeapFree( GetProcessHeap(), 0, pEMR); 270 return lines; 271 } 272