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