wxMSW:
+- possibility to use DIBs for wxBitmap implementation (Derry Bryson)
- wxStaticBitmap doesn't stretch its bitmap any longer (like other ports)
- support for accelerator keys in the owner drawn menus (Derry Bryson)
- wxCaret::SetSize() doesn't hide the caret any longer as it used to
// optional mask for transparent drawing
wxMask *m_bitmapMask;
+
+#if wxUSE_DIB_FOR_BITMAP
+ WXHANDLE m_hFileMap; // file mapping handle for large DIB's
+#endif
};
// ----------------------------------------------------------------------------
void SetHBITMAP(WXHBITMAP bmp) { SetHandle((WXHANDLE)bmp); }
WXHBITMAP GetHBITMAP() const { return (WXHBITMAP)GetHandle(); }
+#if wxUSE_DIB_FOR_BITMAP
+ void SetHFileMap(WXHANDLE hFileMap) { GetBitmapData()->m_hFileMap = hFileMap; }
+ WXHANDLE GetHFileMap() const { return GetBitmapData()->m_hFileMap; }
+#endif // wxUSE_DIB_FOR_BITMAP
+
void SetSelectedInto(wxDC *dc) { if (GetBitmapData()) GetBitmapData()->m_selectedInto = dc; }
wxDC *GetSelectedInto() const { return (GetBitmapData() ? GetBitmapData()->m_selectedInto : (wxDC*) NULL); }
bool CreateFromImage(const wxImage& image, int depth);
#endif // wxUSE_IMAGE
+#if wxUSE_DIB_FOR_BITMAP
+ void *CreateDIB(int width, int height, int depth);
+ void CopyDIBLine(void* src, void* dest, int count) const;
+#endif
+
private:
#ifdef __WIN32__
// common part of CopyFromIcon/CopyFromCursor for Win32
// wxDC cacheing implementation
#define wxUSE_DC_CACHEING 1
+// Set this to 1 to enable the use of DIB's for wxBitmap to support
+// bitmaps > 16MB on Win95/98/Me. Set to 0 to use DDB's only.
+#define wxUSE_DIB_FOR_BITMAP 0
+
// ----------------------------------------------------------------------------
// common dialogs
// ----------------------------------------------------------------------------
-/////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
// Name: bitmap.cpp
// Purpose: wxBitmap
// Author: Julian Smart
m_numColors = 0;
m_bitmapMask = NULL;
m_hBitmap = (WXHBITMAP) NULL;
+#if wxUSE_DIB_FOR_BITMAP
+ m_hFileMap = 0;
+#endif
}
void wxBitmapRefData::Free()
#endif
}
+#if wxUSE_DIB_FOR_BITMAP
+ if(m_hFileMap)
+ {
+ ::CloseHandle((void*)m_hFileMap);
+ m_hFileMap = 0;
+ }
+#endif
+
delete m_bitmapMask;
m_bitmapMask = NULL;
}
m_refData = new wxBitmapRefData;
- GetBitmapData()->m_width = w;
- GetBitmapData()->m_height = h;
- GetBitmapData()->m_depth = d;
-
- HBITMAP hbmp;
-#ifndef __WXMICROWIN__
- if ( d > 0 )
+#if wxUSE_DIB_FOR_BITMAP
+ if ( w && h && d >= 16 )
{
- hbmp = ::CreateBitmap(w, h, 1, d, NULL);
- if ( !hbmp )
- {
- wxLogLastError(wxT("CreateBitmap"));
- }
+ if ( !CreateDIB(w, h, d) )
+ return FALSE;
}
else
-#endif
+#endif // wxUSE_DIB_FOR_BITMAP
{
- ScreenHDC dc;
- hbmp = ::CreateCompatibleBitmap(dc, w, h);
- if ( !hbmp )
+ GetBitmapData()->m_width = w;
+ GetBitmapData()->m_height = h;
+ GetBitmapData()->m_depth = d;
+
+ HBITMAP hbmp;
+#ifndef __WXMICROWIN__
+ if ( d > 0 )
+ {
+ hbmp = ::CreateBitmap(w, h, 1, d, NULL);
+ if ( !hbmp )
+ {
+ wxLogLastError(wxT("CreateBitmap"));
+ }
+ }
+ else
+#endif // !__WXMICROWIN__
{
- wxLogLastError(wxT("CreateCompatibleBitmap"));
+ ScreenHDC dc;
+ hbmp = ::CreateCompatibleBitmap(dc, w, h);
+ if ( !hbmp )
+ {
+ wxLogLastError(wxT("CreateCompatibleBitmap"));
+ }
+
+ GetBitmapData()->m_depth = wxDisplayDepth();
}
- GetBitmapData()->m_depth = wxDisplayDepth();
+ SetHBITMAP((WXHBITMAP)hbmp);
}
- SetHBITMAP((WXHBITMAP)hbmp);
-
#if WXWIN_COMPATIBILITY_2
GetBitmapData()->m_ok = hbmp != 0;
#endif // WXWIN_COMPATIBILITY_2
+
return Ok();
}
+#if wxUSE_DIB_FOR_BITMAP
+
+void *wxBitmap::CreateDIB(int width, int height, int depth)
+{
+ void *dibBits;
+ const int infosize = sizeof(BITMAPINFOHEADER);
+
+ BITMAPINFO *info = (BITMAPINFO *)malloc(infosize);
+ if ( info )
+ {
+ memset(info, 0, infosize);
+
+ info->bmiHeader.biSize = infosize;
+ info->bmiHeader.biWidth = width;
+ info->bmiHeader.biHeight = height;
+ info->bmiHeader.biPlanes = 1;
+ info->bmiHeader.biBitCount = depth;
+ info->bmiHeader.biCompression = BI_RGB;
+ info->bmiHeader.biSizeImage =
+ (((width * (depth/8)) + sizeof(DWORD) - 1) /
+ sizeof(DWORD) * sizeof(DWORD)) * height;
+ info->bmiHeader.biXPelsPerMeter = 0;
+ info->bmiHeader.biYPelsPerMeter = 0;
+ info->bmiHeader.biClrUsed = 0;
+ info->bmiHeader.biClrImportant = 0;
+ GetBitmapData()->m_hFileMap =
+ (WXHANDLE)::CreateFileMapping
+ (
+ INVALID_HANDLE_VALUE,
+ 0,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ info->bmiHeader.biSizeImage,
+ 0
+ );
+
+ // No need to report an error here. If it fails, we just won't use a
+ // file mapping and CreateDIBSection will just allocate memory for us.
+ GetBitmapData()->m_handle =
+ (WXHANDLE)::CreateDIBSection
+ (
+ 0,
+ info,
+ DIB_RGB_COLORS,
+ &dibBits,
+ (HANDLE)GetBitmapData()->m_hFileMap,
+ 0
+ );
+
+ if ( !GetBitmapData()->m_handle )
+ wxLogLastError(wxT("CreateDIBSection"));
+
+ SetWidth(width);
+ SetHeight(height);
+ SetDepth(depth);
+
+ free(info);
+ }
+ else
+ {
+ wxFAIL_MSG( wxT("could not allocate memory for DIB header") );
+
+ dibBits = NULL;
+ }
+
+ return dibBits;
+}
+
+#endif // wxUSE_DIB_FOR_BITMAP
+
// ----------------------------------------------------------------------------
// wxImage to/from conversions
// ----------------------------------------------------------------------------
// so the 'depth' argument is ignored.
HDC hScreenDC = ::GetDC(NULL);
- // printf("Screen planes = %d, bpp = %d\n", hScreenDC->psd->planes, hScreenDC->psd->bpp);
int screenDepth = ::GetDeviceCaps(hScreenDC, BITSPIXEL);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hScreenDC, image.GetWidth(), image.GetHeight());
return TRUE;
-#else
+#else // !__WXMICROWIN__
wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
m_refData = new wxBitmapRefData();
+#if wxUSE_DIB_FOR_BITMAP
+ int h = image.GetHeight();
+ int w = image.GetWidth();
+ unsigned char *dibBits = (unsigned char*)CreateDIB(w, h, 24);
+ if ( !dibBits )
+ return FALSE;
+
+ // DIBs are stored in bottom to top order so we need to copy bits line by
+ // line and starting from the end
+ const int srcBytesPerLine = w * 3;
+ const int dstBytesPerLine = (srcBytesPerLine + sizeof(DWORD) - 1) /
+ sizeof(DWORD) * sizeof(DWORD);
+ const unsigned char *src = image.GetData() + ((h - 1) * srcBytesPerLine);
+ for ( int i = 0; i < h; i++ )
+ {
+ // copy one DIB line
+ int x = w;
+ const unsigned char *rgbBits = src;
+ while ( x-- )
+ {
+ // also, the order of RGB is inversed for DIBs
+ *dibBits++ = rgbBits[2];
+ *dibBits++ = rgbBits[1];
+ *dibBits++ = rgbBits[0];
+
+ rgbBits += 3;
+ }
+
+ // pass to the next line
+ src -= srcBytesPerLine;
+ dibBits += dstBytesPerLine - srcBytesPerLine;
+ }
+
+ if ( image.HasMask() )
+ {
+ SetMask(new wxMask(*this, wxColour(image.GetMaskRed(),
+ image.GetMaskGreen(),
+ image.GetMaskBlue())));
+ }
+#else // wxUSE_DIB_FOR_BITMAP
// sizeLimit is the MS upper limit for the DIB size
#ifdef WIN32
int sizeLimit = 1024*768*3;
#else
- int sizeLimit = 0x7fff ;
+ int sizeLimit = 0x7fff;
#endif
// width and height of the device-dependent bitmap
::ReleaseDC(NULL, hdc);
free(lpDIBh);
free(lpBits);
+#endif // wxUSE_DIB_FOR_BITMAP
#if WXWIN_COMPATIBILITY_2
// check the wxBitmap object
#endif // WXWIN_COMPATIBILITY_2
return TRUE;
-#endif
+#endif // __WXMICROWIN__/!__WXMICROWIN__
}
wxImage wxBitmap::ConvertToImage() const
return image;
-#else // __MICROWIN__
-
+#else // !__WXMICROWIN__
wxImage image;
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
free(lpBits);
return image;
-#endif
+#endif // __WXMICROWIN__/!__WXMICROWIN__
}
#endif // wxUSE_IMAGE
if ( ::GetDeviceCaps(GetHdc(), RASTERCAPS) & RC_STRETCHDIB )
{
- BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) );
- memset( info, 0, sizeof( BITMAPINFOHEADER ) );
+#if wxUSE_DIB_FOR_BITMAP
+ if(bmp.GetHFileMap()) // we already have a dib
+ {
+ DIBSECTION dib;
+ if ( ::GetObject(GetHbitmapOf(bmp),
+ sizeof(dib),
+ &dib) == sizeof(dib) )
+ {
+ if ( ::StretchDIBits
+ (
+ GetHdc(),
+ x, y,
+ width, height,
+ 0, 0,
+ width, height,
+ dib.dsBm.bmBits,
+ (LPBITMAPINFO)&dib.dsBmih,
+ DIB_RGB_COLORS,
+ SRCCOPY
+ ) == GDI_ERROR )
+ {
+ wxLogLastError(wxT("StretchDIBits"));
+ }
+ }
+ else
+ {
+ wxLogLastError(wxT("GetObject"));
+ }
+ }
+ else
+#endif // wxUSE_DIB_FOR_BITMAP
+ {
+ BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) );
+ memset( info, 0, sizeof( BITMAPINFOHEADER ) );
#if wxUSE_DRAWBITMAP_24BITS
- int iBitsSize = (((width * 3) + 3 ) & ~3 ) * height;
+ int iBitsSize = (((width * 3) + 3 ) & ~3 ) * height;
#else
- int iBitsSize = ((width + 3 ) & ~3 ) * height ;
+ int iBitsSize = ((width + 3 ) & ~3 ) * height ;
#endif
- void* bits = malloc( iBitsSize );
+ void* bits = malloc( iBitsSize );
- info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
- info->bmiHeader.biWidth = width;
- info->bmiHeader.biHeight = height;
- info->bmiHeader.biPlanes = 1;
+ info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+ info->bmiHeader.biWidth = width;
+ info->bmiHeader.biHeight = height;
+ info->bmiHeader.biPlanes = 1;
#if wxUSE_DRAWBITMAP_24BITS
- info->bmiHeader.biBitCount = 24;
+ info->bmiHeader.biBitCount = 24;
#else
- info->bmiHeader.biBitCount = 8;
-#endif
- info->bmiHeader.biCompression = BI_RGB;
-
- ScreenHDC display;
- if ( GetDIBits(display, GetHbitmapOf(bmp), 0,
- bmp.GetHeight(), bits, info,
- DIB_RGB_COLORS) )
- {
- if ( ::StretchDIBits(GetHdc(), x, y,
- width, height,
- 0 , 0, width, height,
- bits, info,
- DIB_RGB_COLORS, SRCCOPY) == GDI_ERROR )
+ info->bmiHeader.biBitCount = 8;
+#endif
+ info->bmiHeader.biCompression = BI_RGB;
+
+ ScreenHDC display;
+ if ( GetDIBits(display, GetHbitmapOf(bmp), 0,
+ bmp.GetHeight(), bits, info,
+ DIB_RGB_COLORS) )
{
- wxLogLastError(wxT("StretchDIBits"));
+ if ( ::StretchDIBits(GetHdc(), x, y,
+ width, height,
+ 0 , 0, width, height,
+ bits, info,
+ DIB_RGB_COLORS, SRCCOPY) == GDI_ERROR )
+ {
+ wxLogLastError(wxT("StretchDIBits"));
+ }
}
- }
- free(bits);
- free(info);
+ free(bits);
+ free(info);
+ }
}
else // no support for StretchDIBits()
{
if ( useMask )
{
- // If we are printing source colours are screen colours
- // not printer colours and so we need copy the bitmap
- // pixel by pixel.
+ // If we are printing source colours are screen colours not printer
+ // colours and so we need copy the bitmap pixel by pixel.
RECT rect;
HDC dc_src = GetHdcOf(*source);
HDC dc_mask = ::CreateCompatibleDC(dc_src);
wxBitmap& bmp = source->GetSelectedBitmap();
int width = bmp.GetWidth(),
height = bmp.GetHeight();
+#if wxUSE_DIB_FOR_BITMAP
+ if(bmp.GetHFileMap()) // we already have a dib
+ {
+ DIBSECTION dib;
+ if( ::GetObject(GetHbitmapOf(bmp),
+ sizeof(dib),
+ &dib) == sizeof(dib) )
+ {
+ if ( ::StretchDIBits
+ (
+ GetHdc(),
+ xdest, ydest,
+ width, height,
+ xsrc, ysrc,
+ width, height,
+ dib.dsBm.bmBits,
+ (LPBITMAPINFO)&dib.dsBmih,
+ DIB_RGB_COLORS,
+ SRCCOPY
+ ) == GDI_ERROR )
+ {
+ wxLogLastError(wxT("StretchDIBits"));
+ }
+ }
+ else
+ {
+ wxLogLastError(wxT("GetObject"));
+ }
+ }
+ else
+#endif // wxUSE_DIB_FOR_BITMAP
+ {
+ BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) );
+#if wxUSE_DRAWBITMAP_24BITS
+ int iBitsSize = (((width * 3) + 3 ) & ~3 ) * height;
+#else
+ int iBitsSize = ((width + 3 ) & ~3 ) * height ;
+#endif
- BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) );
- int iBitsSize = ((width + 3 ) & ~3 ) * height;
-
- void* bits = malloc( iBitsSize );
+ void* bits = malloc( iBitsSize );
- memset( info , 0 , sizeof( BITMAPINFOHEADER ) );
+ memset( info , 0 , sizeof( BITMAPINFOHEADER ) );
- info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
- info->bmiHeader.biWidth = width;
- info->bmiHeader.biHeight = height;
- info->bmiHeader.biPlanes = 1;
- info->bmiHeader.biBitCount = 8;
- info->bmiHeader.biCompression = BI_RGB;
+ info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+ info->bmiHeader.biWidth = width;
+ info->bmiHeader.biHeight = height;
+ info->bmiHeader.biPlanes = 1;
+#if wxUSE_DRAWBITMAP_24BITS
+ info->bmiHeader.biBitCount = 24;
+#else
+ info->bmiHeader.biBitCount = 8;
+#endif
+ info->bmiHeader.biCompression = BI_RGB;
- ScreenHDC display;
- if ( !::GetDIBits(display, GetHbitmapOf(bmp), 0,
- height, bits, info, DIB_RGB_COLORS) )
- {
- wxLogLastError(wxT("GetDIBits"));
+ ScreenHDC display;
+ if ( !::GetDIBits(display, GetHbitmapOf(bmp), 0,
+ height, bits, info, DIB_RGB_COLORS) )
+ {
+ wxLogLastError(wxT("GetDIBits"));
- success = FALSE;
- }
+ success = FALSE;
+ }
- if ( success )
- {
- success = ::StretchDIBits(GetHdc(), xdest, ydest,
- width, height,
- xsrc, ysrc,
- width, height,
- bits, info ,
- DIB_RGB_COLORS,
- SRCCOPY) != GDI_ERROR;
- if ( !success )
+ if ( success )
{
- wxLogLastError(wxT("StretchDIBits"));
+ success = ::StretchDIBits(GetHdc(), xdest, ydest,
+ width, height,
+ xsrc, ysrc,
+ width, height,
+ bits, info ,
+ DIB_RGB_COLORS,
+ SRCCOPY) != GDI_ERROR;
+ if ( !success )
+ {
+ wxLogLastError(wxT("StretchDIBits"));
+ }
}
- }
- free(bits);
- free(info);
+ free(bits);
+ free(info);
+ }
}
else // no support for StretchDIBits
{
- // as we are printing, source colours are screen colours not printer
- // colours and so we need copy the bitmap pixel by pixel.
+ // as we are printing, source colours are screen colours not
+ // printer colours and so we need copy the bitmap pixel by pixel.
HDC dc_src = GetHdcOf(*source);
RECT rect;
for (int y = 0; y < height; y++)
{
- // This is Stefan Csomor's optimisation, where identical adjacent
- // pixels are drawn together.
+ // optimization: draw identical adjacent pixels together.
for (int x = 0; x < width; x++)
{
COLORREF col = ::GetPixel(dc_src, x, y);