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