1///////////////////////////////////////////////////////////////////////////// 2// Name: antiflickpl.cpp 3// Purpose: Double-buffering plugin class for reducing flickering. 4// Author: Aleksandras Gluchovas (@Lithuania) 5// Modified by: 6// Created: 23/10/98 7// RCS-ID: $Id: antiflickpl.cpp 35650 2005-09-23 12:56:45Z MR $ 8// Copyright: (c) Aleksandras Gluchovas 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16#pragma hdrstop 17#endif 18 19#ifndef WX_PRECOMP 20#include "wx/wx.h" 21#endif 22 23#include "wx/fl/antiflickpl.h" 24 25/***** Implementation for class cbAntiflickerPlugin *****/ 26 27IMPLEMENT_DYNAMIC_CLASS( cbAntiflickerPlugin, cbPluginBase ) 28 29BEGIN_EVENT_TABLE( cbAntiflickerPlugin, cbPluginBase ) 30 31 EVT_PL_START_DRAW_IN_AREA ( cbAntiflickerPlugin::OnStartDrawInArea ) 32 EVT_PL_FINISH_DRAW_IN_AREA ( cbAntiflickerPlugin::OnFinishDrawInArea ) 33 34END_EVENT_TABLE() 35 36// initialization of static members 37 38int cbAntiflickerPlugin::mRefCount = 0; 39 40wxBitmap* cbAntiflickerPlugin::mpVertBuf = 0; 41wxBitmap* cbAntiflickerPlugin::mpHorizBuf = 0; 42wxMemoryDC* cbAntiflickerPlugin::mpVertBufDc = 0; 43wxMemoryDC* cbAntiflickerPlugin::mpHorizBufDc = 0; 44 45// constructors 46 47cbAntiflickerPlugin::cbAntiflickerPlugin(void) 48 : mpLRUBufDc ( NULL ), 49 mLRUArea ( -1,-1, -1,-1 ) 50{ 51 ++mRefCount; 52} 53 54cbAntiflickerPlugin::cbAntiflickerPlugin( wxFrameLayout* pPanel, int paneMask ) 55 56 : cbPluginBase( pPanel, paneMask ), 57 mpLRUBufDc ( NULL ), 58 mLRUArea ( -1,-1, -1,-1 ) 59{ 60 ++mRefCount; 61} 62 63cbAntiflickerPlugin::~cbAntiflickerPlugin() 64{ 65 if ( --mRefCount == 0 ) 66 { 67 if ( mpHorizBuf ) 68 { 69 mpHorizBufDc->SelectObject( wxNullBitmap ); 70 delete mpHorizBuf; 71 delete mpHorizBufDc; 72 mpHorizBuf = 0; 73 mpHorizBufDc = 0; 74 } 75 76 if ( mpVertBuf ) 77 { 78 mpVertBufDc->SelectObject( wxNullBitmap ); 79 delete mpVertBuf; 80 delete mpVertBufDc; 81 mpVertBuf = 0; 82 mpVertBufDc = 0; 83 } 84 } 85} 86 87wxDC* cbAntiflickerPlugin::FindSuitableBuffer( const wxRect& forArea ) 88{ 89 if ( mpVertBuf ) 90 { 91 if ( mpVertBuf->GetHeight() >= forArea.height && 92 mpVertBuf->GetWidth() >= forArea.width ) 93 return mpVertBufDc; 94 } 95 else 96 if ( mpHorizBuf ) 97 { 98 if ( mpHorizBuf->GetHeight() >= forArea.height && 99 mpHorizBuf->GetWidth() >= forArea.width ) 100 return mpHorizBufDc; 101 } 102 103 return 0; 104} 105 106wxDC* cbAntiflickerPlugin::AllocNewBuffer( const wxRect& forArea ) 107{ 108 // TBD:: preallocate bit larger bitmap at once, to avoid 109 // excessive realocations later 110 111 // check whether the given area is oriented horizontally 112 // or vertically and choose corresponding bitmap to create or 113 // recreate 114 115 if ( forArea.height > forArea.width ) 116 { 117 wxSize prevDim( 0,0 ); 118 119 if ( mpVertBuf ) 120 { 121 prevDim.x = mpVertBuf->GetWidth(); 122 prevDim.y = mpVertBuf->GetHeight(); 123 124 mpVertBufDc->SelectObject( wxNullBitmap ); 125 delete mpVertBuf; 126 } 127 else 128 mpVertBufDc = new wxMemoryDC(); 129 130 mpVertBuf = new wxBitmap( int( wxMax(forArea.width, prevDim.x ) ), 131 int( wxMax(forArea.height, prevDim.y ) ) 132 ); 133 134 mpVertBufDc->SelectObject( *mpVertBuf ); 135 136 return mpVertBufDc; 137 } 138 else 139 { 140 wxSize prevDim( 0,0 ); 141 142 if ( mpHorizBuf ) 143 { 144 prevDim.x = mpHorizBuf->GetWidth(); 145 prevDim.y = mpHorizBuf->GetHeight(); 146 147 mpHorizBufDc->SelectObject( wxNullBitmap ); 148 delete mpHorizBuf; 149 } 150 else 151 mpHorizBufDc = new wxMemoryDC(); 152 153 mpHorizBuf = new wxBitmap( int( wxMax(forArea.width, prevDim.x ) ), 154 int( wxMax(forArea.height, prevDim.y ) ) 155 ); 156 157 mpHorizBufDc->SelectObject( *mpHorizBuf ); 158 159 return mpHorizBufDc; 160 } 161} 162 163void cbAntiflickerPlugin::OnStartDrawInArea( cbStartDrawInAreaEvent& event ) 164{ 165 wxASSERT( mpLRUBufDc == NULL ); // DBG:: see comments in OnFinishDrawInArea(..) method 166 167 // short-cut 168 wxRect& area = event.mArea; 169 170 if ( event.mArea.width < 0 || 171 event.mArea.height < 0 ) return; 172 173 // memorize given area 174 mLRUArea.x = area.x; 175 mLRUArea.y = area.y; 176 mLRUArea.width = area.width; 177 mLRUArea.height = area.height; 178 179 wxDC* pBufDc = FindSuitableBuffer( area ); 180 181 if ( !pBufDc ) 182 pBufDc = AllocNewBuffer( area ); 183 184 pBufDc->SetDeviceOrigin( -area.x, -area.y ); 185 186 pBufDc->SetClippingRegion( area.x, area.y, 187 area.width, area.height ); 188 189 wxClientDC clntDc( &mpLayout->GetParentFrame() ); 190 191 (*event.mppDc) = pBufDc; 192 193 mpLRUBufDc = pBufDc; // memorize buffer, which will be flushed to screen 194 // upon "commiting" the drawing 195 196 /* 197 // OLD STUFF:: 198 mpLRUBufDc->Blit( pos.x, pos.y, size.x, size.y, 199 &clntDc, pos.x, pos.y, wxCOPY ); 200 */ 201} 202 203void cbAntiflickerPlugin::OnFinishDrawInArea( cbFinishDrawInAreaEvent& event ) 204{ 205 wxRect& area = event.mArea; 206 207 if ( event.mArea.width < 0 || 208 event.mArea.height < 0 ) return; 209 210 wxASSERT( mpLRUBufDc ); // DBG:: OnStartDrawInArea should be called first 211 212 // FOR NOW:: OnStartDrawInArea(..) should be immediately followed 213 // by OnFinishDrawInArea(..) for the same area 214 215 wxASSERT( mLRUArea.x == area.x ); 216 wxASSERT( mLRUArea.y == area.y ); 217 wxASSERT( mLRUArea.width == area.width ); 218 wxASSERT( mLRUArea.height == area.height ); 219 220 wxClientDC clntDc( &mpLayout->GetParentFrame() ); 221 222 // "commit" drawings in one-shot 223 clntDc.Blit( area.x, area.y, area.width, area.height, 224 mpLRUBufDc, area.x, area.y, wxCOPY ); 225 226 mpLRUBufDc->DestroyClippingRegion(); 227 mpLRUBufDc = 0; 228} 229 230