2 * Enhanced MetaFile driver BitBlt functions
4 * Copyright 2002 Huw D M Davies for CodeWeavers
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.
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.
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
27 #include "enhmetafiledrv.h"
28 #include "wine/debug.h"
30 BOOL CDECL
EMFDRV_PatBlt( PHYSDEV dev
, INT left
, INT top
,
31 INT width
, INT height
, DWORD rop
)
36 emr
.emr
.iType
= EMR_BITBLT
;
37 emr
.emr
.nSize
= sizeof(emr
);
38 emr
.rclBounds
.left
= left
;
39 emr
.rclBounds
.top
= top
;
40 emr
.rclBounds
.right
= left
+ width
- 1;
41 emr
.rclBounds
.bottom
= top
+ height
- 1;
49 emr
.xformSrc
.eM11
= 1.0;
50 emr
.xformSrc
.eM12
= 0.0;
51 emr
.xformSrc
.eM21
= 0.0;
52 emr
.xformSrc
.eM22
= 1.0;
53 emr
.xformSrc
.eDx
= 0.0;
54 emr
.xformSrc
.eDy
= 0.0;
62 ret
= EMFDRV_WriteRecord( dev
, &emr
.emr
);
64 EMFDRV_UpdateBBox( dev
, &emr
.rclBounds
);
68 /* Utilitarian function used by EMFDRV_BitBlt and EMFDRV_StretchBlt */
70 static BOOL
EMFDRV_BitBlockTransfer(
71 PHYSDEV devDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
72 PHYSDEV devSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, DWORD rop
,
83 LPBITMAPINFOHEADER lpBmiH
;
85 EMFDRV_PDEVICE
* physDevSrc
= (EMFDRV_PDEVICE
*)devSrc
;
86 HBITMAP hBitmap
= NULL
;
88 useSrc
= (((rop
>> 2) & 0x330000) != (rop
& 0x330000));
89 if (!physDevSrc
&& useSrc
) return FALSE
;
91 if (emrType
== EMR_BITBLT
)
92 emrSize
= sizeof(EMRBITBLT
);
93 else if (emrType
== EMR_STRETCHBLT
)
94 emrSize
= sizeof(EMRSTRETCHBLT
);
100 hBitmap
= GetCurrentObject(physDevSrc
->hdc
, OBJ_BITMAP
);
102 if(sizeof(BITMAP
) != GetObjectW(hBitmap
, sizeof(BITMAP
), &BM
))
105 nBPP
= BM
.bmPlanes
* BM
.bmBitsPixel
;
106 if(nBPP
> 8) nBPP
= 24; /* FIXME Can't get 16bpp to work for some reason */
107 bitsSize
= DIB_GetDIBWidthBytes(BM
.bmWidth
, nBPP
) * BM
.bmHeight
;
108 bmiSize
= sizeof(BITMAPINFOHEADER
) +
109 (nBPP
<= 8 ? 1 << nBPP
: 0) * sizeof(RGBQUAD
);
113 bitsSize
= bmiSize
= 0;
116 size
= emrSize
+ bmiSize
+ bitsSize
;
118 pEMR
= HeapAlloc(GetProcessHeap(), 0, size
);
119 if (!pEMR
) return FALSE
;
122 pEMR
->emr
.iType
= emrType
;
123 pEMR
->emr
.nSize
= size
;
124 pEMR
->rclBounds
.left
= xDst
;
125 pEMR
->rclBounds
.top
= yDst
;
126 pEMR
->rclBounds
.right
= xDst
+ widthDst
- 1;
127 pEMR
->rclBounds
.bottom
= yDst
+ heightDst
- 1;
130 pEMR
->cxDest
= widthDst
;
131 pEMR
->cyDest
= heightDst
;
137 GetWorldTransform(physDevSrc
->hdc
, &pEMR
->xformSrc
);
138 pEMR
->crBkColorSrc
= GetBkColor(physDevSrc
->hdc
);
139 pEMR
->iUsageSrc
= DIB_RGB_COLORS
;
140 pEMR
->offBmiSrc
= emrSize
;
141 pEMR
->offBitsSrc
= emrSize
+ bmiSize
;
145 pEMR
->xformSrc
.eM11
= 1.0; /** FIXME: */
146 pEMR
->xformSrc
.eM12
= 0.0; /** Setting default */
147 pEMR
->xformSrc
.eM21
= 0.0; /** value. */
148 pEMR
->xformSrc
.eM22
= 1.0; /** Where should we */
149 pEMR
->xformSrc
.eDx
= 0.0; /** get that info */
150 pEMR
->xformSrc
.eDy
= 0.0; /** ???? */
151 pEMR
->crBkColorSrc
= 0;
154 pEMR
->offBitsSrc
= 0;
156 pEMR
->cbBmiSrc
= bmiSize
;
157 pEMR
->cbBitsSrc
= bitsSize
;
158 if (emrType
== EMR_STRETCHBLT
)
160 PEMRSTRETCHBLT pEMRStretch
= (PEMRSTRETCHBLT
)pEMR
;
161 pEMRStretch
->cxSrc
= widthSrc
;
162 pEMRStretch
->cySrc
= heightSrc
;
167 /* Initialize BITMAPINFO structure */
168 lpBmiH
= (LPBITMAPINFOHEADER
)((BYTE
*)pEMR
+ pEMR
->offBmiSrc
);
170 lpBmiH
->biSize
= sizeof(BITMAPINFOHEADER
);
171 lpBmiH
->biWidth
= BM
.bmWidth
;
172 lpBmiH
->biHeight
= BM
.bmHeight
;
173 lpBmiH
->biPlanes
= BM
.bmPlanes
;
174 lpBmiH
->biBitCount
= nBPP
;
175 /* Assume the bitmap isn't compressed and set the BI_RGB flag. */
176 lpBmiH
->biCompression
= BI_RGB
;
177 lpBmiH
->biSizeImage
= bitsSize
;
178 lpBmiH
->biYPelsPerMeter
= 0;
179 lpBmiH
->biXPelsPerMeter
= 0;
180 lpBmiH
->biClrUsed
= nBPP
<= 8 ? 1 << nBPP
: 0;
181 /* Set biClrImportant to 0, indicating that all of the
182 device colors are important. */
183 lpBmiH
->biClrImportant
= 0;
185 /* Initialize bitmap bits */
186 if (GetDIBits(physDevSrc
->hdc
, hBitmap
, 0, (UINT
)lpBmiH
->biHeight
,
187 (BYTE
*)pEMR
+ pEMR
->offBitsSrc
,
188 (LPBITMAPINFO
)lpBmiH
, DIB_RGB_COLORS
))
190 ret
= EMFDRV_WriteRecord(devDst
, (EMR
*)pEMR
);
191 if (ret
) EMFDRV_UpdateBBox(devDst
, &(pEMR
->rclBounds
));
198 ret
= EMFDRV_WriteRecord(devDst
, (EMR
*)pEMR
);
199 if (ret
) EMFDRV_UpdateBBox(devDst
, &(pEMR
->rclBounds
));
202 HeapFree( GetProcessHeap(), 0, pEMR
);
206 BOOL CDECL
EMFDRV_BitBlt(
207 PHYSDEV devDst
, INT xDst
, INT yDst
, INT width
, INT height
,
208 PHYSDEV devSrc
, INT xSrc
, INT ySrc
, DWORD rop
)
210 return EMFDRV_BitBlockTransfer( devDst
, xDst
, yDst
, width
, height
,
211 devSrc
, xSrc
, ySrc
, width
, height
,
215 BOOL CDECL
EMFDRV_StretchBlt(
216 PHYSDEV devDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
217 PHYSDEV devSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, DWORD rop
)
219 return EMFDRV_BitBlockTransfer( devDst
, xDst
, yDst
, widthDst
, heightDst
,
220 devSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
,
221 rop
, EMR_STRETCHBLT
);
224 INT CDECL
EMFDRV_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
,
225 INT heightDst
, INT xSrc
, INT ySrc
,
226 INT widthSrc
, INT heightSrc
,
227 const void *bits
, const BITMAPINFO
*info
,
228 UINT wUsage
, DWORD dwRop
)
230 EMRSTRETCHDIBITS
*emr
;
232 UINT bmi_size
=0, bits_size
, emr_size
;
234 bits_size
= DIB_GetDIBImageBytes(info
->bmiHeader
.biWidth
,
235 info
->bmiHeader
.biHeight
,
236 info
->bmiHeader
.biBitCount
);
238 /* calculate the size of the colour table */
239 bmi_size
= bitmap_info_size(info
, wUsage
);
241 emr_size
= sizeof (EMRSTRETCHDIBITS
) + bmi_size
+ bits_size
;
242 emr
= HeapAlloc(GetProcessHeap(), 0, emr_size
);
245 /* write a bitmap info header (with colours) to the record */
246 memcpy( &emr
[1], info
, bmi_size
);
248 /* write bitmap bits to the record */
249 memcpy ( ( (BYTE
*) (&emr
[1]) ) + bmi_size
, bits
, bits_size
);
251 /* fill in the EMR header at the front of our piece of memory */
252 emr
->emr
.iType
= EMR_STRETCHDIBITS
;
253 emr
->emr
.nSize
= emr_size
;
257 emr
->cxDest
= widthDst
;
258 emr
->cyDest
= heightDst
;
260 emr
->xSrc
= xSrc
; /* FIXME: only save the piece of the bitmap needed */
263 emr
->iUsageSrc
= wUsage
;
264 emr
->offBmiSrc
= sizeof (EMRSTRETCHDIBITS
);
265 emr
->cbBmiSrc
= bmi_size
;
266 emr
->offBitsSrc
= emr
->offBmiSrc
+ bmi_size
;
267 emr
->cbBitsSrc
= bits_size
;
269 emr
->cxSrc
= widthSrc
;
270 emr
->cySrc
= heightSrc
;
272 emr
->rclBounds
.left
= xDst
;
273 emr
->rclBounds
.top
= yDst
;
274 emr
->rclBounds
.right
= xDst
+ widthDst
;
275 emr
->rclBounds
.bottom
= yDst
+ heightDst
;
277 /* save the record we just created */
278 ret
= EMFDRV_WriteRecord( dev
, &emr
->emr
);
280 EMFDRV_UpdateBBox( dev
, &emr
->rclBounds
);
282 HeapFree(GetProcessHeap(), 0, emr
);
284 return ret
? heightSrc
: GDI_ERROR
;
287 INT CDECL
EMFDRV_SetDIBitsToDevice(
288 PHYSDEV dev
, INT xDst
, INT yDst
, DWORD width
, DWORD height
,
289 INT xSrc
, INT ySrc
, UINT startscan
, UINT lines
,
290 LPCVOID bits
, const BITMAPINFO
*info
, UINT wUsage
)
292 EMRSETDIBITSTODEVICE
* pEMR
;
293 DWORD size
, bmiSize
, bitsSize
;
295 bmiSize
= bitmap_info_size(info
, wUsage
);
296 bitsSize
= DIB_GetDIBImageBytes( info
->bmiHeader
.biWidth
,
297 info
->bmiHeader
.biHeight
,
298 info
->bmiHeader
.biBitCount
);
299 size
= sizeof(EMRSETDIBITSTODEVICE
) + bmiSize
+ bitsSize
;
301 pEMR
= HeapAlloc(GetProcessHeap(), 0, size
);
304 pEMR
->emr
.iType
= EMR_SETDIBITSTODEVICE
;
305 pEMR
->emr
.nSize
= size
;
306 pEMR
->rclBounds
.left
= xDst
;
307 pEMR
->rclBounds
.top
= yDst
;
308 pEMR
->rclBounds
.right
= xDst
+ width
- 1;
309 pEMR
->rclBounds
.bottom
= yDst
+ height
- 1;
315 pEMR
->cySrc
= height
;
316 pEMR
->offBmiSrc
= sizeof(EMRSETDIBITSTODEVICE
);
317 pEMR
->cbBmiSrc
= bmiSize
;
318 pEMR
->offBitsSrc
= sizeof(EMRSETDIBITSTODEVICE
) + bmiSize
;
319 pEMR
->cbBitsSrc
= bitsSize
;
320 pEMR
->iUsageSrc
= wUsage
;
321 pEMR
->iStartScan
= startscan
;
322 pEMR
->cScans
= lines
;
323 memcpy((BYTE
*)pEMR
+ pEMR
->offBmiSrc
, info
, bmiSize
);
324 memcpy((BYTE
*)pEMR
+ pEMR
->offBitsSrc
, bits
, bitsSize
);
326 if (EMFDRV_WriteRecord(dev
, (EMR
*)pEMR
))
327 EMFDRV_UpdateBBox(dev
, &(pEMR
->rclBounds
));
329 HeapFree( GetProcessHeap(), 0, pEMR
);