diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index 54248bc381e..972a84a85dd 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c @@ -1853,92 +1853,97 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2, } -/* helper for _read_bitmap currently unused */ -#if 0 -static int may_use_dibsection(HDC hdc) { - int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); - if (bitspixel>8) - return TRUE; - if (bitspixel<=4) - return FALSE; - return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE; +/*********************************************************************** + * DIB_GetDIBWidthBytes + * + * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned. + */ +static int DIB_GetDIBWidthBytes( int width, int depth ) +{ + int words; + + switch(depth) + { + case 1: words = (width + 31) / 32; break; + case 4: words = (width + 7) / 8; break; + case 8: words = (width + 3) / 4; break; + case 15: + case 16: words = (width + 1) / 2; break; + case 24: words = (width * 3 + 3)/4; break; + + default: + WARN("(%d): Unsupported depth\n", depth ); + /* fall through */ + case 32: + words = width; + break; + } + return 4 * words; } -#endif + +/*********************************************************************** + * DIB_GetDIBImageBytes + * + * Return the number of bytes used to hold the image in a DIB bitmap. + */ +static int DIB_GetDIBImageBytes( int width, int height, int depth ) +{ + return DIB_GetDIBWidthBytes( width, depth ) * abs( height ); +} + /* helper for ImageList_Read, see comments below */ -static BOOL _read_bitmap(HIMAGELIST himl, HDC hdcIml, LPSTREAM pstm, int ilcFlag) +static BOOL _read_bitmap(HIMAGELIST himl, HDC hdcIml, LPSTREAM pstm) { - HDC xdc = 0; BITMAPFILEHEADER bmfh; - BITMAPINFOHEADER bmih; - int bitsperpixel,palspace,longsperline,width,height; - LPBITMAPINFO bmi = NULL; + int bitsperpixel, palspace; + char bmi_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256]; + LPBITMAPINFO bmi = (LPBITMAPINFO)bmi_buf; int result = FALSE; - HBITMAP hDIB = 0; LPBYTE bits = NULL; - int i, j, nheight, nRows, nCols; - POINT pt; - int cy = himl->cy; if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL))) - return result; + return FALSE; if (bmfh.bfType != (('M'<<8)|'B')) - return result; + return FALSE; - if (!SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL))) - return result; + if (!SUCCEEDED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL))) + return FALSE; - if ((bmih.biSize != sizeof(bmih))) - return 0; + if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader))) + return FALSE; - bitsperpixel = bmih.biPlanes * bmih.biBitCount; + TRACE("width %u, height %u, planes %u, bpp %u\n", + bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, + bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount); + + bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount; if (bitsperpixel<=8) palspace = (1<>5; - bmi->bmiHeader.biSizeImage = (longsperline*height)<<2; + bmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bitsperpixel); /* read the palette right after the end of the bitmapinfoheader */ if (palspace && !SUCCEEDED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL))) goto error; - xdc = GetDC(0); - - nheight = cy; - nRows = height/cy; - nCols = width/himl->cx; - - hDIB = CreateDIBSection(xdc, bmi, 0, (LPVOID*) &bits, 0, 0); - if (!hDIB) + bits = Alloc(bmi->bmiHeader.biSizeImage); + if (!bits) goto error; if (!SUCCEEDED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL))) goto error; - /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */ - /* Do not forget that windows bitmaps are bottom->top */ - for (i=0; i < nRows; i++) { - for (j=0; j < nCols; j++) { - imagelist_point_from_index(himl, i*nCols + j, &pt); - StretchDIBits(hdcIml, pt.x, pt.y, himl->cx, cy, - j*himl->cx, (nRows - 1 - i)*himl->cy, himl->cx, cy, bits, - bmi, DIB_RGB_COLORS, SRCCOPY); - } - } - + if (!StretchDIBits(hdcIml, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, + 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, + bits, bmi, DIB_RGB_COLORS, SRCCOPY)) + goto error; result = TRUE; + error: - if (xdc) ReleaseDC(0,xdc); - Free(bmi); - if (hDIB) DeleteObject(hDIB); + Free(bits); return result; } @@ -1972,9 +1977,6 @@ error: * RGBQUAD rgbs[nr_of_paletted_colors]; * * BYTE maskbits[imagesize]; - * - * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect. - * _read_bitmap needs to convert them. */ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) { @@ -1991,16 +1993,23 @@ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) if (ilHead.usVersion != 0x101) /* probably version? */ return NULL; + TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n", + ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage); + himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage); - if (!himl) { + if (!himl) return NULL; - } - if (!_read_bitmap(himl, himl->hdcImage, pstm, ilHead.flags & ~ILC_MASK)) { + + if (!_read_bitmap(himl, himl->hdcImage, pstm)) + { WARN("failed to read bitmap from stream\n"); return NULL; } - if (ilHead.flags & ILC_MASK) { - if (!_read_bitmap(himl, himl->hdcMask, pstm, 0)) { + if (ilHead.flags & ILC_MASK) + { + if (!_read_bitmap(himl, himl->hdcMask, pstm)) + { + WARN("failed to read mask bitmap from stream\n"); return NULL; } } @@ -2651,38 +2660,29 @@ ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay) * currently everything is written as 24 bit RGB, except masks */ static BOOL -_write_bitmap(HBITMAP hBitmap, LPSTREAM pstm, int cx, int cy) +_write_bitmap(HBITMAP hBitmap, LPSTREAM pstm) { LPBITMAPFILEHEADER bmfh; LPBITMAPINFOHEADER bmih; - LPBYTE data = NULL, lpBits = NULL, lpBitsOrg = NULL; + LPBYTE data = NULL, lpBits; BITMAP bm; INT bitCount, sizeImage, offBits, totalSize; - INT nwidth, nheight, nsizeImage, icount; HDC xdc; BOOL result = FALSE; - - xdc = GetDC(0); if (!GetObjectW(hBitmap, sizeof(BITMAP), (LPVOID)&bm)) - goto failed; - - /* XXX is this always correct? */ - icount = bm.bmWidth / cx; - nwidth = cx; - nheight = cy * icount; + return FALSE; bitCount = bm.bmBitsPixel == 1 ? 1 : 24; - sizeImage = ((((bm.bmWidth * bitCount)+31) & ~31) >> 3) * bm.bmHeight; - nsizeImage = ((((nwidth * bitCount)+31) & ~31) >> 3) * nheight; + sizeImage = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, bitCount); totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); if(bitCount != 24) totalSize += (1 << bitCount) * sizeof(RGBQUAD); offBits = totalSize; - totalSize += nsizeImage; + totalSize += sizeImage; - data = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, totalSize); + data = Alloc(totalSize); bmfh = (LPBITMAPFILEHEADER)data; bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER)); lpBits = data + offBits; @@ -2707,25 +2707,15 @@ _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm, int cx, int cy) bmih->biClrUsed = 0; bmih->biClrImportant = 0; - lpBitsOrg = (LPBYTE)LocalAlloc(LMEM_ZEROINIT, sizeImage); - if(!GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBitsOrg, - (BITMAPINFO *)bmih, DIB_RGB_COLORS)) + xdc = GetDC(0); + result = GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBits, (BITMAPINFO *)bmih, DIB_RGB_COLORS) == bm.bmHeight; + ReleaseDC(0, xdc); + if (!result) goto failed; - else { - int i; - int obpl = (((bm.bmWidth*bitCount+31) & ~31)>>3); - int nbpl = (((nwidth*bitCount+31) & ~31)>>3); - for(i = 0; i < nheight; i++) { - int ooff = ((nheight-1-i)%cy) * obpl + ((i/cy) * nbpl); - int noff = (nbpl * (nheight-1-i)); - memcpy(lpBits + noff, lpBitsOrg + ooff, nbpl); - } - } - - bmih->biWidth = nwidth; - bmih->biHeight = nheight; - bmih->biSizeImage = nsizeImage; + TRACE("width %u, height %u, planes %u, bpp %u\n", + bmih->biWidth, bmih->biHeight, + bmih->biPlanes, bmih->biBitCount); if(bitCount == 1) { /* Hack. */ @@ -2739,10 +2729,8 @@ _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm, int cx, int cy) result = TRUE; - failed: - ReleaseDC(0, xdc); - LocalFree((HLOCAL)lpBitsOrg); - LocalFree((HLOCAL)data); +failed: + Free(data); return result; } @@ -2771,6 +2759,8 @@ ImageList_Write (HIMAGELIST himl, LPSTREAM pstm) ILHEAD ilHead; int i; + TRACE("%p %p\n", himl, pstm); + if (!is_valid(himl)) return FALSE; @@ -2787,16 +2777,19 @@ ImageList_Write (HIMAGELIST himl, LPSTREAM pstm) ilHead.ovls[i] = himl->nOvlIdx[i]; } + TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n", + ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage); + if(!SUCCEEDED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL))) return FALSE; /* write the bitmap */ - if(!_write_bitmap(himl->hbmImage, pstm, himl->cx, himl->cy)) + if(!_write_bitmap(himl->hbmImage, pstm)) return FALSE; /* write the mask if we have one */ if(himl->flags & ILC_MASK) { - if(!_write_bitmap(himl->hbmMask, pstm, himl->cx, himl->cy)) + if(!_write_bitmap(himl->hbmMask, pstm)) return FALSE; } @@ -2817,7 +2810,8 @@ static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count, UINT VOID* bits; BITMAPINFO *bmi; - TRACE("Creating DIBSection: %d Bits per Pixel\n", himl->uBitsPixel); + TRACE("Creating DIBSection %d x %d, %d Bits per Pixel\n", + sz.cx, sz.cy, himl->uBitsPixel); if (himl->uBitsPixel <= ILC_COLOR8) {