bitmap.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,776 行 · 第 1/4 页
CPP
1,776 行
////////////////////////////////////////////////////////////////////////////
// Name: bitmap.cpp
// Purpose: wxBitmap
// Author: Julian Smart
// Modified by:
// Created: 04/01/98
// RCS-ID: $Id: bitmap.cpp,v 1.134.2.3 2006/01/21 16:46:43 JS Exp $
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "bitmap.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <stdio.h>
#include "wx/list.h"
#include "wx/utils.h"
#include "wx/app.h"
#include "wx/palette.h"
#include "wx/dcmemory.h"
#include "wx/bitmap.h"
#include "wx/icon.h"
#endif
#include "wx/msw/private.h"
#include "wx/log.h"
#if wxUSE_WXDIB
#include "wx/msw/dib.h"
#endif
#include "wx/image.h"
#include "wx/xpmdecod.h"
#ifdef wxHAVE_RAW_BITMAP
#include "wx/rawbmp.h"
#endif
// missing from mingw32 header
#ifndef CLR_INVALID
#define CLR_INVALID ((COLORREF)-1)
#endif // no CLR_INVALID
// ----------------------------------------------------------------------------
// Bitmap data
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxBitmapRefData : public wxGDIImageRefData
{
public:
wxBitmapRefData();
wxBitmapRefData(const wxBitmapRefData& data);
virtual ~wxBitmapRefData() { Free(); }
virtual void Free();
// set the mask object to use as the mask, we take ownership of it
void SetMask(wxMask *mask)
{
delete m_bitmapMask;
m_bitmapMask = mask;
}
// set the HBITMAP to use as the mask
void SetMask(HBITMAP hbmpMask)
{
SetMask(new wxMask((WXHBITMAP)hbmpMask));
}
// return the mask
wxMask *GetMask() const { return m_bitmapMask; }
public:
#if wxUSE_PALETTE
wxPalette m_bitmapPalette;
#endif // wxUSE_PALETTE
// MSW-specific
// ------------
#ifdef __WXDEBUG__
// this field is solely for error checking: we detect selecting a bitmap
// into more than one DC at once or deleting a bitmap still selected into a
// DC (both are serious programming errors under Windows)
wxDC *m_selectedInto;
#endif // __WXDEBUG__
#if wxUSE_WXDIB
// when GetRawData() is called for a DDB we need to convert it to a DIB
// first to be able to provide direct access to it and we cache that DIB
// here and convert it back to DDB when UngetRawData() is called
wxDIB *m_dib;
#endif
// true if we have alpha transparency info and can be drawn using
// AlphaBlend()
bool m_hasAlpha;
// true if our HBITMAP is a DIB section, false if it is a DDB
bool m_isDIB;
private:
// optional mask for transparent drawing
wxMask *m_bitmapMask;
// not implemented
wxBitmapRefData& operator=(const wxBitmapRefData&);
};
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
// decide whether we should create a DIB or a DDB for the given parameters
//
// NB: we always use DIBs under Windows CE as this is much simpler (even if
// also less efficient...) and we obviously can't use them if there is no
// DIB support compiled in at all
#ifdef __WXWINCE__
static inline bool wxShouldCreateDIB(int, int, int, WXHDC) { return true; }
#define ALWAYS_USE_DIB
#elif !wxUSE_WXDIB
// no sense in defining wxShouldCreateDIB() as we can't compile code
// executed if it is true, so we have to use #if's anyhow
#define NEVER_USE_DIB
#else // wxUSE_WXDIB && !__WXWINCE__
static inline bool wxShouldCreateDIB(int w, int h, int d, WXHDC hdc)
{
// here is the logic:
//
// (a) if hdc is specified, the caller explicitly wants DDB
// (b) otherwise, create a DIB if depth >= 24 (we don't support 16bpp
// or less DIBs anyhow)
// (c) finally, create DIBs under Win9x even if the depth hasn't been
// explicitly specified but the current display depth is 24 or
// more and the image is "big", i.e. > 16Mb which is the
// theoretical limit for DDBs under Win9x
//
// consequences (all of which seem to make sense):
//
// (i) by default, DDBs are created (depth == -1 usually)
// (ii) DIBs can be created by explicitly specifying the depth
// (iii) using a DC always forces creating a DDB
return !hdc &&
(d >= 24 ||
(d == -1 &&
wxDIB::GetLineSize(w, wxDisplayDepth())*h > 16*1024*1024));
}
#define SOMETIMES_USE_DIB
#endif // different DIB usage scenarious
// ----------------------------------------------------------------------------
// wxBitmapRefData
// ----------------------------------------------------------------------------
wxBitmapRefData::wxBitmapRefData()
{
#ifdef __WXDEBUG__
m_selectedInto = NULL;
#endif
m_bitmapMask = NULL;
m_hBitmap = (WXHBITMAP) NULL;
#if wxUSE_WXDIB
m_dib = NULL;
#endif
m_isDIB =
m_hasAlpha = false;
}
wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData& data)
: wxGDIImageRefData(data)
{
#ifdef __WXDEBUG__
m_selectedInto = NULL;
#endif
// can't copy the mask as the other bitmap destroys it
m_bitmapMask = NULL;
wxASSERT_MSG( !data.m_isDIB,
_T("can't copy bitmap locked for raw access!") );
m_isDIB = false;
m_hasAlpha = data.m_hasAlpha;
}
void wxBitmapRefData::Free()
{
wxASSERT_MSG( !m_selectedInto,
wxT("deleting bitmap still selected into wxMemoryDC") );
#if wxUSE_WXDIB
wxASSERT_MSG( !m_dib, _T("forgot to call wxBitmap::UngetRawData()!") );
#endif
if ( m_hBitmap)
{
if ( !::DeleteObject((HBITMAP)m_hBitmap) )
{
wxLogLastError(wxT("DeleteObject(hbitmap)"));
}
}
delete m_bitmapMask;
m_bitmapMask = NULL;
}
// ----------------------------------------------------------------------------
// wxBitmap creation
// ----------------------------------------------------------------------------
// this function should be called from all wxBitmap ctors
void wxBitmap::Init()
{
// m_refData = NULL; done in the base class ctor
}
wxGDIImageRefData *wxBitmap::CreateData() const
{
return new wxBitmapRefData;
}
wxObjectRefData *wxBitmap::CloneRefData(const wxObjectRefData *dataOrig) const
{
const wxBitmapRefData *
data = wx_static_cast(const wxBitmapRefData *, dataOrig);
if ( !data )
return NULL;
wxBitmap *self = wx_const_cast(wxBitmap *, this);
#if wxUSE_WXDIB
// copy the other bitmap
if ( data->m_hBitmap )
{
wxDIB dib((HBITMAP)(data->m_hBitmap));
self->CopyFromDIB(dib);
}
else
#endif // wxUSE_WXDIB
{
// don't copy the bitmap data, but do copy the size, depth, ...
self->m_refData = new wxBitmapRefData(*data);
}
return m_refData;
}
#ifdef __WIN32__
bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon)
{
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
// it may be either HICON or HCURSOR
HICON hicon = (HICON)icon.GetHandle();
ICONINFO iconInfo;
if ( !::GetIconInfo(hicon, &iconInfo) )
{
wxLogLastError(wxT("GetIconInfo"));
return false;
}
wxBitmapRefData *refData = new wxBitmapRefData;
m_refData = refData;
int w = icon.GetWidth(),
h = icon.GetHeight();
refData->m_width = w;
refData->m_height = h;
refData->m_depth = wxDisplayDepth();
refData->m_hBitmap = (WXHBITMAP)iconInfo.hbmColor;
#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; idx<w*h*4; idx+=4)
{
if (pixels[idx+3] != 0)
{
// If there is an alpha byte that is non-zero then set the
// alpha flag and bail out of the loop.
refData->m_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);
return true;
#else
wxUnusedVar(icon);
return false;
#endif
}
#endif // Win32
bool wxBitmap::CopyFromCursor(const wxCursor& cursor)
{
UnRef();
if ( !cursor.Ok() )
return false;
return CopyFromIconOrCursor(cursor);
}
bool wxBitmap::CopyFromIcon(const wxIcon& icon)
{
UnRef();
if ( !icon.Ok() )
return false;
return CopyFromIconOrCursor(icon);
}
#ifndef NEVER_USE_DIB
bool wxBitmap::CopyFromDIB(const wxDIB& dib)
{
wxCHECK_MSG( dib.IsOk(), false, _T("invalid DIB in CopyFromDIB") );
#ifdef SOMETIMES_USE_DIB
HBITMAP hbitmap = dib.CreateDDB();
if ( !hbitmap )
return false;
#else // ALWAYS_USE_DIB
HBITMAP hbitmap = ((wxDIB &)dib).Detach(); // const_cast
#endif // SOMETIMES_USE_DIB/ALWAYS_USE_DIB
UnRef();
wxBitmapRefData *refData = new wxBitmapRefData;
m_refData = refData;
refData->m_width = dib.GetWidth();
refData->m_height = dib.GetHeight();
refData->m_depth = dib.GetDepth();
refData->m_hBitmap = (WXHBITMAP)hbitmap;
#if wxUSE_PALETTE
wxPalette *palette = dib.CreatePalette();
if ( palette )
{
refData->m_bitmapPalette = *palette;
}
delete palette;
#endif // wxUSE_PALETTE
return true;
}
#endif // NEVER_USE_DIB
wxBitmap::~wxBitmap()
{
}
wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
{
Init();
#ifndef __WXMICROWIN__
wxBitmapRefData *refData = new wxBitmapRefData;
m_refData = refData;
refData->m_width = width;
refData->m_height = height;
refData->m_depth = depth;
char *data;
if ( depth == 1 )
{
// 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 reversed!
const size_t bytesPerLine = (width + 7) / 8;
const size_t padding = bytesPerLine % 2;
const size_t len = height * ( padding + bytesPerLine );
data = (char *)malloc(len);
const char *src = bits;
char *dst = data;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?