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