]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
Pop-up menus no longer jump before appearing.
[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
ae1daed0
JS
1364 // First draw a rectangle representing the text background, if a text
1365 // background is specified
1366 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
83df96d6 1367 {
ae1daed0
JS
1368 // Since X draws from the baseline of the text, must add the text height
1369 int cx = 0;
1370 int cy = 0;
1371 int ascent = 0;
1372 int slen;
1373 int direction, descent;
1374
1375 slen = strlen(text);
1376 XCharStruct overall_return;
1377
868741e9 1378 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
ae1daed0
JS
1379 &ascent, &descent, &overall_return);
1380
1381 cx = overall_return.width;
1382 cy = ascent + descent;
1383 m_textBackgroundColour.CalcPixel(m_cmap);
1384 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
1385 XFillRectangle( (Display*) m_display, (Window) m_window,
1386 (GC) m_textGC, x, y, cx, cy );
1387 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1388
83df96d6 1389 }
3cd0b8c5
RR
1390
1391 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1392#if !wxUSE_NANOX
3cd0b8c5 1393 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1394#endif
1395 {
3cd0b8c5 1396 XDrawString( (Display*) m_display, (Window) m_window,
788519c6
JS
1397 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1398 }
83df96d6
JS
1399
1400#if 0
3cd0b8c5 1401 if (m_font.GetUnderlined())
83df96d6 1402 {
788519c6 1403 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5
RR
1404 if (font->descent > 0) ul_y++;
1405 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1406 }
83df96d6 1407
3cd0b8c5
RR
1408 width = wxCoord(width / m_scaleX);
1409 height = wxCoord(height / m_scaleY);
1410
1411 CalcBoundingBox (x + width, y + height);
83df96d6 1412 CalcBoundingBox (x, y);
3cd0b8c5 1413#endif
83df96d6
JS
1414}
1415
3cd0b8c5 1416void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
83df96d6 1417{
3cd0b8c5 1418 // later
83df96d6
JS
1419}
1420
1421void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1422 wxCoord *descent, wxCoord *externalLeading,
1423 wxFont *font ) const
1424{
1425 wxCHECK_RET( Ok(), "invalid dc" );
1426
3cd0b8c5
RR
1427 wxFont fontToUse = m_font;
1428 if (font) fontToUse = *font;
83df96d6 1429
3cd0b8c5 1430 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
83df96d6 1431
3cd0b8c5 1432 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1433
3cd0b8c5
RR
1434 wxCHECK_RET( xfont, wxT("invalid font") );
1435
83df96d6
JS
1436 int direction, ascent, descent2;
1437 XCharStruct overall;
83df96d6 1438
788519c6 1439 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
83df96d6
JS
1440 &ascent, &descent2, &overall);
1441
3cd0b8c5
RR
1442 if (width)
1443 *width = (wxCoord)( overall.width / m_scaleX );
1444 if (height)
1445 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1446 if (descent)
3cd0b8c5 1447 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1448 if (externalLeading)
3cd0b8c5 1449 *externalLeading = 0; // ??
83df96d6
JS
1450}
1451
1452wxCoord wxWindowDC::GetCharWidth() const
1453{
1454 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1455
83df96d6
JS
1456 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1457
3cd0b8c5
RR
1458 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1459
1460 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1461
1462 int direction, ascent, descent;
1463 XCharStruct overall;
3cd0b8c5
RR
1464
1465 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1466
1467 return (wxCoord)(overall.width / m_scaleX);
83df96d6
JS
1468}
1469
1470wxCoord wxWindowDC::GetCharHeight() const
1471{
1472 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1473
83df96d6
JS
1474 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1475
3cd0b8c5
RR
1476 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1477
1478 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1479
1480 int direction, ascent, descent;
1481 XCharStruct overall;
3cd0b8c5
RR
1482
1483 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1484
1485 return (wxCoord)((ascent+descent) / m_scaleY);
83df96d6
JS
1486}
1487
1488void wxWindowDC::Clear()
1489{
3cd0b8c5 1490 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1491
3cd0b8c5 1492 if (!m_window) return;
83df96d6 1493
3cd0b8c5
RR
1494 /* - we either are a memory dc or have a window as the
1495 owner. anything else shouldn't happen.
1496 - we don't use gdk_window_clear() as we don't set
1497 the window's background colour anymore. it is too
1498 much pain to keep the DC's and the window's back-
1499 ground colour in synch. */
83df96d6 1500
3cd0b8c5
RR
1501 if (m_owner)
1502 {
1503 int width,height;
1504 m_owner->GetSize( &width, &height );
1505 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1506 return;
1507 }
83df96d6 1508
3cd0b8c5
RR
1509 if (m_isMemDC)
1510 {
1511 int width,height;
1512 GetSize( &width, &height );
1513 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1514 return;
1515 }
83df96d6
JS
1516}
1517
1518void wxWindowDC::SetFont( const wxFont &font )
1519{
1520 wxCHECK_RET( Ok(), "invalid dc" );
1521
1522 m_font = font;
83df96d6
JS
1523}
1524
1525void wxWindowDC::SetPen( const wxPen &pen )
1526{
3cd0b8c5
RR
1527 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1528
1529 if (m_pen == pen) return;
83df96d6
JS
1530
1531 m_pen = pen;
83df96d6 1532
3cd0b8c5 1533 if (!m_pen.Ok()) return;
83df96d6 1534
3cd0b8c5 1535 if (!m_window) return;
83df96d6 1536
3cd0b8c5
RR
1537 int width = m_pen.GetWidth();
1538 if (width <= 0)
1539 {
1540 // CMB: if width is non-zero scale it with the dc
1541 width = 1;
1542 }
1543 else
1544 {
1545 // X doesn't allow different width in x and y and so we take
1546 // the average
1547 double w = 0.5 +
1548 ( fabs((double) XLOG2DEVREL(width)) +
1549 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1550 width = (int)w;
1551 }
1552
1553 static const wxX11Dash dotted[] = {1, 1};
1554 static const wxX11Dash short_dashed[] = {2, 2};
1555 static const wxX11Dash long_dashed[] = {2, 4};
1556 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1557
1558 // We express dash pattern in pen width unit, so we are
1559 // independent of zoom factor and so on...
1560 int req_nb_dash;
1561 const wxX11Dash *req_dash;
1562
1563 int lineStyle = LineSolid;
1564 switch (m_pen.GetStyle())
83df96d6 1565 {
83df96d6 1566 case wxUSER_DASH:
3cd0b8c5
RR
1567 {
1568 lineStyle = LineOnOffDash;
1569 req_nb_dash = m_pen.GetDashCount();
1570 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1571 break;
3cd0b8c5 1572 }
83df96d6 1573 case wxDOT:
3cd0b8c5
RR
1574 {
1575 lineStyle = LineOnOffDash;
83df96d6
JS
1576 req_nb_dash = 2;
1577 req_dash = dotted;
83df96d6 1578 break;
3cd0b8c5 1579 }
83df96d6 1580 case wxLONG_DASH:
3cd0b8c5
RR
1581 {
1582 lineStyle = LineOnOffDash;
83df96d6
JS
1583 req_nb_dash = 2;
1584 req_dash = long_dashed;
83df96d6 1585 break;
3cd0b8c5
RR
1586 }
1587 case wxSHORT_DASH:
1588 {
1589 lineStyle = LineOnOffDash;
1590 req_nb_dash = 2;
1591 req_dash = short_dashed;
1592 break;
1593 }
83df96d6 1594 case wxDOT_DASH:
3cd0b8c5
RR
1595 {
1596// lineStyle = LineDoubleDash;
1597 lineStyle = LineOnOffDash;
83df96d6
JS
1598 req_nb_dash = 4;
1599 req_dash = dotted_dashed;
83df96d6 1600 break;
3cd0b8c5
RR
1601 }
1602
1603 case wxTRANSPARENT:
1604 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1605 case wxSTIPPLE:
1606 case wxSOLID:
83df96d6 1607 default:
3cd0b8c5
RR
1608 {
1609 lineStyle = LineSolid;
74dc5eb6 1610 req_dash = (wxX11Dash*)NULL;
83df96d6 1611 req_nb_dash = 0;
3cd0b8c5 1612 break;
83df96d6 1613 }
3cd0b8c5 1614 }
83df96d6 1615
3cd0b8c5
RR
1616 int capStyle = CapRound;
1617 switch (m_pen.GetCap())
1618 {
1619 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1620 case wxCAP_BUTT: { capStyle = CapButt; break; }
1621 case wxCAP_ROUND:
1622 default:
83df96d6 1623 {
3cd0b8c5 1624 if (width <= 1)
83df96d6 1625 {
3cd0b8c5
RR
1626 width = 0;
1627 capStyle = CapNotLast;
83df96d6
JS
1628 }
1629 else
1630 {
3cd0b8c5 1631 capStyle = CapRound;
83df96d6 1632 }
83df96d6
JS
1633 break;
1634 }
3cd0b8c5 1635 }
83df96d6 1636
3cd0b8c5
RR
1637 int joinStyle = JoinRound;
1638 switch (m_pen.GetJoin())
1639 {
1640 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1641 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1642 case wxJOIN_ROUND:
3cd0b8c5 1643 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1644 }
1645
3cd0b8c5 1646 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1647
3cd0b8c5
RR
1648 m_pen.GetColour().CalcPixel( m_cmap );
1649 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1650}
83df96d6 1651
3cd0b8c5
RR
1652void wxWindowDC::SetBrush( const wxBrush &brush )
1653{
1654 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1655
3cd0b8c5 1656 if (m_brush == brush) return;
83df96d6 1657
3cd0b8c5
RR
1658 m_brush = brush;
1659
1660 if (!m_brush.Ok()) return;
83df96d6 1661
3cd0b8c5
RR
1662 if (!m_window) return;
1663
1664 m_brush.GetColour().CalcPixel( m_cmap );
1665 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1666
1667 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1668
1669 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1670 {
3cd0b8c5 1671 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1672 {
3cd0b8c5
RR
1673 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1674 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1675 }
1676 else
1677 {
3cd0b8c5 1678 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1679 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1680 }
3cd0b8c5 1681 }
83df96d6 1682
3cd0b8c5
RR
1683 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1684 {
1685 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1686 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1687 }
83df96d6 1688
3cd0b8c5
RR
1689 if (IS_HATCH(m_brush.GetStyle()))
1690 {
1691 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1692 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1693 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1694 }
83df96d6
JS
1695}
1696
3cd0b8c5 1697void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1698{
3cd0b8c5
RR
1699 /* CMB 21/7/98: Added SetBackground. Sets background brush
1700 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1701
3cd0b8c5 1702 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1703
3cd0b8c5 1704 if (m_backgroundBrush == brush) return;
83df96d6 1705
3cd0b8c5 1706 m_backgroundBrush = brush;
83df96d6 1707
3cd0b8c5 1708 if (!m_backgroundBrush.Ok()) return;
83df96d6 1709
3cd0b8c5 1710 if (!m_window) return;
83df96d6 1711
3cd0b8c5
RR
1712 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1713 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1714 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1715 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1716 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1717
3cd0b8c5 1718 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1719
3cd0b8c5 1720 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1721 {
3cd0b8c5 1722 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1723 {
3cd0b8c5
RR
1724 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1725 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1726 }
3cd0b8c5 1727 else
83df96d6 1728 {
3cd0b8c5 1729 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1730 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1731 }
83df96d6
JS
1732 }
1733
3cd0b8c5 1734 if (IS_HATCH(m_backgroundBrush.GetStyle()))
83df96d6 1735 {
3cd0b8c5
RR
1736 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1737 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1738 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1739 }
83df96d6
JS
1740}
1741
1742void wxWindowDC::SetLogicalFunction( int function )
1743{
1744 wxCHECK_RET( Ok(), "invalid dc" );
1745
1746 int x_function;
1747
83df96d6
JS
1748 if (m_logicalFunction == function)
1749 return;
1750
3cd0b8c5
RR
1751 // VZ: shouldn't this be a CHECK?
1752 if (!m_window)
1753 return;
1754
83df96d6
JS
1755 switch (function)
1756 {
1757 case wxCLEAR:
1758 x_function = GXclear;
1759 break;
1760 case wxXOR:
1761 x_function = GXxor;
1762 break;
1763 case wxINVERT:
1764 x_function = GXinvert;
1765 break;
1766 case wxOR_REVERSE:
1767 x_function = GXorReverse;
1768 break;
1769 case wxAND_REVERSE:
1770 x_function = GXandReverse;
1771 break;
1772 case wxAND:
1773 x_function = GXand;
1774 break;
1775 case wxOR:
1776 x_function = GXor;
1777 break;
1778 case wxAND_INVERT:
1779 x_function = GXandInverted;
1780 break;
1781 case wxNO_OP:
1782 x_function = GXnoop;
1783 break;
1784 case wxNOR:
1785 x_function = GXnor;
1786 break;
1787 case wxEQUIV:
1788 x_function = GXequiv;
1789 break;
1790 case wxSRC_INVERT:
1791 x_function = GXcopyInverted;
1792 break;
1793 case wxOR_INVERT:
1794 x_function = GXorInverted;
1795 break;
1796 case wxNAND:
1797 x_function = GXnand;
1798 break;
1799 case wxSET:
1800 x_function = GXset;
1801 break;
1802 case wxCOPY:
1803 default:
1804 x_function = GXcopy;
1805 break;
1806 }
1807
3cd0b8c5
RR
1808 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1809 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 1810
3cd0b8c5
RR
1811 // to stay compatible with wxMSW, we don't apply ROPs to the text
1812 // operations (i.e. DrawText/DrawRotatedText).
1813 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1814 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1815
83df96d6 1816 m_logicalFunction = function;
83df96d6
JS
1817}
1818
1819void wxWindowDC::SetTextForeground( const wxColour &col )
1820{
3cd0b8c5 1821 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1822
3cd0b8c5
RR
1823 // don't set m_textForegroundColour to an invalid colour as we'd crash
1824 // later then (we use m_textForegroundColour.GetColor() without checking
1825 // in a few places)
1826 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
1827 return;
1828
1829 m_textForegroundColour = col;
1830
3cd0b8c5
RR
1831 if (m_window)
1832 {
1833 m_textForegroundColour.CalcPixel( m_cmap );
1834 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1835 }
83df96d6
JS
1836}
1837
1838void wxWindowDC::SetTextBackground( const wxColour &col )
1839{
3cd0b8c5 1840 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1841
3cd0b8c5
RR
1842 // same as above
1843 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
1844 return;
1845
1846 m_textBackgroundColour = col;
3cd0b8c5
RR
1847
1848 if (m_window)
1849 {
1850 m_textBackgroundColour.CalcPixel( m_cmap );
1851 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1852 }
83df96d6
JS
1853}
1854
1855void wxWindowDC::SetBackgroundMode( int mode )
1856{
3cd0b8c5
RR
1857 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1858
83df96d6 1859 m_backgroundMode = mode;
3cd0b8c5 1860
0b5c0e1a
JS
1861#if wxUSE_NANOX
1862 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1863#endif
1864
3cd0b8c5
RR
1865 if (!m_window) return;
1866
1867 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1868 // transparent/solid background mode
1869
1870 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1871 {
1872 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1873 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1874 }
83df96d6
JS
1875}
1876
1877void wxWindowDC::SetPalette( const wxPalette& palette )
1878{
3cd0b8c5 1879#if 0
83df96d6
JS
1880 if (m_window)
1881 {
1882 if (palette.Ok())
1883 /* Use GetXColormap */
1884 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1885 (Colormap) palette.GetXColormap());
1886 else
1887 /* Use wxGetMainColormap */
1888 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1889 (Colormap) wxTheApp->GetMainColormap(m_display));
1890 }
3cd0b8c5 1891#endif
83df96d6
JS
1892}
1893
3cd0b8c5 1894void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 1895{
3cd0b8c5 1896 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1897
3cd0b8c5 1898 if (!m_window) return;
83df96d6 1899
3cd0b8c5
RR
1900 wxRect rect;
1901 rect.x = XLOG2DEV(x);
1902 rect.y = YLOG2DEV(y);
1903 rect.width = XLOG2DEVREL(width);
1904 rect.height = YLOG2DEVREL(height);
1905
1906 if (!m_currentClippingRegion.IsNull())
1907 m_currentClippingRegion.Intersect( rect );
83df96d6 1908 else
3cd0b8c5
RR
1909 m_currentClippingRegion.Union( rect );
1910
1911#if USE_PAINT_REGION
1912 if (!m_paintClippingRegion.IsNull())
1913 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1914#endif
1915
1916 wxCoord xx, yy, ww, hh;
1917 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1918 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1919
1920 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1921 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1922 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1923 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1924}
83df96d6 1925
3cd0b8c5
RR
1926void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1927{
1928 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1929
3cd0b8c5 1930 if (region.Empty())
83df96d6 1931 {
3cd0b8c5
RR
1932 DestroyClippingRegion();
1933 return;
83df96d6 1934 }
3cd0b8c5
RR
1935
1936 if (!m_window) return;
1937
1938 if (!m_currentClippingRegion.IsNull())
1939 m_currentClippingRegion.Intersect( region );
83df96d6 1940 else
3cd0b8c5 1941 m_currentClippingRegion.Union( region );
83df96d6 1942
3cd0b8c5
RR
1943#if USE_PAINT_REGION
1944 if (!m_paintClippingRegion.IsNull())
1945 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1946#endif
83df96d6 1947
3cd0b8c5
RR
1948 wxCoord xx, yy, ww, hh;
1949 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1950 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1951
1952 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1953 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1954 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1955 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1956}
1957
3cd0b8c5 1958void wxWindowDC::DestroyClippingRegion()
83df96d6 1959{
3cd0b8c5 1960 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1961
3cd0b8c5 1962 wxDC::DestroyClippingRegion();
83df96d6 1963
3cd0b8c5 1964 m_currentClippingRegion.Clear();
83df96d6 1965
3cd0b8c5
RR
1966#if USE_PAINT_REGION
1967 if (!m_paintClippingRegion.IsEmpty())
1968 m_currentClippingRegion.Union( m_paintClippingRegion );
1969#endif
83df96d6 1970
3cd0b8c5 1971 if (!m_window) return;
83df96d6 1972
3cd0b8c5
RR
1973 if (m_currentClippingRegion.IsEmpty())
1974 {
1975 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1976 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1977 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1978 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1979 }
1980 else
1981 {
1982 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1983 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1984 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1985 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1986 }
1987}
83df96d6 1988
3cd0b8c5 1989void wxWindowDC::Destroy()
83df96d6 1990{
3cd0b8c5
RR
1991 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1992 m_penGC = NULL;
1993 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1994 m_brushGC = NULL;
1995 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1996 m_textGC = NULL;
1997 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1998 m_bgGC = NULL;
1999}
83df96d6 2000
3cd0b8c5
RR
2001void wxWindowDC::ComputeScaleAndOrigin()
2002{
2003 /* CMB: copy scale to see if it changes */
2004 double origScaleX = m_scaleX;
2005 double origScaleY = m_scaleY;
83df96d6 2006
3cd0b8c5 2007 wxDC::ComputeScaleAndOrigin();
83df96d6 2008
3cd0b8c5
RR
2009 /* CMB: if scale has changed call SetPen to recalulate the line width */
2010 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2011 (m_pen.Ok()))
2012 {
2013 /* this is a bit artificial, but we need to force wxDC to think
2014 the pen has changed */
2015 wxPen pen = m_pen;
2016 m_pen = wxNullPen;
2017 SetPen( pen );
2018 }
83df96d6
JS
2019}
2020
83df96d6
JS
2021wxSize wxWindowDC::GetPPI() const
2022{
2023 return wxSize(100, 100);
2024}
2025
2026int wxWindowDC::GetDepth() const
2027{
3cd0b8c5 2028 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2029
3cd0b8c5
RR
2030 return -1;
2031}
83df96d6 2032
3cd0b8c5
RR
2033//-----------------------------------------------------------------------------
2034// wxClientDC
2035//-----------------------------------------------------------------------------
2036
2037IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2038
ab6b6b15
RR
2039wxClientDC::wxClientDC( wxWindow *window )
2040 : wxWindowDC( window )
83df96d6 2041{
ab6b6b15 2042 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
a11672a4 2043
ab6b6b15
RR
2044 m_window = (WXWindow*) window->GetClientWindow();
2045
2046#if wxUSE_TWO_WINDOWS
2047#else
c2c0dabf
RR
2048 wxPoint ptOrigin = window->GetClientAreaOrigin();
2049 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2050 wxSize size = window->GetClientSize();
2051 SetClippingRegion(wxPoint(0, 0), size);
2052#endif
83df96d6
JS
2053}
2054
3cd0b8c5 2055void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 2056{
3cd0b8c5
RR
2057 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2058
2059 m_owner->GetClientSize( width, height );
83df96d6
JS
2060}
2061
ab6b6b15
RR
2062// ----------------------------------------------------------------------------
2063// wxPaintDC
2064// ----------------------------------------------------------------------------
2065
2066IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2067
2068wxPaintDC::wxPaintDC(wxWindow* window)
2069 : wxClientDC(window)
2070{
2071#if USE_PAINT_REGION
2072 if (!window->GetClipPaintRegion())
2073 return;
2074
2075 m_paintClippingRegion = window->GetUpdateRegion();
2076 Region region = (Region) m_paintClippingRegion.GetX11Region();
2077 if (region)
2078 {
2079 m_currentClippingRegion.Union( m_paintClippingRegion );
2080
2081 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2082 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2083 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2084 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2085 }
2086#endif // USE_PAINT_REGION
2087}
2088
83df96d6 2089// ----------------------------------------------------------------------------
3cd0b8c5 2090// wxDCModule
83df96d6
JS
2091// ----------------------------------------------------------------------------
2092
3cd0b8c5 2093class wxDCModule : public wxModule
83df96d6 2094{
3cd0b8c5
RR
2095public:
2096 bool OnInit();
2097 void OnExit();
83df96d6 2098
3cd0b8c5
RR
2099private:
2100 DECLARE_DYNAMIC_CLASS(wxDCModule)
2101};
83df96d6 2102
3cd0b8c5 2103IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2104
3cd0b8c5
RR
2105bool wxDCModule::OnInit()
2106{
2107 wxInitGCPool();
2108 return TRUE;
83df96d6
JS
2109}
2110
3cd0b8c5 2111void wxDCModule::OnExit()
83df96d6 2112{
3cd0b8c5 2113 wxCleanUpGCPool();
83df96d6 2114}