support for using DIBs for wxBitmap implementation (patch 649866)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18524 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
f178ab7e82
commit
0becd47010
@ -31,6 +31,7 @@ wxGTK:
|
||||
|
||||
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
|
||||
|
@ -63,6 +63,10 @@ public:
|
||||
|
||||
// optional mask for transparent drawing
|
||||
wxMask *m_bitmapMask;
|
||||
|
||||
#if wxUSE_DIB_FOR_BITMAP
|
||||
WXHANDLE m_hFileMap; // file mapping handle for large DIB's
|
||||
#endif
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -177,6 +181,11 @@ public:
|
||||
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); }
|
||||
|
||||
@ -209,6 +218,11 @@ protected:
|
||||
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
|
||||
|
@ -636,6 +636,10 @@
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -1,4 +1,4 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Name: bitmap.cpp
|
||||
// Purpose: wxBitmap
|
||||
// Author: Julian Smart
|
||||
@ -81,6 +81,9 @@ wxBitmapRefData::wxBitmapRefData()
|
||||
m_numColors = 0;
|
||||
m_bitmapMask = NULL;
|
||||
m_hBitmap = (WXHBITMAP) NULL;
|
||||
#if wxUSE_DIB_FOR_BITMAP
|
||||
m_hFileMap = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxBitmapRefData::Free()
|
||||
@ -99,6 +102,14 @@ 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;
|
||||
}
|
||||
@ -341,6 +352,15 @@ bool wxBitmap::Create(int w, int h, int d)
|
||||
|
||||
m_refData = new wxBitmapRefData;
|
||||
|
||||
#if wxUSE_DIB_FOR_BITMAP
|
||||
if ( w && h && d >= 16 )
|
||||
{
|
||||
if ( !CreateDIB(w, h, d) )
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
#endif // wxUSE_DIB_FOR_BITMAP
|
||||
{
|
||||
GetBitmapData()->m_width = w;
|
||||
GetBitmapData()->m_height = h;
|
||||
GetBitmapData()->m_depth = d;
|
||||
@ -356,7 +376,7 @@ bool wxBitmap::Create(int w, int h, int d)
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif // !__WXMICROWIN__
|
||||
{
|
||||
ScreenHDC dc;
|
||||
hbmp = ::CreateCompatibleBitmap(dc, w, h);
|
||||
@ -369,13 +389,85 @@ bool wxBitmap::Create(int w, int h, int d)
|
||||
}
|
||||
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -397,7 +489,6 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
||||
// 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());
|
||||
@ -503,16 +594,56 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
||||
|
||||
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
|
||||
@ -726,6 +857,7 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
||||
::ReleaseDC(NULL, hdc);
|
||||
free(lpDIBh);
|
||||
free(lpBits);
|
||||
#endif // wxUSE_DIB_FOR_BITMAP
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2
|
||||
// check the wxBitmap object
|
||||
@ -733,7 +865,7 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
||||
#endif // WXWIN_COMPATIBILITY_2
|
||||
|
||||
return TRUE;
|
||||
#endif
|
||||
#endif // __WXMICROWIN__/!__WXMICROWIN__
|
||||
}
|
||||
|
||||
wxImage wxBitmap::ConvertToImage() const
|
||||
@ -799,8 +931,7 @@ wxImage wxBitmap::ConvertToImage() const
|
||||
|
||||
return image;
|
||||
|
||||
#else // __MICROWIN__
|
||||
|
||||
#else // !__WXMICROWIN__
|
||||
wxImage image;
|
||||
|
||||
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
|
||||
@ -925,7 +1056,7 @@ wxImage wxBitmap::ConvertToImage() const
|
||||
free(lpBits);
|
||||
|
||||
return image;
|
||||
#endif
|
||||
#endif // __WXMICROWIN__/!__WXMICROWIN__
|
||||
}
|
||||
|
||||
#endif // wxUSE_IMAGE
|
||||
|
@ -430,6 +430,38 @@ void wxPrinterDC::DoDrawBitmap(const wxBitmap &bmp,
|
||||
height = bmp.GetHeight();
|
||||
|
||||
if ( ::GetDeviceCaps(GetHdc(), RASTERCAPS) & RC_STRETCHDIB )
|
||||
{
|
||||
#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 ) );
|
||||
@ -471,6 +503,7 @@ void wxPrinterDC::DoDrawBitmap(const wxBitmap &bmp,
|
||||
free(bits);
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
else // no support for StretchDIBits()
|
||||
{
|
||||
wxMemoryDC memDC;
|
||||
@ -493,9 +526,8 @@ bool wxPrinterDC::DoBlit(wxCoord xdest, wxCoord ydest,
|
||||
|
||||
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);
|
||||
@ -528,9 +560,44 @@ bool wxPrinterDC::DoBlit(wxCoord xdest, wxCoord ydest,
|
||||
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 ) );
|
||||
int iBitsSize = ((width + 3 ) & ~3 ) * height;
|
||||
#if wxUSE_DRAWBITMAP_24BITS
|
||||
int iBitsSize = (((width * 3) + 3 ) & ~3 ) * height;
|
||||
#else
|
||||
int iBitsSize = ((width + 3 ) & ~3 ) * height ;
|
||||
#endif
|
||||
|
||||
void* bits = malloc( iBitsSize );
|
||||
|
||||
@ -540,7 +607,11 @@ bool wxPrinterDC::DoBlit(wxCoord xdest, wxCoord ydest,
|
||||
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;
|
||||
@ -570,16 +641,16 @@ bool wxPrinterDC::DoBlit(wxCoord xdest, wxCoord ydest,
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user