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