⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmap.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        src/mac/carbon/bitmap.cpp
// Purpose:     wxBitmap
// Author:      Stefan Csomor
// Modified by:
// Created:     1998-01-01
// RCS-ID:      $Id: bitmap.cpp,v 1.97 2006/07/17 17:54:39 MW Exp $
// Copyright:   (c) Stefan Csomor
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

#include "wx/wxprec.h"

#include "wx/bitmap.h"

#ifndef WX_PRECOMP
    #include "wx/log.h"
    #include "wx/dcmemory.h"
    #include "wx/icon.h"
    #include "wx/image.h"
#endif

#include "wx/metafile.h"
#include "wx/xpmdecod.h"

#include "wx/rawbmp.h"

IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)

#ifdef __DARWIN__
    #include <ApplicationServices/ApplicationServices.h>
#else
    #include <PictUtils.h>
#endif

#include "wx/mac/uma.h"

// Implementation Notes
// --------------------
//
// we are always working with a 32 bit deep pixel buffer
// under QuickDraw its alpha parts are going to be ignored in the GWorld,
// therefore we have a separate GWorld there for blitting the mask in

// under Quartz then content is transformed into a CGImageRef representing the same data
// which can be transferred to the GPU by the OS for fast rendering

// we don't dare use premultiplied alpha yet
#define wxMAC_USE_PREMULTIPLIED_ALPHA 0

#if wxUSE_BMPBUTTON

void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType )
{
    memset( info , 0 , sizeof(ControlButtonContentInfo) ) ;
    if ( bitmap.Ok() )
    {
        wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
        if ( bmap == NULL )
            return ;

        if ( ( bmap->HasNativeSize() && forceType == 0 ) || forceType == kControlContentIconRef )
        {
            wxBitmap scaleBmp ;
            wxBitmapRefData* bmp = bmap ;

            if ( !bmap->HasNativeSize() )
            {
                // as PICT conversion will only result in a 16x16 icon, let's attempt
                // a few scales for better results

                int w = bitmap.GetWidth() ;
                int h = bitmap.GetHeight() ;
                int sz = wxMax( w , h ) ;
                if ( sz == 24 || sz == 64 )
                {
                    scaleBmp = wxBitmap( bitmap.ConvertToImage().Scale( w * 2 , h * 2 ) ) ;
                    bmp = scaleBmp.GetBitmapData() ;
                }
            }

            info->contentType = kControlContentIconRef ;
            info->u.iconRef = bmp->GetIconRef() ;
            AcquireIconRef( info->u.iconRef ) ;
        }
#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
        else if ( forceType == kControlContentCGImageRef )
        {
            info->contentType = kControlContentCGImageRef ;
            info->u.imageRef = (CGImageRef) bmap->CGImageCreate() ;
        }
#endif
        else
        {
            info->contentType = kControlContentPictHandle ;
            info->u.picture = bmap->GetPictHandle() ;
        }
    }
}

void wxMacReleaseBitmapButton( ControlButtonContentInfo*info )
{
    if ( info->contentType == kControlContentIconRef )
    {
        ReleaseIconRef( info->u.iconRef ) ;
    }
    else if ( info->contentType == kControlNoContent )
    {
        // there's no bitmap at all, fall through silently
    }
    else if ( info->contentType == kControlContentPictHandle )
    {
        // owned by the bitmap, no release here
    }
#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
    else if ( info->contentType == kControlContentCGImageRef )
    {
        CGImageRelease( info->u.imageRef ) ;
    }
#endif
    else
    {
        wxFAIL_MSG(wxT("Unexpected bitmap type") ) ;
    }
}

#endif //wxUSE_BMPBUTTON

#define M_BITMAPDATA ((wxBitmapRefData *)m_refData)

void wxBitmapRefData::Init()
{
    m_width = 0 ;
    m_height = 0 ;
    m_depth = 0 ;
    m_ok = false ;
    m_bitmapMask = NULL ;

#ifdef __WXMAC_OSX__
    m_cgImageRef = NULL ;
#endif

    m_iconRef = NULL ;
    m_pictHandle = NULL ;
    m_hBitmap = NULL ;
    m_hMaskBitmap = NULL;
    m_maskBytesPerRow = 0 ;

    m_rawAccessCount = 0 ;
    m_hasAlpha = false;
}

wxBitmapRefData::wxBitmapRefData()
{
    Init() ;
}

wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
{
    Init() ;
    Create( w , h , d ) ;
}

bool wxBitmapRefData::Create( int w , int h , int d )
{
    m_width = wxMax(1, w);
    m_height = wxMax(1, h);
    m_depth = d ;

    m_bytesPerRow = w * 4 ;
    size_t size = m_bytesPerRow * h ;
    void* data = m_memBuf.GetWriteBuf( size ) ;
    memset( data , 0 , size ) ;
    m_memBuf.UngetWriteBuf( size ) ;

    m_hBitmap = NULL ;
    Rect rect = { 0 , 0 , m_height , m_width } ;
    verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
        (char*) data , m_bytesPerRow ) ) ;
    wxASSERT_MSG( m_hBitmap , wxT("Unable to create GWorld context") ) ;

    m_ok = ( m_hBitmap != NULL ) ;

    return m_ok ;
}

void wxBitmapRefData::UseAlpha( bool use )
{
    if ( m_hasAlpha == use )
        return ;

    m_hasAlpha = use ;
    if ( m_hasAlpha )
    {
        wxASSERT( m_hMaskBitmap == NULL ) ;

        int width = GetWidth() ;
        int height = GetHeight() ;
        m_maskBytesPerRow = ( width * 4 + 3 ) & 0xFFFFFFC ;
        size_t size = height * m_maskBytesPerRow ;
        unsigned char * data = (unsigned char * ) m_maskMemBuf.GetWriteBuf( size ) ;
        wxASSERT( data != NULL ) ;

        memset( data , 0 , size ) ;
        Rect rect = { 0 , 0 , height , width } ;
        verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hMaskBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
            (char*) data , m_maskBytesPerRow ) ) ;
        wxASSERT_MSG( m_hMaskBitmap , wxT("Unable to create GWorld context for alpha mask") ) ;
        m_maskMemBuf.UngetWriteBuf(size) ;

#if !wxMAC_USE_CORE_GRAPHICS
        UpdateAlphaMask() ;
#endif
    }
    else
    {
        DisposeGWorld( m_hMaskBitmap ) ;
        m_hMaskBitmap = NULL ;
        m_maskBytesPerRow = 0 ;
    }
}

void *wxBitmapRefData::GetRawAccess() const
{
    wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
    return m_memBuf.GetData() ;
}

void *wxBitmapRefData::BeginRawAccess()
{
    wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") ) ;
    wxASSERT( m_rawAccessCount == 0 ) ;
    wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL ,
        wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ;

    ++m_rawAccessCount ;

#ifdef __WXMAC_OSX__
    // we must destroy an existing cached image, as
    // the bitmap data may change now
    if ( m_cgImageRef )
    {
        CGImageRelease( m_cgImageRef ) ;
        m_cgImageRef = NULL ;
    }
#endif

    return m_memBuf.GetData() ;
}

void wxBitmapRefData::EndRawAccess()
{
    wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
    wxASSERT( m_rawAccessCount == 1 ) ;

    --m_rawAccessCount ;

#if !wxMAC_USE_CORE_GRAPHICS
    UpdateAlphaMask() ;
#endif
}

bool wxBitmapRefData::HasNativeSize()
{
    int w = GetWidth() ;
    int h = GetHeight() ;
    int sz = wxMax( w , h ) ;

    return ( sz == 128 || sz == 48 || sz == 32 || sz == 16 );
}

IconRef wxBitmapRefData::GetIconRef()
{
    if ( m_iconRef == NULL )
    {
        // Create Icon Family Handle

        IconFamilyHandle iconFamily = NULL ;

#ifdef WORDS_BIGENDIAN
        iconFamily = (IconFamilyHandle) NewHandle( 8 ) ;
        (**iconFamily).resourceType = kIconFamilyType ;
        (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size);
#else
        // test this solution on big endian as well
        iconFamily = (IconFamilyHandle) NewHandle( 0 ) ;
#endif

        int w = GetWidth() ;
        int h = GetHeight() ;
        int sz = wxMax( w , h ) ;

        OSType dataType = 0 ;
        OSType maskType = 0 ;

        switch (sz)
        {
            case 128:
                dataType = kThumbnail32BitData ;
                maskType = kThumbnail8BitMask ;
                break;

            case 48:
                dataType = kHuge32BitData ;
                maskType = kHuge8BitMask ;
                break;

            case 32:
                dataType = kLarge32BitData ;
                maskType = kLarge8BitMask ;
                break;

            case 16:
                dataType = kSmall32BitData ;
                maskType = kSmall8BitMask ;
                break;

            default:
                break;
        }

        if ( dataType != 0 )
        {
            // setup the header properly

            Handle data = NULL ;
            Handle maskdata = NULL ;
            unsigned char * maskptr = NULL ;
            unsigned char * ptr = NULL ;
            size_t datasize, masksize ;

            datasize = sz * sz * 4 ;
            data = NewHandle( datasize ) ;
            HLock( data ) ;
            ptr = (unsigned char*) *data ;
            memset( ptr , 0, datasize ) ;

            masksize = sz * sz ;
            maskdata = NewHandle( masksize ) ;
            HLock( maskdata ) ;
            maskptr = (unsigned char*) *maskdata ;
            memset( maskptr , 0 , masksize ) ;

            bool hasAlpha = HasAlpha() ;
            wxMask *mask = m_bitmapMask ;
            unsigned char * source = (unsigned char*) GetRawAccess() ;
            unsigned char * masksource = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;

            for ( int y = 0 ; y < h ; ++y )
            {
                unsigned char * dest = ptr + y * sz * 4 ;
                unsigned char * maskdest = maskptr + y * sz ;
                unsigned char a, r, g, b;

                for ( int x = 0 ; x < w ; ++x )
                {
                    a = *source ++ ;
                    r = *source ++ ;
                    g = *source ++ ;
                    b = *source ++ ;

                    *dest++ = 0 ;
                    *dest++ = r ;
                    *dest++ = g ;
                    *dest++ = b ;

                    if ( mask )
                    {
                        *maskdest++ = 0xFF - *masksource++ ;
                        masksource++ ;
                        masksource++ ;
                        masksource++ ;
                    }
                    else if ( hasAlpha )
                        *maskdest++ = a ;
                    else
                        *maskdest++ = 0xFF ;
                }
            }

            OSStatus err = SetIconFamilyData( iconFamily, dataType , data ) ;
            wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;

            err = SetIconFamilyData( iconFamily, maskType , maskdata ) ;
            wxASSERT_MSG( err == noErr , wxT("Error when adding mask") ) ;

            HUnlock( data ) ;
            HUnlock( maskdata ) ;
            DisposeHandle( data ) ;
            DisposeHandle( maskdata ) ;
        }
        else
        {
            PicHandle pic = GetPictHandle() ;
            SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ;
        }
        // transform into IconRef
#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
        // cleaner version existing from 10.3 upwards
        HLock((Handle) iconFamily);
        OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &m_iconRef );
        HUnlock((Handle) iconFamily);
        wxASSERT_MSG( err == noErr , wxT("Error when constructing icon ref") );
#else
        static int iconCounter = 2 ;

        OSStatus err = RegisterIconRefFromIconFamily( 'WXNG' , (OSType) iconCounter, iconFamily, &m_iconRef ) ;
        wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;

        // we have to retain a reference, as Unregister will decrement it
        AcquireIconRef( m_iconRef ) ;
        UnregisterIconRef( 'WXNG' , (OSType) iconCounter ) ;
        ++iconCounter ;
#endif
        DisposeHandle( (Handle) iconFamily ) ;
    }

    return m_iconRef ;
}

PicHandle wxBitmapRefData::GetPictHandle()
{
    if ( m_pictHandle == NULL )
    {
        CGrafPtr origPort = NULL ;
        GDHandle origDev = NULL ;
        GWorldPtr wp = NULL ;
        GWorldPtr mask = NULL ;
        int height = GetHeight() ;
        int width = GetWidth() ;

        Rect rect = { 0 , 0 , height , width } ;
        RgnHandle clipRgn = NULL ;

        GetGWorld( &origPort , &origDev ) ;
        wp = GetHBITMAP( &mask ) ;

        if ( mask )
        {
            GWorldPtr monoworld ;
            clipRgn = NewRgn() ;
            OSStatus err = NewGWorld( &monoworld , 1 , &rect , NULL , NULL , 0 ) ;
            verify_noerr(err) ;
            LockPixels( GetGWorldPixMap( monoworld ) ) ;
            LockPixels( GetGWorldPixMap( mask ) ) ;
            SetGWorld( monoworld , NULL ) ;

            RGBColor white = { 0xffff , 0xffff , 0xffff } ;
            RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;
            RGBForeColor( &black ) ;
            RGBBackColor( &white ) ;

            CopyBits(GetPortBitMapForCopyBits(mask),
                    GetPortBitMapForCopyBits(monoworld),
                    &rect,
                    &rect,
                    srcCopy, NULL);
            BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( monoworld ) ) ;

            UnlockPixels( GetGWorldPixMap( monoworld ) ) ;
            UnlockPixels( GetGWorldPixMap( mask ) ) ;
            DisposeGWorld( monoworld ) ;
        }

        SetGWorld( wp , NULL ) ;
        Rect portRect ;
        GetPortBounds( wp , &portRect ) ;
        m_pictHandle = OpenPicture(&portRect);

        if (m_pictHandle)
        {
            RGBColor white = { 0xffff , 0xffff , 0xffff } ;
            RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;

            RGBForeColor( &black ) ;
            RGBBackColor( &white ) ;

            if ( clipRgn )
                SetClip( clipRgn ) ;

            LockPixels( GetGWorldPixMap( wp ) ) ;
            CopyBits(GetPortBitMapForCopyBits(wp),
                    GetPortBitMapForCopyBits(wp),
                    &portRect,
                    &portRect,
                    srcCopy,clipRgn);
            UnlockPixels( GetGWorldPixMap( wp ) ) ;
            ClosePicture();
        }

        SetGWorld( origPort , origDev ) ;
        if ( clipRgn )
            DisposeRgn( clipRgn ) ;
    }

    return m_pictHandle ;
}

#ifdef __WXMAC_OSX__
void wxMacMemoryBufferReleaseProc(void *info, const void *data, size_t size)
{
    wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ;

    wxASSERT( data == membuf->GetData() ) ;

    delete membuf ;
}

CGImageRef wxBitmapRefData::CGImageCreate() const
{
    wxASSERT( m_ok ) ;
    wxASSERT( m_rawAccessCount >= 0 ) ;
    CGImageRef image ;
    if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
    {
        size_t imageSize = m_width * m_height * 4 ;
        void * dataBuffer = m_memBuf.GetData() ;
        int w = m_width ;
        int h = m_height ;
        CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ;
        wxMemoryBuffer* membuf = NULL ;

        if ( m_bitmapMask )
        {
            alphaInfo = kCGImageAlphaFirst ;
            membuf = new wxMemoryBuffer( imageSize ) ;
            memcpy( membuf->GetData() , dataBuffer , imageSize ) ;
            unsigned char *sourcemaskstart = (unsigned char *) m_bitmapMask->GetRawAccess() ;
            int maskrowbytes = m_bitmapMask->GetBytesPerRow() ;
            unsigned char *destalpha = (unsigned char *) membuf->GetData() ;
            for ( int y = 0 ; y < h ; ++y , sourcemaskstart += maskrowbytes)
            {
                unsigned char *sourcemask = sourcemaskstart ;
                for ( int x = 0 ; x < w ; ++x , sourcemask += 4 , destalpha += 4 )
                {
                    *destalpha = 0xFF - *sourcemask ;
                }
            }
        }
        else
        {
            if ( m_hasAlpha )
            {
#if wxMAC_USE_PREMULTIPLIED_ALPHA
                alphaInfo = kCGImageAlphaPremultipliedFirst ;
#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -