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
EMFDRV_PatBlt( PHYSDEV dev
, struct bitblt_coords
*dst
, DWORD rop
)
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
;
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;
61 ret
= EMFDRV_WriteRecord( dev
, &emr
.emr
);
63 EMFDRV_UpdateBBox( dev
, &emr
.rclBounds
);
67 BOOL
EMFDRV_StretchBlt( PHYSDEV devDst
, struct bitblt_coords
*dst
,
68 PHYSDEV devSrc
, struct bitblt_coords
*src
, DWORD rop
)
78 LPBITMAPINFOHEADER lpBmiH
;
79 HBITMAP hBitmap
= NULL
;
82 if (devSrc
->funcs
== devDst
->funcs
) return FALSE
; /* can't use a metafile DC as source */
84 if (src
->log_width
== dst
->log_width
&& src
->log_height
== dst
->log_height
)
87 emrSize
= sizeof(EMRBITBLT
);
91 emrType
= EMR_STRETCHBLT
;
92 emrSize
= sizeof(EMRSTRETCHBLT
);
95 hBitmap
= GetCurrentObject(devSrc
->hdc
, OBJ_BITMAP
);
97 if(sizeof(BITMAP
) != GetObjectW(hBitmap
, sizeof(BITMAP
), &BM
))
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
);
106 size
= emrSize
+ bmiSize
+ bitsSize
;
108 pEMR
= HeapAlloc(GetProcessHeap(), 0, size
);
109 if (!pEMR
) return FALSE
;
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
;
123 pEMR
->xSrc
= src
->log_x
;
124 pEMR
->ySrc
= src
->log_y
;
125 GetWorldTransform(devSrc
->hdc
, &pEMR
->xformSrc
);
126 pEMR
->crBkColorSrc
= GetBkColor(devSrc
->hdc
);
127 pEMR
->iUsageSrc
= DIB_RGB_COLORS
;
128 pEMR
->offBmiSrc
= emrSize
;
129 pEMR
->offBitsSrc
= emrSize
+ bmiSize
;
130 pEMR
->cbBmiSrc
= bmiSize
;
131 pEMR
->cbBitsSrc
= bitsSize
;
132 if (emrType
== EMR_STRETCHBLT
)
134 PEMRSTRETCHBLT pEMRStretch
= (PEMRSTRETCHBLT
)pEMR
;
135 pEMRStretch
->cxSrc
= src
->log_width
;
136 pEMRStretch
->cySrc
= src
->log_height
;
139 /* Initialize BITMAPINFO structure */
140 lpBmiH
= (LPBITMAPINFOHEADER
)((BYTE
*)pEMR
+ pEMR
->offBmiSrc
);
142 lpBmiH
->biSize
= sizeof(BITMAPINFOHEADER
);
143 lpBmiH
->biWidth
= BM
.bmWidth
;
144 lpBmiH
->biHeight
= BM
.bmHeight
;
145 lpBmiH
->biPlanes
= BM
.bmPlanes
;
146 lpBmiH
->biBitCount
= nBPP
;
147 /* Assume the bitmap isn't compressed and set the BI_RGB flag. */
148 lpBmiH
->biCompression
= BI_RGB
;
149 lpBmiH
->biSizeImage
= bitsSize
;
150 lpBmiH
->biYPelsPerMeter
= 0;
151 lpBmiH
->biXPelsPerMeter
= 0;
152 lpBmiH
->biClrUsed
= nBPP
<= 8 ? 1 << nBPP
: 0;
153 /* Set biClrImportant to 0, indicating that all of the
154 device colors are important. */
155 lpBmiH
->biClrImportant
= 0;
157 /* Initialize bitmap bits */
158 if (GetDIBits(devSrc
->hdc
, hBitmap
, 0, (UINT
)lpBmiH
->biHeight
,
159 (BYTE
*)pEMR
+ pEMR
->offBitsSrc
,
160 (LPBITMAPINFO
)lpBmiH
, DIB_RGB_COLORS
))
162 ret
= EMFDRV_WriteRecord(devDst
, (EMR
*)pEMR
);
163 if (ret
) EMFDRV_UpdateBBox(devDst
, &(pEMR
->rclBounds
));
168 HeapFree( GetProcessHeap(), 0, pEMR
);
172 INT
EMFDRV_StretchDIBits( PHYSDEV dev
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
173 INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
, const void *bits
,
174 BITMAPINFO
*info
, UINT wUsage
, DWORD dwRop
)
176 EMRSTRETCHDIBITS
*emr
;
178 UINT bmi_size
, emr_size
;
180 /* calculate the size of the colour table */
181 bmi_size
= bitmap_info_size(info
, wUsage
);
183 emr_size
= sizeof (EMRSTRETCHDIBITS
) + bmi_size
+ info
->bmiHeader
.biSizeImage
;
184 emr
= HeapAlloc(GetProcessHeap(), 0, emr_size
);
187 /* write a bitmap info header (with colours) to the record */
188 memcpy( &emr
[1], info
, bmi_size
);
190 /* write bitmap bits to the record */
191 memcpy ( ( (BYTE
*) (&emr
[1]) ) + bmi_size
, bits
, info
->bmiHeader
.biSizeImage
);
193 /* fill in the EMR header at the front of our piece of memory */
194 emr
->emr
.iType
= EMR_STRETCHDIBITS
;
195 emr
->emr
.nSize
= emr_size
;
199 emr
->cxDest
= widthDst
;
200 emr
->cyDest
= heightDst
;
202 emr
->xSrc
= xSrc
; /* FIXME: only save the piece of the bitmap needed */
205 emr
->iUsageSrc
= wUsage
;
206 emr
->offBmiSrc
= sizeof (EMRSTRETCHDIBITS
);
207 emr
->cbBmiSrc
= bmi_size
;
208 emr
->offBitsSrc
= emr
->offBmiSrc
+ bmi_size
;
209 emr
->cbBitsSrc
= info
->bmiHeader
.biSizeImage
;
211 emr
->cxSrc
= widthSrc
;
212 emr
->cySrc
= heightSrc
;
214 emr
->rclBounds
.left
= xDst
;
215 emr
->rclBounds
.top
= yDst
;
216 emr
->rclBounds
.right
= xDst
+ widthDst
;
217 emr
->rclBounds
.bottom
= yDst
+ heightDst
;
219 /* save the record we just created */
220 ret
= EMFDRV_WriteRecord( dev
, &emr
->emr
);
222 EMFDRV_UpdateBBox( dev
, &emr
->rclBounds
);
224 HeapFree(GetProcessHeap(), 0, emr
);
226 return ret
? heightSrc
: GDI_ERROR
;
229 INT
EMFDRV_SetDIBitsToDevice( PHYSDEV dev
, INT xDst
, INT yDst
, DWORD width
, DWORD height
,
230 INT xSrc
, INT ySrc
, UINT startscan
, UINT lines
,
231 LPCVOID bits
, BITMAPINFO
*info
, UINT wUsage
)
233 EMRSETDIBITSTODEVICE
* pEMR
;
234 DWORD bmiSize
= bitmap_info_size(info
, wUsage
);
235 DWORD size
= sizeof(EMRSETDIBITSTODEVICE
) + bmiSize
+ info
->bmiHeader
.biSizeImage
;
237 pEMR
= HeapAlloc(GetProcessHeap(), 0, size
);
240 pEMR
->emr
.iType
= EMR_SETDIBITSTODEVICE
;
241 pEMR
->emr
.nSize
= size
;
242 pEMR
->rclBounds
.left
= xDst
;
243 pEMR
->rclBounds
.top
= yDst
;
244 pEMR
->rclBounds
.right
= xDst
+ width
- 1;
245 pEMR
->rclBounds
.bottom
= yDst
+ height
- 1;
251 pEMR
->cySrc
= height
;
252 pEMR
->offBmiSrc
= sizeof(EMRSETDIBITSTODEVICE
);
253 pEMR
->cbBmiSrc
= bmiSize
;
254 pEMR
->offBitsSrc
= sizeof(EMRSETDIBITSTODEVICE
) + bmiSize
;
255 pEMR
->cbBitsSrc
= info
->bmiHeader
.biSizeImage
;
256 pEMR
->iUsageSrc
= wUsage
;
257 pEMR
->iStartScan
= startscan
;
258 pEMR
->cScans
= lines
;
259 memcpy((BYTE
*)pEMR
+ pEMR
->offBmiSrc
, info
, bmiSize
);
260 memcpy((BYTE
*)pEMR
+ pEMR
->offBitsSrc
, bits
, info
->bmiHeader
.biSizeImage
);
262 if (EMFDRV_WriteRecord(dev
, (EMR
*)pEMR
))
263 EMFDRV_UpdateBBox(dev
, &(pEMR
->rclBounds
));
265 HeapFree( GetProcessHeap(), 0, pEMR
);