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