From 7b46ecac6415b5c9d76bfca160163aa5dbfd0256 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Thu, 3 Sep 1998 07:34:26 +0000 Subject: [PATCH] Dang, can't remember what I changed now git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@650 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/bitmap.h | 13 +++++ include/wx/msw/dc.h | 4 ++ src/msw/bitmap.cpp | 107 +++++++++++++++++++++++++++++++++++++++- src/msw/dc.cpp | 6 +++ src/msw/dcmemory.cpp | 15 +++++- 5 files changed, 141 insertions(+), 4 deletions(-) diff --git a/include/wx/msw/bitmap.h b/include/wx/msw/bitmap.h index a8c9c2507b..200f9705ee 100644 --- a/include/wx/msw/bitmap.h +++ b/include/wx/msw/bitmap.h @@ -197,6 +197,19 @@ public: inline wxDC *GetSelectedInto(void) const { return (M_BITMAPDATA ? M_BITMAPDATA->m_selectedInto : NULL); } bool FreeResource(bool force = FALSE); + // Creates a bitmap that matches the device context's depth, from + // an arbitray bitmap. At present, the original bitmap must have an + // associated palette. (TODO: use a default palette if no palette exists.) + // This function is necessary for you to Blit an arbitrary bitmap (which may have + // the wrong depth). wxDC::SelectObject will compare the depth of the bitmap + // with the DC's depth, and create a new bitmap if the depths differ. + // Eventually we should perhaps make this a public API function so that + // an app can efficiently produce bitmaps of the correct depth. + // The Windows solution is to use SetDibBits to blit an arbotrary DIB directly to a DC, but + // this is too Windows-specific, hence this solution of quietly converting the wxBitmap. + // Contributed by Frederic Villeneuve + wxBitmap GetBitmapForDC(wxDC& dc) const; + }; #endif // _WX_BITMAP_H_ diff --git a/include/wx/msw/dc.h b/include/wx/msw/dc.h index ab4d2b1c87..94e313b973 100644 --- a/include/wx/msw/dc.h +++ b/include/wx/msw/dc.h @@ -261,6 +261,10 @@ public: GetClippingBox(&x, &y, &w, &h); rect.x = x; rect.y = y; rect.width = w; rect.height = h; } + // This should probably be made available on other platforms + int wxDC::GetDepth(void) const ; + +// Implementation virtual void SetRop(WXHDC cdc); virtual void DoClipping(WXHDC cdc); virtual void SelectOldObjects(WXHDC dc); diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index d3ed8bc019..a7c0cb8e1d 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -379,6 +379,47 @@ wxBitmapHandler *wxBitmap::FindHandler(long bitmapType) return NULL; } +// New Create/FreeDIB functions since ones in dibutils.cpp are confusing +static long createDIB(long xSize, long ySize, long bitsPerPixel, + HPALETTE hPal, LPBITMAPINFO* lpDIBHeader); +static long freeDIB(LPBITMAPINFO lpDIBHeader); + +// Creates a bitmap that matches the device context, from +// an arbitray bitmap. At present, the original bitmap must have an +// associated palette. TODO: use a default palette if no palette exists. +// Contributed by Frederic Villeneuve +wxBitmap wxBitmap::GetBitmapForDC(wxDC& dc) const +{ + wxMemoryDC memDC; + wxBitmap tmpBitmap(this->GetWidth(), this->GetHeight(), dc.GetDepth()); + HPALETTE hPal = NULL; + LPBITMAPINFO lpDib; + void *lpBits = NULL; + + wxASSERT( this->GetPalette() && this->GetPalette()->Ok() && (this->GetPalette()->GetHPALETTE() != NULL) ); + + tmpBitmap.SetPalette(this->GetPalette()); + memDC.SelectObject(tmpBitmap); + memDC.SetPalette(this->GetPalette()); + + hPal = (HPALETTE) this->GetPalette()->GetHPALETTE(); + + // set the height negative because in a DIB the order of the lines is reversed + createDIB(this->GetWidth(), -this->GetHeight(), this->GetDepth(), hPal, &lpDib); + + lpBits = malloc(lpDib->bmiHeader.biSizeImage); + + ::GetBitmapBits((HBITMAP)GetHBITMAP(), lpDib->bmiHeader.biSizeImage, lpBits); + + ::SetDIBitsToDevice((HDC) memDC.GetHDC(), 0, 0, this->GetWidth(), this->GetHeight(), + 0, 0, 0, this->GetHeight(), lpBits, lpDib, DIB_RGB_COLORS); + + free(lpBits); + + freeDIB(lpDib); + return (tmpBitmap); +} + /* * wxMask */ @@ -573,7 +614,7 @@ bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long GetObject((HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap, sizeof(BITMAP), (LPSTR) &bm); M_BITMAPHANDLERDATA->m_width = bm.bmWidth; M_BITMAPHANDLERDATA->m_height = bm.bmHeight; - M_BITMAPHANDLERDATA->m_depth = bm.bmPlanes; + M_BITMAPHANDLERDATA->m_depth = bm.bmBitsPixel; return TRUE; } @@ -821,4 +862,66 @@ void wxBitmap::InitStandardHandlers(void) AddHandler(new wxXPMDataHandler); AddHandler(new wxICOResourceHandler); AddHandler(new wxICOFileHandler); -} \ No newline at end of file +} + +static long createDIB(long xSize, long ySize, long bitsPerPixel, + HPALETTE hPal, LPBITMAPINFO* lpDIBHeader) +{ + unsigned long i, headerSize; + LPBITMAPINFO lpDIBheader = NULL; + LPPALETTEENTRY lpPe = NULL; + + + // Allocate space for a DIB header + headerSize = (sizeof(BITMAPINFOHEADER) + (256 * sizeof(PALETTEENTRY))); + lpDIBheader = (BITMAPINFO *) malloc(headerSize); + lpPe = (PALETTEENTRY *)((BYTE*)lpDIBheader + sizeof(BITMAPINFOHEADER)); + + GetPaletteEntries(hPal, 0, 256, lpPe); + + + memset(lpDIBheader, 0x00, sizeof(BITMAPINFOHEADER)); + + + // Fill in the static parts of the DIB header + lpDIBheader->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + lpDIBheader->bmiHeader.biWidth = xSize; + lpDIBheader->bmiHeader.biHeight = ySize; + lpDIBheader->bmiHeader.biPlanes = 1; + + // 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.biClrUsed = 256; + + + // Initialize the DIB palette + for (i = 0; i < 256; i++) { + lpDIBheader->bmiColors[i].rgbReserved = lpPe[i].peFlags; + lpDIBheader->bmiColors[i].rgbRed = lpPe[i].peRed; + lpDIBheader->bmiColors[i].rgbGreen = lpPe[i].peGreen; + lpDIBheader->bmiColors[i].rgbBlue = lpPe[i].peBlue; + } + + *lpDIBHeader = lpDIBheader; + + + return (0); + +} + + + +static long freeDIB(LPBITMAPINFO lpDIBHeader) +{ + + if (lpDIBHeader != NULL) { + free(lpDIBHeader); + } + + return (0); +} + + diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index f4201d6e49..432769c8c0 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1441,3 +1441,9 @@ void wxDC::GetTextExtent(const wxString& string, float *x, float *y, } #endif +int wxDC::GetDepth(void) const +{ + return (int) ::GetDeviceCaps((HDC) m_hDC,BITSPIXEL); +} + + diff --git a/src/msw/dcmemory.cpp b/src/msw/dcmemory.cpp index a89b217bcb..243861facc 100644 --- a/src/msw/dcmemory.cpp +++ b/src/msw/dcmemory.cpp @@ -84,8 +84,19 @@ void wxMemoryDC::SelectObject(const wxBitmap& bitmap) wxFatalError("Error in wxMemoryDC::SelectObject\nBitmap is selected in another wxMemoryDC.\nDelete the first wxMemoryDC or use SelectObject(NULL)"); return; } - - m_selectedBitmap = bitmap; + + // Check if the bitmap has the correct depth for this device context + if (bitmap.Ok() && (bitmap.GetDepth() != GetDepth())) + { + // Make a new bitmap that has the correct depth. + wxBitmap newBitmap = bitmap.GetBitmapForDC(* this); + + m_selectedBitmap = newBitmap ; + } + else + { + m_selectedBitmap = bitmap; + } if (!m_selectedBitmap.Ok()) return; -- 2.45.2