source: trunk/src/gdi32/blit.cpp@ 3830

Last change on this file since 3830 was 3726, checked in by sandervl, 25 years ago

minor update

File size: 13.9 KB
Line 
1/* $Id: blit.cpp,v 1.15 2000-06-17 11:58:07 sandervl Exp $ */
2
3/*
4 * GDI32 blit code
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#include <os2win.h>
13#include <stdlib.h>
14#include <stdarg.h>
15#include <string.h>
16#include <cpuhlp.h>
17#include "misc.h"
18#include "dibsect.h"
19#include "rgbcvt.h"
20
21#define DBG_LOCALLOG DBG_blit
22#include "dbglocal.h"
23
24static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr);
25static ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
26
27//******************************************************************************
28//******************************************************************************
29BOOL WIN32API StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,
30 int nWidthDest, int nHeightDest,
31 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
32 int nWidthSrc, int nHeightSrc, DWORD dwRop)
33{
34 BOOL rc;
35
36 dprintf(("GDI32: StretchBlt Dest: %x (%d, %d) size (%d, %d)\n",
37 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest));
38 dprintf(("GDI32: StretchBlt Src : %x (%d, %d) size (%d, %d)\n",
39 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc));
40 SetLastError(ERROR_SUCCESS);
41 if(DIBSection::getSection() != NULL)
42 {
43 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
44 if(dsect)
45 {
46 rc = dsect->BitBlt( hdcDest,
47 nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
48 nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
49 dwRop);
50 return rc;
51 }
52 }
53 return O32_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);
54}
55//******************************************************************************
56//******************************************************************************
57BOOL WIN32API BitBlt(HDC hdcDest, int arg2, int arg3, int arg4, int arg5, HDC hdcSrc, int arg7, int arg8, DWORD arg9)
58{
59 BOOL rc;
60
61 SetLastError(ERROR_SUCCESS);
62 if(DIBSection::getSection() != NULL) {
63 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
64 if(dsect) {
65 return dsect->BitBlt(hdcDest, arg2, arg3, arg4, arg5, arg7, arg8, arg4, arg5, arg9);
66 }
67 }
68 dprintf(("GDI32: BitBlt to hdc %X from (%d,%d) to (%d,%d), (%d,%d) rop %X\n", hdcDest, arg7, arg8, arg2, arg3, arg4, arg5, arg9));
69 return O32_BitBlt(hdcDest, arg2, arg3, arg4, arg5, hdcSrc, arg7, arg8, arg9);
70}
71//******************************************************************************
72//******************************************************************************
73INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
74 DWORD cy, INT xSrc, INT ySrc,
75 UINT startscan, UINT lines, LPCVOID bits,
76 const BITMAPINFO *info, UINT coloruse)
77{
78 INT result, imgsize, palsize, height, width;
79 char *ptr;
80 ULONG compression = 0, iHeight, bmpsize;
81 WORD *newbits = 0;
82
83 SetLastError(ERROR_SUCCESS);
84 if(info == NULL) {
85 goto invalid_parameter;
86 }
87 height = info->bmiHeader.biHeight;
88 width = info->bmiHeader.biWidth;
89
90 if (height < 0) height = -height;
91 if (!lines || (startscan >= height)) {
92 goto invalid_parameter;
93 }
94 if (startscan + lines > height) lines = height - startscan;
95
96 if (ySrc < startscan) ySrc = startscan;
97 else if (ySrc >= startscan + lines) goto invalid_parameter;
98
99 if (xSrc >= width) goto invalid_parameter;
100
101 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
102
103 if (xSrc + cx >= width) cx = width - xSrc;
104
105 if (!cx || !cy) goto invalid_parameter;
106
107 // EB: ->>> Crazy. Nobody seen this Open32 bug ?
108 // Dont't like dirty pointers, but Open32 needs a bit help.
109 // Only tested with winmine.
110 palsize = QueryPaletteSize((BITMAPINFOHEADER*)&info->bmiHeader);
111 imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
112 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
113 ptr = ((char *)info) + palsize + sizeof(BITMAPINFOHEADER);
114 if(bits >= ptr && bits < ptr + imgsize)
115 {
116 bits = (char *)bits - imgsize +
117 CalcBitmapSize(info->bmiHeader.biBitCount,
118 info->bmiHeader.biWidth, lines);
119 }
120 // EB: <<<-
121
122 //SvL: RP7's bitmap size is not correct; fix it here or else
123 // the blit is messed up in Open32
124 bmpsize = info->bmiHeader.biSizeImage;
125 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
126 info->bmiHeader.biSizeImage < imgsize)
127 {
128 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
129 }
130
131 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
132 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
133 DWORD *bitfields = (DWORD *)info->bmiColors;
134
135 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
136 compression = BI_BITFIELDS;
137
138 if(*(bitfields+1) == 0x3E0)
139 {//RGB 555?
140 dprintf(("BI_BITFIELDS compression %x %x %x", *bitfields, *(bitfields+1), *(bitfields+2)));
141
142 newbits = (WORD *)malloc(imgsize);
143 if(CPUFeatures & CPUID_MMX) {
144 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
145 }
146 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
147 bits = newbits;
148 }
149 }
150
151 iHeight = info->bmiHeader.biHeight;
152 if(info->bmiHeader.biHeight < 0) {
153 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
154 }
155 result = O32_SetDIBitsToDevice(hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (PVOID) bits, (PBITMAPINFO)info, coloruse);
156 //SvL: Wrong Open32 return value
157// result = (result == TRUE) ? lines : 0;
158 result = (result == TRUE) ? cy : 0;
159
160 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d returned %d",
161 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
162 dprintf(("GDI32: SetDIBitsToDevice %d %d %d %d %x %d", info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biPlanes, info->bmiHeader.biBitCount, info->bmiHeader.biCompression, info->bmiHeader.biSizeImage));
163
164 if(compression == BI_BITFIELDS) {
165 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
166 if(newbits) free(newbits);
167 }
168 ((BITMAPINFO *)info)->bmiHeader.biHeight = iHeight;
169 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
170 return result;
171
172invalid_parameter:
173 SetLastError(ERROR_INVALID_PARAMETER);
174 return 0;
175}
176//******************************************************************************
177//******************************************************************************
178BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
179{
180 BOOL rc;
181
182 //CB: Open32 bug: negative width/height not supported!
183 if (nWidth < 0)
184 {
185 nXLeft += nWidth+1;
186 nWidth = -nWidth;
187 }
188 if (nHeight < 0)
189 {
190 nYLeft += nHeight+1;
191 nHeight = -nHeight;
192 }
193 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
194 if(rc) {
195 DIBSection *destdib = DIBSection::findHDC(hdc);
196 if(destdib) {
197 destdib->sync(hdc, nYLeft, nHeight);
198 }
199 }
200
201 dprintf(("GDI32: PatBlt hdc %x (%d,%d) (%d,%d) returned %d\n",hdc, nXLeft,nYLeft,nWidth,nHeight,rc));
202 return(rc);
203}
204//******************************************************************************
205//******************************************************************************
206BOOL WIN32API MaskBlt( HDC arg1, int arg2, int arg3, int arg4, int arg5, HDC arg6, int arg7, int arg8, HBITMAP arg9, int arg10, int arg11, DWORD arg12)
207{
208 dprintf(("GDI32: MaskBlt"));
209 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
210}
211//******************************************************************************
212//******************************************************************************
213BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
214 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
215 int xMast, int yMask)
216{
217 dprintf(("GDI32: PlgBlt, not implemented\n"));
218 return(FALSE);
219}
220//******************************************************************************
221//******************************************************************************
222INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
223 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
224 INT heightSrc, const void *bits,
225 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
226{
227#if 1
228 INT rc;
229
230 dprintf(("GDI32: StretchDIBits %x to (%d,%d) (%d,%d) from (%d,%d) (%d,%d), %x %x %x %x", hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop));
231
232 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
233 {
234 // workaround for open32 bug.
235 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
236
237 int i;
238 USHORT *pColorIndex = (USHORT *)info->bmiColors;
239 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
240 sizeof(RGBQUAD));
241 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
242 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
243
244 memcpy(infoLoc, info, sizeof(BITMAPINFO));
245
246 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0)
247 return FALSE;
248
249 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
250 {
251 infoLoc->bmiColors[i] = pColors[*pColorIndex];
252 }
253
254 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
255 widthSrc, heightSrc, (void *)bits,
256 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
257
258 if(rc != heightSrc) {
259 dprintf(("StretchDIBits failed with rc %x", rc));
260 }
261 else {
262 DIBSection *destdib = DIBSection::findHDC(hdc);
263 if(destdib) {
264 destdib->sync(hdc, yDst, heightDst);
265 }
266 }
267
268 return rc;
269 }
270
271 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
272 widthSrc, heightSrc, (void *)bits,
273 (PBITMAPINFO)info, wUsage, dwRop);
274 if(rc != heightSrc) {
275 dprintf(("StretchDIBits failed with rc %x", rc));
276 }
277 else {
278 DIBSection *destdib = DIBSection::findHDC(hdc);
279 if(destdib) {
280 destdib->sync(hdc, yDst, heightDst);
281 }
282 }
283
284 return rc;
285#else
286 dprintf(("GDI32: StretchDIBits\n"));
287 return O32_StretchDIBits(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, (void *)arg10, (PBITMAPINFO)arg11, arg12, arg13);
288#endif
289}
290//******************************************************************************
291//******************************************************************************
292int WIN32API SetStretchBltMode( HDC arg1, int arg2)
293{
294 dprintf(("GDI32: SetStretchBltMode 0x%08X, 0x%08X\n",arg1, arg2));
295
296 if(DIBSection::getSection() != NULL)
297 {
298 DIBSection *dsect = DIBSection::findHDC(arg1);
299 if(dsect)
300 {
301 dprintf((" - DC is DIBSection\n"));
302 }
303 }
304 return O32_SetStretchBltMode(arg1, arg2);
305}
306//******************************************************************************
307//******************************************************************************
308int WIN32API GetStretchBltMode( HDC arg1)
309{
310 dprintf(("GDI32: GetStretchBltMode"));
311 return O32_GetStretchBltMode(arg1);
312}
313//******************************************************************************
314//******************************************************************************
315static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
316{
317 ULONG cbPalette;
318
319 switch (pBHdr->biBitCount)
320 {
321 case 1:
322 case 4:
323 case 8:
324 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
325 break;
326
327 case 16:
328 case 24:
329 case 32:
330 cbPalette = 0;
331 break;
332
333 default:
334 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
335 cbPalette = -1;
336 }
337
338 return cbPalette;
339}
340//******************************************************************************
341//******************************************************************************
342static ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
343{
344 ULONG alignment;
345 ULONG factor;
346 BOOL flag = TRUE; //true: '*' false: '/'
347
348 cy = cy < 0 ? -cy : cy;
349
350 switch(cBits)
351 {
352 case 1:
353 factor = 8;
354 flag = FALSE;
355 break;
356
357 case 4:
358 factor = 2;
359 flag = FALSE;
360 break;
361
362 case 8:
363 factor = 1;
364 break;
365
366 case 16:
367 factor = 2;
368 break;
369
370 case 24:
371 factor = 3;
372 break;
373
374 case 32:
375 return cx*cy;
376
377 default:
378 return 0;
379 }
380
381 if (flag)
382 alignment = (cx = (cx*factor)) % 4;
383 else
384 alignment = (cx = ((cx+factor-1)/factor)) % 4;
385
386 if (alignment != 0)
387 cx += 4 - alignment;
388
389 return cx*cy;
390}
391//******************************************************************************
392//******************************************************************************
Note: See TracBrowser for help on using the repository browser.