Changeset 10495 for trunk/src/gdi32/blit.cpp
- Timestamp:
- Mar 9, 2004, 11:03:21 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gdi32/blit.cpp
r10486 r10495 1 /* $Id: blit.cpp,v 1.4 7 2004-02-27 18:56:12sandervl Exp $ */1 /* $Id: blit.cpp,v 1.48 2004-03-09 10:03:21 sandervl Exp $ */ 2 2 3 3 /* … … 10 10 * 11 11 */ 12 #include <stdio.h> 12 13 #include <os2win.h> 13 14 #include <stdlib.h> … … 28 29 ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy); 29 30 31 #ifdef DEBUG 32 void dumpBitmapBytes (char *name, int width, int height, char *bits) 33 { 34 int i; 35 char buf[4096]; 36 char *p = &buf[0]; 37 38 dprintf(("%s:\n", name)); 39 40 for (i = 0; i < width * height; i++) 41 { 42 if (i % width == 0) 43 { 44 if (i > 0) 45 { 46 dprintf(("%s\n", buf)); 47 p = &buf[0]; 48 } 49 50 sprintf(p, "%2.2d:", i / width); 51 p += strlen (p); 52 } 53 54 sprintf(p, " %2.2x", bits[i]); 55 p += strlen (p); 56 } 57 58 dprintf(("%s\n", buf)); 59 } 60 #else 61 #define dumpBitmapBytes(a, b, c) 62 #endif 30 63 //****************************************************************************** 31 64 //****************************************************************************** … … 198 231 //****************************************************************************** 199 232 //****************************************************************************** 233 //always extract actual bits to be drawn and construct new bitmap before 234 //calling O32_* API if only part of bitmap is drawn 200 235 INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx, 201 236 DWORD cy, INT xSrc, INT ySrc, … … 203 238 const BITMAPINFO *info, UINT coloruse) 204 239 { 205 static BOOL fMatrox32BppBug = FALSE;206 240 INT height, width; 207 241 INT rc = 0; 208 242 char *newBits = NULL; 209 243 210 if(startscan != 0 || lines != abs(info->bmiHeader.biHeight)) { 211 dprintf(("WARNING: SetDIBitsToDevice: startscan != 0 || lines != abs(info->bmiHeader.biHeight")); 212 } 213 244 // save a copy of header as it will be changed probably 245 BITMAPINFOHEADER originalHeader = info->bmiHeader; 246 214 247 SetLastError(ERROR_SUCCESS); 248 215 249 if(info == NULL) { 216 250 goto invalid_parameter; 217 251 } 252 253 dprintf(("BITMAP: (%d,%d) %d bytes", 254 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biSizeImage)); 255 218 256 height = info->bmiHeader.biHeight; 219 257 width = info->bmiHeader.biWidth; 220 258 221 259 if (height < 0) height = -height; 260 222 261 if (!lines || (startscan >= height)) { 223 262 goto invalid_parameter; 224 263 } 264 225 265 if (startscan + lines > height) lines = height - startscan; 226 266 227 if (ySrc < startscan) ySrc = startscan;267 if (ySrc < startscan) { cy -= startscan - ySrc; ySrc = startscan; } 228 268 else if (ySrc >= startscan + lines) goto invalid_parameter; 229 269 … … 236 276 if (!cx || !cy) goto invalid_parameter; 237 277 238 //If upside down, reverse scanlines and call SetDIBitsToDevice again 239 if(info->bmiHeader.biHeight < 0 && (info->bmiHeader.biCompression == BI_RGB || 240 info->bmiHeader.biCompression == BI_BITFIELDS)) 241 { 242 // upside down 243 INT rc = -1; 244 245 UINT lLineByte = DIB_GetDIBWidthBytes(info->bmiHeader.biWidth, info->bmiHeader.biBitCount); 246 UINT lLineCopy, xOffset; 247 UINT lHeight = -info->bmiHeader.biHeight; 248 249 xOffset = (xSrc*info->bmiHeader.biBitCount)/8; 250 xSrc = (xSrc*info->bmiHeader.biBitCount)%8; 251 ySrc -= startscan; 252 253 // Calculate destination line width 254 lLineCopy = cx; 255 if(xSrc + cx > info->bmiHeader.biWidth) 256 lLineCopy = info->bmiHeader.biWidth - xSrc; 257 258 // Plus xSrc in case rounding makes us start at a smaller x coordinate 259 lLineCopy = DIB_GetDIBWidthBytes(lLineCopy+xSrc, info->bmiHeader.biBitCount); 260 261 //TODO: doesn't work if memory is readonly!! 262 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight; 263 264 char *newBits = (char *)malloc( lLineByte * lHeight ); 265 if(newBits) { 266 unsigned char *pbSrc = (unsigned char *)bits + xOffset + lLineByte * ySrc; 267 unsigned char *pbDst = (unsigned char *)newBits + lLineByte * (lHeight - 1); 268 for(int y = 0; y < min(cy, min(lHeight, lines)); y++) { 269 memcpy( pbDst, pbSrc, lLineCopy); 270 pbSrc += lLineByte; 271 pbDst -= lLineByte; 278 //testestset 279 if(xSrc != 0 || ySrc != 0) 280 { 281 dprintf(("xSrc %d ySrc %d bpp %d", xSrc, ySrc, info->bmiHeader.biBitCount)); 282 // return lines; 283 } 284 //testestest 285 286 // check if new bitmap must be created 287 if (xSrc == 0 && ySrc == 0 && startscan == 0 && lines == height && 288 cx == width && cy == height && info->bmiHeader.biHeight > 0) 289 { 290 // bitmap is ok and can be drawn directly 291 } 292 else 293 { 294 // create new bits if we know the bits format 295 if (info->bmiHeader.biCompression == BI_RGB || 296 info->bmiHeader.biCompression == BI_BITFIELDS) 297 { 298 // compute size of memory buffer 299 UINT lBytesPerLineOrig = DIB_GetDIBWidthBytes (info->bmiHeader.biWidth, info->bmiHeader.biBitCount); 300 UINT lBytesToCopyInLine = DIB_GetDIBWidthBytes (cx, info->bmiHeader.biBitCount); 301 302 newBits = (char *)malloc (lBytesToCopyInLine * cy); 303 304 if (newBits) 305 { 306 // copy bits to new buffer 307 int i; 308 // starting pointer 309 char *pBits = (char *)bits + // origin 310 (ySrc - startscan) * lBytesPerLineOrig + // y offset 311 (xSrc * info->bmiHeader.biBitCount) / 8; // x offset 312 313 if (info->bmiHeader.biHeight > 0) 314 { 315 char *pNewBits = (char *)newBits; 316 317 for (i = 0; i < cy; i++) 318 { 319 memcpy (pNewBits, pBits, lBytesToCopyInLine); 320 pBits += lBytesPerLineOrig; 321 pNewBits += lBytesToCopyInLine; 322 } 323 } 324 else 325 { 326 char *pNewBits = (char *)newBits + (cy - 1) * lBytesToCopyInLine; 327 328 for (i = 0; i < cy; i++) 329 { 330 memcpy (pNewBits, pBits, lBytesToCopyInLine); 331 pBits += lBytesPerLineOrig; 332 pNewBits -= lBytesToCopyInLine; 333 } 334 } 335 336 // newBits contain partial bitmap, correct the header 337 // todo bitcount < 8 338 ((BITMAPINFO *)info)->bmiHeader.biWidth = cx; 339 ((BITMAPINFO *)info)->bmiHeader.biHeight = cy; 340 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = lBytesToCopyInLine * cy; 341 342 xSrc = (xSrc * info->bmiHeader.biBitCount) % 8; 343 ySrc = startscan = 0; 344 lines = cy; 345 dprintf(("Converted BITMAP: (%d,%d) %d bytes", 346 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biSizeImage)); 272 347 } 273 //We only convert the necessary data so xSrc & ySrc are now 0 274 //xSrc can be non-zero for < 8bpp bitmap where it starts at the wrong boundary 275 rc = SetDIBitsToDevice( hdc, xDest, yDest, cx, cy, xSrc, 0, startscan, lines, (void *)newBits, info, coloruse ); 276 free( newBits ); 277 } 278 else DebugInt3(); 279 280 //TODO: doesn't work if memory is readonly!! 281 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight; 282 283 return rc; 284 } 285 rc = SetDIBitsToDevice_( hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse ); 286 348 } 349 } 350 351 // draw bits 352 rc = SetDIBitsToDevice_( hdc, xDest, yDest, 353 cx, cy, xSrc, ySrc, startscan, lines, 354 newBits? newBits: bits, info, coloruse ); 355 356 if (newBits) 357 { 358 // restore original header 359 *(BITMAPINFOHEADER *)&info->bmiHeader = originalHeader; 360 free (newBits); 361 } 362 287 363 return rc; 288 364
Note:
See TracChangeset
for help on using the changeset viewer.