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