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