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