]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/fl/antiflickpl.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[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 // 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
27 IMPLEMENT_DYNAMIC_CLASS( cbAntiflickerPlugin, cbPluginBase )
28
29 BEGIN_EVENT_TABLE( cbAntiflickerPlugin, cbPluginBase )
30
31 EVT_PL_START_DRAW_IN_AREA ( cbAntiflickerPlugin::OnStartDrawInArea )
32 EVT_PL_FINISH_DRAW_IN_AREA ( cbAntiflickerPlugin::OnFinishDrawInArea )
33
34 END_EVENT_TABLE()
35
36 // initialization of static members
37
38 int cbAntiflickerPlugin::mRefCount = 0;
39
40 wxBitmap* cbAntiflickerPlugin::mpVertBuf = 0;
41 wxBitmap* cbAntiflickerPlugin::mpHorizBuf = 0;
42 wxMemoryDC* cbAntiflickerPlugin::mpVertBufDc = 0;
43 wxMemoryDC* cbAntiflickerPlugin::mpHorizBufDc = 0;
44
45 // constructors
46
47 cbAntiflickerPlugin::cbAntiflickerPlugin(void)
48 : mpLRUBufDc ( NULL ),
49 mLRUArea ( -1,-1, -1,-1 )
50 {
51 ++mRefCount;
52 }
53
54 cbAntiflickerPlugin::cbAntiflickerPlugin( wxFrameLayout* pPanel, int paneMask )
55
56 : cbPluginBase( pPanel, paneMask ),
57 mpLRUBufDc ( NULL ),
58 mLRUArea ( -1,-1, -1,-1 )
59 {
60 ++mRefCount;
61 }
62
63 cbAntiflickerPlugin::~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
87 wxDC* 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
106 wxDC* 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
163 void 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
203 void 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