X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/907173e51df6d2a91d65463ddf6ce810d3fd921a..5f7348ce627157e21bec507623ebd31c1e9dc762:/src/msw/bitmap.cpp?ds=inline diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index 16e23a409d..e41a8cf197 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -310,10 +310,37 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon) refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor; - // the mask returned by GetIconInfo() is inversed compared to the usual - // wxWin convention - refData->SetMask(wxInvertMask(iconInfo.hbmMask, w, h)); - +#if wxUSE_WXDIB + // If the icon is 32 bits per pixel then it may have alpha channel data, + // although there are some icons that are 32 bpp but have no alpha... So + // convert to a DIB and manually check the 4th byte for each pixel. + BITMAP bm; + if ( ::GetObject(iconInfo.hbmColor, sizeof(BITMAP), (LPVOID)&bm) + && bm.bmBitsPixel == 32) + { + wxDIB dib(iconInfo.hbmColor); + if (dib.IsOk()) + { + unsigned char* pixels = dib.GetData(); + for (int idx=0; idxm_hasAlpha = true; + break; + } + } + } + } +#endif + if ( !refData->m_hasAlpha ) + { + // the mask returned by GetIconInfo() is inverted compared to the usual + // wxWin convention + refData->SetMask(wxInvertMask(iconInfo.hbmMask, w, h)); + } // delete the old one now as we don't need it any more ::DeleteObject(iconInfo.hbmMask); @@ -408,7 +435,7 @@ wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { // we assume that it is in XBM format which is not quite the same as // the format CreateBitmap() wants because the order of bytes in the - // line is inversed! + // line is reversed! const size_t bytesPerLine = (width + 7) / 8; const size_t padding = bytesPerLine % 2; const size_t len = height * ( padding + bytesPerLine ); @@ -843,9 +870,42 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth, WXHDC hdc) // finally also set the mask if we have one if ( image.HasMask() ) { - SetMask(new wxMask(*this, wxColour(image.GetMaskRed(), - image.GetMaskGreen(), - image.GetMaskBlue()))); + const size_t len = 2*((w+15)/16); + BYTE *src = image.GetData(); + BYTE *data = new BYTE[h*len]; + memset(data, 0, h*len); + BYTE r = image.GetMaskRed(), + g = image.GetMaskGreen(), + b = image.GetMaskBlue(); + BYTE *dst = data; + for ( int y = 0; y < h; y++, dst += len ) + { + BYTE *dstLine = dst; + BYTE mask = 0x80; + for ( int x = 0; x < w; x++, src += 3 ) + { + if (src[0] != r || src[1] != g || src[2] != b) + *dstLine |= mask; + + if ( (mask >>= 1) == 0 ) + { + dstLine++; + mask = 0x80; + } + } + } + + hbitmap = ::CreateBitmap(w, h, 1, 1, data); + if ( !hbitmap ) + { + wxLogLastError(_T("CreateBitmap(mask)")); + } + else + { + SetMask(new wxMask((WXHBITMAP)hbitmap)); + } + + delete[] data; } return true; @@ -1092,6 +1152,15 @@ wxMask *wxBitmap::GetMask() const return GetBitmapData() ? GetBitmapData()->GetMask() : (wxMask *) NULL; } +wxBitmap wxBitmap::GetMaskBitmap() const +{ + wxBitmap bmp; + wxMask *mask = GetMask(); + if ( mask ) + bmp.SetHBITMAP(mask->GetMaskBitmap()); + return bmp; +} + #ifdef __WXDEBUG__ wxDC *wxBitmap::GetSelectedInto() const @@ -1181,7 +1250,7 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) HBITMAP hDIB; if ( !GetBitmapData()->m_isDIB ) { - wxCHECK_MSG( !GetBitmapData()->m_dib, FALSE, + wxCHECK_MSG( !GetBitmapData()->m_dib, NULL, _T("GetRawData() may be called only once") ); wxDIB *dib = new wxDIB(*this); @@ -1530,7 +1599,7 @@ bool wxCreateDIB(long xSize, long ySize, long bitsPerPixel, // this value must be 1, 4, 8 or 24 so PixelDepth can only be lpDIBheader->bmiHeader.biBitCount = (WORD)(bitsPerPixel); lpDIBheader->bmiHeader.biCompression = BI_RGB; - lpDIBheader->bmiHeader.biSizeImage = xSize * abs(ySize) * bitsPerPixel >> 3; + lpDIBheader->bmiHeader.biSizeImage = (xSize * abs(ySize) * bitsPerPixel) >> 3; lpDIBheader->bmiHeader.biClrUsed = 256; @@ -1570,7 +1639,23 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, return 0; } - wxMask *mask = bmp.GetMask(); + wxMask* mask; + wxBitmap newbmp; + if ( bmp.HasAlpha() ) + { + // Convert alpha to a mask. NOTE: It would be better to actually put + // the alpha into the icon instead of making a mask, but I don't have + // time to figure that out today. + wxImage img = bmp.ConvertToImage(); + img.ConvertAlphaToMask(); + newbmp = wxBitmap(img); + mask = newbmp.GetMask(); + } + else + { + mask = bmp.GetMask(); + } + if ( !mask ) { // we must have a mask for an icon, so even if it's probably incorrect, @@ -1607,7 +1692,7 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, HICON hicon = ::CreateIconIndirect(&iconInfo); - if ( !bmp.GetMask() ) + if ( !bmp.GetMask() && !bmp.HasAlpha() ) { // we created the mask, now delete it delete mask;