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