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