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