+#if wxUSE_DC_CACHEING
+
+/*
+ * This implementation is a bit ugly and uses the old-fashioned wxList class, so I will
+ * improve it in due course, either using arrays, or simply storing pointers to one
+ * entry for the bitmap, and two for the DCs. -- JACS
+ */
+
+wxList wxDC::sm_bitmapCache;
+wxList wxDC::sm_dcCache;
+
+wxDCCacheEntry::wxDCCacheEntry(WXHBITMAP hBitmap, int w, int h, int depth)
+{
+ m_bitmap = hBitmap;
+ m_dc = 0;
+ m_width = w;
+ m_height = h;
+ m_depth = depth;
+}
+
+wxDCCacheEntry::wxDCCacheEntry(WXHDC hDC, int depth)
+{
+ m_bitmap = 0;
+ m_dc = hDC;
+ m_width = 0;
+ m_height = 0;
+ m_depth = depth;
+}
+
+wxDCCacheEntry::~wxDCCacheEntry()
+{
+ if (m_bitmap)
+ ::DeleteObject((HBITMAP) m_bitmap);
+ if (m_dc)
+ ::DeleteDC((HDC) m_dc);
+}
+
+wxDCCacheEntry* wxDC::FindBitmapInCache(WXHDC dc, int w, int h)
+{
+ int depth = ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
+ wxNode* node = sm_bitmapCache.First();
+ while (node)
+ {
+ wxDCCacheEntry* entry = (wxDCCacheEntry*) node->Data();
+
+ if (entry->m_depth == depth)
+ {
+ if (entry->m_width < w || entry->m_height < h)
+ {
+ ::DeleteObject((HBITMAP) entry->m_bitmap);
+ entry->m_bitmap = (WXHBITMAP) ::CreateCompatibleBitmap((HDC) dc, w, h);
+ if ( !entry->m_bitmap)
+ {
+ wxLogLastError(wxT("CreateCompatibleBitmap"));
+ }
+ entry->m_width = w; entry->m_height = h;
+ return entry;
+ }
+ return entry;
+ }
+
+ node = node->Next();
+ }
+ WXHBITMAP hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap((HDC) dc, w, h);
+ if ( !hBitmap)
+ {
+ wxLogLastError(wxT("CreateCompatibleBitmap"));
+ }
+ wxDCCacheEntry* entry = new wxDCCacheEntry(hBitmap, w, h, depth);
+ AddToBitmapCache(entry);
+ return entry;
+}
+
+wxDCCacheEntry* wxDC::FindDCInCache(wxDCCacheEntry* notThis, WXHDC dc)
+{
+ int depth = ::GetDeviceCaps((HDC) dc, PLANES) * ::GetDeviceCaps((HDC) dc, BITSPIXEL);
+ wxNode* node = sm_dcCache.First();
+ while (node)
+ {
+ wxDCCacheEntry* entry = (wxDCCacheEntry*) node->Data();
+
+ // Don't return the same one as we already have
+ if (!notThis || (notThis != entry))
+ {
+ if (entry->m_depth == depth)
+ {
+ return entry;
+ }
+ }
+
+ node = node->Next();
+ }
+ WXHDC hDC = (WXHDC) ::CreateCompatibleDC((HDC) dc);
+ if ( !hDC)
+ {
+ wxLogLastError(wxT("CreateCompatibleDC"));
+ }
+ wxDCCacheEntry* entry = new wxDCCacheEntry(hDC, depth);
+ AddToDCCache(entry);
+ return entry;
+}
+
+void wxDC::AddToBitmapCache(wxDCCacheEntry* entry)
+{
+ sm_bitmapCache.Append(entry);
+}
+
+void wxDC::AddToDCCache(wxDCCacheEntry* entry)
+{
+ sm_dcCache.Append(entry);
+}
+
+void wxDC::ClearCache()
+{
+ sm_dcCache.DeleteContents(TRUE);
+ sm_dcCache.Clear();
+ sm_dcCache.DeleteContents(FALSE);
+ sm_bitmapCache.DeleteContents(TRUE);
+ sm_bitmapCache.Clear();
+ sm_bitmapCache.DeleteContents(FALSE);
+}
+
+// Clean up cache at app exit
+class wxDCModule : public wxModule
+{
+public:
+ virtual bool OnInit() { return TRUE; }
+ virtual void OnExit() { wxDC::ClearCache(); }
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxDCModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
+
+#endif
+ // wxUSE_DC_CACHEING