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