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