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