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

Last change on this file since 5087 was 4968, checked in by sandervl, 25 years ago

another SetDIBitsToDevice fix (MS Developer startup window)

File size: 16.0 KB
Line 
1/* $Id: blit.cpp,v 1.23 2001-01-18 21:09:34 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) ROP %x",
37 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop));
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,
58 int nXDest,
59 int nYDest,
60 int nWidth,
61 int nHeight,
62 HDC hdcSrc,
63 int nXSrc,
64 int nYSrc,
65 DWORD dwRop)
66{
67 BOOL rc;
68
69 SetLastError(ERROR_SUCCESS);
70 if(DIBSection::getSection() != NULL)
71 {
72 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
73 if(dsect)
74 {
75 return dsect->BitBlt(hdcDest,
76 nXDest,
77 nYDest,
78 nWidth,
79 nHeight,
80 nXSrc,
81 nYSrc,
82 nWidth,
83 nHeight,
84 dwRop);
85 }
86 }
87 dprintf(("GDI32: BitBlt to hdc %X from hdc %x (%d,%d) to (%d,%d), (%d,%d) rop %X\n",
88 hdcDest, hdcSrc, nXSrc, nYSrc, nXDest, nYDest, nWidth, nHeight, dwRop));
89 return O32_BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);
90}
91//******************************************************************************
92//******************************************************************************
93INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
94 DWORD cy, INT xSrc, INT ySrc,
95 UINT startscan, UINT lines, LPCVOID bits,
96 const BITMAPINFO *info, UINT coloruse)
97{
98 INT result, imgsize, palsize, height, width;
99 char *ptr;
100 ULONG compression = 0, bmpsize;
101 WORD *newbits = 0;
102
103 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",
104 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse));
105
106 SetLastError(ERROR_SUCCESS);
107 if(info == NULL) {
108 goto invalid_parameter;
109 }
110 height = info->bmiHeader.biHeight;
111 width = info->bmiHeader.biWidth;
112
113 if (height < 0) height = -height;
114 if (!lines || (startscan >= height)) {
115 goto invalid_parameter;
116 }
117 if (startscan + lines > height) lines = height - startscan;
118
119 if (ySrc < startscan) ySrc = startscan;
120 else if (ySrc >= startscan + lines) goto invalid_parameter;
121
122 if (xSrc >= width) goto invalid_parameter;
123
124 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
125
126 if (xSrc + cx >= width) cx = width - xSrc;
127
128 if (!cx || !cy) goto invalid_parameter;
129
130 // EB: ->>> Crazy. Nobody seen this Open32 bug ?
131 // Dont't like dirty pointers, but Open32 needs a bit help.
132 // Only tested with winmine.
133 palsize = QueryPaletteSize((BITMAPINFOHEADER*)&info->bmiHeader);
134 imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
135 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
136 ptr = ((char *)info) + palsize + sizeof(BITMAPINFOHEADER);
137 if(bits >= ptr && bits < ptr + imgsize)
138 {
139 bits = (char *)bits - imgsize +
140 CalcBitmapSize(info->bmiHeader.biBitCount,
141 info->bmiHeader.biWidth, lines);
142 }
143 // EB: <<<-
144
145 //SvL: RP7's bitmap size is not correct; fix it here or else
146 // the blit is messed up in Open32
147 bmpsize = info->bmiHeader.biSizeImage;
148 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
149 info->bmiHeader.biSizeImage < imgsize)
150 {
151 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
152 }
153
154 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
155 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
156 DWORD *bitfields = (DWORD *)info->bmiColors;
157
158 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
159 compression = BI_BITFIELDS;
160
161 if(*(bitfields+1) == 0x3E0)
162 {//RGB 555?
163 dprintf(("BI_BITFIELDS compression %x %x %x", *bitfields, *(bitfields+1), *(bitfields+2)));
164
165 newbits = (WORD *)malloc(imgsize);
166 if(CPUFeatures & CPUID_MMX) {
167 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
168 }
169 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
170 bits = newbits;
171 }
172 }
173
174 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
175 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
176 }
177
178 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
179 cx, cy, (void *)bits,
180 (PBITMAPINFO)info, coloruse, SRCCOPY);
181
182 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
183 if(result != info->bmiHeader.biHeight) {
184 dprintf(("SetDIBitsToDevice failed with rc %x", result));
185 }
186 else
187 {
188 result = info->bmiHeader.biHeight;
189
190 DIBSection *destdib = DIBSection::findHDC(hdc);
191 if(destdib) {
192 if(cx == info->bmiHeader.biWidth && cy == info->bmiHeader.biHeight &&
193 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
194 destdib->GetBitCount() == 8)
195 {
196 destdib->sync(xDest, yDest, cx, cy, (PVOID)bits);
197 }
198 else destdib->sync(hdc, yDest, cy);
199 }
200 }
201 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",
202 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
203 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));
204
205 if(compression == BI_BITFIELDS) {
206 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
207 if(newbits) free(newbits);
208 }
209 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
210 return result;
211
212invalid_parameter:
213 SetLastError(ERROR_INVALID_PARAMETER);
214 return 0;
215}
216//******************************************************************************
217//******************************************************************************
218BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
219{
220 BOOL rc;
221
222 //CB: Open32 bug: negative width/height not supported!
223 if (nWidth < 0)
224 {
225 nXLeft += nWidth+1;
226 nWidth = -nWidth;
227 }
228 if (nHeight < 0)
229 {
230 nYLeft += nHeight+1;
231 nHeight = -nHeight;
232 }
233 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
234 if(rc) {
235 DIBSection *destdib = DIBSection::findHDC(hdc);
236 if(destdib) {
237 destdib->sync(hdc, nYLeft, nHeight);
238 }
239 }
240
241 dprintf(("GDI32: PatBlt hdc %x (%d,%d) (%d,%d) returned %d\n",hdc, nXLeft,nYLeft,nWidth,nHeight,rc));
242 return(rc);
243}
244//******************************************************************************
245//******************************************************************************
246BOOL 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)
247{
248 dprintf(("GDI32: MaskBlt"));
249 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
250}
251//******************************************************************************
252//******************************************************************************
253BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
254 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
255 int xMast, int yMask)
256{
257 dprintf(("GDI32: PlgBlt, not implemented\n"));
258 return(FALSE);
259}
260//******************************************************************************
261//******************************************************************************
262INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
263 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
264 INT heightSrc, const void *bits,
265 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
266{
267 INT rc;
268
269 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));
270
271 if(info->bmiHeader.biBitCount == 1) {
272 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
273 }
274
275 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
276 {
277 // workaround for open32 bug.
278 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
279
280 int i;
281 USHORT *pColorIndex = (USHORT *)info->bmiColors;
282 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
283 sizeof(RGBQUAD));
284 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
285 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
286
287 memcpy(infoLoc, info, sizeof(BITMAPINFO));
288
289 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0) {
290 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
291 return FALSE;
292 }
293 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
294 {
295 infoLoc->bmiColors[i] = pColors[*pColorIndex];
296 }
297
298 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
299 widthSrc, heightSrc, (void *)bits,
300 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
301
302 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
303 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
304 dprintf(("StretchDIBits failed with rc %x", rc));
305 }
306 else {
307 rc = heightSrc;
308
309 DIBSection *destdib = DIBSection::findHDC(hdc);
310 if(destdib) {
311 if(widthDst == widthSrc && heightDst == heightSrc &&
312 destdib->GetBitCount() == infoLoc->bmiHeader.biBitCount &&
313 destdib->GetBitCount() == 8)
314 {
315 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
316 }
317 else destdib->sync(hdc, yDst, heightDst);
318 }
319 }
320
321 return rc;
322 }
323 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
324 widthSrc, heightSrc, (void *)bits,
325 (PBITMAPINFO)info, wUsage, dwRop);
326 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
327 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
328 dprintf(("StretchDIBits failed with rc %x", rc));
329 }
330 else
331 {
332 rc = heightSrc;
333
334 DIBSection *destdib = DIBSection::findHDC(hdc);
335 if(destdib) {
336 if(widthDst == widthSrc && heightDst == heightSrc &&
337 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
338 destdib->GetBitCount() == 8)
339 {
340 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
341 }
342 else destdib->sync(hdc, yDst, heightDst);
343 }
344 }
345
346 return rc;
347}
348//******************************************************************************
349//******************************************************************************
350int WIN32API SetStretchBltMode( HDC arg1, int arg2)
351{
352 dprintf(("GDI32: SetStretchBltMode 0x%08X, 0x%08X\n",arg1, arg2));
353
354 if(DIBSection::getSection() != NULL)
355 {
356 DIBSection *dsect = DIBSection::findHDC(arg1);
357 if(dsect)
358 {
359 dprintf((" - DC is DIBSection\n"));
360 }
361 }
362 return O32_SetStretchBltMode(arg1, arg2);
363}
364//******************************************************************************
365//******************************************************************************
366int WIN32API GetStretchBltMode( HDC arg1)
367{
368 dprintf(("GDI32: GetStretchBltMode"));
369 return O32_GetStretchBltMode(arg1);
370}
371//******************************************************************************
372//******************************************************************************
373static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
374{
375 ULONG cbPalette;
376
377 switch (pBHdr->biBitCount)
378 {
379 case 1:
380 case 4:
381 case 8:
382 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
383 break;
384
385 case 16:
386 case 24:
387 case 32:
388 cbPalette = 0;
389 break;
390
391 default:
392 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
393 cbPalette = -1;
394 }
395
396 return cbPalette;
397}
398//******************************************************************************
399//******************************************************************************
400static ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
401{
402 ULONG alignment;
403 ULONG factor;
404 BOOL flag = TRUE; //true: '*' false: '/'
405
406 cy = cy < 0 ? -cy : cy;
407
408 switch(cBits)
409 {
410 case 1:
411 factor = 8;
412 flag = FALSE;
413 break;
414
415 case 4:
416 factor = 2;
417 flag = FALSE;
418 break;
419
420 case 8:
421 factor = 1;
422 break;
423
424 case 16:
425 factor = 2;
426 break;
427
428 case 24:
429 factor = 3;
430 break;
431
432 case 32:
433 return cx*cy;
434
435 default:
436 return 0;
437 }
438
439 if (flag)
440 alignment = (cx = (cx*factor)) % 4;
441 else
442 alignment = (cx = ((cx+factor-1)/factor)) % 4;
443
444 if (alignment != 0)
445 cx += 4 - alignment;
446
447 return cx*cy;
448}
449//******************************************************************************
450//******************************************************************************
Note: See TracBrowser for help on using the repository browser.