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