]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
Optimize pixels rotation in wxImage::Rotate90().
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
df91131c 2// Name: src/os2/dcclient.cpp
0e320a79 3// Purpose: wxClientDC class
f0a56ab0 4// Author: David Webster
0e320a79 5// Modified by:
f0a56ab0 6// Created: 09/21/99
0e320a79 7// RCS-ID: $Id$
f0a56ab0 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
0e320a79 22
df91131c 23#include "wx/dcclient.h"
2c24e7ad 24#include "wx/os2/dcclient.h"
df91131c
WS
25
26#ifndef WX_PRECOMP
27 #include "wx/string.h"
e4db172a 28 #include "wx/log.h"
670f9935 29 #include "wx/app.h"
cdccdfab 30 #include "wx/window.h"
df91131c
WS
31#endif
32
ce44c50e 33#include "wx/os2/private.h"
0e320a79 34
23e4b7d8
DW
35// ----------------------------------------------------------------------------
36// array/list types
37// ----------------------------------------------------------------------------
0e320a79 38
23e4b7d8 39struct WXDLLEXPORT wxPaintDCInfo
0e320a79 40{
e99762c0 41 wxPaintDCInfo( wxWindow* pWin
2c24e7ad 42 ,wxPaintDCImpl* pDC
e99762c0 43 )
23e4b7d8 44 {
e99762c0
DW
45 m_hWnd = pWin->GetHWND();
46 m_hDC = pDC->GetHDC();
47 m_nCount = 1;
23e4b7d8 48 }
0e320a79 49
e99762c0
DW
50 WXHWND m_hWnd; // window for this DC
51 WXHDC m_hDC; // the DC handle
52 size_t m_nCount; // usage count
53}; // end of wxPaintDCInfot
0e320a79 54
23e4b7d8 55#include "wx/arrimpl.cpp"
1408104d 56
23e4b7d8 57WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 58
23e4b7d8
DW
59// ----------------------------------------------------------------------------
60// global variables
61// ----------------------------------------------------------------------------
1408104d 62
ce44c50e 63static RECT g_paintStruct;
1408104d 64
657a8a35 65#ifdef wxHAS_PAINT_DEBUG
23e4b7d8
DW
66 // a global variable which we check to verify that wxPaintDC are only
67 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
77ffb593 68 // common programming error among wxWidgets programmers and might lead to
23e4b7d8
DW
69 // very subtle and difficult to debug refresh/repaint bugs.
70 int g_isPainting = 0;
657a8a35 71#endif // wxHAS_PAINT_DEBUG
1408104d 72
23e4b7d8
DW
73// ===========================================================================
74// implementation
75// ===========================================================================
1408104d 76
23e4b7d8 77// ----------------------------------------------------------------------------
2c24e7ad 78// wxWindowDCImpl
23e4b7d8 79// ----------------------------------------------------------------------------
0e320a79 80
2c24e7ad
SN
81IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxPMDCImpl)
82
83wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) :
84 wxPMDCImpl( owner )
0e320a79 85{
1d27f802 86 m_PageSize.cx = m_PageSize.cy = 0;
23e4b7d8 87}
0e320a79 88
2c24e7ad
SN
89wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow* pTheCanvas) :
90 wxPMDCImpl( owner )
0e320a79 91{
26ac77db
DW
92 ERRORID vError;
93 wxString sError;
1d27f802 94 int nWidth, nHeight;
1408104d 95
e99762c0 96 m_pCanvas = pTheCanvas;
1d27f802
SN
97 DoGetSize(&nWidth, &nHeight);
98 m_PageSize.cx = nWidth;
99 m_PageSize.cy = nHeight;
e99762c0 100 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
e1a688e4 101
23e4b7d8 102 //
26ac77db
DW
103 // default under PM is that Window and Client DC's are the same
104 // so we offer a separate Presentation Space to use for the
105 // entire window. Otherwise, calling BeginPaint will just create
106 // chached-micro client presentation space
23e4b7d8 107 //
e1a688e4
DW
108 m_hPS = ::GpiCreatePS( vHabmain
109 ,m_hDC
110 ,&m_PageSize
111 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
112 );
1d27f802
SN
113 if (!m_hPS)
114 {
115 vError = ::WinGetLastError(vHabmain);
116 sError = wxPMErrorToStr(vError);
9a83f860 117 wxLogError(wxT("Unable to create presentation space. Error: %s\n"), sError.c_str());
1d27f802 118 }
26ac77db
DW
119 ::GpiAssociate(m_hPS, NULLHANDLE);
120 ::GpiAssociate(m_hPS, m_hDC);
e1a688e4
DW
121
122 //
77ffb593 123 // Set the wxWidgets color table
e1a688e4 124 //
26ac77db
DW
125 if (!::GpiCreateLogColorTable( m_hPS
126 ,0L
127 ,LCOLF_CONSECRGB
128 ,0L
129 ,(LONG)wxTheColourDatabase->m_nSize
130 ,(PLONG)wxTheColourDatabase->m_palTable
131 ))
7e99520b 132 {
26ac77db
DW
133 vError = ::WinGetLastError(vHabmain);
134 sError = wxPMErrorToStr(vError);
9a83f860 135 wxLogError(wxT("Unable to set current color table (3). Error: %s\n"), sError.c_str());
7e99520b 136 }
5afb9458
DW
137 ::GpiCreateLogColorTable( m_hPS
138 ,0L
139 ,LCOLF_RGB
140 ,0L
141 ,0L
142 ,NULL
143 );
5afb9458
DW
144 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
145 ,&m_vRclPaint
146 );
e1a688e4 147 InitDC();
2c24e7ad 148} // end of wxWindowDCImpl::wxWindowDCImpl
1408104d 149
2c24e7ad 150void wxWindowDCImpl::InitDC()
26ac77db 151{
2b0ec34b 152
e1a688e4
DW
153 //
154 // The background mode is only used for text background and is set in
155 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
156 //
157 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
26ac77db 158
e1a688e4
DW
159 //
160 // Default bg colour is pne of the window
161 //
162 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
938aa9c4 163
19bc1514
WS
164 m_pen.SetColour(*wxBLACK);
165 m_brush.SetColour(*wxWHITE);
2c24e7ad
SN
166 // since we are a window dc we need to grab the palette from the window
167#if wxUSE_PALETTE
938aa9c4 168 InitializePalette();
2c24e7ad 169#endif
19bc1514 170 wxFont* pFont = new wxFont( 10, wxMODERN, wxNORMAL, wxBOLD );
c354beea
DW
171 SetFont(*pFont);
172 delete pFont;
173 //
d6922577 174 // OS/2 default vertical character alignment needs to match the other OS's
c354beea
DW
175 //
176 ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
177
2c24e7ad 178} // end of wxWindowDCImpl::InitDC
0e320a79 179
2c24e7ad 180void wxWindowDCImpl::DoGetSize(
bc5a847c
DW
181 int* pnWidth
182, int* pnHeight
183) const
184{
9a83f860 185 wxCHECK_RET( m_pCanvas, wxT("wxWindowDC without a window?") );
bc5a847c
DW
186 m_pCanvas->GetSize( pnWidth
187 ,pnHeight
188 );
2c24e7ad 189} // end of wxWindowDCImpl::DoGetSize
bc5a847c 190
23e4b7d8
DW
191// ----------------------------------------------------------------------------
192// wxClientDC
193// ----------------------------------------------------------------------------
0e320a79 194
2c24e7ad
SN
195IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
196
197wxClientDCImpl::wxClientDCImpl( wxDC *owner ) :
198 wxWindowDCImpl( owner )
0e320a79 199{
26ac77db 200 m_pCanvas = NULL;
23e4b7d8 201}
0e320a79 202
2c24e7ad
SN
203wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *pTheCanvas) :
204 wxWindowDCImpl( owner )
0e320a79 205{
7e99520b 206 SIZEL vSizl = { 0,0};
26ac77db
DW
207 ERRORID vError;
208 wxString sError;
0e320a79 209
e99762c0 210 m_pCanvas = pTheCanvas;
1408104d 211
7e99520b
DW
212 //
213 // default under PM is that Window and Client DC's are the same
214 //
2c24e7ad 215
e99762c0 216 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
2c24e7ad
SN
217 printf("Got WindowDC %X for window handle %X\n", m_hDC, pTheCanvas);
218
7e99520b
DW
219 m_hPS = ::GpiCreatePS( wxGetInstance()
220 ,m_hDC
f44fdfb0 221 ,&vSizl
7e99520b
DW
222 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
223 );
2c24e7ad
SN
224 ::GpiAssociate(m_hPS, NULLHANDLE);
225 ::GpiAssociate(m_hPS, m_hDC);
7e99520b 226
2c24e7ad 227 printf("Got m_hPS %X\n", m_hPS);
77ffb593 228 // Set the wxWidgets color table
26ac77db
DW
229 if (!::GpiCreateLogColorTable( m_hPS
230 ,0L
231 ,LCOLF_CONSECRGB
232 ,0L
233 ,(LONG)wxTheColourDatabase->m_nSize
234 ,(PLONG)wxTheColourDatabase->m_palTable
235 ))
236 {
237 vError = ::WinGetLastError(vHabmain);
238 sError = wxPMErrorToStr(vError);
9a83f860 239 wxLogError(wxT("Unable to set current color table (4). Error: %s\n"), sError.c_str());
26ac77db 240 }
5afb9458
DW
241 ::GpiCreateLogColorTable( m_hPS
242 ,0L
243 ,LCOLF_RGB
244 ,0L
245 ,0L
246 ,NULL
247 );
7e99520b 248 //
5afb9458
DW
249 // Set the DC/PS rectangle
250 //
251 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
252 ,&m_vRclPaint
253 );
e1a688e4 254 InitDC();
2c24e7ad 255} // end of wxClientDCImpl::wxClientDCImpl
0e320a79 256
2c24e7ad 257void wxClientDCImpl::InitDC()
0367c1c0 258{
2c24e7ad 259 wxWindowDCImpl::InitDC();
0367c1c0
DW
260
261 // in wxUniv build we must manually do some DC adjustments usually
262 // performed by Windows for us
263#ifdef __WXUNIVERSAL__
19193a2c 264 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
0367c1c0
DW
265 if ( ptOrigin.x || ptOrigin.y )
266 {
267 // no need to shift DC origin if shift is null
268 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
269 }
270
271 // clip the DC to avoid overwriting the non client area
19193a2c 272 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
0367c1c0 273#endif // __WXUNIVERSAL__
2c24e7ad 274} // end of wxClientDCImpl::InitDC
0367c1c0 275
2c24e7ad 276wxClientDCImpl::~wxClientDCImpl()
0367c1c0 277{
2c24e7ad 278} // end of wxClientDCImpl::~wxClientDCImpl
0367c1c0 279
2c24e7ad 280void wxClientDCImpl::DoGetSize(
bc5a847c
DW
281 int* pnWidth
282, int* pnHeight
283) const
284{
9a83f860 285 wxCHECK_RET( m_pCanvas, wxT("wxWindowDC without a window?") );
bc5a847c
DW
286 m_pCanvas->GetClientSize( pnWidth
287 ,pnHeight
288 );
2c24e7ad 289} // end of wxClientDCImpl::DoGetSize
bc5a847c 290
23e4b7d8
DW
291// ----------------------------------------------------------------------------
292// wxPaintDC
293// ----------------------------------------------------------------------------
294
2c24e7ad 295IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxWindowDCImpl)
23e4b7d8 296
2c24e7ad
SN
297wxArrayDCInfo wxPaintDCImpl::ms_cache;
298
299wxPaintDCImpl::wxPaintDCImpl( wxDC *owner ) :
300 wxClientDCImpl( owner )
23e4b7d8 301{
f6bcfd97 302 m_pCanvas = NULL;
23e4b7d8
DW
303 m_hDC = 0;
304}
0e320a79 305
2c24e7ad
SN
306wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *pCanvas) :
307 wxClientDCImpl( owner )
0e320a79 308{
f44fdfb0 309 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
1408104d 310
657a8a35 311#ifdef wxHAS_PAINT_DEBUG
7e99520b 312 if (g_isPainting <= 0)
23e4b7d8 313 {
223d09f6 314 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
23e4b7d8
DW
315 return;
316 }
4b6a582b 317#endif // wxHAS_PAINT_DEBUG
0e320a79 318
7e99520b 319 m_pCanvas = pCanvas;
1408104d 320
7e99520b
DW
321 //
322 // Do we have a DC for this window in the cache?
323 //
324 wxPaintDCInfo* pInfo = FindInCache();
325
326 if (pInfo)
0e320a79 327 {
e99762c0
DW
328 m_hDC = pInfo->m_hDC;
329 pInfo->m_nCount++;
23e4b7d8
DW
330 }
331 else // not in cache, create a new one
332 {
7e99520b
DW
333 HPS hPS;
334
52315bc3 335 m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
7e99520b
DW
336 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
337 ,NULLHANDLE
338 ,&g_paintStruct
339 );
340 if(hPS)
341 {
ba3e10c9 342 ::GpiAssociate(hPS, m_hDC);
7e99520b
DW
343 m_hOldPS = m_hPS;
344 m_hPS = hPS;
26ac77db
DW
345 ::GpiCreateLogColorTable( m_hPS
346 ,0L
347 ,LCOLF_CONSECRGB
348 ,0L
349 ,(LONG)wxTheColourDatabase->m_nSize
350 ,(PLONG)wxTheColourDatabase->m_palTable
351 );
352 ::GpiCreateLogColorTable( m_hPS
353 ,0L
354 ,LCOLF_RGB
355 ,0L
356 ,0L
357 ,NULL
358 );
8d854fa9
DW
359
360 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
eeff964a
DW
361 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
362 ,&m_vRclPaint
363 );
7e99520b 364 }
e99762c0 365
df91131c 366 m_bIsPaintTime = true;
f6bcfd97 367 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
0e320a79 368 }
e1a688e4 369 InitDC();
2c24e7ad 370} // end of wxPaintDCImpl::wxPaintDCImpl
0e320a79 371
2c24e7ad 372wxPaintDCImpl::~wxPaintDCImpl()
0e320a79 373{
23e4b7d8
DW
374 if ( m_hDC )
375 {
376 SelectOldObjects(m_hDC);
0e320a79 377
e99762c0
DW
378 size_t nIndex;
379 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
0e320a79 380
e99762c0 381 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
0e320a79 382
e99762c0 383 if ( !--pInfo->m_nCount )
23e4b7d8 384 {
ce44c50e 385 ::WinEndPaint(m_hPS);
f44fdfb0 386 m_hPS = m_hOldPS;
df91131c 387 m_bIsPaintTime = false;
893758d5 388 ms_cache.RemoveAt(nIndex);
23e4b7d8
DW
389 }
390 //else: cached DC entry is still in use
0e320a79 391
23e4b7d8
DW
392 // prevent the base class dtor from ReleaseDC()ing it again
393 m_hDC = 0;
0e320a79
DW
394 }
395}
396
2c24e7ad 397wxPaintDCInfo* wxPaintDCImpl::FindInCache(
e99762c0
DW
398 size_t* pIndex
399) const
0e320a79 400{
e99762c0
DW
401 wxPaintDCInfo* pInfo = NULL;
402 size_t nCache = ms_cache.GetCount();
403
404 for (size_t n = 0; n < nCache; n++)
0e320a79 405 {
e99762c0
DW
406 pInfo = &ms_cache[n];
407 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
23e4b7d8 408 {
e99762c0
DW
409 if (pIndex)
410 *pIndex = n;
23e4b7d8
DW
411 break;
412 }
0e320a79 413 }
e99762c0 414 return pInfo;
2c24e7ad 415} // end of wxPaintDCImpl::FindInCache
0e320a79 416
e1a688e4 417// find the entry for this DC in the cache (keyed by the window)
2c24e7ad 418WXHDC wxPaintDCImpl::FindDCInCache(
e1a688e4
DW
419 wxWindow* pWin
420)
421{
422 wxPaintDCInfo* pInfo = NULL;
423 size_t nCache = ms_cache.GetCount();
424
425 for (size_t n = 0; n < nCache; n++)
426 {
427 pInfo = &ms_cache[n];
428 if (pInfo->m_hWnd == pWin->GetHWND())
429 {
430 return pInfo->m_hDC;
431 }
432 }
433 return 0;
2c24e7ad 434} // end of wxPaintDCImpl::FindInCache