Ignore:
Timestamp:
Mar 9, 2004, 11:03:21 AM (21 years ago)
Author:
sandervl
Message:

VP: Fixes for partial blits in SetDIBitsToDevice

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gdi32/blit.cpp

    r10486 r10495  
    1 /* $Id: blit.cpp,v 1.47 2004-02-27 18:56:12 sandervl Exp $ */
     1/* $Id: blit.cpp,v 1.48 2004-03-09 10:03:21 sandervl Exp $ */
    22
    33/*
     
    1010 *
    1111 */
     12#include <stdio.h>
    1213#include <os2win.h>
    1314#include <stdlib.h>
     
    2829ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
    2930
     31#ifdef DEBUG
     32void 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
    3063//******************************************************************************
    3164//******************************************************************************
     
    198231//******************************************************************************
    199232//******************************************************************************
     233//always extract actual bits to be drawn and construct new bitmap before
     234//calling O32_* API if only part of bitmap is drawn
    200235INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
    201236                               DWORD cy, INT xSrc, INT ySrc,
     
    203238                               const BITMAPINFO *info, UINT coloruse)
    204239{
    205     static BOOL fMatrox32BppBug = FALSE;
    206240    INT   height, width;
    207241    INT   rc = 0;
    208242    char *newBits = NULL;
    209243
    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   
    214247    SetLastError(ERROR_SUCCESS);
     248
    215249    if(info == NULL) {
    216250        goto invalid_parameter;
    217251    }
     252   
     253    dprintf(("BITMAP: (%d,%d) %d bytes",
     254             info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biSizeImage));
     255   
    218256    height = info->bmiHeader.biHeight;
    219257    width  = info->bmiHeader.biWidth;
    220258
    221259    if (height < 0) height = -height;
     260
    222261    if (!lines || (startscan >= height)) {
    223262        goto invalid_parameter;
    224263    }
     264
    225265    if (startscan + lines > height) lines = height - startscan;
    226266
    227     if (ySrc < startscan) ySrc = startscan;
     267    if (ySrc < startscan) { cy -= startscan - ySrc; ySrc = startscan; }
    228268    else if (ySrc >= startscan + lines) goto invalid_parameter;
    229269
     
    236276    if (!cx || !cy) goto invalid_parameter;
    237277
    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));
    272347            }
    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   
    287363    return rc;
    288364
Note: See TracChangeset for help on using the changeset viewer.