]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
1. handle Alt-F4 in wxUniv, not wxMGL
[wxWidgets.git] / src / x11 / dcclient.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
3cd0b8c5 2// Name: x11/dcclient.cpp
83df96d6 3// Purpose: wxClientDC class
3cd0b8c5 4// Author: Julian Smart, Robert Roebling
83df96d6
JS
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
3cd0b8c5 8// Copyright: (c) Julian Smart, Robert Roebling
83df96d6
JS
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
83df96d6
JS
12#ifdef __GNUG__
13 #pragma implementation "dcclient.h"
14#endif
15
16#include "wx/dcclient.h"
17#include "wx/dcmemory.h"
18#include "wx/window.h"
19#include "wx/app.h"
20#include "wx/image.h"
21
3cd0b8c5
RR
22#include "wx/x11/private.h"
23
83df96d6
JS
24#include <math.h>
25
3cd0b8c5
RR
26//-----------------------------------------------------------------------------
27// local defines
28//-----------------------------------------------------------------------------
83df96d6 29
3cd0b8c5 30#define USE_PAINT_REGION 1
83df96d6 31
3cd0b8c5
RR
32//-----------------------------------------------------------------------------
33// local data
34//-----------------------------------------------------------------------------
83df96d6
JS
35
36#include "bdiag.xbm"
37#include "fdiag.xbm"
38#include "cdiag.xbm"
39#include "horiz.xbm"
40#include "verti.xbm"
41#include "cross.xbm"
3cd0b8c5 42#define num_hatches 6
83df96d6 43
3cd0b8c5
RR
44#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
83df96d6 46
3cd0b8c5
RR
47static Pixmap hatches[num_hatches];
48static Pixmap *hatch_bitmap = (Pixmap *) NULL;
49
50//-----------------------------------------------------------------------------
83df96d6 51// constants
3cd0b8c5 52//-----------------------------------------------------------------------------
83df96d6 53
3cd0b8c5 54const double RAD2DEG = 180.0 / M_PI;
83df96d6
JS
55
56// ----------------------------------------------------------------------------
3cd0b8c5 57// private functions
83df96d6
JS
58// ----------------------------------------------------------------------------
59
3cd0b8c5
RR
60static inline double dmax(double a, double b) { return a > b ? a : b; }
61static inline double dmin(double a, double b) { return a < b ? a : b; }
83df96d6 62
3cd0b8c5
RR
63static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
64
65//-----------------------------------------------------------------------------
66// Implement Pool of Graphic contexts. Creating them takes too much time.
67//-----------------------------------------------------------------------------
68
69#define GC_POOL_SIZE 200
70
71enum wxPoolGCType
72{
73 wxGC_ERROR = 0,
74 wxTEXT_MONO,
75 wxBG_MONO,
76 wxPEN_MONO,
77 wxBRUSH_MONO,
78 wxTEXT_COLOUR,
79 wxBG_COLOUR,
80 wxPEN_COLOUR,
81 wxBRUSH_COLOUR,
82 wxTEXT_SCREEN,
83 wxBG_SCREEN,
84 wxPEN_SCREEN,
85 wxBRUSH_SCREEN
86};
87
88struct wxGC
89{
90 GC m_gc;
91 wxPoolGCType m_type;
92 bool m_used;
93};
94
95static wxGC wxGCPool[GC_POOL_SIZE];
96
97static void wxInitGCPool()
98{
99 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
100}
83df96d6 101
3cd0b8c5 102static void wxCleanUpGCPool()
83df96d6 103{
3cd0b8c5
RR
104 for (int i = 0; i < GC_POOL_SIZE; i++)
105 {
106 if (wxGCPool[i].m_gc)
107 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
108 }
83df96d6
JS
109}
110
3cd0b8c5 111static GC wxGetPoolGC( Window window, wxPoolGCType type )
83df96d6 112{
3cd0b8c5
RR
113 for (int i = 0; i < GC_POOL_SIZE; i++)
114 {
115 if (!wxGCPool[i].m_gc)
116 {
117 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
119 wxGCPool[i].m_type = type;
120 wxGCPool[i].m_used = FALSE;
121 }
122 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
123 {
124 wxGCPool[i].m_used = TRUE;
125 return wxGCPool[i].m_gc;
126 }
127 }
128
129 wxFAIL_MSG( wxT("No GC available") );
130
131 return (GC) NULL;
83df96d6
JS
132}
133
3cd0b8c5
RR
134static void wxFreePoolGC( GC gc )
135{
136 for (int i = 0; i < GC_POOL_SIZE; i++)
137 {
138 if (wxGCPool[i].m_gc == gc)
139 {
140 wxGCPool[i].m_used = FALSE;
141 return;
142 }
143 }
144
145 wxFAIL_MSG( wxT("Wrong GC") );
146}
83df96d6
JS
147
148// ----------------------------------------------------------------------------
149// wxWindowDC
150// ----------------------------------------------------------------------------
151
3cd0b8c5
RR
152IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
153
83df96d6
JS
154wxWindowDC::wxWindowDC()
155{
3cd0b8c5
RR
156 m_display = (WXDisplay *) NULL;
157 m_penGC = (WXGC *) NULL;
158 m_brushGC = (WXGC *) NULL;
159 m_textGC = (WXGC *) NULL;
160 m_bgGC = (WXGC *) NULL;
161 m_cmap = (WXColormap *) NULL;
162 m_isMemDC = FALSE;
163 m_isScreenDC = FALSE;
164 m_owner = (wxWindow *)NULL;
83df96d6
JS
165}
166
167wxWindowDC::wxWindowDC( wxWindow *window )
168{
3cd0b8c5
RR
169 wxASSERT_MSG( window, wxT("DC needs a window") );
170
171 m_display = (WXDisplay *) NULL;
172 m_penGC = (WXGC *) NULL;
173 m_brushGC = (WXGC *) NULL;
174 m_textGC = (WXGC *) NULL;
175 m_bgGC = (WXGC *) NULL;
176 m_cmap = (WXColormap *) NULL;
177 m_owner = (wxWindow *)NULL;
178 m_isMemDC = FALSE;
179 m_isScreenDC = FALSE;
83df96d6 180 m_font = window->GetFont();
83df96d6 181
3cd0b8c5 182 m_window = (WXWindow*) window->GetMainWindow();
83df96d6 183
3cd0b8c5
RR
184 // not realized ?
185 if (!m_window)
186 {
187 // don't report problems
188 m_ok = TRUE;
189
190 return;
191 }
83df96d6 192
3cd0b8c5
RR
193 m_display = (WXDisplay *) wxGlobalDisplay();
194
195 int screen = DefaultScreen( (Display*) m_display );
196 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
83df96d6 197
3cd0b8c5 198 SetUpDC();
83df96d6 199
3cd0b8c5
RR
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
83df96d6 206
3cd0b8c5 207 m_owner = window;
83df96d6
JS
208}
209
210wxWindowDC::~wxWindowDC()
211{
3cd0b8c5
RR
212 Destroy();
213}
214
215void wxWindowDC::SetUpDC()
216{
217 m_ok = TRUE;
218
219 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
220
221 if (m_isScreenDC)
222 {
223 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
224 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
225 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
226 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
227 }
3cd0b8c5
RR
228 else
229 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
230 {
231 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
232 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
233 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
234 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
235 }
3cd0b8c5 236 else
83df96d6 237 {
3cd0b8c5
RR
238 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
239 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
240 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
241 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
83df96d6
JS
242 }
243
3cd0b8c5
RR
244 /* background colour */
245 m_backgroundBrush = *wxWHITE_BRUSH;
246 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
247 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
248
249 /* m_textGC */
250 m_textForegroundColour.CalcPixel( m_cmap );
251 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
252
253 m_textBackgroundColour.CalcPixel( m_cmap );
254 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
255
256 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
257
0b5c0e1a
JS
258#if wxUSE_NANOX
259 // By default, draw transparently
260 GrSetGCUseBackground((GC) m_textGC, FALSE);
261#endif
262
3cd0b8c5
RR
263 /* m_penGC */
264 m_pen.GetColour().CalcPixel( m_cmap );
265 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
266 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col );
267
268 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound );
269
270 /* m_brushGC */
271 m_brush.GetColour().CalcPixel( m_cmap );
272 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
273 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col );
274
275 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
276
277 /* m_bgGC */
278 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col );
279 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col );
280
281 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
282
283 /* ROPs */
284 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy );
285 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy );
286 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy );
287
288 /* clipping */
289 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
290 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
291 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
292 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
83df96d6 293
3cd0b8c5
RR
294 if (!hatch_bitmap)
295 {
1180fb81
RR
296 int xscreen = DefaultScreen( (Display*) m_display );
297 Window xroot = RootWindow( (Display*) m_display, xscreen );
298
3cd0b8c5 299 hatch_bitmap = hatches;
1180fb81
RR
300 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height );
301 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height );
302 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height );
303 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height );
304 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height );
305 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height );
3cd0b8c5
RR
306 }
307}
83df96d6 308
3cd0b8c5
RR
309void wxWindowDC::DoGetSize( int* width, int* height ) const
310{
311 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
83df96d6 312
3cd0b8c5 313 m_owner->GetSize(width, height);
83df96d6
JS
314}
315
316void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
317 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
318{
319 wxFAIL_MSG("not implemented");
320}
321
322bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
323{
324 // Generic (and therefore rather inefficient) method.
325 // Could be improved.
326 wxMemoryDC memdc;
327 wxBitmap bitmap(1, 1);
328 memdc.SelectObject(bitmap);
329 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
330 memdc.SelectObject(wxNullBitmap);
331 wxImage image(bitmap);
332 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
333 return TRUE;
334}
335
336void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
337{
3cd0b8c5 338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 339
3cd0b8c5
RR
340 if (m_pen.GetStyle() != wxTRANSPARENT)
341 {
342 if (m_window)
343 XDrawLine( (Display*) m_display, (Window) m_window,
344 (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
83df96d6 345
3cd0b8c5
RR
346 CalcBoundingBox(x1, y1);
347 CalcBoundingBox(x2, y2);
348 }
83df96d6
JS
349}
350
351void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
352{
3cd0b8c5 353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 354
3cd0b8c5
RR
355 if (m_pen.GetStyle() != wxTRANSPARENT)
356 {
357 int w = 0;
358 int h = 0;
359 GetSize( &w, &h );
360 wxCoord xx = XLOG2DEV(x);
361 wxCoord yy = YLOG2DEV(y);
362 if (m_window)
363 {
364 XDrawLine( (Display*) m_display, (Window) m_window,
365 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy );
366 XDrawLine( (Display*) m_display, (Window) m_window,
367 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
368 }
369 }
83df96d6
JS
370}
371
372void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
373{
3cd0b8c5
RR
374 wxCHECK_RET( Ok(), wxT("invalid window dc") );
375
376 wxCoord xx1 = XLOG2DEV(x1);
377 wxCoord yy1 = YLOG2DEV(y1);
378 wxCoord xx2 = XLOG2DEV(x2);
379 wxCoord yy2 = YLOG2DEV(y2);
380 wxCoord xxc = XLOG2DEV(xc);
381 wxCoord yyc = YLOG2DEV(yc);
382 double dx = xx1 - xxc;
383 double dy = yy1 - yyc;
384 double radius = sqrt((double)(dx*dx+dy*dy));
385 wxCoord r = (wxCoord)radius;
83df96d6
JS
386 double radius1, radius2;
387
388 if (xx1 == xx2 && yy1 == yy2)
389 {
390 radius1 = 0.0;
391 radius2 = 360.0;
392 }
83df96d6 393 else
3cd0b8c5 394 if (radius == 0.0)
83df96d6 395 {
3cd0b8c5 396 radius1 = radius2 = 0.0;
83df96d6 397 }
3cd0b8c5 398 else
83df96d6 399 {
3cd0b8c5
RR
400 radius1 = (xx1 - xxc == 0) ?
401 (yy1 - yyc < 0) ? 90.0 : -90.0 :
402 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
403 radius2 = (xx2 - xxc == 0) ?
404 (yy2 - yyc < 0) ? 90.0 : -90.0 :
405 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
83df96d6 406 }
3cd0b8c5
RR
407 wxCoord alpha1 = wxCoord(radius1 * 64.0);
408 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
409 while (alpha2 <= 0) alpha2 += 360*64;
410 while (alpha1 > 360*64) alpha1 -= 360*64;
83df96d6 411
3cd0b8c5 412 if (m_window)
83df96d6 413 {
3cd0b8c5
RR
414 if (m_brush.GetStyle() != wxTRANSPARENT)
415 {
416 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
417 {
418 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
419 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
420 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
421
422 XFillArc( (Display*) m_display, (Window) m_window,
423 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
424
425 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
426 } else
427 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
428 {
429 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
430 m_deviceOriginX % 15, m_deviceOriginY % 15 );
431
432 XFillArc( (Display*) m_display, (Window) m_window,
433 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
434
435 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
436 } else
437 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
438 {
439 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
440 m_deviceOriginX % 16, m_deviceOriginY % 16 );
441
442 XFillArc( (Display*) m_display, (Window) m_window,
443 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
444
445 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
446 } else
447 if (m_brush.GetStyle() == wxSTIPPLE)
448 {
449 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
450 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
451 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
452
453 XFillArc( (Display*) m_display, (Window) m_window,
454 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
455
456 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
457 }
458 else
459 {
460 XFillArc( (Display*) m_display, (Window) m_window,
461 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
462 }
463 }
464
465 if (m_pen.GetStyle() != wxTRANSPARENT)
466 {
467 XDrawArc( (Display*) m_display, (Window) m_window,
468 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
469
470 XDrawLine( (Display*) m_display, (Window) m_window,
471 (GC) m_penGC, xx1, yy1, xxc, yyc );
472
473 XDrawLine( (Display*) m_display, (Window) m_window,
474 (GC) m_penGC, xxc, yyc, xx2, yy2 );
475 }
83df96d6 476 }
3cd0b8c5 477
83df96d6
JS
478 CalcBoundingBox (x1, y1);
479 CalcBoundingBox (x2, y2);
480}
481
482void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
483{
3cd0b8c5 484 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 485
3cd0b8c5
RR
486 wxCoord xx = XLOG2DEV(x);
487 wxCoord yy = YLOG2DEV(y);
488 wxCoord ww = m_signX * XLOG2DEVREL(width);
489 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 490
3cd0b8c5
RR
491 // CMB: handle -ve width and/or height
492 if (ww < 0) { ww = -ww; xx = xx - ww; }
493 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 494
3cd0b8c5 495 if (m_window)
83df96d6 496 {
3cd0b8c5
RR
497 wxCoord start = wxCoord(sa * 64.0);
498 wxCoord end = wxCoord((ea-sa) * 64.0);
83df96d6 499
3cd0b8c5
RR
500 if (m_brush.GetStyle() != wxTRANSPARENT)
501 {
502 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
503 {
504 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
505 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
506 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
507
508 XFillArc( (Display*) m_display, (Window) m_window,
509 (GC) m_textGC, xx, yy, ww, hh, start, end );
510
511 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
512 } else
513 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
514 {
515 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
516 m_deviceOriginX % 15, m_deviceOriginY % 15 );
517
518 XFillArc( (Display*) m_display, (Window) m_window,
519 (GC) m_brushGC, xx, yy, ww, hh, start, end );
520
521 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
522 } else
523 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
524 {
525 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
526 m_deviceOriginX % 16, m_deviceOriginY % 16 );
527
528 XFillArc( (Display*) m_display, (Window) m_window,
529 (GC) m_brushGC, xx, yy, ww, hh, start, end );
530
531 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
532 } else
533 if (m_brush.GetStyle() == wxSTIPPLE)
534 {
535 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
536 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
537 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
538
539 XFillArc( (Display*) m_display, (Window) m_window,
540 (GC) m_brushGC, xx, yy, ww, hh, start, end );
541
542 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
543 }
544 else
545 {
546 XFillArc( (Display*) m_display, (Window) m_window,
547 (GC) m_brushGC, xx, yy, ww, hh, start, end );
548 }
549 }
83df96d6 550
3cd0b8c5
RR
551 if (m_pen.GetStyle() != wxTRANSPARENT)
552 {
553 XDrawArc( (Display*) m_display, (Window) m_window,
554 (GC) m_penGC, xx, yy, ww, hh, start, end );
555 }
83df96d6 556 }
3cd0b8c5 557
83df96d6
JS
558 CalcBoundingBox (x, y);
559 CalcBoundingBox (x + width, y + height);
560}
561
562void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
563{
3cd0b8c5 564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 565
3cd0b8c5
RR
566 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
567 XDrawPoint( (Display*) m_display, (Window) m_window,
568 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
83df96d6 569
83df96d6
JS
570 CalcBoundingBox (x, y);
571}
572
573void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
574{
3cd0b8c5 575 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 576
3cd0b8c5
RR
577 if (m_pen.GetStyle() == wxTRANSPARENT) return;
578 if (n <= 0) return;
83df96d6 579
3cd0b8c5
RR
580 XPoint *xpoints = new XPoint[n];
581 for (int i = 0; i < n; i++)
83df96d6 582 {
3cd0b8c5
RR
583 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
584 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
585
586 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
83df96d6 587 }
3cd0b8c5
RR
588 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 );
589
590 delete[] xpoints;
83df96d6
JS
591}
592
593void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
594 wxCoord xoffset, wxCoord yoffset, int fillStyle )
595{
3cd0b8c5 596 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 597
3cd0b8c5 598 if (n <= 0) return;
83df96d6 599
3cd0b8c5 600 XPoint *xpoints = new XPoint[n + 1];
83df96d6
JS
601 int i;
602 for (i = 0; i < n; i++)
603 {
3cd0b8c5
RR
604 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
605 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
606
83df96d6
JS
607 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
608 }
609
3cd0b8c5 610 if (m_window)
83df96d6 611 {
3cd0b8c5
RR
612 if (m_brush.GetStyle() != wxTRANSPARENT)
613 {
614
615 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
616 {
617 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
618 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
619 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
620
621 XFillPolygon( (Display*) m_display, (Window) m_window,
622 (GC) m_textGC, xpoints, n, Complex, 0);
623
624 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
625 } else
626 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
627 {
628 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
629 m_deviceOriginX % 15, m_deviceOriginY % 15 );
630
631 XFillPolygon( (Display*) m_display, (Window) m_window,
632 (GC) m_brushGC, xpoints, n, Complex, 0);
633
634 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
635 } else
636 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
637 {
638 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
639 m_deviceOriginX % 16, m_deviceOriginY % 16 );
640
641 XFillPolygon( (Display*) m_display, (Window) m_window,
642 (GC) m_brushGC, xpoints, n, Complex, 0);
643
644 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
645 } else
646 if (m_brush.GetStyle() == wxSTIPPLE)
647 {
648 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
649 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
650 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
651
652 XFillPolygon( (Display*) m_display, (Window) m_window,
653 (GC) m_brushGC, xpoints, n, Complex, 0);
654
655 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
656 }
657 else
658 {
659 XFillPolygon( (Display*) m_display, (Window) m_window,
660 (GC) m_brushGC, xpoints, n, Complex, 0);
661 }
662 }
83df96d6 663
3cd0b8c5
RR
664 if (m_pen.GetStyle () != wxTRANSPARENT)
665 {
666 // Close figure for XDrawLines
667 xpoints[i].x = xpoints[0].x;
668 xpoints[i].y = xpoints[0].y;
669
670 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n + 1, 0);
671 }
83df96d6
JS
672 }
673
3cd0b8c5 674 delete[] xpoints;
83df96d6
JS
675}
676
677void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
678{
3cd0b8c5 679 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 680
3cd0b8c5
RR
681 wxCoord xx = XLOG2DEV(x);
682 wxCoord yy = YLOG2DEV(y);
683 wxCoord ww = m_signX * XLOG2DEVREL(width);
684 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 685
3cd0b8c5
RR
686 // CMB: draw nothing if transformed w or h is 0
687 if (ww == 0 || hh == 0) return;
83df96d6 688
3cd0b8c5
RR
689 // CMB: handle -ve width and/or height
690 if (ww < 0) { ww = -ww; xx = xx - ww; }
691 if (hh < 0) { hh = -hh; yy = yy - hh; }
692
693 if (m_window)
83df96d6 694 {
3cd0b8c5
RR
695 if (m_brush.GetStyle() != wxTRANSPARENT)
696 {
697 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
698 {
699 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
700 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
701 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
702
703 XFillRectangle( (Display*) m_display, (Window) m_window,
704 (GC) m_textGC, xx, yy, ww, hh );
705
706 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
707 } else
708 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
709 {
710 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
711 m_deviceOriginX % 15, m_deviceOriginY % 15 );
712
713 XFillRectangle( (Display*) m_display, (Window) m_window,
714 (GC) m_brushGC, xx, yy, ww, hh );
715
716 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
717 } else
718 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
719 {
720 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
721 m_deviceOriginX % 16, m_deviceOriginY % 16 );
722
723 XFillRectangle( (Display*) m_display, (Window) m_window,
724 (GC) m_brushGC, xx, yy, ww, hh );
725
726 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
727 } else
728 if (m_brush.GetStyle() == wxSTIPPLE)
729 {
730 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
731 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
732 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
733
734 XFillRectangle( (Display*) m_display, (Window) m_window,
735 (GC) m_brushGC, xx, yy, ww, hh );
736
737 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
738 }
739 else
740 {
741 XFillRectangle( (Display*) m_display, (Window) m_window,
742 (GC) m_brushGC, xx, yy, ww, hh );
743 }
744 }
83df96d6 745
3cd0b8c5
RR
746 if (m_pen.GetStyle () != wxTRANSPARENT)
747 {
748 XDrawRectangle( (Display*) m_display, (Window) m_window,
887dd52f 749 (GC) m_penGC, xx, yy, ww-1, hh-1 );
3cd0b8c5 750 }
83df96d6 751 }
3cd0b8c5
RR
752
753 CalcBoundingBox( x, y );
754 CalcBoundingBox( x + width, y + height );
83df96d6
JS
755}
756
757void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
758{
3cd0b8c5
RR
759 // later
760}
83df96d6 761
3cd0b8c5
RR
762void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
763{
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 765
3cd0b8c5
RR
766 wxCoord xx = XLOG2DEV(x);
767 wxCoord yy = YLOG2DEV(y);
768 wxCoord ww = m_signX * XLOG2DEVREL(width);
769 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 770
3cd0b8c5
RR
771 // CMB: handle -ve width and/or height
772 if (ww < 0) { ww = -ww; xx = xx - ww; }
773 if (hh < 0) { hh = -hh; yy = yy - hh; }
83df96d6 774
3cd0b8c5 775 if (m_window)
83df96d6 776 {
3cd0b8c5
RR
777 if (m_brush.GetStyle() != wxTRANSPARENT)
778 {
779 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
780 {
781 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
782 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
783 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
784
785 XFillArc( (Display*) m_display, (Window) m_window,
786 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
787
788 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
789 } else
790 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
791 {
792 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
793 m_deviceOriginX % 15, m_deviceOriginY % 15 );
794
795 XFillArc( (Display*) m_display, (Window) m_window,
796 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
797
798 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
799 } else
800 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
801 {
802 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
803 m_deviceOriginX % 16, m_deviceOriginY % 16 );
804
805 XFillArc( (Display*) m_display, (Window) m_window,
806 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
807
808 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
809 } else
810 if (m_brush.GetStyle() == wxSTIPPLE)
811 {
812 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
813 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
814 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
815
816 XFillArc( (Display*) m_display, (Window) m_window,
817 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
818
819 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
820 }
821 else
822 {
823 XFillArc( (Display*) m_display, (Window) m_window,
824 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
825 }
826 }
83df96d6 827
3cd0b8c5
RR
828 if (m_pen.GetStyle () != wxTRANSPARENT)
829 {
830 XDrawArc( (Display*) m_display, (Window) m_window,
831 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 );
832 }
83df96d6 833 }
83df96d6 834
3cd0b8c5
RR
835 CalcBoundingBox( x, y );
836 CalcBoundingBox( x + width, y + height );
837}
83df96d6 838
3cd0b8c5
RR
839void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
840{
21689736 841 DoDrawBitmap(icon, x, y, TRUE);
83df96d6
JS
842}
843
c978d361
JS
844#if wxUSE_NANOX
845void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
846 wxCoord x, wxCoord y,
847 bool useMask )
848{
849 wxCHECK_RET( Ok(), wxT("invalid window dc") );
850
851 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
852
853 bool is_mono = (bitmap.GetBitmap() != NULL);
854
855 /* scale/translate size and position */
856 int xx = XLOG2DEV(x);
857 int yy = YLOG2DEV(y);
858
859 int w = bitmap.GetWidth();
860 int h = bitmap.GetHeight();
861
862 CalcBoundingBox( x, y );
863 CalcBoundingBox( x + w, y + h );
864
865 if (!m_window) return;
866
867 int ww = XLOG2DEVREL(w);
868 int hh = YLOG2DEVREL(h);
869
870 /* compare to current clipping region */
871 if (!m_currentClippingRegion.IsNull())
872 {
873 wxRegion tmp( xx,yy,ww,hh );
874 tmp.Intersect( m_currentClippingRegion );
875 if (tmp.IsEmpty())
876 return;
877 }
878
879 /* scale bitmap if required */
880 wxBitmap use_bitmap;
881 if ((w != ww) || (h != hh))
882 {
883 wxImage image( bitmap );
884 image.Rescale( ww, hh );
885#if 0
886 if (is_mono)
887 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
888 else
889#endif
890 use_bitmap = image.ConvertToBitmap();
891 }
892 else
893 {
894 use_bitmap = bitmap;
895 }
896
897 /* apply mask if any */
898 WXPixmap mask = NULL;
899 if (use_bitmap.GetMask())
900 mask = use_bitmap.GetMask()->GetBitmap();
901
902 if (useMask && mask)
903 {
904 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
905 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
906 Pixmap bufPixmap = GrNewPixmap(w, h, 0);
907 GC gc = GrNewGC();
908 GrSetGCUseBackground(gc, FALSE);
909 GrSetGCMode(gc, GR_MODE_COPY);
910
911 // This code assumes that background and foreground
912 // colours are used in ROPs, like in MSW.
913 // Not sure if this is true.
914
915 // Copy destination to buffer.
916 // In DoBlit, we need this step because Blit has
917 // a ROP argument. Here, we don't need it.
918 // In DoBlit, we may be able to eliminate this step
919 // if we check if the rop = copy
920#if 0
921 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
922 0, 0, GR_MODE_COPY);
923#endif
924
925 // Copy src to buffer using selected raster op (none selected
926 // in DrawBitmap, so just use Gxcopy)
927 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
928 0, 0, GR_MODE_COPY);
929
930 // Set masked area in buffer to BLACK (pixel value 0)
931 GrSetGCBackground(gc, WHITE);
932 GrSetGCForeground(gc, BLACK);
933 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
934 0, 0, GR_MODE_AND);
935
936 // set unmasked area in dest to BLACK
937 GrSetGCBackground(gc, BLACK);
938 GrSetGCForeground(gc, WHITE);
939 GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
940 0, 0, GR_MODE_AND);
941
942 // OR buffer to dest
943 GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
944 0, 0, GR_MODE_OR);
945
946 GrDestroyGC(gc);
947 GrDestroyWindow(bufPixmap);
948 }
949 else
950 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
951 (GC) m_penGC, 0, 0, w, h, xx, yy );
952
953 /* remove mask again if any */
954 if (useMask && mask)
955 {
956 if (!m_currentClippingRegion.IsNull())
957 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
958 }
959}
960
961#else
962
963// Normal X11
3cd0b8c5
RR
964void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
965 wxCoord x, wxCoord y,
966 bool useMask )
83df96d6 967{
3cd0b8c5 968 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 969
3cd0b8c5
RR
970 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
971
3cd0b8c5 972 bool is_mono = (bitmap.GetBitmap() != NULL);
83df96d6 973
b1633d20 974 // scale/translate size and position
3cd0b8c5
RR
975 int xx = XLOG2DEV(x);
976 int yy = YLOG2DEV(y);
83df96d6 977
3cd0b8c5
RR
978 int w = bitmap.GetWidth();
979 int h = bitmap.GetHeight();
83df96d6 980
3cd0b8c5
RR
981 CalcBoundingBox( x, y );
982 CalcBoundingBox( x + w, y + h );
83df96d6 983
3cd0b8c5 984 if (!m_window) return;
83df96d6 985
3cd0b8c5
RR
986 int ww = XLOG2DEVREL(w);
987 int hh = YLOG2DEVREL(h);
83df96d6 988
b1633d20 989 // compare to current clipping region
3cd0b8c5 990 if (!m_currentClippingRegion.IsNull())
83df96d6 991 {
3cd0b8c5
RR
992 wxRegion tmp( xx,yy,ww,hh );
993 tmp.Intersect( m_currentClippingRegion );
994 if (tmp.IsEmpty())
995 return;
83df96d6
JS
996 }
997
b1633d20 998 // scale bitmap if required
3cd0b8c5
RR
999 wxBitmap use_bitmap;
1000 if ((w != ww) || (h != hh))
83df96d6 1001 {
3cd0b8c5
RR
1002 wxImage image( bitmap );
1003 image.Rescale( ww, hh );
a11672a4 1004#if 0
3cd0b8c5
RR
1005 if (is_mono)
1006 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1007 else
a11672a4 1008#endif
3cd0b8c5
RR
1009 use_bitmap = image.ConvertToBitmap();
1010 }
1011 else
1012 {
1013 use_bitmap = bitmap;
83df96d6 1014 }
83df96d6 1015
b1633d20 1016 // apply mask if any
a11672a4 1017 WXPixmap mask = NULL;
3cd0b8c5 1018 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
b1633d20 1019
3cd0b8c5
RR
1020 if (useMask && mask)
1021 {
a11672a4
RR
1022 WXPixmap new_mask = NULL;
1023#if 0
3cd0b8c5
RR
1024 if (!m_currentClippingRegion.IsNull())
1025 {
1026 GdkColor col;
1027 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1028 GdkGC *gc = gdk_gc_new( new_mask );
1029 col.pixel = 0;
1030 gdk_gc_set_foreground( gc, &col );
1031 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1032 col.pixel = 0;
1033 gdk_gc_set_background( gc, &col );
1034 col.pixel = 1;
1035 gdk_gc_set_foreground( gc, &col );
1036 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1037 gdk_gc_set_clip_origin( gc, -xx, -yy );
1038 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1039 gdk_gc_set_stipple( gc, mask );
1040 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1041 gdk_gc_unref( gc );
1042 }
a11672a4 1043#endif
3cd0b8c5
RR
1044 if (is_mono)
1045 {
1046 if (new_mask)
a11672a4 1047 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1048 else
a11672a4
RR
1049 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1050 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
3cd0b8c5
RR
1051 }
1052 else
1053 {
1054 if (new_mask)
a11672a4 1055 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1056 else
a11672a4
RR
1057 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1058 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
3cd0b8c5 1059 }
a11672a4 1060
3cd0b8c5 1061 if (new_mask)
a11672a4 1062 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1063 }
83df96d6 1064
b1633d20
RR
1065 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1066 // drawing a mono-bitmap (XBitmap) we use the current text GC
3cd0b8c5 1067 if (is_mono)
a11672a4
RR
1068 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1069 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
3cd0b8c5 1070 else
a11672a4
RR
1071 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1072 (GC) m_penGC, 0, 0, w, h, xx, yy );
3cd0b8c5 1073
b1633d20 1074 // remove mask again if any
3cd0b8c5 1075 if (useMask && mask)
83df96d6 1076 {
3cd0b8c5 1077 if (is_mono)
83df96d6 1078 {
a11672a4
RR
1079 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1080 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1081 if (!m_currentClippingRegion.IsNull())
a11672a4 1082 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1083 }
1084 else
1085 {
a11672a4
RR
1086 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1087 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1088 if (!m_currentClippingRegion.IsNull())
a11672a4 1089 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6 1090 }
83df96d6 1091 }
83df96d6 1092}
c978d361
JS
1093#endif
1094 // wxUSE_NANOX/!wxUSE_NANOX
83df96d6 1095
83df96d6 1096bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
b1633d20 1097 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
83df96d6
JS
1098 wxCoord xsrcMask, wxCoord ysrcMask )
1099{
3cd0b8c5
RR
1100 /* this is the nth try to get this utterly useless function to
1101 work. it now completely ignores the scaling or translation
1102 of the source dc, but scales correctly on the target dc and
1103 knows about possible mask information in a memory dc. */
83df96d6 1104
3cd0b8c5 1105 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
83df96d6 1106
3cd0b8c5 1107 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
83df96d6 1108
3cd0b8c5 1109 if (!m_window) return FALSE;
83df96d6 1110
3cd0b8c5
RR
1111 // transform the source DC coords to the device ones
1112 xsrc = source->XLOG2DEV(xsrc);
1113 ysrc = source->YLOG2DEV(ysrc);
83df96d6 1114
3cd0b8c5
RR
1115 wxClientDC *srcDC = (wxClientDC*)source;
1116 wxMemoryDC *memDC = (wxMemoryDC*)source;
83df96d6 1117
3cd0b8c5
RR
1118 bool use_bitmap_method = FALSE;
1119 bool is_mono = FALSE;
83df96d6 1120
b1633d20 1121 // TODO: use the mask origin when drawing transparently
83df96d6
JS
1122 if (xsrcMask == -1 && ysrcMask == -1)
1123 {
b1633d20
RR
1124 xsrcMask = xsrc;
1125 ysrcMask = ysrc;
83df96d6 1126 }
a11672a4 1127
3cd0b8c5 1128 if (srcDC->m_isMemDC)
83df96d6 1129 {
3cd0b8c5 1130 if (!memDC->m_selected.Ok()) return FALSE;
83df96d6 1131
3cd0b8c5
RR
1132 /* we use the "XCopyArea" way to copy a memory dc into
1133 y different window if the memory dc BOTH
1134 a) doesn't have any mask or its mask isn't used
1135 b) it is clipped
1136 c) is not 1-bit */
83df96d6 1137
3cd0b8c5 1138 if (useMask && (memDC->m_selected.GetMask()))
83df96d6 1139 {
3cd0b8c5
RR
1140 /* we HAVE TO use the direct way for memory dcs
1141 that have mask since the XCopyArea doesn't know
1142 about masks */
1143 use_bitmap_method = TRUE;
1144 }
1145 else if (memDC->m_selected.GetDepth() == 1)
1146 {
1147 /* we HAVE TO use the direct way for memory dcs
1148 that are bitmaps because XCopyArea doesn't cope
1149 with different bit depths */
1150 is_mono = TRUE;
1151 use_bitmap_method = TRUE;
1152 }
1153 else if ((xsrc == 0) && (ysrc == 0) &&
1154 (width == memDC->m_selected.GetWidth()) &&
1155 (height == memDC->m_selected.GetHeight()))
1156 {
1157 /* we SHOULD use the direct way if all of the bitmap
1158 in the memory dc is copied in which case XCopyArea
1159 wouldn't be able able to boost performace by reducing
1160 the area to be scaled */
1161 use_bitmap_method = TRUE;
83df96d6
JS
1162 }
1163 else
1164 {
3cd0b8c5 1165 use_bitmap_method = FALSE;
83df96d6
JS
1166 }
1167 }
83df96d6 1168
3cd0b8c5
RR
1169 CalcBoundingBox( xdest, ydest );
1170 CalcBoundingBox( xdest + width, ydest + height );
1171
b1633d20 1172 // scale/translate size and position
3cd0b8c5
RR
1173 wxCoord xx = XLOG2DEV(xdest);
1174 wxCoord yy = YLOG2DEV(ydest);
1175
1176 wxCoord ww = XLOG2DEVREL(width);
1177 wxCoord hh = YLOG2DEVREL(height);
1178
b1633d20 1179 // compare to current clipping region
3cd0b8c5 1180 if (!m_currentClippingRegion.IsNull())
83df96d6 1181 {
3cd0b8c5
RR
1182 wxRegion tmp( xx,yy,ww,hh );
1183 tmp.Intersect( m_currentClippingRegion );
1184 if (tmp.IsEmpty())
1185 return TRUE;
1186 }
83df96d6 1187
3cd0b8c5
RR
1188 int old_logical_func = m_logicalFunction;
1189 SetLogicalFunction( logical_func );
83df96d6 1190
3cd0b8c5
RR
1191 if (use_bitmap_method)
1192 {
b1633d20 1193 // scale/translate bitmap size
3cd0b8c5
RR
1194 wxCoord bm_width = memDC->m_selected.GetWidth();
1195 wxCoord bm_height = memDC->m_selected.GetHeight();
83df96d6 1196
3cd0b8c5
RR
1197 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1198 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1199
b1633d20 1200 // scale bitmap if required
3cd0b8c5 1201 wxBitmap use_bitmap;
83df96d6 1202
3cd0b8c5
RR
1203 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1204 {
1205 wxImage image( memDC->m_selected );
1206 image = image.Scale( bm_ww, bm_hh );
83df96d6 1207
b1633d20 1208#if 0
3cd0b8c5
RR
1209 if (is_mono)
1210 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1211 else
b1633d20 1212#endif
3cd0b8c5
RR
1213 use_bitmap = image.ConvertToBitmap();
1214 }
1215 else
1216 {
1217 use_bitmap = memDC->m_selected;
1218 }
1219
b1633d20
RR
1220 // apply mask if any
1221 WXPixmap mask = NULL;
3cd0b8c5 1222 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1223
3cd0b8c5 1224 if (useMask && mask)
83df96d6 1225 {
b1633d20
RR
1226 WXPixmap new_mask = NULL;
1227#if 0
3cd0b8c5 1228 if (!m_currentClippingRegion.IsNull())
83df96d6 1229 {
3cd0b8c5
RR
1230 GdkColor col;
1231 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1232 GdkGC *gc = gdk_gc_new( new_mask );
1233 col.pixel = 0;
1234 gdk_gc_set_foreground( gc, &col );
1235 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1236 col.pixel = 0;
1237 gdk_gc_set_background( gc, &col );
1238 col.pixel = 1;
1239 gdk_gc_set_foreground( gc, &col );
1240 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1241 gdk_gc_set_clip_origin( gc, -xx, -yy );
1242 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1243 gdk_gc_set_stipple( gc, mask );
1244 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1245 gdk_gc_unref( gc );
83df96d6 1246 }
b1633d20 1247#endif
3cd0b8c5 1248 if (is_mono)
83df96d6 1249 {
3cd0b8c5 1250 if (new_mask)
b1633d20 1251 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1252 else
b1633d20
RR
1253 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1254 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
83df96d6
JS
1255 }
1256 else
1257 {
3cd0b8c5 1258 if (new_mask)
b1633d20 1259 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1260 else
b1633d20
RR
1261 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1262 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
83df96d6 1263 }
b1633d20 1264
3cd0b8c5 1265 if (new_mask)
b1633d20 1266 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1267 }
83df96d6 1268
b1633d20
RR
1269 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1270 // drawing a mono-bitmap (XBitmap) we use the current text GC
83df96d6 1271
3cd0b8c5 1272 if (is_mono)
b1633d20
RR
1273 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1274 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
83df96d6 1275 else
b1633d20
RR
1276 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1277 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
83df96d6 1278
b1633d20 1279 // remove mask again if any
3cd0b8c5 1280 if (useMask && mask)
83df96d6 1281 {
3cd0b8c5
RR
1282 if (is_mono)
1283 {
b1633d20
RR
1284 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1285 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1286 if (!m_currentClippingRegion.IsNull())
b1633d20 1287 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
3cd0b8c5
RR
1288 }
1289 else
83df96d6 1290 {
b1633d20
RR
1291 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1292 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1293 if (!m_currentClippingRegion.IsNull())
b1633d20 1294 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1295 }
1296 }
83df96d6 1297 }
b1633d20 1298 else // use_bitmap_method
83df96d6 1299 {
3cd0b8c5 1300 if ((width != ww) || (height != hh))
83df96d6 1301 {
b1633d20 1302 /* Draw source window into a bitmap as we cannot scale
3cd0b8c5
RR
1303 a window in contrast to a bitmap. this would actually
1304 work with memory dcs as well, but we'd lose the mask
1305 information and waste one step in this process since
1306 a memory already has a bitmap. all this is slightly
1307 inefficient as we could take an XImage directly from
1308 an X window, but we'd then also have to care that
1309 the window is not outside the screen (in which case
1310 we'd get a BadMatch or what not).
1311 Is a double XGetImage and combined XGetPixel and
1312 XPutPixel really faster? I'm not sure. look at wxXt
1313 for a different implementation of the same problem. */
1314
1315 wxBitmap bitmap( width, height );
1316
b1633d20
RR
1317 // copy including child window contents
1318 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1319 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1320 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1321 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1322
b1633d20 1323 // scale image
3cd0b8c5
RR
1324 wxImage image( bitmap );
1325 image = image.Scale( ww, hh );
1326
b1633d20 1327 // convert to bitmap
3cd0b8c5
RR
1328 bitmap = image.ConvertToBitmap();
1329
b1633d20
RR
1330 // draw scaled bitmap
1331 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1332 (GC) m_penGC, 0, 0, width, height, xx, yy );
83df96d6
JS
1333 }
1334 else
3cd0b8c5 1335 {
b1633d20
RR
1336 // No scaling and not a memory dc with a mask either
1337
1338 // copy including child window contents
1339 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1340 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1341 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1342 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1343 }
83df96d6
JS
1344 }
1345
3cd0b8c5 1346 SetLogicalFunction( old_logical_func );
b1633d20 1347
3cd0b8c5 1348 return TRUE;
83df96d6
JS
1349}
1350
3cd0b8c5 1351void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1352{
3cd0b8c5 1353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1354
3cd0b8c5 1355 if (!m_window) return;
83df96d6 1356
3cd0b8c5 1357 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
83df96d6 1358
3cd0b8c5 1359 wxCHECK_RET( xfont, wxT("invalid font") );
83df96d6 1360
3cd0b8c5
RR
1361 x = XLOG2DEV(x);
1362 y = YLOG2DEV(y);
83df96d6 1363
3cd0b8c5
RR
1364#if 0
1365 wxCoord width = gdk_string_width( font, text.mbc_str() );
1366 wxCoord height = font->ascent + font->descent;
83df96d6 1367
3cd0b8c5 1368 if ( m_backgroundMode == wxSOLID )
83df96d6 1369 {
3cd0b8c5
RR
1370 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
1371 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
1372 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
83df96d6 1373 }
3cd0b8c5
RR
1374#endif
1375
1376 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1377#if !wxUSE_NANOX
3cd0b8c5 1378 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1379#endif
1380 {
3cd0b8c5 1381 XDrawString( (Display*) m_display, (Window) m_window,
788519c6
JS
1382 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1383 }
83df96d6
JS
1384
1385#if 0
3cd0b8c5 1386 if (m_font.GetUnderlined())
83df96d6 1387 {
788519c6 1388 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5
RR
1389 if (font->descent > 0) ul_y++;
1390 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1391 }
83df96d6 1392
3cd0b8c5
RR
1393 width = wxCoord(width / m_scaleX);
1394 height = wxCoord(height / m_scaleY);
1395
1396 CalcBoundingBox (x + width, y + height);
83df96d6 1397 CalcBoundingBox (x, y);
3cd0b8c5 1398#endif
83df96d6
JS
1399}
1400
3cd0b8c5 1401void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
83df96d6 1402{
3cd0b8c5 1403 // later
83df96d6
JS
1404}
1405
1406void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1407 wxCoord *descent, wxCoord *externalLeading,
1408 wxFont *font ) const
1409{
1410 wxCHECK_RET( Ok(), "invalid dc" );
1411
3cd0b8c5
RR
1412 wxFont fontToUse = m_font;
1413 if (font) fontToUse = *font;
83df96d6 1414
3cd0b8c5 1415 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
83df96d6 1416
3cd0b8c5 1417 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1418
3cd0b8c5
RR
1419 wxCHECK_RET( xfont, wxT("invalid font") );
1420
83df96d6
JS
1421 int direction, ascent, descent2;
1422 XCharStruct overall;
83df96d6 1423
788519c6 1424 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
83df96d6
JS
1425 &ascent, &descent2, &overall);
1426
3cd0b8c5
RR
1427 if (width)
1428 *width = (wxCoord)( overall.width / m_scaleX );
1429 if (height)
1430 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1431 if (descent)
3cd0b8c5 1432 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1433 if (externalLeading)
3cd0b8c5 1434 *externalLeading = 0; // ??
83df96d6
JS
1435}
1436
1437wxCoord wxWindowDC::GetCharWidth() const
1438{
1439 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1440
83df96d6
JS
1441 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1442
3cd0b8c5
RR
1443 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1444
1445 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1446
1447 int direction, ascent, descent;
1448 XCharStruct overall;
3cd0b8c5
RR
1449
1450 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1451
1452 return (wxCoord)(overall.width / m_scaleX);
83df96d6
JS
1453}
1454
1455wxCoord wxWindowDC::GetCharHeight() const
1456{
1457 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1458
83df96d6
JS
1459 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1460
3cd0b8c5
RR
1461 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1462
1463 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1464
1465 int direction, ascent, descent;
1466 XCharStruct overall;
3cd0b8c5
RR
1467
1468 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1469
1470 return (wxCoord)((ascent+descent) / m_scaleY);
83df96d6
JS
1471}
1472
1473void wxWindowDC::Clear()
1474{
3cd0b8c5 1475 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1476
3cd0b8c5 1477 if (!m_window) return;
83df96d6 1478
3cd0b8c5
RR
1479 /* - we either are a memory dc or have a window as the
1480 owner. anything else shouldn't happen.
1481 - we don't use gdk_window_clear() as we don't set
1482 the window's background colour anymore. it is too
1483 much pain to keep the DC's and the window's back-
1484 ground colour in synch. */
83df96d6 1485
3cd0b8c5
RR
1486 if (m_owner)
1487 {
1488 int width,height;
1489 m_owner->GetSize( &width, &height );
1490 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1491 return;
1492 }
83df96d6 1493
3cd0b8c5
RR
1494 if (m_isMemDC)
1495 {
1496 int width,height;
1497 GetSize( &width, &height );
1498 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1499 return;
1500 }
83df96d6
JS
1501}
1502
1503void wxWindowDC::SetFont( const wxFont &font )
1504{
1505 wxCHECK_RET( Ok(), "invalid dc" );
1506
1507 m_font = font;
83df96d6
JS
1508}
1509
1510void wxWindowDC::SetPen( const wxPen &pen )
1511{
3cd0b8c5
RR
1512 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1513
1514 if (m_pen == pen) return;
83df96d6
JS
1515
1516 m_pen = pen;
83df96d6 1517
3cd0b8c5 1518 if (!m_pen.Ok()) return;
83df96d6 1519
3cd0b8c5 1520 if (!m_window) return;
83df96d6 1521
3cd0b8c5
RR
1522 int width = m_pen.GetWidth();
1523 if (width <= 0)
1524 {
1525 // CMB: if width is non-zero scale it with the dc
1526 width = 1;
1527 }
1528 else
1529 {
1530 // X doesn't allow different width in x and y and so we take
1531 // the average
1532 double w = 0.5 +
1533 ( fabs((double) XLOG2DEVREL(width)) +
1534 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1535 width = (int)w;
1536 }
1537
1538 static const wxX11Dash dotted[] = {1, 1};
1539 static const wxX11Dash short_dashed[] = {2, 2};
1540 static const wxX11Dash long_dashed[] = {2, 4};
1541 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1542
1543 // We express dash pattern in pen width unit, so we are
1544 // independent of zoom factor and so on...
1545 int req_nb_dash;
1546 const wxX11Dash *req_dash;
1547
1548 int lineStyle = LineSolid;
1549 switch (m_pen.GetStyle())
83df96d6 1550 {
83df96d6 1551 case wxUSER_DASH:
3cd0b8c5
RR
1552 {
1553 lineStyle = LineOnOffDash;
1554 req_nb_dash = m_pen.GetDashCount();
1555 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1556 break;
3cd0b8c5 1557 }
83df96d6 1558 case wxDOT:
3cd0b8c5
RR
1559 {
1560 lineStyle = LineOnOffDash;
83df96d6
JS
1561 req_nb_dash = 2;
1562 req_dash = dotted;
83df96d6 1563 break;
3cd0b8c5 1564 }
83df96d6 1565 case wxLONG_DASH:
3cd0b8c5
RR
1566 {
1567 lineStyle = LineOnOffDash;
83df96d6
JS
1568 req_nb_dash = 2;
1569 req_dash = long_dashed;
83df96d6 1570 break;
3cd0b8c5
RR
1571 }
1572 case wxSHORT_DASH:
1573 {
1574 lineStyle = LineOnOffDash;
1575 req_nb_dash = 2;
1576 req_dash = short_dashed;
1577 break;
1578 }
83df96d6 1579 case wxDOT_DASH:
3cd0b8c5
RR
1580 {
1581// lineStyle = LineDoubleDash;
1582 lineStyle = LineOnOffDash;
83df96d6
JS
1583 req_nb_dash = 4;
1584 req_dash = dotted_dashed;
83df96d6 1585 break;
3cd0b8c5
RR
1586 }
1587
1588 case wxTRANSPARENT:
1589 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1590 case wxSTIPPLE:
1591 case wxSOLID:
83df96d6 1592 default:
3cd0b8c5
RR
1593 {
1594 lineStyle = LineSolid;
74dc5eb6 1595 req_dash = (wxX11Dash*)NULL;
83df96d6 1596 req_nb_dash = 0;
3cd0b8c5 1597 break;
83df96d6 1598 }
3cd0b8c5 1599 }
83df96d6 1600
3cd0b8c5
RR
1601 int capStyle = CapRound;
1602 switch (m_pen.GetCap())
1603 {
1604 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1605 case wxCAP_BUTT: { capStyle = CapButt; break; }
1606 case wxCAP_ROUND:
1607 default:
83df96d6 1608 {
3cd0b8c5 1609 if (width <= 1)
83df96d6 1610 {
3cd0b8c5
RR
1611 width = 0;
1612 capStyle = CapNotLast;
83df96d6
JS
1613 }
1614 else
1615 {
3cd0b8c5 1616 capStyle = CapRound;
83df96d6 1617 }
83df96d6
JS
1618 break;
1619 }
3cd0b8c5 1620 }
83df96d6 1621
3cd0b8c5
RR
1622 int joinStyle = JoinRound;
1623 switch (m_pen.GetJoin())
1624 {
1625 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1626 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1627 case wxJOIN_ROUND:
3cd0b8c5 1628 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1629 }
1630
3cd0b8c5 1631 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1632
3cd0b8c5
RR
1633 m_pen.GetColour().CalcPixel( m_cmap );
1634 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1635}
83df96d6 1636
3cd0b8c5
RR
1637void wxWindowDC::SetBrush( const wxBrush &brush )
1638{
1639 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1640
3cd0b8c5 1641 if (m_brush == brush) return;
83df96d6 1642
3cd0b8c5
RR
1643 m_brush = brush;
1644
1645 if (!m_brush.Ok()) return;
83df96d6 1646
3cd0b8c5
RR
1647 if (!m_window) return;
1648
1649 m_brush.GetColour().CalcPixel( m_cmap );
1650 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1651
1652 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1653
1654 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1655 {
3cd0b8c5 1656 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1657 {
3cd0b8c5
RR
1658 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1659 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1660 }
1661 else
1662 {
3cd0b8c5 1663 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1664 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1665 }
3cd0b8c5 1666 }
83df96d6 1667
3cd0b8c5
RR
1668 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1669 {
1670 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1671 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1672 }
83df96d6 1673
3cd0b8c5
RR
1674 if (IS_HATCH(m_brush.GetStyle()))
1675 {
1676 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1677 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1678 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1679 }
83df96d6
JS
1680}
1681
3cd0b8c5 1682void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1683{
3cd0b8c5
RR
1684 /* CMB 21/7/98: Added SetBackground. Sets background brush
1685 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1686
3cd0b8c5 1687 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1688
3cd0b8c5 1689 if (m_backgroundBrush == brush) return;
83df96d6 1690
3cd0b8c5 1691 m_backgroundBrush = brush;
83df96d6 1692
3cd0b8c5 1693 if (!m_backgroundBrush.Ok()) return;
83df96d6 1694
3cd0b8c5 1695 if (!m_window) return;
83df96d6 1696
3cd0b8c5
RR
1697 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1698 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1699 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1700 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1701 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1702
3cd0b8c5 1703 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1704
3cd0b8c5 1705 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1706 {
3cd0b8c5 1707 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1708 {
3cd0b8c5
RR
1709 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1710 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1711 }
3cd0b8c5 1712 else
83df96d6 1713 {
3cd0b8c5 1714 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1715 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1716 }
83df96d6
JS
1717 }
1718
3cd0b8c5 1719 if (IS_HATCH(m_backgroundBrush.GetStyle()))
83df96d6 1720 {
3cd0b8c5
RR
1721 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1722 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1723 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1724 }
83df96d6
JS
1725}
1726
1727void wxWindowDC::SetLogicalFunction( int function )
1728{
1729 wxCHECK_RET( Ok(), "invalid dc" );
1730
1731 int x_function;
1732
83df96d6
JS
1733 if (m_logicalFunction == function)
1734 return;
1735
3cd0b8c5
RR
1736 // VZ: shouldn't this be a CHECK?
1737 if (!m_window)
1738 return;
1739
83df96d6
JS
1740 switch (function)
1741 {
1742 case wxCLEAR:
1743 x_function = GXclear;
1744 break;
1745 case wxXOR:
1746 x_function = GXxor;
1747 break;
1748 case wxINVERT:
1749 x_function = GXinvert;
1750 break;
1751 case wxOR_REVERSE:
1752 x_function = GXorReverse;
1753 break;
1754 case wxAND_REVERSE:
1755 x_function = GXandReverse;
1756 break;
1757 case wxAND:
1758 x_function = GXand;
1759 break;
1760 case wxOR:
1761 x_function = GXor;
1762 break;
1763 case wxAND_INVERT:
1764 x_function = GXandInverted;
1765 break;
1766 case wxNO_OP:
1767 x_function = GXnoop;
1768 break;
1769 case wxNOR:
1770 x_function = GXnor;
1771 break;
1772 case wxEQUIV:
1773 x_function = GXequiv;
1774 break;
1775 case wxSRC_INVERT:
1776 x_function = GXcopyInverted;
1777 break;
1778 case wxOR_INVERT:
1779 x_function = GXorInverted;
1780 break;
1781 case wxNAND:
1782 x_function = GXnand;
1783 break;
1784 case wxSET:
1785 x_function = GXset;
1786 break;
1787 case wxCOPY:
1788 default:
1789 x_function = GXcopy;
1790 break;
1791 }
1792
3cd0b8c5
RR
1793 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1794 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 1795
3cd0b8c5
RR
1796 // to stay compatible with wxMSW, we don't apply ROPs to the text
1797 // operations (i.e. DrawText/DrawRotatedText).
1798 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1799 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1800
83df96d6 1801 m_logicalFunction = function;
83df96d6
JS
1802}
1803
1804void wxWindowDC::SetTextForeground( const wxColour &col )
1805{
3cd0b8c5 1806 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1807
3cd0b8c5
RR
1808 // don't set m_textForegroundColour to an invalid colour as we'd crash
1809 // later then (we use m_textForegroundColour.GetColor() without checking
1810 // in a few places)
1811 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
1812 return;
1813
1814 m_textForegroundColour = col;
1815
3cd0b8c5
RR
1816 if (m_window)
1817 {
1818 m_textForegroundColour.CalcPixel( m_cmap );
1819 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1820 }
83df96d6
JS
1821}
1822
1823void wxWindowDC::SetTextBackground( const wxColour &col )
1824{
3cd0b8c5 1825 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1826
3cd0b8c5
RR
1827 // same as above
1828 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
1829 return;
1830
1831 m_textBackgroundColour = col;
3cd0b8c5
RR
1832
1833 if (m_window)
1834 {
1835 m_textBackgroundColour.CalcPixel( m_cmap );
1836 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1837 }
83df96d6
JS
1838}
1839
1840void wxWindowDC::SetBackgroundMode( int mode )
1841{
3cd0b8c5
RR
1842 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1843
83df96d6 1844 m_backgroundMode = mode;
3cd0b8c5 1845
0b5c0e1a
JS
1846#if wxUSE_NANOX
1847 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1848#endif
1849
3cd0b8c5
RR
1850 if (!m_window) return;
1851
1852 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1853 // transparent/solid background mode
1854
1855 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1856 {
1857 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1858 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1859 }
83df96d6
JS
1860}
1861
1862void wxWindowDC::SetPalette( const wxPalette& palette )
1863{
3cd0b8c5 1864#if 0
83df96d6
JS
1865 if (m_window)
1866 {
1867 if (palette.Ok())
1868 /* Use GetXColormap */
1869 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1870 (Colormap) palette.GetXColormap());
1871 else
1872 /* Use wxGetMainColormap */
1873 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1874 (Colormap) wxTheApp->GetMainColormap(m_display));
1875 }
3cd0b8c5 1876#endif
83df96d6
JS
1877}
1878
3cd0b8c5 1879void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 1880{
3cd0b8c5 1881 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1882
3cd0b8c5 1883 if (!m_window) return;
83df96d6 1884
3cd0b8c5
RR
1885 wxRect rect;
1886 rect.x = XLOG2DEV(x);
1887 rect.y = YLOG2DEV(y);
1888 rect.width = XLOG2DEVREL(width);
1889 rect.height = YLOG2DEVREL(height);
1890
1891 if (!m_currentClippingRegion.IsNull())
1892 m_currentClippingRegion.Intersect( rect );
83df96d6 1893 else
3cd0b8c5
RR
1894 m_currentClippingRegion.Union( rect );
1895
1896#if USE_PAINT_REGION
1897 if (!m_paintClippingRegion.IsNull())
1898 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1899#endif
1900
1901 wxCoord xx, yy, ww, hh;
1902 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1903 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1904
1905 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1906 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1907 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1908 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1909}
83df96d6 1910
3cd0b8c5
RR
1911void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1912{
1913 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1914
3cd0b8c5 1915 if (region.Empty())
83df96d6 1916 {
3cd0b8c5
RR
1917 DestroyClippingRegion();
1918 return;
83df96d6 1919 }
3cd0b8c5
RR
1920
1921 if (!m_window) return;
1922
1923 if (!m_currentClippingRegion.IsNull())
1924 m_currentClippingRegion.Intersect( region );
83df96d6 1925 else
3cd0b8c5 1926 m_currentClippingRegion.Union( region );
83df96d6 1927
3cd0b8c5
RR
1928#if USE_PAINT_REGION
1929 if (!m_paintClippingRegion.IsNull())
1930 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1931#endif
83df96d6 1932
3cd0b8c5
RR
1933 wxCoord xx, yy, ww, hh;
1934 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1935 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1936
1937 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1938 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1939 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1940 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1941}
1942
3cd0b8c5 1943void wxWindowDC::DestroyClippingRegion()
83df96d6 1944{
3cd0b8c5 1945 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1946
3cd0b8c5 1947 wxDC::DestroyClippingRegion();
83df96d6 1948
3cd0b8c5 1949 m_currentClippingRegion.Clear();
83df96d6 1950
3cd0b8c5
RR
1951#if USE_PAINT_REGION
1952 if (!m_paintClippingRegion.IsEmpty())
1953 m_currentClippingRegion.Union( m_paintClippingRegion );
1954#endif
83df96d6 1955
3cd0b8c5 1956 if (!m_window) return;
83df96d6 1957
3cd0b8c5
RR
1958 if (m_currentClippingRegion.IsEmpty())
1959 {
1960 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1961 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1962 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1963 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1964 }
1965 else
1966 {
1967 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1968 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1969 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1970 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1971 }
1972}
83df96d6 1973
3cd0b8c5 1974void wxWindowDC::Destroy()
83df96d6 1975{
3cd0b8c5
RR
1976 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1977 m_penGC = NULL;
1978 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1979 m_brushGC = NULL;
1980 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1981 m_textGC = NULL;
1982 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1983 m_bgGC = NULL;
1984}
83df96d6 1985
3cd0b8c5
RR
1986void wxWindowDC::ComputeScaleAndOrigin()
1987{
1988 /* CMB: copy scale to see if it changes */
1989 double origScaleX = m_scaleX;
1990 double origScaleY = m_scaleY;
83df96d6 1991
3cd0b8c5 1992 wxDC::ComputeScaleAndOrigin();
83df96d6 1993
3cd0b8c5
RR
1994 /* CMB: if scale has changed call SetPen to recalulate the line width */
1995 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1996 (m_pen.Ok()))
1997 {
1998 /* this is a bit artificial, but we need to force wxDC to think
1999 the pen has changed */
2000 wxPen pen = m_pen;
2001 m_pen = wxNullPen;
2002 SetPen( pen );
2003 }
83df96d6
JS
2004}
2005
83df96d6
JS
2006wxSize wxWindowDC::GetPPI() const
2007{
2008 return wxSize(100, 100);
2009}
2010
2011int wxWindowDC::GetDepth() const
2012{
3cd0b8c5 2013 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2014
3cd0b8c5
RR
2015 return -1;
2016}
83df96d6
JS
2017
2018// ----------------------------------------------------------------------------
2019// wxPaintDC
2020// ----------------------------------------------------------------------------
2021
3cd0b8c5
RR
2022IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2023
1934d291 2024wxPaintDC::wxPaintDC(wxWindow* win)
3cd0b8c5
RR
2025 : wxClientDC(win)
2026{
2027#if USE_PAINT_REGION
2028 if (!win->GetClipPaintRegion())
2029 return;
2030
2031 m_paintClippingRegion = win->GetUpdateRegion();
2032 Region region = (Region) m_paintClippingRegion.GetX11Region();
2033 if (region)
2034 {
2035 m_paintClippingRegion = win->GetUpdateRegion();
2036 Region region2 = (Region) m_paintClippingRegion.GetX11Region();
2037 if (region2)
2038 {
2039 m_currentClippingRegion.Union( m_paintClippingRegion );
2040
2041 XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
2042 XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
2043 XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
2044 XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
2045 }
2046 }
2047#endif // USE_PAINT_REGION
2048}
2049
2050//-----------------------------------------------------------------------------
2051// wxClientDC
2052//-----------------------------------------------------------------------------
2053
2054IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2055
2056wxClientDC::wxClientDC( wxWindow *win )
2057 : wxWindowDC( win )
83df96d6 2058{
3cd0b8c5 2059 wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
a11672a4
RR
2060
2061#ifdef __WXUNIVERSAL__
2062 wxPoint ptOrigin = win->GetClientAreaOrigin();
2063 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2064 wxSize size = win->GetClientSize();
2065 SetClippingRegion(wxPoint(0, 0), size);
2066#endif // __WXUNIVERSAL__
83df96d6
JS
2067}
2068
3cd0b8c5 2069void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 2070{
3cd0b8c5
RR
2071 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2072
2073 m_owner->GetClientSize( width, height );
83df96d6
JS
2074}
2075
2076// ----------------------------------------------------------------------------
3cd0b8c5 2077// wxDCModule
83df96d6
JS
2078// ----------------------------------------------------------------------------
2079
3cd0b8c5 2080class wxDCModule : public wxModule
83df96d6 2081{
3cd0b8c5
RR
2082public:
2083 bool OnInit();
2084 void OnExit();
83df96d6 2085
3cd0b8c5
RR
2086private:
2087 DECLARE_DYNAMIC_CLASS(wxDCModule)
2088};
83df96d6 2089
3cd0b8c5 2090IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2091
3cd0b8c5
RR
2092bool wxDCModule::OnInit()
2093{
2094 wxInitGCPool();
2095 return TRUE;
83df96d6
JS
2096}
2097
3cd0b8c5 2098void wxDCModule::OnExit()
83df96d6 2099{
3cd0b8c5 2100 wxCleanUpGCPool();
83df96d6 2101}