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