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