Milán Major

netscape-revival

1 branch
Code

sun-java/awt/win/awt_resource.cpp

#include <stddef.h>     // offsetof()

#include "awt_object.h"
#include "awt_resource.h"

#ifdef DEBUG_CONSOLE
#include "awt_toolkit.h"
#endif

//#define DEBUG_GDI


//-------------------------------------------------------------------------
//
// AwtCachedBrush implementation
//
//-------------------------------------------------------------------------
AwtCList AwtCachedBrush::m_freeChain;
AwtCList AwtCachedBrush::m_liveChain;
AwtMutex AwtCachedBrush::m_cacheMutex;


AwtCachedBrush::AwtCachedBrush()
{
}

AwtCachedBrush::~AwtCachedBrush()
{
}

//-------------------------------------------------------------------------
//
// Create an AwtCachedBrush object of the requested color.
//
// If an object already exists for the color, then return it, otherwise
// create a new one...
//
//-------------------------------------------------------------------------
AwtCachedBrush *AwtCachedBrush::Create( COLORREF color ) 
{
    AwtCList *qp;
    AwtCachedBrush *pBrush;
    AwtCachedBrush *pNewBrush = NULL;


    // Lock the brush cache...
    m_cacheMutex.Lock();
    
    //
    // Scan the list of allocated brushes to see if the requested color
    // has already been created...
    //
    qp = m_liveChain.next;
    while (qp != &m_liveChain) {
        pBrush = (AwtCachedBrush *)RESOURCE_PTR(qp);
        if (pBrush->m_color == color) {
            pBrush->m_refCount++;
            pNewBrush = pBrush;
            break;
        }
        qp = qp->next;
    }

    //
    // Allocate a new brush
    //
    if (pNewBrush == NULL) {
        // Allocate from the free chain if possible...
        if (m_freeChain.IsEmpty()) {
            pNewBrush = new AwtCachedBrush();
        } else {
            pNewBrush = (AwtCachedBrush *)RESOURCE_PTR( m_freeChain.next );
            pNewBrush->m_link.Remove();
        }

        //
        // Initialize the object and place it in the brush cache...
        //
        pNewBrush->Initialize(color);
        m_liveChain.Append(pNewBrush->m_link);
    }

    // Unlock the brush cache...
    m_cacheMutex.Unlock();

    return pNewBrush;
}


//-------------------------------------------------------------------------
//
// Delete all of the objects in the cache...
//
//-------------------------------------------------------------------------
void AwtCachedBrush::DeleteCache(void)
{
    AwtCachedBrush *pObject;


    // Lock the cache...
    m_cacheMutex.Lock();
    
    //
    // Scan the list of allocated brushes to see if the requested color
    // has already been created...
    //
    while (!m_liveChain.IsEmpty()) {
        pObject = (AwtCachedBrush *)RESOURCE_PTR(m_liveChain.next);
        pObject->m_link.Remove();

        // Release the GDI object
        if (pObject->m_hObject) {
            VERIFY( ::DeleteObject(pObject->m_hObject) );
        }

        delete pObject;
    }

    // Unlock the cache...
    m_cacheMutex.Unlock();
}


//-------------------------------------------------------------------------
//
// Select or remove a brush in a GDI DC
//
//-------------------------------------------------------------------------
void AwtCachedBrush::Select( HDC hDC, BOOL bFlag )
{
    // Lock the brush cache...
    m_cacheMutex.Lock();

    if (bFlag) {
        VERIFY( ::SelectObject(hDC, m_hObject) );
        m_lockCount++;
    }
    else {
        --m_lockCount;
    }

    // Lock the brush cache...
    m_cacheMutex.Unlock();
}


//------------------------------------------------------------------------
//
//------------------------------------------------------------------------
void AwtCachedBrush::AddRef()
{
    // Lock the brush cache...
    m_cacheMutex.Lock();

    m_refCount++;

    // Unlock the brush cache...
    m_cacheMutex.Unlock();
}


//-------------------------------------------------------------------------
//
// Release an AwtCachedBrush object.  If this is the last reference to the
// object, then free all native resources (ie. GDI) and place the object
// on the free chain.
//
//-------------------------------------------------------------------------
void AwtCachedBrush::Release( void )
{
    // Lock the brush cache...
    m_cacheMutex.Lock();

    if (--m_refCount == 0) {
#ifdef DEBUG_GDI
        char buf[100];
        wsprintf(buf, "Delete Brush = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
        OutputDebugString(buf);
#endif

        VERIFY( ::DeleteObject(m_hObject) );
        m_hObject = 0;

        //
        // Remove the object from the cache and place it on the free chain.
        //
        m_link.Remove();
        m_freeChain.Append(m_link);
    }

    // Unlock the brush cache...
    m_cacheMutex.Unlock();
}


//-------------------------------------------------------------------------
//
// Initialize either a new object or one just removed from the free chain
// The reference count is initially 1
//
//-------------------------------------------------------------------------
void AwtCachedBrush::Initialize( COLORREF color )
{
    AwtCachedResource::Initialize();

    m_color = color;
    VERIFY( m_hObject = ::CreateSolidBrush(color) );
#ifdef DEBUG_GDI
    char buf[100];
    wsprintf(buf, "Create Brush = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
    OutputDebugString(buf);
#endif
}





//-------------------------------------------------------------------------
//
// AwtCachedPen implementation
//
//-------------------------------------------------------------------------
AwtCList AwtCachedPen::m_freeChain;
AwtCList AwtCachedPen::m_liveChain;
AwtMutex AwtCachedPen::m_cacheMutex;


AwtCachedPen::AwtCachedPen()
{
}

AwtCachedPen::~AwtCachedPen()
{
}

AwtCachedPen *AwtCachedPen::Create( COLORREF color ) 
{
    AwtCList *qp;
    AwtCachedPen *pPen;
    AwtCachedPen *pNewPen = NULL;

    // Lock the pen cache...
    m_cacheMutex.Lock();
    
    //
    // Scan the list of allocated pens to see if the requested color
    // has already been created...
    //
    qp = m_liveChain.next;
    while (qp != &m_liveChain) {
        pPen = (AwtCachedPen *)RESOURCE_PTR(qp);
        if(pPen->m_color == color) {
            pPen->m_refCount++;
            pNewPen = pPen;
            break;
        }
        qp = qp->next;
    }

    //
    // Allocate a new pen
    //
    if (pNewPen == NULL) {
        // Allocate from the free chain if possible...
        if (m_freeChain.IsEmpty()) {
            pNewPen = new AwtCachedPen();
        } else {
            pNewPen = (AwtCachedPen *)RESOURCE_PTR( m_freeChain.next );
            pNewPen->m_link.Remove();
        }

        pNewPen->Initialize(color);
        m_liveChain.Append(pNewPen->m_link);
    }

    // Unlock the pen cache...
    m_cacheMutex.Unlock();

    return pNewPen;
}


//-------------------------------------------------------------------------
//
// Delete all of the objects in the cache...
//
//-------------------------------------------------------------------------
void AwtCachedPen::DeleteCache(void)
{
    AwtCachedPen *pObject;


    // Lock the cache...
    m_cacheMutex.Lock();

    // Empty out the cache...
    while (!m_liveChain.IsEmpty()) {
        pObject = (AwtCachedPen *)RESOURCE_PTR(m_liveChain.next);
        pObject->m_link.Remove();

        // Release the GDI object
        if (pObject->m_hObject) {
            VERIFY( ::DeleteObject(pObject->m_hObject) );
        }

        delete pObject;
    }

    // Unlock the cache...
    m_cacheMutex.Unlock();
}

//-------------------------------------------------------------------------
//
// Select or remove a pen in a GDI DC
//
//-------------------------------------------------------------------------
void AwtCachedPen::Select( HDC hDC, BOOL bFlag )
{
    if (bFlag) {
        VERIFY( ::SelectObject(hDC, m_hObject) );
        m_lockCount++;
    }
    else {
        --m_lockCount;
    }
}


//------------------------------------------------------------------------
//
//------------------------------------------------------------------------
void AwtCachedPen::AddRef()
{
    // Lock the brush cache...
    m_cacheMutex.Lock();

    m_refCount++;

    // Unlock the brush cache...
    m_cacheMutex.Unlock();
}


//-------------------------------------------------------------------------
//
// Release an AwtCachedPen object.  If this is the last reference to the
// object, then free all native resources (ie. GDI) and place the object
// on the free chain.
//
//-------------------------------------------------------------------------
void AwtCachedPen::Release( void )
{
    m_cacheMutex.Lock();
    if (--m_refCount == 0) {
#ifdef DEBUG_GDI
        char buf[100];
        wsprintf(buf, "Delete Pen = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
        OutputDebugString(buf);
#endif

        VERIFY( ::DeleteObject(m_hObject) );
        m_hObject = 0;

        //
        // Remove the object from the cache and place it on the free chain.
        //
        m_link.Remove();
        m_freeChain.Append(m_link);

    }
    m_cacheMutex.Unlock();
}


//-------------------------------------------------------------------------
//
// Initialize either a new object or one just removed from the free chain
// The reference count is initially 1
//
//-------------------------------------------------------------------------
void AwtCachedPen::Initialize( COLORREF color )
{
    AwtCachedResource::Initialize();

    m_color = color;
    VERIFY( m_hObject = ::CreatePen(PS_SOLID, 1, color) );
#ifdef DEBUG_GDI
    char buf[100];
    wsprintf(buf, "Create Pen = 0x%x, thrid=%d\n",m_hObject, PR_GetCurrentThreadID() );
    OutputDebugString(buf);
#endif
}