]> git.saurik.com Git - wxWidgets.git/blob - src/x11/dcclient.cpp
remove streams tests: they're very basic and already-existing CppUnit stream tests...
[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, 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 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 wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1574 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
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 wxCHECK_RET( IsOk(), wxT("invalid dc") );
1662
1663 if (string.empty())
1664 {
1665 if (width) (*width) = 0;
1666 if (height) (*height) = 0;
1667 return;
1668 }
1669
1670 #if wxUSE_UNICODE
1671 PangoLayout *layout = pango_layout_new( m_context );
1672
1673 if (font)
1674 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1675 else
1676 pango_layout_set_font_description(layout, m_fontdesc);
1677
1678 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1679 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1680
1681 // Measure text.
1682 int w,h;
1683 pango_layout_get_pixel_size(layout, &w, &h);
1684
1685 if (width) (*width) = (wxCoord) w;
1686 if (height) (*height) = (wxCoord) h;
1687 if (descent)
1688 {
1689 // Do something about metrics here. TODO.
1690 (*descent) = 0;
1691 }
1692 if (externalLeading) (*externalLeading) = 0; // ??
1693
1694 g_object_unref( G_OBJECT( layout ) );
1695 #else
1696 wxFont fontToUse = m_font;
1697 if (font) fontToUse = *font;
1698
1699 wxCHECK_RET( fontToUse.IsOk(), wxT("invalid font") );
1700
1701 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1702
1703 wxCHECK_RET( xfont, wxT("invalid font") );
1704
1705 int direction, ascent, descent2;
1706 XCharStruct overall;
1707
1708 XTextExtents( xfont, (const char*) string.c_str(), string.length(), &direction,
1709 &ascent, &descent2, &overall);
1710
1711 if (width)
1712 *width = (wxCoord)( overall.width / m_scaleX );
1713 if (height)
1714 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1715 if (descent)
1716 *descent = (wxCoord)(descent2 / m_scaleY );
1717 if (externalLeading)
1718 *externalLeading = 0; // ??
1719 #endif
1720 }
1721
1722 wxCoord wxWindowDCImpl::GetCharWidth() const
1723 {
1724 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
1725
1726 #if wxUSE_UNICODE
1727 PangoLayout *layout = pango_layout_new( m_context );
1728
1729 if (m_fontdesc)
1730 pango_layout_set_font_description(layout, m_fontdesc);
1731 else
1732 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1733
1734 pango_layout_set_text(layout, "H", 1 );
1735 int w,h;
1736 pango_layout_get_pixel_size(layout, &w, &h);
1737 g_object_unref( G_OBJECT( layout ) );
1738
1739 return w;
1740 #else
1741 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
1742
1743 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1744
1745 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1746
1747 int direction, ascent, descent;
1748 XCharStruct overall;
1749
1750 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1751
1752 return (wxCoord)(overall.width / m_scaleX);
1753 #endif
1754 }
1755
1756 wxCoord wxWindowDCImpl::GetCharHeight() const
1757 {
1758 wxCHECK_MSG( IsOk(), 0, wxT("invalid dc") );
1759
1760 #if wxUSE_UNICODE
1761 PangoLayout *layout = pango_layout_new( m_context );
1762
1763 if (m_fontdesc)
1764 pango_layout_set_font_description(layout, m_fontdesc);
1765 else
1766 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1767
1768 pango_layout_set_text(layout, "H", 1 );
1769 int w,h;
1770 pango_layout_get_pixel_size(layout, &w, &h);
1771 g_object_unref( G_OBJECT( layout ) );
1772
1773 return h;
1774 #else
1775 wxCHECK_MSG( m_font.IsOk(), 0, wxT("invalid font") );
1776
1777 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1778
1779 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1780
1781 int direction, ascent, descent;
1782 XCharStruct overall;
1783
1784 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1785
1786 return (wxCoord)((ascent+descent) / m_scaleY);
1787 #endif
1788 }
1789
1790 void wxWindowDCImpl::Clear()
1791 {
1792 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
1793
1794 if (!m_x11window) return;
1795
1796 /* - we either are a memory dc or have a window as the
1797 owner. anything else shouldn't happen.
1798 - we don't use gdk_window_clear() as we don't set
1799 the window's background colour anymore. it is too
1800 much pain to keep the DC's and the window's back-
1801 ground colour in synch. */
1802
1803 if (m_window)
1804 {
1805 int width,height;
1806 m_window->GetSize( &width, &height );
1807 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
1808 return;
1809 }
1810
1811 if (m_isMemDC)
1812 {
1813 int width,height;
1814 DoGetSize( &width, &height );
1815 XFillRectangle( (Display*) m_display, (Window) m_x11window, (GC) m_bgGC, 0, 0, width, height );
1816 return;
1817 }
1818 }
1819
1820 void wxWindowDCImpl::SetFont( const wxFont &font )
1821 {
1822 wxCHECK_RET( IsOk(), wxT("invalid dc") );
1823
1824 m_font = font;
1825
1826 #if wxUSE_UNICODE
1827 m_fontdesc = font.GetNativeFontInfo()->description;
1828 #endif
1829 }
1830
1831 void wxWindowDCImpl::SetPen( const wxPen &pen )
1832 {
1833 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
1834
1835 if (m_pen == pen) return;
1836
1837 m_pen = pen;
1838
1839 if (!m_pen.IsOk()) return;
1840
1841 if (!m_x11window) return;
1842
1843 int width = m_pen.GetWidth();
1844 if (width <= 0)
1845 {
1846 // CMB: if width is non-zero scale it with the dc
1847 width = 1;
1848 }
1849 else
1850 {
1851 // X doesn't allow different width in x and y and so we take
1852 // the average
1853 double w = 0.5 +
1854 ( fabs((double) XLOG2DEVREL(width)) +
1855 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1856 width = (int)w;
1857 }
1858
1859 static const wxX11Dash dotted[] = {1, 1};
1860 static const wxX11Dash short_dashed[] = {2, 2};
1861 static const wxX11Dash long_dashed[] = {2, 4};
1862 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1863
1864 // We express dash pattern in pen width unit, so we are
1865 // independent of zoom factor and so on...
1866 int req_nb_dash;
1867 const wxX11Dash *req_dash;
1868
1869 int lineStyle = LineSolid;
1870 switch (m_pen.GetStyle())
1871 {
1872 case wxUSER_DASH:
1873 {
1874 lineStyle = LineOnOffDash;
1875 req_nb_dash = m_pen.GetDashCount();
1876 req_dash = (wxX11Dash*)m_pen.GetDash();
1877 break;
1878 }
1879 case wxDOT:
1880 {
1881 lineStyle = LineOnOffDash;
1882 req_nb_dash = 2;
1883 req_dash = dotted;
1884 break;
1885 }
1886 case wxLONG_DASH:
1887 {
1888 lineStyle = LineOnOffDash;
1889 req_nb_dash = 2;
1890 req_dash = long_dashed;
1891 break;
1892 }
1893 case wxSHORT_DASH:
1894 {
1895 lineStyle = LineOnOffDash;
1896 req_nb_dash = 2;
1897 req_dash = short_dashed;
1898 break;
1899 }
1900 case wxDOT_DASH:
1901 {
1902 // lineStyle = LineDoubleDash;
1903 lineStyle = LineOnOffDash;
1904 req_nb_dash = 4;
1905 req_dash = dotted_dashed;
1906 break;
1907 }
1908
1909 case wxTRANSPARENT:
1910 case wxSTIPPLE_MASK_OPAQUE:
1911 case wxSTIPPLE:
1912 case wxSOLID:
1913 default:
1914 {
1915 lineStyle = LineSolid;
1916 req_dash = NULL;
1917 req_nb_dash = 0;
1918 break;
1919 }
1920 }
1921
1922 int capStyle = CapRound;
1923 switch (m_pen.GetCap())
1924 {
1925 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1926 case wxCAP_BUTT: { capStyle = CapButt; break; }
1927 case wxCAP_ROUND:
1928 default:
1929 {
1930 if (width <= 1)
1931 {
1932 width = 0;
1933 capStyle = CapNotLast;
1934 }
1935 else
1936 {
1937 capStyle = CapRound;
1938 }
1939 break;
1940 }
1941 }
1942
1943 int joinStyle = JoinRound;
1944 switch (m_pen.GetJoin())
1945 {
1946 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1947 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1948 case wxJOIN_ROUND:
1949 default: { joinStyle = JoinRound; break; }
1950 }
1951
1952 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1953
1954 m_pen.GetColour().CalcPixel( m_cmap );
1955 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1956 }
1957
1958 void wxWindowDCImpl::SetBrush( const wxBrush &brush )
1959 {
1960 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
1961
1962 if (m_brush == brush) return;
1963
1964 m_brush = brush;
1965
1966 if (!m_brush.IsOk()) return;
1967
1968 if (!m_x11window) return;
1969
1970 m_brush.GetColour().CalcPixel( m_cmap );
1971 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1972
1973 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1974
1975 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->IsOk()))
1976 {
1977 if (m_brush.GetStipple()->GetPixmap())
1978 {
1979 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1980 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1981 }
1982 else
1983 {
1984 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1985 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1986 }
1987 }
1988
1989 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1990 {
1991 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1992 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1993 }
1994
1995 if (m_brush.IsHatch())
1996 {
1997 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1998 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1999 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
2000 }
2001 }
2002
2003 void wxWindowDCImpl::SetBackground( const wxBrush &brush )
2004 {
2005 /* CMB 21/7/98: Added SetBackground. Sets background brush
2006 * for Clear() and bg colour for shapes filled with cross-hatch brush */
2007
2008 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2009
2010 if (m_backgroundBrush == brush) return;
2011
2012 m_backgroundBrush = brush;
2013
2014 if (!m_backgroundBrush.IsOk()) return;
2015
2016 if (!m_x11window) return;
2017
2018 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
2019 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
2020 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
2021 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
2022 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
2023
2024 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
2025
2026 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->IsOk()))
2027 {
2028 if (m_backgroundBrush.GetStipple()->GetPixmap())
2029 {
2030 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
2031 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
2032 }
2033 else
2034 {
2035 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2036 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
2037 }
2038 }
2039
2040 if (m_backgroundBrush.IsHatch())
2041 {
2042 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
2043 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
2044 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
2045 }
2046 }
2047
2048 void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function )
2049 {
2050 wxCHECK_RET( IsOk(), wxT("invalid dc") );
2051
2052 int x_function;
2053
2054 if (m_logicalFunction == function)
2055 return;
2056
2057 // VZ: shouldn't this be a CHECK?
2058 if (!m_x11window)
2059 return;
2060
2061 switch (function)
2062 {
2063 case wxCLEAR:
2064 x_function = GXclear;
2065 break;
2066 case wxXOR:
2067 x_function = GXxor;
2068 break;
2069 case wxINVERT:
2070 x_function = GXinvert;
2071 break;
2072 case wxOR_REVERSE:
2073 x_function = GXorReverse;
2074 break;
2075 case wxAND_REVERSE:
2076 x_function = GXandReverse;
2077 break;
2078 case wxAND:
2079 x_function = GXand;
2080 break;
2081 case wxOR:
2082 x_function = GXor;
2083 break;
2084 case wxAND_INVERT:
2085 x_function = GXandInverted;
2086 break;
2087 case wxNO_OP:
2088 x_function = GXnoop;
2089 break;
2090 case wxNOR:
2091 x_function = GXnor;
2092 break;
2093 case wxEQUIV:
2094 x_function = GXequiv;
2095 break;
2096 case wxSRC_INVERT:
2097 x_function = GXcopyInverted;
2098 break;
2099 case wxOR_INVERT:
2100 x_function = GXorInverted;
2101 break;
2102 case wxNAND:
2103 x_function = GXnand;
2104 break;
2105 case wxSET:
2106 x_function = GXset;
2107 break;
2108 case wxCOPY:
2109 default:
2110 x_function = GXcopy;
2111 break;
2112 }
2113
2114 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2115 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
2116
2117 // to stay compatible with wxMSW, we don't apply ROPs to the text
2118 // operations (i.e. DrawText/DrawRotatedText).
2119 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2120 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
2121
2122 m_logicalFunction = function;
2123 }
2124
2125 void wxWindowDCImpl::SetTextForeground( const wxColour &col )
2126 {
2127 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2128
2129 // don't set m_textForegroundColour to an invalid colour as we'd crash
2130 // later then (we use m_textForegroundColour.GetColor() without checking
2131 // in a few places)
2132 if ( !col.IsOk() || (m_textForegroundColour == col) )
2133 return;
2134
2135 m_textForegroundColour = col;
2136
2137 if (m_x11window)
2138 {
2139 m_textForegroundColour.CalcPixel( m_cmap );
2140 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2141 }
2142 }
2143
2144 void wxWindowDCImpl::SetTextBackground( const wxColour &col )
2145 {
2146 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2147
2148 // same as above
2149 if ( !col.IsOk() || (m_textBackgroundColour == col) )
2150 return;
2151
2152 m_textBackgroundColour = col;
2153
2154 if (m_x11window)
2155 {
2156 m_textBackgroundColour.CalcPixel( m_cmap );
2157 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2158 }
2159 }
2160
2161 void wxWindowDCImpl::SetBackgroundMode( int mode )
2162 {
2163 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2164
2165 m_backgroundMode = mode;
2166
2167 #if wxUSE_NANOX
2168 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2169 #endif
2170
2171 if (!m_x11window) return;
2172
2173 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2174 // transparent/solid background mode
2175
2176 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2177 {
2178 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2179 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2180 }
2181 }
2182
2183 void wxWindowDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) )
2184 {
2185 #if 0
2186 if (m_x11window)
2187 {
2188 if (palette.IsOk())
2189 /* Use GetXColormap */
2190 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
2191 (Colormap) palette.GetXColormap());
2192 else
2193 /* Use wxGetMainColormap */
2194 XSetWindowColormap ((Display*) m_display, (Window) m_x11window->GetXWindow(),
2195 (Colormap) wxTheApp->GetMainColormap(m_display));
2196 }
2197 #endif
2198 }
2199
2200 void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
2201 {
2202 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2203
2204 if (!m_x11window) return;
2205
2206 if (width <= 0)
2207 width = 1;
2208
2209 if (height <= 0)
2210 height = 1;
2211
2212 wxRect rect;
2213 rect.x = XLOG2DEV(x);
2214 rect.y = YLOG2DEV(y);
2215 rect.width = XLOG2DEVREL(width);
2216 rect.height = YLOG2DEVREL(height);
2217
2218 if (!m_currentClippingRegion.IsEmpty())
2219 m_currentClippingRegion.Intersect( rect );
2220 else
2221 m_currentClippingRegion = rect;
2222
2223 #if USE_PAINT_REGION
2224 if (!m_paintClippingRegion.IsEmpty())
2225 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2226 #endif
2227
2228 wxCoord xx, yy, ww, hh;
2229 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2230 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
2231
2232 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2233 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2234 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2235 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2236 }
2237
2238 void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion& region )
2239 {
2240 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2241
2242 if (region.Empty())
2243 {
2244 DestroyClippingRegion();
2245 return;
2246 }
2247
2248 if (!m_x11window) return;
2249
2250 if (!m_currentClippingRegion.IsEmpty())
2251 m_currentClippingRegion.Intersect( region );
2252 else
2253 m_currentClippingRegion = region;
2254
2255 #if USE_PAINT_REGION
2256 if (!m_paintClippingRegion.IsEmpty())
2257 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2258 #endif
2259
2260 wxCoord xx, yy, ww, hh;
2261 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2262 wxX11DCImpl::DoSetClippingRegion( xx, yy, ww, hh );
2263
2264 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2265 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2266 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2267 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2268 }
2269
2270 void wxWindowDCImpl::DestroyClippingRegion()
2271 {
2272 wxCHECK_RET( IsOk(), wxT("invalid window dc") );
2273
2274 wxDCImpl::DestroyClippingRegion();
2275
2276 m_currentClippingRegion.Clear();
2277
2278 #if USE_PAINT_REGION
2279 if (!m_paintClippingRegion.IsEmpty())
2280 m_currentClippingRegion.Union( m_paintClippingRegion );
2281 #endif
2282
2283 if (!m_x11window) return;
2284
2285 if (m_currentClippingRegion.IsEmpty())
2286 {
2287 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2288 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2289 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2290 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2291 }
2292 else
2293 {
2294 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2295 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2296 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2297 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2298 }
2299 }
2300
2301 void wxWindowDCImpl::Destroy()
2302 {
2303 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2304 m_penGC = NULL;
2305 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2306 m_brushGC = NULL;
2307 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2308 m_textGC = NULL;
2309 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2310 m_bgGC = NULL;
2311 }
2312
2313 void wxWindowDCImpl::ComputeScaleAndOrigin()
2314 {
2315 /* CMB: copy scale to see if it changes */
2316 double origScaleX = m_scaleX;
2317 double origScaleY = m_scaleY;
2318
2319 wxDCImpl::ComputeScaleAndOrigin();
2320
2321 /* CMB: if scale has changed call SetPen to recalulate the line width */
2322 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2323 (m_pen.IsOk()))
2324 {
2325 /* this is a bit artificial, but we need to force wxDC to think
2326 the pen has changed */
2327 wxPen pen = m_pen;
2328 m_pen = wxNullPen;
2329 SetPen( pen );
2330 }
2331 }
2332
2333 wxSize wxWindowDCImpl::GetPPI() const
2334 {
2335 return wxSize(100, 100);
2336 }
2337
2338 int wxWindowDCImpl::GetDepth() const
2339 {
2340 wxFAIL_MSG(wxT("not implemented"));
2341
2342 return -1;
2343 }
2344
2345 //-----------------------------------------------------------------------------
2346 // wxClientDC
2347 //-----------------------------------------------------------------------------
2348
2349 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
2350
2351 wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window )
2352 : wxWindowDCImpl( owner, window )
2353 {
2354 wxCHECK_RET( window, wxT("NULL window in wxClientDC::wxClientDC") );
2355
2356 m_x11window = (WXWindow*) window->GetClientAreaWindow();
2357
2358 // Adjust the client area when the wxWindow is not using 2 X11 windows.
2359 if (m_x11window == (WXWindow*) window->X11GetMainWindow())
2360 {
2361 wxPoint ptOrigin = window->GetClientAreaOrigin();
2362 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2363 wxSize size = window->GetClientSize();
2364 DoSetClippingRegion( 0, 0, size.x, size.y );
2365 }
2366 }
2367
2368 void wxClientDCImpl::DoGetSize(int *width, int *height) const
2369 {
2370 wxCHECK_RET( m_window, wxT("GetSize() doesn't work without window") );
2371
2372 m_window->GetClientSize( width, height );
2373 }
2374
2375 // ----------------------------------------------------------------------------
2376 // wxPaintDC
2377 // ----------------------------------------------------------------------------
2378
2379 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl)
2380
2381 wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* window)
2382 : wxClientDCImpl(owner, window)
2383 {
2384 #if USE_PAINT_REGION
2385 if (!window->GetClipPaintRegion())
2386 return;
2387
2388 m_paintClippingRegion = window->GetUpdateRegion();
2389 Region region = (Region) m_paintClippingRegion.GetX11Region();
2390 if (region)
2391 {
2392 m_currentClippingRegion.Union( m_paintClippingRegion );
2393
2394 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2395 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2396 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2397 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2398 }
2399 #endif // USE_PAINT_REGION
2400 }
2401
2402 // ----------------------------------------------------------------------------
2403 // wxDCModule
2404 // ----------------------------------------------------------------------------
2405
2406 class wxDCModule : public wxModule
2407 {
2408 public:
2409 // we must be cleaned up before wxDisplayModule which closes the global
2410 // display
2411 wxDCModule()
2412 {
2413 AddDependency(wxClassInfo::FindClass(wxT("wxX11DisplayModule")));
2414 }
2415
2416 bool OnInit() { wxInitGCPool(); return true; }
2417 void OnExit() { wxCleanUpGCPool(); }
2418
2419 private:
2420 DECLARE_DYNAMIC_CLASS(wxDCModule)
2421 };
2422
2423 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2424