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