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

Last change on this file since 5677 was 5677, checked in by sandervl, 24 years ago

bugfixes

File size: 19.9 KB
Line 
1/* $Id: blit.cpp,v 1.25 2001-05-10 17:03:17 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//******************************************************************************
93static INT 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 //SvL: RP7's bitmap size is not correct; fix it here or else
131 // the blit is messed up in Open32
132 bmpsize = info->bmiHeader.biSizeImage;
133 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
134 info->bmiHeader.biSizeImage < imgsize)
135 {
136 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
137 }
138
139 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
140 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
141 DWORD *bitfields = (DWORD *)info->bmiColors;
142
143 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
144 compression = BI_BITFIELDS;
145
146 if(*(bitfields+1) == 0x3E0)
147 {//RGB 555?
148 dprintf(("BI_BITFIELDS compression %x %x %x", *bitfields, *(bitfields+1), *(bitfields+2)));
149
150 newbits = (WORD *)malloc(imgsize);
151 if(CPUFeatures & CPUID_MMX) {
152 RGB555to565MMX(newbits, (WORD *)bits, imgsize/sizeof(WORD));
153 }
154 else RGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
155 bits = newbits;
156 }
157 }
158
159 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
160 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
161 }
162
163 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
164 cx, cy, (void *)bits,
165 (PBITMAPINFO)info, coloruse, SRCCOPY);
166
167 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
168 if(result != info->bmiHeader.biHeight) {
169 dprintf(("SetDIBitsToDevice failed with rc %x", result));
170 }
171 else
172 {
173 result = info->bmiHeader.biHeight;
174
175 DIBSection *destdib = DIBSection::findHDC(hdc);
176 if(destdib) {
177 if(cx == info->bmiHeader.biWidth && cy == info->bmiHeader.biHeight &&
178 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
179 destdib->GetBitCount() == 8)
180 {
181 destdib->sync(xDest, yDest, cx, cy, (PVOID)bits);
182 }
183 else destdib->sync(hdc, yDest, cy);
184 }
185 }
186 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",
187 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
188 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));
189
190 if(compression == BI_BITFIELDS) {
191 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
192 if(newbits) free(newbits);
193 }
194 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
195 return result;
196
197invalid_parameter:
198 SetLastError(ERROR_INVALID_PARAMETER);
199 return 0;
200}
201//******************************************************************************
202//******************************************************************************
203INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
204 DWORD cy, INT xSrc, INT ySrc,
205 UINT startscan, UINT lines, LPCVOID bits,
206 const BITMAPINFO *info, UINT coloruse)
207{
208 if(info->bmiHeader.biHeight < 0 && info->bmiHeader.biBitCount != 8 && info->bmiHeader.biCompression == 0) {
209 // upside down
210 INT rc = 0;
211 BITMAPINFO newInfo;
212 newInfo.bmiHeader = info->bmiHeader;
213 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
214 long lHeight = -newInfo.bmiHeader.biHeight;
215 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
216
217 char *newBits = (char *)malloc( lLineByte * lHeight );
218 if(newBits) {
219 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
220 unsigned char *pbDst = (unsigned char *)newBits;
221 for(int y = 0; y < lHeight; y++) {
222 memcpy( pbDst, pbSrc, lLineByte );
223 pbDst += lLineByte;
224 pbSrc -= lLineByte;
225 }
226 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, DIB_RGB_COLORS );
227 free( newBits );
228 }
229 return rc;
230 }
231 else
232 if(info->bmiHeader.biBitCount == 8 && info->bmiHeader.biCompression == 0 && !(GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE)) {
233 INT rc = 0;
234 // convert 8bit to 24bit
235
236 BITMAPINFO newInfo;
237 newInfo.bmiHeader = info->bmiHeader;
238 newInfo.bmiHeader.biBitCount = 24;
239 long lLineByte24 = ((newInfo.bmiHeader.biWidth * 24 + 31) / 32) * 4;
240 long lLineByte8 = ((newInfo.bmiHeader.biWidth * 8 + 31) / 32) * 4;
241 long lHeight = newInfo.bmiHeader.biHeight;
242 if(lHeight < 0) lHeight = -lHeight;
243
244 char *newBits = (char *)malloc( lLineByte24 * lHeight );
245 if(newBits) {
246 //
247 // Get Palette Entries
248 //
249 PALETTEENTRY aEntries[256];
250 LOGPALETTE *pLog = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256 );
251 pLog->palVersion = 0x300;
252 pLog->palNumEntries = 256;
253
254 HPALETTE hPaletteDummy = CreatePalette( pLog );
255 free( pLog );
256 HPALETTE hPalette = SelectPalette( hdc, hPaletteDummy, FALSE );
257 GetPaletteEntries( hPalette, 0, 255, aEntries );
258 SelectPalette( hdc, hPalette, FALSE );
259 DeleteObject( hPaletteDummy );
260
261 //
262 // convert 8bit to 24bit
263 //
264 if(newInfo.bmiHeader.biHeight > 0) {
265 unsigned char *pbSrc = (unsigned char *)bits;
266 unsigned char *pbDst = (unsigned char *)newBits;
267 for(int y = 0; y < lHeight; y++) {
268 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
269 PALETTEENTRY src = aEntries[pbSrc[x]];
270 pbDst[x * 3 + 0] = src.peBlue;
271 pbDst[x * 3 + 1] = src.peGreen;
272 pbDst[x * 3 + 2] = src.peRed;
273 }
274 pbDst += lLineByte24;
275 pbSrc += lLineByte8;
276 }
277 } else {
278 // upside down
279 newInfo.bmiHeader.biHeight = -info->bmiHeader.biHeight;
280 unsigned char *pbSrc = (unsigned char *)bits + lLineByte8 * (lHeight - 1);
281 unsigned char *pbDst = (unsigned char *)newBits;
282 for(int y = 0; y < lHeight; y++) {
283 for(int x = 0; x < newInfo.bmiHeader.biWidth; x++) {
284 PALETTEENTRY src = aEntries[pbSrc[x]];
285 pbDst[x * 3 + 0] = src.peBlue;
286 pbDst[x * 3 + 1] = src.peGreen;
287 pbDst[x * 3 + 2] = src.peRed;
288 }
289 pbDst += lLineByte24;
290 pbSrc -= lLineByte8;
291 }
292 }
293 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (void *)newBits, &newInfo, DIB_RGB_COLORS );
294 free( newBits );
295 }
296 return rc;
297 } else {
298 return SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse );
299 }
300}
301//******************************************************************************
302//******************************************************************************
303BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
304{
305 BOOL rc;
306
307 //CB: Open32 bug: negative width/height not supported!
308 if (nWidth < 0)
309 {
310 nXLeft += nWidth+1;
311 nWidth = -nWidth;
312 }
313 if (nHeight < 0)
314 {
315 nYLeft += nHeight+1;
316 nHeight = -nHeight;
317 }
318 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
319 if(rc) {
320 DIBSection *destdib = DIBSection::findHDC(hdc);
321 if(destdib) {
322 destdib->sync(hdc, nYLeft, nHeight);
323 }
324 }
325
326 dprintf(("GDI32: PatBlt hdc %x (%d,%d) (%d,%d) returned %d\n",hdc, nXLeft,nYLeft,nWidth,nHeight,rc));
327 return(rc);
328}
329//******************************************************************************
330//******************************************************************************
331BOOL 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)
332{
333 dprintf(("GDI32: MaskBlt"));
334 return O32_MaskBlt(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
335}
336//******************************************************************************
337//******************************************************************************
338BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
339 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
340 int xMast, int yMask)
341{
342 dprintf(("GDI32: PlgBlt, not implemented\n"));
343 return(FALSE);
344}
345//******************************************************************************
346//******************************************************************************
347INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
348 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
349 INT heightSrc, const void *bits,
350 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
351{
352 INT rc;
353
354 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));
355
356 if(info->bmiHeader.biBitCount == 1) {
357 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
358 }
359
360 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
361 {
362 // workaround for open32 bug.
363 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
364
365 int i;
366 USHORT *pColorIndex = (USHORT *)info->bmiColors;
367 RGBQUAD *pColors = (RGBQUAD *) alloca(info->bmiHeader.biClrUsed *
368 sizeof(RGBQUAD));
369 BITMAPINFO *infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) +
370 info->bmiHeader.biClrUsed * sizeof(RGBQUAD));
371
372 memcpy(infoLoc, info, sizeof(BITMAPINFO));
373
374 if(GetDIBColorTable(hdc, 0, info->bmiHeader.biClrUsed, pColors) == 0) {
375 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
376 return FALSE;
377 }
378 for(i=0;i<info->bmiHeader.biClrUsed;i++, pColorIndex++)
379 {
380 infoLoc->bmiColors[i] = pColors[*pColorIndex];
381 }
382
383 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
384 widthSrc, heightSrc, (void *)bits,
385 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
386
387 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
388 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
389 dprintf(("StretchDIBits failed with rc %x", rc));
390 }
391 else {
392 rc = heightSrc;
393
394 DIBSection *destdib = DIBSection::findHDC(hdc);
395 if(destdib) {
396 if(widthDst == widthSrc && heightDst == heightSrc &&
397 destdib->GetBitCount() == infoLoc->bmiHeader.biBitCount &&
398 destdib->GetBitCount() == 8)
399 {
400 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
401 }
402 else destdib->sync(hdc, yDst, heightDst);
403 }
404 }
405
406 return rc;
407 }
408 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
409 widthSrc, heightSrc, (void *)bits,
410 (PBITMAPINFO)info, wUsage, dwRop);
411 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
412 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
413 dprintf(("StretchDIBits failed with rc %x", rc));
414 }
415 else
416 {
417 rc = heightSrc;
418
419 DIBSection *destdib = DIBSection::findHDC(hdc);
420 if(destdib) {
421 if(widthDst == widthSrc && heightDst == heightSrc &&
422 destdib->GetBitCount() == info->bmiHeader.biBitCount &&
423 destdib->GetBitCount() == 8)
424 {
425 destdib->sync(xDst, yDst, widthDst, heightDst, (PVOID)bits);
426 }
427 else destdib->sync(hdc, yDst, heightDst);
428 }
429 }
430
431 return rc;
432}
433//******************************************************************************
434//******************************************************************************
435int WIN32API SetStretchBltMode( HDC arg1, int arg2)
436{
437 dprintf(("GDI32: SetStretchBltMode 0x%08X, 0x%08X\n",arg1, arg2));
438
439 if(DIBSection::getSection() != NULL)
440 {
441 DIBSection *dsect = DIBSection::findHDC(arg1);
442 if(dsect)
443 {
444 dprintf((" - DC is DIBSection\n"));
445 }
446 }
447 return O32_SetStretchBltMode(arg1, arg2);
448}
449//******************************************************************************
450//******************************************************************************
451int WIN32API GetStretchBltMode( HDC arg1)
452{
453 dprintf(("GDI32: GetStretchBltMode"));
454 return O32_GetStretchBltMode(arg1);
455}
456//******************************************************************************
457//******************************************************************************
458static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
459{
460 ULONG cbPalette;
461
462 switch (pBHdr->biBitCount)
463 {
464 case 1:
465 case 4:
466 case 8:
467 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
468 break;
469
470 case 16:
471 case 24:
472 case 32:
473 cbPalette = 0;
474 break;
475
476 default:
477 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
478 cbPalette = -1;
479 }
480
481 return cbPalette;
482}
483//******************************************************************************
484//******************************************************************************
485static ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
486{
487 ULONG alignment;
488 ULONG factor;
489 BOOL flag = TRUE; //true: '*' false: '/'
490
491 cy = cy < 0 ? -cy : cy;
492
493 switch(cBits)
494 {
495 case 1:
496 factor = 8;
497 flag = FALSE;
498 break;
499
500 case 4:
501 factor = 2;
502 flag = FALSE;
503 break;
504
505 case 8:
506 factor = 1;
507 break;
508
509 case 16:
510 factor = 2;
511 break;
512
513 case 24:
514 factor = 3;
515 break;
516
517 case 32:
518 return cx*cy;
519
520 default:
521 return 0;
522 }
523
524 if (flag)
525 alignment = (cx = (cx*factor)) % 4;
526 else
527 alignment = (cx = ((cx+factor-1)/factor)) % 4;
528
529 if (alignment != 0)
530 cx += 4 - alignment;
531
532 return cx*cy;
533}
534//******************************************************************************
535//******************************************************************************
Note: See TracBrowser for help on using the repository browser.