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