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