]> git.saurik.com Git - wxWidgets.git/blob - src/x11/dcclient.cpp
split wxUSE_MDI from wxUSE_MDI_ARCHITECTURE (which is wxUSE_MDI + wxUSE_DOCVIEW)
[wxWidgets.git] / src / x11 / dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart, Robert Roebling
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "dcclient.h"
14 #endif
15
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
19 #include "wx/app.h"
20 #include "wx/image.h"
21 #include "wx/module.h"
22 #include "wx/fontutil.h"
23
24 #include "wx/x11/private.h"
25
26 #include <math.h>
27
28 #if wxUSE_UNICODE
29 #include "glib.h"
30 #include "pango/pangox.h"
31 #include "pango/pangoxft.h"
32
33 #include "pango_x.cpp"
34 #endif
35
36 //-----------------------------------------------------------------------------
37 // local defines
38 //-----------------------------------------------------------------------------
39
40 #define USE_PAINT_REGION 1
41
42 //-----------------------------------------------------------------------------
43 // local data
44 //-----------------------------------------------------------------------------
45
46 #include "bdiag.xbm"
47 #include "fdiag.xbm"
48 #include "cdiag.xbm"
49 #include "horiz.xbm"
50 #include "verti.xbm"
51 #include "cross.xbm"
52 #define num_hatches 6
53
54 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
55 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
56
57 static Pixmap hatches[num_hatches];
58 static Pixmap *hatch_bitmap = (Pixmap *) NULL;
59
60 //-----------------------------------------------------------------------------
61 // constants
62 //-----------------------------------------------------------------------------
63
64 const double RAD2DEG = 180.0 / M_PI;
65
66 // ----------------------------------------------------------------------------
67 // private functions
68 // ----------------------------------------------------------------------------
69
70 static inline double dmax(double a, double b) { return a > b ? a : b; }
71 static inline double dmin(double a, double b) { return a < b ? a : b; }
72
73 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
74
75 //-----------------------------------------------------------------------------
76 // Implement Pool of Graphic contexts. Creating them takes too much time.
77 //-----------------------------------------------------------------------------
78
79 #define GC_POOL_SIZE 200
80
81 enum wxPoolGCType
82 {
83 wxGC_ERROR = 0,
84 wxTEXT_MONO,
85 wxBG_MONO,
86 wxPEN_MONO,
87 wxBRUSH_MONO,
88 wxTEXT_COLOUR,
89 wxBG_COLOUR,
90 wxPEN_COLOUR,
91 wxBRUSH_COLOUR,
92 wxTEXT_SCREEN,
93 wxBG_SCREEN,
94 wxPEN_SCREEN,
95 wxBRUSH_SCREEN
96 };
97
98 struct wxGC
99 {
100 GC m_gc;
101 wxPoolGCType m_type;
102 bool m_used;
103 };
104
105 static wxGC wxGCPool[GC_POOL_SIZE];
106
107 static void wxInitGCPool()
108 {
109 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
110 }
111
112 static void wxCleanUpGCPool()
113 {
114 for (int i = 0; i < GC_POOL_SIZE; i++)
115 {
116 if (wxGCPool[i].m_gc)
117 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
118 }
119 }
120
121 static GC wxGetPoolGC( Window window, wxPoolGCType type )
122 {
123 for (int i = 0; i < GC_POOL_SIZE; i++)
124 {
125 if (!wxGCPool[i].m_gc)
126 {
127 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
128 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
129 wxGCPool[i].m_type = type;
130 wxGCPool[i].m_used = FALSE;
131 }
132 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
133 {
134 wxGCPool[i].m_used = TRUE;
135 return wxGCPool[i].m_gc;
136 }
137 }
138
139 wxFAIL_MSG( wxT("No GC available") );
140
141 return (GC) NULL;
142 }
143
144 static void wxFreePoolGC( GC gc )
145 {
146 for (int i = 0; i < GC_POOL_SIZE; i++)
147 {
148 if (wxGCPool[i].m_gc == gc)
149 {
150 wxGCPool[i].m_used = FALSE;
151 return;
152 }
153 }
154
155 wxFAIL_MSG( wxT("Wrong GC") );
156 }
157
158 // ----------------------------------------------------------------------------
159 // wxWindowDC
160 // ----------------------------------------------------------------------------
161
162 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
163
164 wxWindowDC::wxWindowDC()
165 {
166 m_display = (WXDisplay *) NULL;
167 m_penGC = (WXGC *) NULL;
168 m_brushGC = (WXGC *) NULL;
169 m_textGC = (WXGC *) NULL;
170 m_bgGC = (WXGC *) NULL;
171 m_cmap = (WXColormap *) NULL;
172 m_isMemDC = FALSE;
173 m_isScreenDC = FALSE;
174 m_owner = (wxWindow *)NULL;
175
176 #if wxUSE_UNICODE
177 m_context = (PangoContext *)NULL;
178 m_fontdesc = (PangoFontDescription *)NULL;
179 #endif
180 }
181
182 wxWindowDC::wxWindowDC( wxWindow *window )
183 {
184 wxASSERT_MSG( window, wxT("DC needs a window") );
185
186 m_display = (WXDisplay *) NULL;
187 m_penGC = (WXGC *) NULL;
188 m_brushGC = (WXGC *) NULL;
189 m_textGC = (WXGC *) NULL;
190 m_bgGC = (WXGC *) NULL;
191 m_cmap = (WXColormap *) NULL;
192 m_owner = (wxWindow *)NULL;
193 m_isMemDC = FALSE;
194 m_isScreenDC = FALSE;
195 m_font = window->GetFont();
196
197 m_window = (WXWindow*) window->GetMainWindow();
198
199 // not realized ?
200 if (!m_window)
201 {
202 // don't report problems
203 m_ok = TRUE;
204
205 return;
206 }
207
208 m_display = (WXDisplay *) wxGlobalDisplay();
209
210 #if wxUSE_UNICODE
211 m_context = wxTheApp->GetPangoContext();
212 m_fontdesc = window->GetFont().GetNativeFontInfo()->description;
213 #endif
214
215 int screen = DefaultScreen( (Display*) m_display );
216 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
217
218 SetUpDC();
219
220 /* this must be done after SetUpDC, bacause SetUpDC calls the
221 repective SetBrush, SetPen, SetBackground etc functions
222 to set up the DC. SetBackground call m_owner->SetBackground
223 and this might not be desired as the standard dc background
224 is white whereas a window might assume gray to be the
225 standard (as e.g. wxStatusBar) */
226
227 m_owner = window;
228 }
229
230 wxWindowDC::~wxWindowDC()
231 {
232 Destroy();
233 }
234
235 void wxWindowDC::SetUpDC()
236 {
237 m_ok = TRUE;
238
239 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
240
241 if (m_isScreenDC)
242 {
243 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
244 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
245 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
246 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
247 }
248 else
249 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
250 {
251 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
252 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
253 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
254 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
255 }
256 else
257 {
258 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
259 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
260 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
261 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
262 }
263
264 /* background colour */
265 m_backgroundBrush = *wxWHITE_BRUSH;
266 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
267 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
268
269 /* m_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 if (useMask && mask)
1173 {
1174 WXPixmap new_mask = NULL;
1175 #if 0
1176 if (!m_currentClippingRegion.IsNull())
1177 {
1178 GdkColor col;
1179 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1180 GdkGC *gc = gdk_gc_new( new_mask );
1181 col.pixel = 0;
1182 gdk_gc_set_foreground( gc, &col );
1183 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1184 col.pixel = 0;
1185 gdk_gc_set_background( gc, &col );
1186 col.pixel = 1;
1187 gdk_gc_set_foreground( gc, &col );
1188 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1189 gdk_gc_set_clip_origin( gc, -xx, -yy );
1190 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1191 gdk_gc_set_stipple( gc, mask );
1192 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1193 gdk_gc_unref( gc );
1194 }
1195 #endif
1196 if (is_mono)
1197 {
1198 if (new_mask)
1199 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1200 else
1201 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1202 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1203 }
1204 else
1205 {
1206 if (new_mask)
1207 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1208 else
1209 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1210 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1211 }
1212
1213 if (new_mask)
1214 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1215 }
1216
1217 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1218 // drawing a mono-bitmap (XBitmap) we use the current text GC
1219 if (is_mono)
1220 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1221 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
1222 else
1223 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1224 (GC) m_penGC, 0, 0, w, h, xx, yy );
1225
1226 // remove mask again if any
1227 if (useMask && mask)
1228 {
1229 if (is_mono)
1230 {
1231 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1232 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1233 if (!m_currentClippingRegion.IsNull())
1234 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1235 }
1236 else
1237 {
1238 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1239 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1240 if (!m_currentClippingRegion.IsNull())
1241 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1242 }
1243 }
1244 }
1245 #endif
1246 // wxUSE_NANOX/!wxUSE_NANOX
1247
1248 bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1249 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
1250 wxCoord xsrcMask, wxCoord ysrcMask )
1251 {
1252 /* this is the nth try to get this utterly useless function to
1253 work. it now completely ignores the scaling or translation
1254 of the source dc, but scales correctly on the target dc and
1255 knows about possible mask information in a memory dc. */
1256
1257 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
1258
1259 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
1260
1261 if (!m_window) return FALSE;
1262
1263 // transform the source DC coords to the device ones
1264 xsrc = source->XLOG2DEV(xsrc);
1265 ysrc = source->YLOG2DEV(ysrc);
1266
1267 wxClientDC *srcDC = (wxClientDC*)source;
1268 wxMemoryDC *memDC = (wxMemoryDC*)source;
1269
1270 bool use_bitmap_method = FALSE;
1271 bool is_mono = FALSE;
1272
1273 // TODO: use the mask origin when drawing transparently
1274 if (xsrcMask == -1 && ysrcMask == -1)
1275 {
1276 xsrcMask = xsrc;
1277 ysrcMask = ysrc;
1278 }
1279
1280 if (srcDC->m_isMemDC)
1281 {
1282 if (!memDC->m_selected.Ok()) return FALSE;
1283
1284 /* we use the "XCopyArea" way to copy a memory dc into
1285 y different window if the memory dc BOTH
1286 a) doesn't have any mask or its mask isn't used
1287 b) it is clipped
1288 c) is not 1-bit */
1289
1290 if (useMask && (memDC->m_selected.GetMask()))
1291 {
1292 /* we HAVE TO use the direct way for memory dcs
1293 that have mask since the XCopyArea doesn't know
1294 about masks */
1295 use_bitmap_method = TRUE;
1296 }
1297 else if (memDC->m_selected.GetDepth() == 1)
1298 {
1299 /* we HAVE TO use the direct way for memory dcs
1300 that are bitmaps because XCopyArea doesn't cope
1301 with different bit depths */
1302 is_mono = TRUE;
1303 use_bitmap_method = TRUE;
1304 }
1305 else if ((xsrc == 0) && (ysrc == 0) &&
1306 (width == memDC->m_selected.GetWidth()) &&
1307 (height == memDC->m_selected.GetHeight()))
1308 {
1309 /* we SHOULD use the direct way if all of the bitmap
1310 in the memory dc is copied in which case XCopyArea
1311 wouldn't be able able to boost performace by reducing
1312 the area to be scaled */
1313 use_bitmap_method = TRUE;
1314 }
1315 else
1316 {
1317 use_bitmap_method = FALSE;
1318 }
1319 }
1320
1321 CalcBoundingBox( xdest, ydest );
1322 CalcBoundingBox( xdest + width, ydest + height );
1323
1324 // scale/translate size and position
1325 wxCoord xx = XLOG2DEV(xdest);
1326 wxCoord yy = YLOG2DEV(ydest);
1327
1328 wxCoord ww = XLOG2DEVREL(width);
1329 wxCoord hh = YLOG2DEVREL(height);
1330
1331 // compare to current clipping region
1332 if (!m_currentClippingRegion.IsNull())
1333 {
1334 wxRegion tmp( xx,yy,ww,hh );
1335 tmp.Intersect( m_currentClippingRegion );
1336 if (tmp.IsEmpty())
1337 return TRUE;
1338 }
1339
1340 int old_logical_func = m_logicalFunction;
1341 SetLogicalFunction( logical_func );
1342
1343 if (use_bitmap_method)
1344 {
1345 // scale/translate bitmap size
1346 wxCoord bm_width = memDC->m_selected.GetWidth();
1347 wxCoord bm_height = memDC->m_selected.GetHeight();
1348
1349 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1350 wxCoord bm_hh = YLOG2DEVREL( bm_height );
1351
1352 // scale bitmap if required
1353 wxBitmap use_bitmap;
1354
1355 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1356 {
1357 wxImage image( memDC->m_selected.ConvertToImage() );
1358 image = image.Scale( bm_ww, bm_hh );
1359
1360 #if 0
1361 if (is_mono)
1362 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1363 else
1364 #endif
1365 use_bitmap = image;
1366 }
1367 else
1368 {
1369 use_bitmap = memDC->m_selected;
1370 }
1371
1372 // apply mask if any
1373 WXPixmap mask = NULL;
1374 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1375
1376 if (useMask && mask)
1377 {
1378 WXPixmap new_mask = NULL;
1379 #if 0
1380 if (!m_currentClippingRegion.IsNull())
1381 {
1382 GdkColor col;
1383 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1384 GdkGC *gc = gdk_gc_new( new_mask );
1385 col.pixel = 0;
1386 gdk_gc_set_foreground( gc, &col );
1387 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1388 col.pixel = 0;
1389 gdk_gc_set_background( gc, &col );
1390 col.pixel = 1;
1391 gdk_gc_set_foreground( gc, &col );
1392 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1393 gdk_gc_set_clip_origin( gc, -xx, -yy );
1394 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1395 gdk_gc_set_stipple( gc, mask );
1396 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1397 gdk_gc_unref( gc );
1398 }
1399 #endif
1400 if (is_mono)
1401 {
1402 if (new_mask)
1403 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1404 else
1405 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1406 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1407 }
1408 else
1409 {
1410 if (new_mask)
1411 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1412 else
1413 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1414 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1415 }
1416
1417 if (new_mask)
1418 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1419 }
1420
1421 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1422 // drawing a mono-bitmap (XBitmap) we use the current text GC
1423
1424 if (is_mono)
1425 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1426 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
1427 else
1428 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1429 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1430
1431 // remove mask again if any
1432 if (useMask && mask)
1433 {
1434 if (is_mono)
1435 {
1436 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1437 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1438 if (!m_currentClippingRegion.IsNull())
1439 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1440 }
1441 else
1442 {
1443 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1444 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1445 if (!m_currentClippingRegion.IsNull())
1446 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1447 }
1448 }
1449 }
1450 else // use_bitmap_method
1451 {
1452 if ((width != ww) || (height != hh))
1453 {
1454 /* Draw source window into a bitmap as we cannot scale
1455 a window in contrast to a bitmap. this would actually
1456 work with memory dcs as well, but we'd lose the mask
1457 information and waste one step in this process since
1458 a memory already has a bitmap. all this is slightly
1459 inefficient as we could take an XImage directly from
1460 an X window, but we'd then also have to care that
1461 the window is not outside the screen (in which case
1462 we'd get a BadMatch or what not).
1463 Is a double XGetImage and combined XGetPixel and
1464 XPutPixel really faster? I'm not sure. look at wxXt
1465 for a different implementation of the same problem. */
1466
1467 wxBitmap bitmap( width, height );
1468
1469 // copy including child window contents
1470 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1471 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1472 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1473 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1474
1475 // scale image
1476 wxImage image( bitmap.ConvertToImage() );
1477 image = image.Scale( ww, hh );
1478
1479 // convert to bitmap
1480 bitmap = image;
1481
1482 // draw scaled bitmap
1483 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1484 (GC) m_penGC, 0, 0, width, height, xx, yy );
1485 }
1486 else
1487 {
1488 // No scaling and not a memory dc with a mask either
1489
1490 // copy including child window contents
1491 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1492 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1493 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1494 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1495 }
1496 }
1497
1498 SetLogicalFunction( old_logical_func );
1499
1500 return TRUE;
1501 }
1502
1503 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1504 {
1505 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1506
1507 if (!m_window) return;
1508
1509 x = XLOG2DEV(x);
1510 y = YLOG2DEV(y);
1511
1512 #if wxUSE_UNICODE
1513 PangoLayout *layout = pango_layout_new(m_context);
1514 pango_layout_set_font_description(layout, m_fontdesc);
1515
1516 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1517 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1518
1519 // Measure layout.
1520 int w,h;
1521 pango_layout_get_pixel_size(layout, &w, &h);
1522 wxCoord width = w;
1523 wxCoord height = h;
1524
1525 // Draw layout.
1526 x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
1527
1528 g_object_unref( G_OBJECT( layout ) );
1529
1530 CalcBoundingBox (x + width, y + height);
1531 CalcBoundingBox (x, y);
1532 #else
1533 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1534
1535 wxCHECK_RET( xfont, wxT("invalid font") );
1536
1537 // First draw a rectangle representing the text background, if a text
1538 // background is specified
1539 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1540 {
1541 // Since X draws from the baseline of the text, must add the text height
1542 int cx = 0;
1543 int cy = 0;
1544 int ascent = 0;
1545 int slen;
1546 int direction, descent;
1547
1548 slen = strlen(text);
1549 XCharStruct overall_return;
1550
1551 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
1552 &ascent, &descent, &overall_return);
1553
1554 cx = overall_return.width;
1555 cy = ascent + descent;
1556 m_textBackgroundColour.CalcPixel(m_cmap);
1557 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
1558 XFillRectangle( (Display*) m_display, (Window) m_window,
1559 (GC) m_textGC, x, y, cx, cy );
1560 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1561
1562 }
1563
1564 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
1565 #if !wxUSE_NANOX
1566 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1567 #endif
1568 {
1569 XDrawString( (Display*) m_display, (Window) m_window,
1570 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1571 }
1572
1573 #if 0
1574 if (m_font.GetUnderlined())
1575 {
1576 wxCoord ul_y = y + XFontStructGetAscent(font);
1577 if (font->descent > 0) ul_y++;
1578 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
1579 }
1580
1581 width = wxCoord(width / m_scaleX);
1582 height = wxCoord(height / m_scaleY);
1583
1584 CalcBoundingBox (x + width, y + height);
1585 CalcBoundingBox (x, y);
1586 #endif
1587 #endif
1588 }
1589
1590 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1591 {
1592 // later
1593 }
1594
1595 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1596 wxCoord *descent, wxCoord *externalLeading,
1597 wxFont *font ) const
1598 {
1599 wxCHECK_RET( Ok(), wxT("invalid dc") );
1600
1601 if (string.IsEmpty())
1602 {
1603 if (width) (*width) = 0;
1604 if (height) (*height) = 0;
1605 return;
1606 }
1607
1608 #if wxUSE_UNICODE
1609 PangoLayout *layout = pango_layout_new( m_context );
1610
1611 if (font)
1612 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1613 else
1614 pango_layout_set_font_description(layout, m_fontdesc);
1615
1616 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1617 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1618
1619 // Measure text.
1620 int w,h;
1621 pango_layout_get_pixel_size(layout, &w, &h);
1622
1623 if (width) (*width) = (wxCoord) w;
1624 if (height) (*height) = (wxCoord) h;
1625 if (descent)
1626 {
1627 // Do something about metrics here. TODO.
1628 (*descent) = 0;
1629 }
1630 if (externalLeading) (*externalLeading) = 0; // ??
1631
1632 g_object_unref( G_OBJECT( layout ) );
1633 #else
1634 wxFont fontToUse = m_font;
1635 if (font) fontToUse = *font;
1636
1637 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
1638
1639 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1640
1641 wxCHECK_RET( xfont, wxT("invalid font") );
1642
1643 int direction, ascent, descent2;
1644 XCharStruct overall;
1645
1646 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
1647 &ascent, &descent2, &overall);
1648
1649 if (width)
1650 *width = (wxCoord)( overall.width / m_scaleX );
1651 if (height)
1652 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1653 if (descent)
1654 *descent = (wxCoord)(descent2 / m_scaleY );
1655 if (externalLeading)
1656 *externalLeading = 0; // ??
1657 #endif
1658 }
1659
1660 wxCoord wxWindowDC::GetCharWidth() const
1661 {
1662 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
1663
1664 #if wxUSE_UNICODE
1665 PangoLayout *layout = pango_layout_new( m_context );
1666
1667 if (!m_fontdesc)
1668 {
1669 char *crash = NULL;
1670 *crash = 0;
1671 }
1672
1673 pango_layout_set_font_description(layout, m_fontdesc);
1674 pango_layout_set_text(layout, "H", 1 );
1675 int w,h;
1676 pango_layout_get_pixel_size(layout, &w, &h);
1677 g_object_unref( G_OBJECT( layout ) );
1678
1679 return w;
1680 #else
1681 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
1682
1683 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1684
1685 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1686
1687 int direction, ascent, descent;
1688 XCharStruct overall;
1689
1690 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1691
1692 return (wxCoord)(overall.width / m_scaleX);
1693 #endif
1694 }
1695
1696 wxCoord wxWindowDC::GetCharHeight() const
1697 {
1698 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
1699
1700 #if wxUSE_UNICODE
1701 PangoLayout *layout = pango_layout_new( m_context );
1702
1703 if (!m_fontdesc)
1704 {
1705 char *crash = NULL;
1706 *crash = 0;
1707 }
1708
1709 pango_layout_set_font_description(layout, m_fontdesc);
1710
1711 pango_layout_set_text(layout, "H", 1 );
1712 int w,h;
1713 pango_layout_get_pixel_size(layout, &w, &h);
1714 g_object_unref( G_OBJECT( layout ) );
1715
1716 return h;
1717 #else
1718 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
1719
1720 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1721
1722 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1723
1724 int direction, ascent, descent;
1725 XCharStruct overall;
1726
1727 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1728
1729 return (wxCoord)((ascent+descent) / m_scaleY);
1730 #endif
1731 }
1732
1733 void wxWindowDC::Clear()
1734 {
1735 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1736
1737 if (!m_window) return;
1738
1739 /* - we either are a memory dc or have a window as the
1740 owner. anything else shouldn't happen.
1741 - we don't use gdk_window_clear() as we don't set
1742 the window's background colour anymore. it is too
1743 much pain to keep the DC's and the window's back-
1744 ground colour in synch. */
1745
1746 if (m_owner)
1747 {
1748 int width,height;
1749 m_owner->GetSize( &width, &height );
1750 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1751 return;
1752 }
1753
1754 if (m_isMemDC)
1755 {
1756 int width,height;
1757 GetSize( &width, &height );
1758 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1759 return;
1760 }
1761 }
1762
1763 void wxWindowDC::SetFont( const wxFont &font )
1764 {
1765 wxCHECK_RET( Ok(), wxT("invalid dc") );
1766
1767 m_font = font;
1768 }
1769
1770 void wxWindowDC::SetPen( const wxPen &pen )
1771 {
1772 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1773
1774 if (m_pen == pen) return;
1775
1776 m_pen = pen;
1777
1778 if (!m_pen.Ok()) return;
1779
1780 if (!m_window) return;
1781
1782 int width = m_pen.GetWidth();
1783 if (width <= 0)
1784 {
1785 // CMB: if width is non-zero scale it with the dc
1786 width = 1;
1787 }
1788 else
1789 {
1790 // X doesn't allow different width in x and y and so we take
1791 // the average
1792 double w = 0.5 +
1793 ( fabs((double) XLOG2DEVREL(width)) +
1794 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1795 width = (int)w;
1796 }
1797
1798 static const wxX11Dash dotted[] = {1, 1};
1799 static const wxX11Dash short_dashed[] = {2, 2};
1800 static const wxX11Dash long_dashed[] = {2, 4};
1801 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1802
1803 // We express dash pattern in pen width unit, so we are
1804 // independent of zoom factor and so on...
1805 int req_nb_dash;
1806 const wxX11Dash *req_dash;
1807
1808 int lineStyle = LineSolid;
1809 switch (m_pen.GetStyle())
1810 {
1811 case wxUSER_DASH:
1812 {
1813 lineStyle = LineOnOffDash;
1814 req_nb_dash = m_pen.GetDashCount();
1815 req_dash = (wxX11Dash*)m_pen.GetDash();
1816 break;
1817 }
1818 case wxDOT:
1819 {
1820 lineStyle = LineOnOffDash;
1821 req_nb_dash = 2;
1822 req_dash = dotted;
1823 break;
1824 }
1825 case wxLONG_DASH:
1826 {
1827 lineStyle = LineOnOffDash;
1828 req_nb_dash = 2;
1829 req_dash = long_dashed;
1830 break;
1831 }
1832 case wxSHORT_DASH:
1833 {
1834 lineStyle = LineOnOffDash;
1835 req_nb_dash = 2;
1836 req_dash = short_dashed;
1837 break;
1838 }
1839 case wxDOT_DASH:
1840 {
1841 // lineStyle = LineDoubleDash;
1842 lineStyle = LineOnOffDash;
1843 req_nb_dash = 4;
1844 req_dash = dotted_dashed;
1845 break;
1846 }
1847
1848 case wxTRANSPARENT:
1849 case wxSTIPPLE_MASK_OPAQUE:
1850 case wxSTIPPLE:
1851 case wxSOLID:
1852 default:
1853 {
1854 lineStyle = LineSolid;
1855 req_dash = (wxX11Dash*)NULL;
1856 req_nb_dash = 0;
1857 break;
1858 }
1859 }
1860
1861 int capStyle = CapRound;
1862 switch (m_pen.GetCap())
1863 {
1864 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1865 case wxCAP_BUTT: { capStyle = CapButt; break; }
1866 case wxCAP_ROUND:
1867 default:
1868 {
1869 if (width <= 1)
1870 {
1871 width = 0;
1872 capStyle = CapNotLast;
1873 }
1874 else
1875 {
1876 capStyle = CapRound;
1877 }
1878 break;
1879 }
1880 }
1881
1882 int joinStyle = JoinRound;
1883 switch (m_pen.GetJoin())
1884 {
1885 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1886 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1887 case wxJOIN_ROUND:
1888 default: { joinStyle = JoinRound; break; }
1889 }
1890
1891 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1892
1893 m_pen.GetColour().CalcPixel( m_cmap );
1894 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1895 }
1896
1897 void wxWindowDC::SetBrush( const wxBrush &brush )
1898 {
1899 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1900
1901 if (m_brush == brush) return;
1902
1903 m_brush = brush;
1904
1905 if (!m_brush.Ok()) return;
1906
1907 if (!m_window) return;
1908
1909 m_brush.GetColour().CalcPixel( m_cmap );
1910 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1911
1912 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1913
1914 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
1915 {
1916 if (m_brush.GetStipple()->GetPixmap())
1917 {
1918 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1919 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1920 }
1921 else
1922 {
1923 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1924 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1925 }
1926 }
1927
1928 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1929 {
1930 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1931 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1932 }
1933
1934 if (IS_HATCH(m_brush.GetStyle()))
1935 {
1936 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1937 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1938 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1939 }
1940 }
1941
1942 void wxWindowDC::SetBackground( const wxBrush &brush )
1943 {
1944 /* CMB 21/7/98: Added SetBackground. Sets background brush
1945 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1946
1947 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1948
1949 if (m_backgroundBrush == brush) return;
1950
1951 m_backgroundBrush = brush;
1952
1953 if (!m_backgroundBrush.Ok()) return;
1954
1955 if (!m_window) return;
1956
1957 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1958 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1959 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1960 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1961 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1962
1963 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
1964
1965 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
1966 {
1967 if (m_backgroundBrush.GetStipple()->GetPixmap())
1968 {
1969 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1970 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
1971 }
1972 else
1973 {
1974 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1975 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1976 }
1977 }
1978
1979 if (IS_HATCH(m_backgroundBrush.GetStyle()))
1980 {
1981 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1982 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1983 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
1984 }
1985 }
1986
1987 void wxWindowDC::SetLogicalFunction( int function )
1988 {
1989 wxCHECK_RET( Ok(), wxT("invalid dc") );
1990
1991 int x_function;
1992
1993 if (m_logicalFunction == function)
1994 return;
1995
1996 // VZ: shouldn't this be a CHECK?
1997 if (!m_window)
1998 return;
1999
2000 switch (function)
2001 {
2002 case wxCLEAR:
2003 x_function = GXclear;
2004 break;
2005 case wxXOR:
2006 x_function = GXxor;
2007 break;
2008 case wxINVERT:
2009 x_function = GXinvert;
2010 break;
2011 case wxOR_REVERSE:
2012 x_function = GXorReverse;
2013 break;
2014 case wxAND_REVERSE:
2015 x_function = GXandReverse;
2016 break;
2017 case wxAND:
2018 x_function = GXand;
2019 break;
2020 case wxOR:
2021 x_function = GXor;
2022 break;
2023 case wxAND_INVERT:
2024 x_function = GXandInverted;
2025 break;
2026 case wxNO_OP:
2027 x_function = GXnoop;
2028 break;
2029 case wxNOR:
2030 x_function = GXnor;
2031 break;
2032 case wxEQUIV:
2033 x_function = GXequiv;
2034 break;
2035 case wxSRC_INVERT:
2036 x_function = GXcopyInverted;
2037 break;
2038 case wxOR_INVERT:
2039 x_function = GXorInverted;
2040 break;
2041 case wxNAND:
2042 x_function = GXnand;
2043 break;
2044 case wxSET:
2045 x_function = GXset;
2046 break;
2047 case wxCOPY:
2048 default:
2049 x_function = GXcopy;
2050 break;
2051 }
2052
2053 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2054 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
2055
2056 // to stay compatible with wxMSW, we don't apply ROPs to the text
2057 // operations (i.e. DrawText/DrawRotatedText).
2058 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2059 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
2060
2061 m_logicalFunction = function;
2062 }
2063
2064 void wxWindowDC::SetTextForeground( const wxColour &col )
2065 {
2066 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2067
2068 // don't set m_textForegroundColour to an invalid colour as we'd crash
2069 // later then (we use m_textForegroundColour.GetColor() without checking
2070 // in a few places)
2071 if ( !col.Ok() || (m_textForegroundColour == col) )
2072 return;
2073
2074 m_textForegroundColour = col;
2075
2076 if (m_window)
2077 {
2078 m_textForegroundColour.CalcPixel( m_cmap );
2079 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2080 }
2081 }
2082
2083 void wxWindowDC::SetTextBackground( const wxColour &col )
2084 {
2085 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2086
2087 // same as above
2088 if ( !col.Ok() || (m_textBackgroundColour == col) )
2089 return;
2090
2091 m_textBackgroundColour = col;
2092
2093 if (m_window)
2094 {
2095 m_textBackgroundColour.CalcPixel( m_cmap );
2096 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2097 }
2098 }
2099
2100 void wxWindowDC::SetBackgroundMode( int mode )
2101 {
2102 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2103
2104 m_backgroundMode = mode;
2105
2106 #if wxUSE_NANOX
2107 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2108 #endif
2109
2110 if (!m_window) return;
2111
2112 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2113 // transparent/solid background mode
2114
2115 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2116 {
2117 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2118 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2119 }
2120 }
2121
2122 void wxWindowDC::SetPalette( const wxPalette& palette )
2123 {
2124 #if 0
2125 if (m_window)
2126 {
2127 if (palette.Ok())
2128 /* Use GetXColormap */
2129 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2130 (Colormap) palette.GetXColormap());
2131 else
2132 /* Use wxGetMainColormap */
2133 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2134 (Colormap) wxTheApp->GetMainColormap(m_display));
2135 }
2136 #endif
2137 }
2138
2139 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2140 {
2141 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2142
2143 if (!m_window) return;
2144
2145 wxRect rect;
2146 rect.x = XLOG2DEV(x);
2147 rect.y = YLOG2DEV(y);
2148 rect.width = XLOG2DEVREL(width);
2149 rect.height = YLOG2DEVREL(height);
2150
2151 if (!m_currentClippingRegion.IsNull())
2152 m_currentClippingRegion.Intersect( rect );
2153 else
2154 m_currentClippingRegion.Union( rect );
2155
2156 #if USE_PAINT_REGION
2157 if (!m_paintClippingRegion.IsNull())
2158 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2159 #endif
2160
2161 wxCoord xx, yy, ww, hh;
2162 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2163 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2164
2165 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2166 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2167 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2168 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2169 }
2170
2171 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2172 {
2173 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2174
2175 if (region.Empty())
2176 {
2177 DestroyClippingRegion();
2178 return;
2179 }
2180
2181 if (!m_window) return;
2182
2183 if (!m_currentClippingRegion.IsNull())
2184 m_currentClippingRegion.Intersect( region );
2185 else
2186 m_currentClippingRegion.Union( region );
2187
2188 #if USE_PAINT_REGION
2189 if (!m_paintClippingRegion.IsNull())
2190 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2191 #endif
2192
2193 wxCoord xx, yy, ww, hh;
2194 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2195 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2196
2197 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2198 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2199 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2200 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2201 }
2202
2203 void wxWindowDC::DestroyClippingRegion()
2204 {
2205 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2206
2207 wxDC::DestroyClippingRegion();
2208
2209 m_currentClippingRegion.Clear();
2210
2211 #if USE_PAINT_REGION
2212 if (!m_paintClippingRegion.IsEmpty())
2213 m_currentClippingRegion.Union( m_paintClippingRegion );
2214 #endif
2215
2216 if (!m_window) return;
2217
2218 if (m_currentClippingRegion.IsEmpty())
2219 {
2220 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2221 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2222 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2223 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2224 }
2225 else
2226 {
2227 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2228 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2229 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2230 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2231 }
2232 }
2233
2234 void wxWindowDC::Destroy()
2235 {
2236 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2237 m_penGC = NULL;
2238 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2239 m_brushGC = NULL;
2240 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2241 m_textGC = NULL;
2242 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2243 m_bgGC = NULL;
2244 }
2245
2246 void wxWindowDC::ComputeScaleAndOrigin()
2247 {
2248 /* CMB: copy scale to see if it changes */
2249 double origScaleX = m_scaleX;
2250 double origScaleY = m_scaleY;
2251
2252 wxDC::ComputeScaleAndOrigin();
2253
2254 /* CMB: if scale has changed call SetPen to recalulate the line width */
2255 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2256 (m_pen.Ok()))
2257 {
2258 /* this is a bit artificial, but we need to force wxDC to think
2259 the pen has changed */
2260 wxPen pen = m_pen;
2261 m_pen = wxNullPen;
2262 SetPen( pen );
2263 }
2264 }
2265
2266 wxSize wxWindowDC::GetPPI() const
2267 {
2268 return wxSize(100, 100);
2269 }
2270
2271 int wxWindowDC::GetDepth() const
2272 {
2273 wxFAIL_MSG(wxT("not implemented"));
2274
2275 return -1;
2276 }
2277
2278 //-----------------------------------------------------------------------------
2279 // wxClientDC
2280 //-----------------------------------------------------------------------------
2281
2282 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2283
2284 wxClientDC::wxClientDC( wxWindow *window )
2285 : wxWindowDC( window )
2286 {
2287 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
2288
2289 m_window = (WXWindow*) window->GetClientAreaWindow();
2290
2291 // Adjust the client area when the wxWindow is not using 2 X11 windows.
2292 if (m_window == (WXWindow*) window->GetMainWindow())
2293 {
2294 wxPoint ptOrigin = window->GetClientAreaOrigin();
2295 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2296 wxSize size = window->GetClientSize();
2297 SetClippingRegion(wxPoint(0, 0), size);
2298 }
2299 }
2300
2301 void wxClientDC::DoGetSize(int *width, int *height) const
2302 {
2303 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2304
2305 m_owner->GetClientSize( width, height );
2306 }
2307
2308 // ----------------------------------------------------------------------------
2309 // wxPaintDC
2310 // ----------------------------------------------------------------------------
2311
2312 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2313
2314 wxPaintDC::wxPaintDC(wxWindow* window)
2315 : wxClientDC(window)
2316 {
2317 #if USE_PAINT_REGION
2318 if (!window->GetClipPaintRegion())
2319 return;
2320
2321 m_paintClippingRegion = window->GetUpdateRegion();
2322 Region region = (Region) m_paintClippingRegion.GetX11Region();
2323 if (region)
2324 {
2325 m_currentClippingRegion.Union( m_paintClippingRegion );
2326
2327 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2328 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2329 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2330 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2331 }
2332 #endif // USE_PAINT_REGION
2333 }
2334
2335 // ----------------------------------------------------------------------------
2336 // wxDCModule
2337 // ----------------------------------------------------------------------------
2338
2339 class wxDCModule : public wxModule
2340 {
2341 public:
2342 bool OnInit();
2343 void OnExit();
2344
2345 private:
2346 DECLARE_DYNAMIC_CLASS(wxDCModule)
2347 };
2348
2349 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2350
2351 bool wxDCModule::OnInit()
2352 {
2353 wxInitGCPool();
2354 return TRUE;
2355 }
2356
2357 void wxDCModule::OnExit()
2358 {
2359 wxCleanUpGCPool();
2360 }