//---------------------------------------------------------------------------- // ObjectWindows // (C) Copyright 1992, 1994 by Borland International, All Rights Reserved // // Implementation of TMemoryDC and TDibDC encapsulation classes //---------------------------------------------------------------------------- #include #include DIAG_DECLARE_GROUP(OwlGDI); // General GDI diagnostic group const int MemDCCacheSize = 2; // Number of mem DCs allocated in the cache // // Cache of screen-compatible memory HDCs used automatically by TMemoryDC when // the default ctor is called. Reduces the amount of HDC creations & allows // centralized sharing of these memory HDCs // class TMemDCCache { public: struct TEntry { HDC Handle; bool Busy; }; TMemDCCache(int numEntries); ~TMemDCCache(); HDC Get(); void Release(HDC hDC); private: TEntry* Entries; int NumEntries; }; TMemDCCache::TMemDCCache(int numEntries) { NumEntries = numEntries; Entries = new TEntry[NumEntries]; for (int i = 0; i < NumEntries; i++) { Entries[i].Handle = ::CreateCompatibleDC(0); Entries[i].Busy = false; } } TMemDCCache::~TMemDCCache() { for (int i = 0; i < NumEntries; i++) { WARNX(OwlGDI, Entries[i].Busy, 0, "Unreleased DC " << hex << uint(Entries[i].Handle) << " in MemDCCache"); if (Entries[i].Handle) ::DeleteDC(Entries[i].Handle); } delete [] Entries; } HDC TMemDCCache::Get() { for (int i = 0; i < NumEntries; i++) if (!Entries[i].Busy) { Entries[i].Busy = true; return Entries[i].Handle; } return 0; } void TMemDCCache::Release(HDC hDC) { for (int i = 0; i < NumEntries; i++) if (Entries[i].Handle == hDC) { WARNX(OwlGDI, !Entries[i].Busy, 0, "Releasing non-busy DC " << hex << uint(Entries[i].Handle) << " in MemDCCache"); Entries[i].Busy = false; return; } } static TMemDCCache MemDCCache(MemDCCacheSize); // // construct a screen-compatible memory DC. Try to get one from the cache first // TMemoryDC::TMemoryDC() : TCreatedDC() { Handle = MemDCCache.Get(); if (Handle) ShouldDelete = false; else { Handle = ::CreateCompatibleDC(0); CheckValid(); } OrgBitmap = 0; } TMemoryDC::TMemoryDC(const TDC& dc) : TCreatedDC() { Handle = ::CreateCompatibleDC(dc); CheckValid(); OrgBitmap = 0; } // // Use an existing HDC. Delete it on destruction as requested. Allow bitmap // selection // TMemoryDC::TMemoryDC(HDC handle, TAutoDelete autoDelete) : TCreatedDC(handle, autoDelete) { } void TMemoryDC::SelectObject(const TBitmap& bitmap) { HBITMAP oldBitmap = (HBITMAP)::SelectObject(HDC(Handle), bitmap); if (oldBitmap) { OBJ_REF_INC(bitmap); if ((bool)oldBitmap > 1) if (!OrgBitmap) OrgBitmap = oldBitmap; else OBJ_REF_DEC(oldBitmap, false); } } void TMemoryDC::RestoreBitmap() { if (OrgBitmap) { OBJ_REF_DEC(::SelectObject(HDC(Handle), OrgBitmap), false); OrgBitmap = 0; } } TMemoryDC::~TMemoryDC() { RestoreBitmap(); RestoreObjects(); MemDCCache.Release(HDC(Handle)); }