Applied patch [ 1407318 ] bitmap clipping / transparency mask (X11 port)
[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 bool setClipMask = false;
1174
1175 if (!m_currentClippingRegion.IsNull() || (useMask && mask))
1176 {
1177 // XSetClipMask() call is necessary (because of clip region and/or transparent mask)
1178 setClipMask = true;
1179 Pixmap new_pixmap = 0;
1180
1181 if (!m_currentClippingRegion.IsNull())
1182 {
1183 // clipping necessary => create new_pixmap
1184 Display *xdisplay = (Display*) m_display;
1185 int xscreen = DefaultScreen( xdisplay );
1186 Window xroot = RootWindow( xdisplay, xscreen );
1187
1188 new_pixmap = XCreatePixmap( xdisplay, xroot, w, h, 1 );
1189 GC gc = XCreateGC( xdisplay, new_pixmap, 0, NULL );
1190
1191 int bpp = wxTheApp->GetVisualInfo(m_display)->m_visualDepth;
1192 if (bpp == 8)
1193 XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) );
1194 else
1195 XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) );
1196
1197 XSetFillStyle( xdisplay, gc, FillSolid );
1198 XFillRectangle( xdisplay, new_pixmap, gc, 0, 0, w, h );
1199
1200 if (bpp == 8)
1201 XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) );
1202 else
1203 XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) );
1204
1205 if (useMask && mask)
1206 {
1207 // transparent mask => call XSetStipple
1208 XSetFillStyle( xdisplay, gc, FillStippled );
1209 XSetTSOrigin( xdisplay, gc, 0, 0);
1210 XSetStipple( xdisplay, gc, (Pixmap) mask);
1211 }
1212
1213 wxCoord clip_x, clip_y, clip_w, clip_h;
1214 m_currentClippingRegion.GetBox(clip_x, clip_y, clip_w, clip_h);
1215 XFillRectangle( xdisplay, new_pixmap, gc, clip_x-xx, clip_y-yy, clip_w, clip_h );
1216
1217 XFreeGC( xdisplay, gc );
1218 }
1219
1220 if (is_mono)
1221 {
1222 if (new_pixmap)
1223 XSetClipMask( (Display*) m_display, (GC) m_textGC, new_pixmap );
1224 else
1225 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1226 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1227 }
1228 else
1229 {
1230 if (new_pixmap)
1231 XSetClipMask( (Display*) m_display, (GC) m_penGC, new_pixmap );
1232 else
1233 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1234 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1235 }
1236
1237 if (new_pixmap)
1238 XFreePixmap( (Display*) m_display, new_pixmap );
1239 }
1240
1241 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1242 // drawing a mono-bitmap (XBitmap) we use the current text GC
1243 if (is_mono)
1244 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1245 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
1246 else
1247 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1248 (GC) m_penGC, 0, 0, w, h, xx, yy );
1249
1250 // remove mask again if any
1251 if (setClipMask)
1252 {
1253 if (is_mono)
1254 {
1255 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1256 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1257 if (!m_currentClippingRegion.IsNull())
1258 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1259 }
1260 else
1261 {
1262 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1263 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1264 if (!m_currentClippingRegion.IsNull())
1265 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1266 }
1267 }
1268 }
1269 #endif
1270 // wxUSE_NANOX/!wxUSE_NANOX
1271
1272 bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1273 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
1274 wxCoord xsrcMask, wxCoord ysrcMask )
1275 {
1276 /* this is the nth try to get this utterly useless function to
1277 work. it now completely ignores the scaling or translation
1278 of the source dc, but scales correctly on the target dc and
1279 knows about possible mask information in a memory dc. */
1280
1281 wxCHECK_MSG( Ok(), false, wxT("invalid window dc") );
1282
1283 wxCHECK_MSG( source, false, wxT("invalid source dc") );
1284
1285 if (!m_window) return false;
1286
1287 // transform the source DC coords to the device ones
1288 xsrc = source->XLOG2DEV(xsrc);
1289 ysrc = source->YLOG2DEV(ysrc);
1290
1291 wxClientDC *srcDC = (wxClientDC*)source;
1292 wxMemoryDC *memDC = (wxMemoryDC*)source;
1293
1294 bool use_bitmap_method = false;
1295 bool is_mono = false;
1296
1297 // TODO: use the mask origin when drawing transparently
1298 if (xsrcMask == -1 && ysrcMask == -1)
1299 {
1300 xsrcMask = xsrc;
1301 ysrcMask = ysrc;
1302 }
1303
1304 if (srcDC->m_isMemDC)
1305 {
1306 if (!memDC->m_selected.Ok()) return false;
1307
1308 /* we use the "XCopyArea" way to copy a memory dc into
1309 y different window if the memory dc BOTH
1310 a) doesn't have any mask or its mask isn't used
1311 b) it is clipped
1312 c) is not 1-bit */
1313
1314 if (useMask && (memDC->m_selected.GetMask()))
1315 {
1316 /* we HAVE TO use the direct way for memory dcs
1317 that have mask since the XCopyArea doesn't know
1318 about masks */
1319 use_bitmap_method = true;
1320 }
1321 else if (memDC->m_selected.GetDepth() == 1)
1322 {
1323 /* we HAVE TO use the direct way for memory dcs
1324 that are bitmaps because XCopyArea doesn't cope
1325 with different bit depths */
1326 is_mono = true;
1327 use_bitmap_method = true;
1328 }
1329 else if ((xsrc == 0) && (ysrc == 0) &&
1330 (width == memDC->m_selected.GetWidth()) &&
1331 (height == memDC->m_selected.GetHeight()))
1332 {
1333 /* we SHOULD use the direct way if all of the bitmap
1334 in the memory dc is copied in which case XCopyArea
1335 wouldn't be able able to boost performace by reducing
1336 the area to be scaled */
1337 use_bitmap_method = true;
1338 }
1339 else
1340 {
1341 use_bitmap_method = false;
1342 }
1343 }
1344
1345 CalcBoundingBox( xdest, ydest );
1346 CalcBoundingBox( xdest + width, ydest + height );
1347
1348 // scale/translate size and position
1349 wxCoord xx = XLOG2DEV(xdest);
1350 wxCoord yy = YLOG2DEV(ydest);
1351
1352 wxCoord ww = XLOG2DEVREL(width);
1353 wxCoord hh = YLOG2DEVREL(height);
1354
1355 // compare to current clipping region
1356 if (!m_currentClippingRegion.IsNull())
1357 {
1358 wxRegion tmp( xx,yy,ww,hh );
1359 tmp.Intersect( m_currentClippingRegion );
1360 if (tmp.IsEmpty())
1361 return true;
1362 }
1363
1364 int old_logical_func = m_logicalFunction;
1365 SetLogicalFunction( logical_func );
1366
1367 if (use_bitmap_method)
1368 {
1369 // scale/translate bitmap size
1370 wxCoord bm_width = memDC->m_selected.GetWidth();
1371 wxCoord bm_height = memDC->m_selected.GetHeight();
1372
1373 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1374 wxCoord bm_hh = YLOG2DEVREL( bm_height );
1375
1376 // scale bitmap if required
1377 wxBitmap use_bitmap;
1378
1379 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1380 {
1381 wxImage image( memDC->m_selected.ConvertToImage() );
1382 image = image.Scale( bm_ww, bm_hh );
1383
1384 #if 0
1385 if (is_mono)
1386 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1387 else
1388 #endif
1389 use_bitmap = image;
1390 }
1391 else
1392 {
1393 use_bitmap = memDC->m_selected;
1394 }
1395
1396 // apply mask if any
1397 WXPixmap mask = NULL;
1398 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1399
1400 if (useMask && mask)
1401 {
1402 WXPixmap new_mask = NULL;
1403 #if 0
1404 if (!m_currentClippingRegion.IsNull())
1405 {
1406 GdkColor col;
1407 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1408 GdkGC *gc = gdk_gc_new( new_mask );
1409 col.pixel = 0;
1410 gdk_gc_set_foreground( gc, &col );
1411 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1412 col.pixel = 0;
1413 gdk_gc_set_background( gc, &col );
1414 col.pixel = 1;
1415 gdk_gc_set_foreground( gc, &col );
1416 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1417 gdk_gc_set_clip_origin( gc, -xx, -yy );
1418 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1419 gdk_gc_set_stipple( gc, mask );
1420 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1421 gdk_gc_unref( gc );
1422 }
1423 #endif
1424 if (is_mono)
1425 {
1426 if (new_mask)
1427 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1428 else
1429 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1430 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1431 }
1432 else
1433 {
1434 if (new_mask)
1435 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1436 else
1437 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1438 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1439 }
1440
1441 if (new_mask)
1442 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1443 }
1444
1445 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1446 // drawing a mono-bitmap (XBitmap) we use the current text GC
1447
1448 if (is_mono)
1449 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1450 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
1451 else
1452 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1453 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1454
1455 // remove mask again if any
1456 if (useMask && mask)
1457 {
1458 if (is_mono)
1459 {
1460 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1461 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1462 if (!m_currentClippingRegion.IsNull())
1463 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1464 }
1465 else
1466 {
1467 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1468 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1469 if (!m_currentClippingRegion.IsNull())
1470 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1471 }
1472 }
1473 }
1474 else // use_bitmap_method
1475 {
1476 if ((width != ww) || (height != hh))
1477 {
1478 /* Draw source window into a bitmap as we cannot scale
1479 a window in contrast to a bitmap. this would actually
1480 work with memory dcs as well, but we'd lose the mask
1481 information and waste one step in this process since
1482 a memory already has a bitmap. all this is slightly
1483 inefficient as we could take an XImage directly from
1484 an X window, but we'd then also have to care that
1485 the window is not outside the screen (in which case
1486 we'd get a BadMatch or what not).
1487 Is a double XGetImage and combined XGetPixel and
1488 XPutPixel really faster? I'm not sure. look at wxXt
1489 for a different implementation of the same problem. */
1490
1491 wxBitmap bitmap( width, height );
1492
1493 // copy including child window contents
1494 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1495 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1496 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1497 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1498
1499 // scale image
1500 wxImage image( bitmap.ConvertToImage() );
1501 image = image.Scale( ww, hh );
1502
1503 // convert to bitmap
1504 bitmap = image;
1505
1506 // draw scaled bitmap
1507 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1508 (GC) m_penGC, 0, 0, width, height, xx, yy );
1509 }
1510 else
1511 {
1512 // No scaling and not a memory dc with a mask either
1513
1514 // copy including child window contents
1515 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1516 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1517 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1518 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1519 }
1520 }
1521
1522 SetLogicalFunction( old_logical_func );
1523
1524 return true;
1525 }
1526
1527 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1528 {
1529 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1530
1531 if (!m_window) return;
1532
1533 x = XLOG2DEV(x);
1534 y = YLOG2DEV(y);
1535
1536 #if wxUSE_UNICODE
1537 PangoLayout *layout = pango_layout_new(m_context);
1538 pango_layout_set_font_description(layout, m_fontdesc);
1539
1540 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1541 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1542
1543 // Measure layout.
1544 int w,h;
1545 pango_layout_get_pixel_size(layout, &w, &h);
1546 wxCoord width = w;
1547 wxCoord height = h;
1548
1549 // Draw layout.
1550 x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
1551
1552 g_object_unref( G_OBJECT( layout ) );
1553
1554 CalcBoundingBox (x + width, y + height);
1555 CalcBoundingBox (x, y);
1556 #else
1557 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1558
1559 wxCHECK_RET( xfont, wxT("invalid font") );
1560
1561 // First draw a rectangle representing the text background, if a text
1562 // background is specified
1563 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1564 {
1565 // Since X draws from the baseline of the text, must add the text height
1566 int cx = 0;
1567 int cy = 0;
1568 int ascent = 0;
1569 int slen;
1570 int direction, descent;
1571
1572 slen = strlen(text);
1573 XCharStruct overall_return;
1574
1575 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
1576 &ascent, &descent, &overall_return);
1577
1578 cx = overall_return.width;
1579 cy = ascent + descent;
1580 m_textBackgroundColour.CalcPixel(m_cmap);
1581 m_textForegroundColour.CalcPixel(m_cmap);
1582 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
1583 XFillRectangle( (Display*) m_display, (Window) m_window,
1584 (GC) m_textGC, x, y, cx, cy );
1585 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1586
1587 }
1588
1589 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
1590 #if !wxUSE_NANOX
1591 // This may be a test for whether the font is 16-bit, but it also
1592 // seems to fail for valid 8-bit fonts too.
1593 if (1) // (xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1594 #endif
1595 {
1596 XDrawString( (Display*) m_display, (Window) m_window,
1597 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1598 }
1599
1600 #if 0
1601 if (m_font.GetUnderlined())
1602 {
1603 wxCoord ul_y = y + XFontStructGetAscent(font);
1604 if (font->descent > 0) ul_y++;
1605 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
1606 }
1607
1608 width = wxCoord(width / m_scaleX);
1609 height = wxCoord(height / m_scaleY);
1610
1611 CalcBoundingBox (x + width, y + height);
1612 CalcBoundingBox (x, y);
1613 #endif
1614 #endif
1615 }
1616
1617 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1618 {
1619 // later
1620 }
1621
1622 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1623 wxCoord *descent, wxCoord *externalLeading,
1624 wxFont *font ) const
1625 {
1626 wxCHECK_RET( Ok(), wxT("invalid dc") );
1627
1628 if (string.empty())
1629 {
1630 if (width) (*width) = 0;
1631 if (height) (*height) = 0;
1632 return;
1633 }
1634
1635 #if wxUSE_UNICODE
1636 PangoLayout *layout = pango_layout_new( m_context );
1637
1638 if (font)
1639 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1640 else
1641 pango_layout_set_font_description(layout, m_fontdesc);
1642
1643 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1644 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1645
1646 // Measure text.
1647 int w,h;
1648 pango_layout_get_pixel_size(layout, &w, &h);
1649
1650 if (width) (*width) = (wxCoord) w;
1651 if (height) (*height) = (wxCoord) h;
1652 if (descent)
1653 {
1654 // Do something about metrics here. TODO.
1655 (*descent) = 0;
1656 }
1657 if (externalLeading) (*externalLeading) = 0; // ??
1658
1659 g_object_unref( G_OBJECT( layout ) );
1660 #else
1661 wxFont fontToUse = m_font;
1662 if (font) fontToUse = *font;
1663
1664 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
1665
1666 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1667
1668 wxCHECK_RET( xfont, wxT("invalid font") );
1669
1670 int direction, ascent, descent2;
1671 XCharStruct overall;
1672
1673 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
1674 &ascent, &descent2, &overall);
1675
1676 if (width)
1677 *width = (wxCoord)( overall.width / m_scaleX );
1678 if (height)
1679 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1680 if (descent)
1681 *descent = (wxCoord)(descent2 / m_scaleY );
1682 if (externalLeading)
1683 *externalLeading = 0; // ??
1684 #endif
1685 }
1686
1687 wxCoord wxWindowDC::GetCharWidth() const
1688 {
1689 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
1690
1691 #if wxUSE_UNICODE
1692 PangoLayout *layout = pango_layout_new( m_context );
1693
1694 if (m_fontdesc)
1695 pango_layout_set_font_description(layout, m_fontdesc);
1696 else
1697 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1698
1699 pango_layout_set_text(layout, "H", 1 );
1700 int w,h;
1701 pango_layout_get_pixel_size(layout, &w, &h);
1702 g_object_unref( G_OBJECT( layout ) );
1703
1704 return w;
1705 #else
1706 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
1707
1708 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1709
1710 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1711
1712 int direction, ascent, descent;
1713 XCharStruct overall;
1714
1715 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1716
1717 return (wxCoord)(overall.width / m_scaleX);
1718 #endif
1719 }
1720
1721 wxCoord wxWindowDC::GetCharHeight() const
1722 {
1723 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
1724
1725 #if wxUSE_UNICODE
1726 PangoLayout *layout = pango_layout_new( m_context );
1727
1728 if (m_fontdesc)
1729 pango_layout_set_font_description(layout, m_fontdesc);
1730 else
1731 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1732
1733 pango_layout_set_text(layout, "H", 1 );
1734 int w,h;
1735 pango_layout_get_pixel_size(layout, &w, &h);
1736 g_object_unref( G_OBJECT( layout ) );
1737
1738 return h;
1739 #else
1740 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
1741
1742 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1743
1744 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1745
1746 int direction, ascent, descent;
1747 XCharStruct overall;
1748
1749 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1750
1751 return (wxCoord)((ascent+descent) / m_scaleY);
1752 #endif
1753 }
1754
1755 void wxWindowDC::Clear()
1756 {
1757 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1758
1759 if (!m_window) return;
1760
1761 /* - we either are a memory dc or have a window as the
1762 owner. anything else shouldn't happen.
1763 - we don't use gdk_window_clear() as we don't set
1764 the window's background colour anymore. it is too
1765 much pain to keep the DC's and the window's back-
1766 ground colour in synch. */
1767
1768 if (m_owner)
1769 {
1770 int width,height;
1771 m_owner->GetSize( &width, &height );
1772 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1773 return;
1774 }
1775
1776 if (m_isMemDC)
1777 {
1778 int width,height;
1779 GetSize( &width, &height );
1780 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1781 return;
1782 }
1783 }
1784
1785 void wxWindowDC::SetFont( const wxFont &font )
1786 {
1787 wxCHECK_RET( Ok(), wxT("invalid dc") );
1788
1789 m_font = font;
1790
1791 return;
1792
1793 #if wxUSE_UNICODE
1794 m_fontdesc = font.GetNativeFontInfo()->description;
1795 #endif
1796 }
1797
1798 void wxWindowDC::SetPen( const wxPen &pen )
1799 {
1800 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1801
1802 if (m_pen == pen) return;
1803
1804 m_pen = pen;
1805
1806 if (!m_pen.Ok()) return;
1807
1808 if (!m_window) return;
1809
1810 int width = m_pen.GetWidth();
1811 if (width <= 0)
1812 {
1813 // CMB: if width is non-zero scale it with the dc
1814 width = 1;
1815 }
1816 else
1817 {
1818 // X doesn't allow different width in x and y and so we take
1819 // the average
1820 double w = 0.5 +
1821 ( fabs((double) XLOG2DEVREL(width)) +
1822 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1823 width = (int)w;
1824 }
1825
1826 static const wxX11Dash dotted[] = {1, 1};
1827 static const wxX11Dash short_dashed[] = {2, 2};
1828 static const wxX11Dash long_dashed[] = {2, 4};
1829 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1830
1831 // We express dash pattern in pen width unit, so we are
1832 // independent of zoom factor and so on...
1833 int req_nb_dash;
1834 const wxX11Dash *req_dash;
1835
1836 int lineStyle = LineSolid;
1837 switch (m_pen.GetStyle())
1838 {
1839 case wxUSER_DASH:
1840 {
1841 lineStyle = LineOnOffDash;
1842 req_nb_dash = m_pen.GetDashCount();
1843 req_dash = (wxX11Dash*)m_pen.GetDash();
1844 break;
1845 }
1846 case wxDOT:
1847 {
1848 lineStyle = LineOnOffDash;
1849 req_nb_dash = 2;
1850 req_dash = dotted;
1851 break;
1852 }
1853 case wxLONG_DASH:
1854 {
1855 lineStyle = LineOnOffDash;
1856 req_nb_dash = 2;
1857 req_dash = long_dashed;
1858 break;
1859 }
1860 case wxSHORT_DASH:
1861 {
1862 lineStyle = LineOnOffDash;
1863 req_nb_dash = 2;
1864 req_dash = short_dashed;
1865 break;
1866 }
1867 case wxDOT_DASH:
1868 {
1869 // lineStyle = LineDoubleDash;
1870 lineStyle = LineOnOffDash;
1871 req_nb_dash = 4;
1872 req_dash = dotted_dashed;
1873 break;
1874 }
1875
1876 case wxTRANSPARENT:
1877 case wxSTIPPLE_MASK_OPAQUE:
1878 case wxSTIPPLE:
1879 case wxSOLID:
1880 default:
1881 {
1882 lineStyle = LineSolid;
1883 req_dash = (wxX11Dash*)NULL;
1884 req_nb_dash = 0;
1885 break;
1886 }
1887 }
1888
1889 int capStyle = CapRound;
1890 switch (m_pen.GetCap())
1891 {
1892 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1893 case wxCAP_BUTT: { capStyle = CapButt; break; }
1894 case wxCAP_ROUND:
1895 default:
1896 {
1897 if (width <= 1)
1898 {
1899 width = 0;
1900 capStyle = CapNotLast;
1901 }
1902 else
1903 {
1904 capStyle = CapRound;
1905 }
1906 break;
1907 }
1908 }
1909
1910 int joinStyle = JoinRound;
1911 switch (m_pen.GetJoin())
1912 {
1913 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1914 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1915 case wxJOIN_ROUND:
1916 default: { joinStyle = JoinRound; break; }
1917 }
1918
1919 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1920
1921 m_pen.GetColour().CalcPixel( m_cmap );
1922 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1923 }
1924
1925 void wxWindowDC::SetBrush( const wxBrush &brush )
1926 {
1927 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1928
1929 if (m_brush == brush) return;
1930
1931 m_brush = brush;
1932
1933 if (!m_brush.Ok()) return;
1934
1935 if (!m_window) return;
1936
1937 m_brush.GetColour().CalcPixel( m_cmap );
1938 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1939
1940 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1941
1942 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
1943 {
1944 if (m_brush.GetStipple()->GetPixmap())
1945 {
1946 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1947 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1948 }
1949 else
1950 {
1951 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1952 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1953 }
1954 }
1955
1956 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1957 {
1958 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1959 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1960 }
1961
1962 if (m_brush.IsHatch())
1963 {
1964 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1965 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1966 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1967 }
1968 }
1969
1970 void wxWindowDC::SetBackground( const wxBrush &brush )
1971 {
1972 /* CMB 21/7/98: Added SetBackground. Sets background brush
1973 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1974
1975 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1976
1977 if (m_backgroundBrush == brush) return;
1978
1979 m_backgroundBrush = brush;
1980
1981 if (!m_backgroundBrush.Ok()) return;
1982
1983 if (!m_window) return;
1984
1985 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1986 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1987 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1988 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1989 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1990
1991 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
1992
1993 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
1994 {
1995 if (m_backgroundBrush.GetStipple()->GetPixmap())
1996 {
1997 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1998 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
1999 }
2000 else
2001 {
2002 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2003 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
2004 }
2005 }
2006
2007 if (m_backgroundBrush.IsHatch())
2008 {
2009 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2010 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
2011 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
2012 }
2013 }
2014
2015 void wxWindowDC::SetLogicalFunction( int function )
2016 {
2017 wxCHECK_RET( Ok(), wxT("invalid dc") );
2018
2019 int x_function;
2020
2021 if (m_logicalFunction == function)
2022 return;
2023
2024 // VZ: shouldn't this be a CHECK?
2025 if (!m_window)
2026 return;
2027
2028 switch (function)
2029 {
2030 case wxCLEAR:
2031 x_function = GXclear;
2032 break;
2033 case wxXOR:
2034 x_function = GXxor;
2035 break;
2036 case wxINVERT:
2037 x_function = GXinvert;
2038 break;
2039 case wxOR_REVERSE:
2040 x_function = GXorReverse;
2041 break;
2042 case wxAND_REVERSE:
2043 x_function = GXandReverse;
2044 break;
2045 case wxAND:
2046 x_function = GXand;
2047 break;
2048 case wxOR:
2049 x_function = GXor;
2050 break;
2051 case wxAND_INVERT:
2052 x_function = GXandInverted;
2053 break;
2054 case wxNO_OP:
2055 x_function = GXnoop;
2056 break;
2057 case wxNOR:
2058 x_function = GXnor;
2059 break;
2060 case wxEQUIV:
2061 x_function = GXequiv;
2062 break;
2063 case wxSRC_INVERT:
2064 x_function = GXcopyInverted;
2065 break;
2066 case wxOR_INVERT:
2067 x_function = GXorInverted;
2068 break;
2069 case wxNAND:
2070 x_function = GXnand;
2071 break;
2072 case wxSET:
2073 x_function = GXset;
2074 break;
2075 case wxCOPY:
2076 default:
2077 x_function = GXcopy;
2078 break;
2079 }
2080
2081 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2082 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
2083
2084 // to stay compatible with wxMSW, we don't apply ROPs to the text
2085 // operations (i.e. DrawText/DrawRotatedText).
2086 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2087 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
2088
2089 m_logicalFunction = function;
2090 }
2091
2092 void wxWindowDC::SetTextForeground( const wxColour &col )
2093 {
2094 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2095
2096 // don't set m_textForegroundColour to an invalid colour as we'd crash
2097 // later then (we use m_textForegroundColour.GetColor() without checking
2098 // in a few places)
2099 if ( !col.Ok() || (m_textForegroundColour == col) )
2100 return;
2101
2102 m_textForegroundColour = col;
2103
2104 if (m_window)
2105 {
2106 m_textForegroundColour.CalcPixel( m_cmap );
2107 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2108 }
2109 }
2110
2111 void wxWindowDC::SetTextBackground( const wxColour &col )
2112 {
2113 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2114
2115 // same as above
2116 if ( !col.Ok() || (m_textBackgroundColour == col) )
2117 return;
2118
2119 m_textBackgroundColour = col;
2120
2121 if (m_window)
2122 {
2123 m_textBackgroundColour.CalcPixel( m_cmap );
2124 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2125 }
2126 }
2127
2128 void wxWindowDC::SetBackgroundMode( int mode )
2129 {
2130 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2131
2132 m_backgroundMode = mode;
2133
2134 #if wxUSE_NANOX
2135 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2136 #endif
2137
2138 if (!m_window) return;
2139
2140 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2141 // transparent/solid background mode
2142
2143 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2144 {
2145 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2146 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2147 }
2148 }
2149
2150 void wxWindowDC::SetPalette( const wxPalette& palette )
2151 {
2152 #if 0
2153 if (m_window)
2154 {
2155 if (palette.Ok())
2156 /* Use GetXColormap */
2157 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2158 (Colormap) palette.GetXColormap());
2159 else
2160 /* Use wxGetMainColormap */
2161 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2162 (Colormap) wxTheApp->GetMainColormap(m_display));
2163 }
2164 #endif
2165 }
2166
2167 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2168 {
2169 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2170
2171 if (!m_window) return;
2172
2173 wxRect rect;
2174 rect.x = XLOG2DEV(x);
2175 rect.y = YLOG2DEV(y);
2176 rect.width = XLOG2DEVREL(width);
2177 rect.height = YLOG2DEVREL(height);
2178
2179 if (!m_currentClippingRegion.IsNull())
2180 m_currentClippingRegion.Intersect( rect );
2181 else
2182 m_currentClippingRegion.Union( rect );
2183
2184 #if USE_PAINT_REGION
2185 if (!m_paintClippingRegion.IsNull())
2186 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2187 #endif
2188
2189 wxCoord xx, yy, ww, hh;
2190 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2191 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2192
2193 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2194 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2195 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2196 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2197 }
2198
2199 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2200 {
2201 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2202
2203 if (region.Empty())
2204 {
2205 DestroyClippingRegion();
2206 return;
2207 }
2208
2209 if (!m_window) return;
2210
2211 if (!m_currentClippingRegion.IsNull())
2212 m_currentClippingRegion.Intersect( region );
2213 else
2214 m_currentClippingRegion.Union( region );
2215
2216 #if USE_PAINT_REGION
2217 if (!m_paintClippingRegion.IsNull())
2218 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2219 #endif
2220
2221 wxCoord xx, yy, ww, hh;
2222 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2223 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2224
2225 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2226 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2227 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2228 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2229 }
2230
2231 void wxWindowDC::DestroyClippingRegion()
2232 {
2233 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2234
2235 wxDC::DestroyClippingRegion();
2236
2237 m_currentClippingRegion.Clear();
2238
2239 #if USE_PAINT_REGION
2240 if (!m_paintClippingRegion.IsEmpty())
2241 m_currentClippingRegion.Union( m_paintClippingRegion );
2242 #endif
2243
2244 if (!m_window) return;
2245
2246 if (m_currentClippingRegion.IsEmpty())
2247 {
2248 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2249 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2250 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2251 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2252 }
2253 else
2254 {
2255 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2256 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2257 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2258 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2259 }
2260 }
2261
2262 void wxWindowDC::Destroy()
2263 {
2264 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2265 m_penGC = NULL;
2266 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2267 m_brushGC = NULL;
2268 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2269 m_textGC = NULL;
2270 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2271 m_bgGC = NULL;
2272 }
2273
2274 void wxWindowDC::ComputeScaleAndOrigin()
2275 {
2276 /* CMB: copy scale to see if it changes */
2277 double origScaleX = m_scaleX;
2278 double origScaleY = m_scaleY;
2279
2280 wxDC::ComputeScaleAndOrigin();
2281
2282 /* CMB: if scale has changed call SetPen to recalulate the line width */
2283 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2284 (m_pen.Ok()))
2285 {
2286 /* this is a bit artificial, but we need to force wxDC to think
2287 the pen has changed */
2288 wxPen pen = m_pen;
2289 m_pen = wxNullPen;
2290 SetPen( pen );
2291 }
2292 }
2293
2294 wxSize wxWindowDC::GetPPI() const
2295 {
2296 return wxSize(100, 100);
2297 }
2298
2299 int wxWindowDC::GetDepth() const
2300 {
2301 wxFAIL_MSG(wxT("not implemented"));
2302
2303 return -1;
2304 }
2305
2306 //-----------------------------------------------------------------------------
2307 // wxClientDC
2308 //-----------------------------------------------------------------------------
2309
2310 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2311
2312 wxClientDC::wxClientDC( wxWindow *window )
2313 : wxWindowDC( window )
2314 {
2315 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
2316
2317 m_window = (WXWindow*) window->GetClientAreaWindow();
2318
2319 // Adjust the client area when the wxWindow is not using 2 X11 windows.
2320 if (m_window == (WXWindow*) window->GetMainWindow())
2321 {
2322 wxPoint ptOrigin = window->GetClientAreaOrigin();
2323 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2324 wxSize size = window->GetClientSize();
2325 SetClippingRegion(wxPoint(0, 0), size);
2326 }
2327 }
2328
2329 void wxClientDC::DoGetSize(int *width, int *height) const
2330 {
2331 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2332
2333 m_owner->GetClientSize( width, height );
2334 }
2335
2336 // ----------------------------------------------------------------------------
2337 // wxPaintDC
2338 // ----------------------------------------------------------------------------
2339
2340 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2341
2342 wxPaintDC::wxPaintDC(wxWindow* window)
2343 : wxClientDC(window)
2344 {
2345 #if USE_PAINT_REGION
2346 if (!window->GetClipPaintRegion())
2347 return;
2348
2349 m_paintClippingRegion = window->GetUpdateRegion();
2350 Region region = (Region) m_paintClippingRegion.GetX11Region();
2351 if (region)
2352 {
2353 m_currentClippingRegion.Union( m_paintClippingRegion );
2354
2355 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2356 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2357 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2358 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2359 }
2360 #endif // USE_PAINT_REGION
2361 }
2362
2363 // ----------------------------------------------------------------------------
2364 // wxDCModule
2365 // ----------------------------------------------------------------------------
2366
2367 class wxDCModule : public wxModule
2368 {
2369 public:
2370 bool OnInit();
2371 void OnExit();
2372
2373 private:
2374 DECLARE_DYNAMIC_CLASS(wxDCModule)
2375 };
2376
2377 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2378
2379 bool wxDCModule::OnInit()
2380 {
2381 wxInitGCPool();
2382 return true;
2383 }
2384
2385 void wxDCModule::OnExit()
2386 {
2387 wxCleanUpGCPool();
2388 }