Added reparenting helper classes to help apps to grab the windows
[wxWidgets.git] / src / x11 / dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: Julian Smart, Robert Roebling
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart, Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "dcclient.h"
14 #endif
15
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
18 #include "wx/window.h"
19 #include "wx/app.h"
20 #include "wx/image.h"
21
22 #include "wx/x11/private.h"
23
24 #include <math.h>
25
26 //-----------------------------------------------------------------------------
27 // local defines
28 //-----------------------------------------------------------------------------
29
30 #define USE_PAINT_REGION 1
31
32 //-----------------------------------------------------------------------------
33 // local data
34 //-----------------------------------------------------------------------------
35
36 #include "bdiag.xbm"
37 #include "fdiag.xbm"
38 #include "cdiag.xbm"
39 #include "horiz.xbm"
40 #include "verti.xbm"
41 #include "cross.xbm"
42 #define num_hatches 6
43
44 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
45 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
46
47 static Pixmap hatches[num_hatches];
48 static Pixmap *hatch_bitmap = (Pixmap *) NULL;
49
50 //-----------------------------------------------------------------------------
51 // constants
52 //-----------------------------------------------------------------------------
53
54 const double RAD2DEG = 180.0 / M_PI;
55
56 // ----------------------------------------------------------------------------
57 // private functions
58 // ----------------------------------------------------------------------------
59
60 static inline double dmax(double a, double b) { return a > b ? a : b; }
61 static inline double dmin(double a, double b) { return a < b ? a : b; }
62
63 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
64
65 //-----------------------------------------------------------------------------
66 // Implement Pool of Graphic contexts. Creating them takes too much time.
67 //-----------------------------------------------------------------------------
68
69 #define GC_POOL_SIZE 200
70
71 enum wxPoolGCType
72 {
73 wxGC_ERROR = 0,
74 wxTEXT_MONO,
75 wxBG_MONO,
76 wxPEN_MONO,
77 wxBRUSH_MONO,
78 wxTEXT_COLOUR,
79 wxBG_COLOUR,
80 wxPEN_COLOUR,
81 wxBRUSH_COLOUR,
82 wxTEXT_SCREEN,
83 wxBG_SCREEN,
84 wxPEN_SCREEN,
85 wxBRUSH_SCREEN
86 };
87
88 struct wxGC
89 {
90 GC m_gc;
91 wxPoolGCType m_type;
92 bool m_used;
93 };
94
95 static wxGC wxGCPool[GC_POOL_SIZE];
96
97 static void wxInitGCPool()
98 {
99 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
100 }
101
102 static void wxCleanUpGCPool()
103 {
104 for (int i = 0; i < GC_POOL_SIZE; i++)
105 {
106 if (wxGCPool[i].m_gc)
107 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
108 }
109 }
110
111 static GC wxGetPoolGC( Window window, wxPoolGCType type )
112 {
113 for (int i = 0; i < GC_POOL_SIZE; i++)
114 {
115 if (!wxGCPool[i].m_gc)
116 {
117 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
118 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
119 wxGCPool[i].m_type = type;
120 wxGCPool[i].m_used = FALSE;
121 }
122 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
123 {
124 wxGCPool[i].m_used = TRUE;
125 return wxGCPool[i].m_gc;
126 }
127 }
128
129 wxFAIL_MSG( wxT("No GC available") );
130
131 return (GC) NULL;
132 }
133
134 static void wxFreePoolGC( GC gc )
135 {
136 for (int i = 0; i < GC_POOL_SIZE; i++)
137 {
138 if (wxGCPool[i].m_gc == gc)
139 {
140 wxGCPool[i].m_used = FALSE;
141 return;
142 }
143 }
144
145 wxFAIL_MSG( wxT("Wrong GC") );
146 }
147
148 // ----------------------------------------------------------------------------
149 // wxWindowDC
150 // ----------------------------------------------------------------------------
151
152 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
153
154 wxWindowDC::wxWindowDC()
155 {
156 m_display = (WXDisplay *) NULL;
157 m_penGC = (WXGC *) NULL;
158 m_brushGC = (WXGC *) NULL;
159 m_textGC = (WXGC *) NULL;
160 m_bgGC = (WXGC *) NULL;
161 m_cmap = (WXColormap *) NULL;
162 m_isMemDC = FALSE;
163 m_isScreenDC = FALSE;
164 m_owner = (wxWindow *)NULL;
165 }
166
167 wxWindowDC::wxWindowDC( wxWindow *window )
168 {
169 wxASSERT_MSG( window, wxT("DC needs a window") );
170
171 m_display = (WXDisplay *) NULL;
172 m_penGC = (WXGC *) NULL;
173 m_brushGC = (WXGC *) NULL;
174 m_textGC = (WXGC *) NULL;
175 m_bgGC = (WXGC *) NULL;
176 m_cmap = (WXColormap *) NULL;
177 m_owner = (wxWindow *)NULL;
178 m_isMemDC = FALSE;
179 m_isScreenDC = FALSE;
180 m_font = window->GetFont();
181
182 m_window = (WXWindow*) window->GetMainWindow();
183
184 // not realized ?
185 if (!m_window)
186 {
187 // don't report problems
188 m_ok = TRUE;
189
190 return;
191 }
192
193 m_display = (WXDisplay *) wxGlobalDisplay();
194
195 int screen = DefaultScreen( (Display*) m_display );
196 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
197
198 SetUpDC();
199
200 /* this must be done after SetUpDC, bacause SetUpDC calls the
201 repective SetBrush, SetPen, SetBackground etc functions
202 to set up the DC. SetBackground call m_owner->SetBackground
203 and this might not be desired as the standard dc background
204 is white whereas a window might assume gray to be the
205 standard (as e.g. wxStatusBar) */
206
207 m_owner = window;
208 }
209
210 wxWindowDC::~wxWindowDC()
211 {
212 Destroy();
213 }
214
215 void wxWindowDC::SetUpDC()
216 {
217 m_ok = TRUE;
218
219 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
220
221 if (m_isScreenDC)
222 {
223 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
224 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
225 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
226 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
227 }
228 else
229 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
230 {
231 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
232 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
233 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
234 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
235 }
236 else
237 {
238 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
239 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
240 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
241 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
242 }
243
244 /* background colour */
245 m_backgroundBrush = *wxWHITE_BRUSH;
246 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
247 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
248
249 /* m_textGC */
250 m_textForegroundColour.CalcPixel( m_cmap );
251 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
252
253 m_textBackgroundColour.CalcPixel( m_cmap );
254 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
255
256 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillSolid );
257
258 #if wxUSE_NANOX
259 // By default, draw transparently
260 GrSetGCUseBackground((GC) m_textGC, FALSE);
261 #endif
262
263 /* m_penGC */
264 m_pen.GetColour().CalcPixel( m_cmap );
265 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
266 XSetBackground( (Display*) m_display, (GC) m_penGC, bg_col );
267
268 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, 0, LineSolid, CapNotLast, JoinRound );
269
270 /* m_brushGC */
271 m_brush.GetColour().CalcPixel( m_cmap );
272 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
273 XSetBackground( (Display*) m_display, (GC) m_brushGC, bg_col );
274
275 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
276
277 /* m_bgGC */
278 XSetForeground( (Display*) m_display, (GC) m_bgGC, bg_col );
279 XSetBackground( (Display*) m_display, (GC) m_bgGC, bg_col );
280
281 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
282
283 /* ROPs */
284 XSetFunction( (Display*) m_display, (GC) m_textGC, GXcopy );
285 XSetFunction( (Display*) m_display, (GC) m_brushGC, GXcopy );
286 XSetFunction( (Display*) m_display, (GC)m_penGC, GXcopy );
287
288 /* clipping */
289 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
290 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
291 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
292 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
293
294 if (!hatch_bitmap)
295 {
296 int xscreen = DefaultScreen( (Display*) m_display );
297 Window xroot = RootWindow( (Display*) m_display, xscreen );
298
299 hatch_bitmap = hatches;
300 hatch_bitmap[0] = XCreateBitmapFromData( (Display*) m_display, xroot, bdiag_bits, bdiag_width, bdiag_height );
301 hatch_bitmap[1] = XCreateBitmapFromData( (Display*) m_display, xroot, cdiag_bits, cdiag_width, cdiag_height );
302 hatch_bitmap[2] = XCreateBitmapFromData( (Display*) m_display, xroot, fdiag_bits, fdiag_width, fdiag_height );
303 hatch_bitmap[3] = XCreateBitmapFromData( (Display*) m_display, xroot, cross_bits, cross_width, cross_height );
304 hatch_bitmap[4] = XCreateBitmapFromData( (Display*) m_display, xroot, horiz_bits, horiz_width, horiz_height );
305 hatch_bitmap[5] = XCreateBitmapFromData( (Display*) m_display, xroot, verti_bits, verti_width, verti_height );
306 }
307 }
308
309 void wxWindowDC::DoGetSize( int* width, int* height ) const
310 {
311 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
312
313 m_owner->GetSize(width, height);
314 }
315
316 void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
317 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
318 {
319 wxFAIL_MSG("not implemented");
320 }
321
322 bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
323 {
324 // Generic (and therefore rather inefficient) method.
325 // Could be improved.
326 wxMemoryDC memdc;
327 wxBitmap bitmap(1, 1);
328 memdc.SelectObject(bitmap);
329 memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
330 memdc.SelectObject(wxNullBitmap);
331 wxImage image(bitmap);
332 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
333 return TRUE;
334 }
335
336 void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
337 {
338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
339
340 if (m_pen.GetStyle() != wxTRANSPARENT)
341 {
342 if (m_window)
343 XDrawLine( (Display*) m_display, (Window) m_window,
344 (GC) m_penGC, XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2) );
345
346 CalcBoundingBox(x1, y1);
347 CalcBoundingBox(x2, y2);
348 }
349 }
350
351 void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
352 {
353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
354
355 if (m_pen.GetStyle() != wxTRANSPARENT)
356 {
357 int w = 0;
358 int h = 0;
359 GetSize( &w, &h );
360 wxCoord xx = XLOG2DEV(x);
361 wxCoord yy = YLOG2DEV(y);
362 if (m_window)
363 {
364 XDrawLine( (Display*) m_display, (Window) m_window,
365 (GC) m_penGC, 0, yy, XLOG2DEVREL(w), yy );
366 XDrawLine( (Display*) m_display, (Window) m_window,
367 (GC) m_penGC, xx, 0, xx, YLOG2DEVREL(h) );
368 }
369 }
370 }
371
372 void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
373 {
374 wxCHECK_RET( Ok(), wxT("invalid window dc") );
375
376 wxCoord xx1 = XLOG2DEV(x1);
377 wxCoord yy1 = YLOG2DEV(y1);
378 wxCoord xx2 = XLOG2DEV(x2);
379 wxCoord yy2 = YLOG2DEV(y2);
380 wxCoord xxc = XLOG2DEV(xc);
381 wxCoord yyc = YLOG2DEV(yc);
382 double dx = xx1 - xxc;
383 double dy = yy1 - yyc;
384 double radius = sqrt((double)(dx*dx+dy*dy));
385 wxCoord r = (wxCoord)radius;
386 double radius1, radius2;
387
388 if (xx1 == xx2 && yy1 == yy2)
389 {
390 radius1 = 0.0;
391 radius2 = 360.0;
392 }
393 else
394 if (radius == 0.0)
395 {
396 radius1 = radius2 = 0.0;
397 }
398 else
399 {
400 radius1 = (xx1 - xxc == 0) ?
401 (yy1 - yyc < 0) ? 90.0 : -90.0 :
402 -atan2(double(yy1-yyc), double(xx1-xxc)) * RAD2DEG;
403 radius2 = (xx2 - xxc == 0) ?
404 (yy2 - yyc < 0) ? 90.0 : -90.0 :
405 -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
406 }
407 wxCoord alpha1 = wxCoord(radius1 * 64.0);
408 wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
409 while (alpha2 <= 0) alpha2 += 360*64;
410 while (alpha1 > 360*64) alpha1 -= 360*64;
411
412 if (m_window)
413 {
414 if (m_brush.GetStyle() != wxTRANSPARENT)
415 {
416 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
417 {
418 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
419 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
420 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
421
422 XFillArc( (Display*) m_display, (Window) m_window,
423 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
424
425 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
426 } else
427 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
428 {
429 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
430 m_deviceOriginX % 15, m_deviceOriginY % 15 );
431
432 XFillArc( (Display*) m_display, (Window) m_window,
433 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
434
435 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
436 } else
437 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
438 {
439 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
440 m_deviceOriginX % 16, m_deviceOriginY % 16 );
441
442 XFillArc( (Display*) m_display, (Window) m_window,
443 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
444
445 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
446 } else
447 if (m_brush.GetStyle() == wxSTIPPLE)
448 {
449 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
450 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
451 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
452
453 XFillArc( (Display*) m_display, (Window) m_window,
454 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
455
456 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
457 }
458 else
459 {
460 XFillArc( (Display*) m_display, (Window) m_window,
461 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
462 }
463 }
464
465 if (m_pen.GetStyle() != wxTRANSPARENT)
466 {
467 XDrawArc( (Display*) m_display, (Window) m_window,
468 (GC) m_penGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
469
470 XDrawLine( (Display*) m_display, (Window) m_window,
471 (GC) m_penGC, xx1, yy1, xxc, yyc );
472
473 XDrawLine( (Display*) m_display, (Window) m_window,
474 (GC) m_penGC, xxc, yyc, xx2, yy2 );
475 }
476 }
477
478 CalcBoundingBox (x1, y1);
479 CalcBoundingBox (x2, y2);
480 }
481
482 void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
483 {
484 wxCHECK_RET( Ok(), wxT("invalid window dc") );
485
486 wxCoord xx = XLOG2DEV(x);
487 wxCoord yy = YLOG2DEV(y);
488 wxCoord ww = m_signX * XLOG2DEVREL(width);
489 wxCoord hh = m_signY * YLOG2DEVREL(height);
490
491 // CMB: handle -ve width and/or height
492 if (ww < 0) { ww = -ww; xx = xx - ww; }
493 if (hh < 0) { hh = -hh; yy = yy - hh; }
494
495 if (m_window)
496 {
497 wxCoord start = wxCoord(sa * 64.0);
498 wxCoord end = wxCoord((ea-sa) * 64.0);
499
500 if (m_brush.GetStyle() != wxTRANSPARENT)
501 {
502 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
503 {
504 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
505 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
506 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
507
508 XFillArc( (Display*) m_display, (Window) m_window,
509 (GC) m_textGC, xx, yy, ww, hh, start, end );
510
511 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
512 } else
513 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
514 {
515 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
516 m_deviceOriginX % 15, m_deviceOriginY % 15 );
517
518 XFillArc( (Display*) m_display, (Window) m_window,
519 (GC) m_brushGC, xx, yy, ww, hh, start, end );
520
521 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
522 } else
523 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
524 {
525 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
526 m_deviceOriginX % 16, m_deviceOriginY % 16 );
527
528 XFillArc( (Display*) m_display, (Window) m_window,
529 (GC) m_brushGC, xx, yy, ww, hh, start, end );
530
531 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
532 } else
533 if (m_brush.GetStyle() == wxSTIPPLE)
534 {
535 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
536 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
537 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
538
539 XFillArc( (Display*) m_display, (Window) m_window,
540 (GC) m_brushGC, xx, yy, ww, hh, start, end );
541
542 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
543 }
544 else
545 {
546 XFillArc( (Display*) m_display, (Window) m_window,
547 (GC) m_brushGC, xx, yy, ww, hh, start, end );
548 }
549 }
550
551 if (m_pen.GetStyle() != wxTRANSPARENT)
552 {
553 XDrawArc( (Display*) m_display, (Window) m_window,
554 (GC) m_penGC, xx, yy, ww, hh, start, end );
555 }
556 }
557
558 CalcBoundingBox (x, y);
559 CalcBoundingBox (x + width, y + height);
560 }
561
562 void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
563 {
564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
565
566 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
567 XDrawPoint( (Display*) m_display, (Window) m_window,
568 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
569
570 CalcBoundingBox (x, y);
571 }
572
573 void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
574 {
575 wxCHECK_RET( Ok(), wxT("invalid window dc") );
576
577 if (m_pen.GetStyle() == wxTRANSPARENT) return;
578 if (n <= 0) return;
579
580 XPoint *xpoints = new XPoint[n];
581 for (int i = 0; i < n; i++)
582 {
583 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
584 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
585
586 CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
587 }
588 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 );
589
590 delete[] xpoints;
591 }
592
593 void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
594 wxCoord xoffset, wxCoord yoffset, int fillStyle )
595 {
596 wxCHECK_RET( Ok(), wxT("invalid window dc") );
597
598 if (n <= 0) return;
599
600 XPoint *xpoints = new XPoint[n + 1];
601 int i;
602 for (i = 0; i < n; i++)
603 {
604 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
605 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
606
607 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
608 }
609
610 if (m_window)
611 {
612 if (m_brush.GetStyle() != wxTRANSPARENT)
613 {
614
615 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
616 {
617 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
618 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
619 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
620
621 XFillPolygon( (Display*) m_display, (Window) m_window,
622 (GC) m_textGC, xpoints, n, Complex, 0);
623
624 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
625 } else
626 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
627 {
628 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
629 m_deviceOriginX % 15, m_deviceOriginY % 15 );
630
631 XFillPolygon( (Display*) m_display, (Window) m_window,
632 (GC) m_brushGC, xpoints, n, Complex, 0);
633
634 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
635 } else
636 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
637 {
638 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
639 m_deviceOriginX % 16, m_deviceOriginY % 16 );
640
641 XFillPolygon( (Display*) m_display, (Window) m_window,
642 (GC) m_brushGC, xpoints, n, Complex, 0);
643
644 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
645 } else
646 if (m_brush.GetStyle() == wxSTIPPLE)
647 {
648 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
649 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
650 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
651
652 XFillPolygon( (Display*) m_display, (Window) m_window,
653 (GC) m_brushGC, xpoints, n, Complex, 0);
654
655 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
656 }
657 else
658 {
659 XFillPolygon( (Display*) m_display, (Window) m_window,
660 (GC) m_brushGC, xpoints, n, Complex, 0);
661 }
662 }
663
664 if (m_pen.GetStyle () != wxTRANSPARENT)
665 {
666 // Close figure for XDrawLines
667 xpoints[i].x = xpoints[0].x;
668 xpoints[i].y = xpoints[0].y;
669
670 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n + 1, 0);
671 }
672 }
673
674 delete[] xpoints;
675 }
676
677 void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
678 {
679 wxCHECK_RET( Ok(), wxT("invalid window dc") );
680
681 wxCoord xx = XLOG2DEV(x);
682 wxCoord yy = YLOG2DEV(y);
683 wxCoord ww = m_signX * XLOG2DEVREL(width);
684 wxCoord hh = m_signY * YLOG2DEVREL(height);
685
686 // CMB: draw nothing if transformed w or h is 0
687 if (ww == 0 || hh == 0) return;
688
689 // CMB: handle -ve width and/or height
690 if (ww < 0) { ww = -ww; xx = xx - ww; }
691 if (hh < 0) { hh = -hh; yy = yy - hh; }
692
693 if (m_window)
694 {
695 if (m_brush.GetStyle() != wxTRANSPARENT)
696 {
697 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
698 {
699 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
700 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
701 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
702
703 XFillRectangle( (Display*) m_display, (Window) m_window,
704 (GC) m_textGC, xx, yy, ww, hh );
705
706 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
707 } else
708 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
709 {
710 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
711 m_deviceOriginX % 15, m_deviceOriginY % 15 );
712
713 XFillRectangle( (Display*) m_display, (Window) m_window,
714 (GC) m_brushGC, xx, yy, ww, hh );
715
716 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
717 } else
718 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
719 {
720 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
721 m_deviceOriginX % 16, m_deviceOriginY % 16 );
722
723 XFillRectangle( (Display*) m_display, (Window) m_window,
724 (GC) m_brushGC, xx, yy, ww, hh );
725
726 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
727 } else
728 if (m_brush.GetStyle() == wxSTIPPLE)
729 {
730 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
731 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
732 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
733
734 XFillRectangle( (Display*) m_display, (Window) m_window,
735 (GC) m_brushGC, xx, yy, ww, hh );
736
737 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
738 }
739 else
740 {
741 XFillRectangle( (Display*) m_display, (Window) m_window,
742 (GC) m_brushGC, xx, yy, ww, hh );
743 }
744 }
745
746 if (m_pen.GetStyle () != wxTRANSPARENT)
747 {
748 XDrawRectangle( (Display*) m_display, (Window) m_window,
749 (GC) m_penGC, xx, yy, ww-1, hh-1 );
750 }
751 }
752
753 CalcBoundingBox( x, y );
754 CalcBoundingBox( x + width, y + height );
755 }
756
757 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
758 {
759 // later
760 }
761
762 void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
763 {
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
765
766 wxCoord xx = XLOG2DEV(x);
767 wxCoord yy = YLOG2DEV(y);
768 wxCoord ww = m_signX * XLOG2DEVREL(width);
769 wxCoord hh = m_signY * YLOG2DEVREL(height);
770
771 // CMB: handle -ve width and/or height
772 if (ww < 0) { ww = -ww; xx = xx - ww; }
773 if (hh < 0) { hh = -hh; yy = yy - hh; }
774
775 if (m_window)
776 {
777 if (m_brush.GetStyle() != wxTRANSPARENT)
778 {
779 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
780 {
781 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
782 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
783 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
784
785 XFillArc( (Display*) m_display, (Window) m_window,
786 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
787
788 XSetTSOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
789 } else
790 if (IS_15_PIX_HATCH(m_brush.GetStyle()))
791 {
792 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
793 m_deviceOriginX % 15, m_deviceOriginY % 15 );
794
795 XFillArc( (Display*) m_display, (Window) m_window,
796 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
797
798 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
799 } else
800 if (IS_16_PIX_HATCH(m_brush.GetStyle()))
801 {
802 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
803 m_deviceOriginX % 16, m_deviceOriginY % 16 );
804
805 XFillArc( (Display*) m_display, (Window) m_window,
806 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
807
808 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
809 } else
810 if (m_brush.GetStyle() == wxSTIPPLE)
811 {
812 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
813 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
814 m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
815
816 XFillArc( (Display*) m_display, (Window) m_window,
817 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
818
819 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC, 0, 0 );
820 }
821 else
822 {
823 XFillArc( (Display*) m_display, (Window) m_window,
824 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
825 }
826 }
827
828 if (m_pen.GetStyle () != wxTRANSPARENT)
829 {
830 XDrawArc( (Display*) m_display, (Window) m_window,
831 (GC) m_penGC, xx, yy, ww, hh, 0, 360*64 );
832 }
833 }
834
835 CalcBoundingBox( x, y );
836 CalcBoundingBox( x + width, y + height );
837 }
838
839 void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
840 {
841 }
842
843 #if wxUSE_NANOX
844 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
845 wxCoord x, wxCoord y,
846 bool useMask )
847 {
848 wxCHECK_RET( Ok(), wxT("invalid window dc") );
849
850 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
851
852 bool is_mono = (bitmap.GetBitmap() != NULL);
853
854 /* scale/translate size and position */
855 int xx = XLOG2DEV(x);
856 int yy = YLOG2DEV(y);
857
858 int w = bitmap.GetWidth();
859 int h = bitmap.GetHeight();
860
861 CalcBoundingBox( x, y );
862 CalcBoundingBox( x + w, y + h );
863
864 if (!m_window) return;
865
866 int ww = XLOG2DEVREL(w);
867 int hh = YLOG2DEVREL(h);
868
869 /* compare to current clipping region */
870 if (!m_currentClippingRegion.IsNull())
871 {
872 wxRegion tmp( xx,yy,ww,hh );
873 tmp.Intersect( m_currentClippingRegion );
874 if (tmp.IsEmpty())
875 return;
876 }
877
878 /* scale bitmap if required */
879 wxBitmap use_bitmap;
880 if ((w != ww) || (h != hh))
881 {
882 wxImage image( bitmap );
883 image.Rescale( ww, hh );
884 #if 0
885 if (is_mono)
886 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
887 else
888 #endif
889 use_bitmap = image.ConvertToBitmap();
890 }
891 else
892 {
893 use_bitmap = bitmap;
894 }
895
896 /* apply mask if any */
897 WXPixmap mask = NULL;
898 if (use_bitmap.GetMask())
899 mask = use_bitmap.GetMask()->GetBitmap();
900
901 if (useMask && mask)
902 {
903 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
904 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
905 Pixmap bufPixmap = GrNewPixmap(w, h, 0);
906 GC gc = GrNewGC();
907 GrSetGCUseBackground(gc, FALSE);
908 GrSetGCMode(gc, GR_MODE_COPY);
909
910 // This code assumes that background and foreground
911 // colours are used in ROPs, like in MSW.
912 // Not sure if this is true.
913
914 // Copy destination to buffer.
915 // In DoBlit, we need this step because Blit has
916 // a ROP argument. Here, we don't need it.
917 // In DoBlit, we may be able to eliminate this step
918 // if we check if the rop = copy
919 #if 0
920 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
921 0, 0, GR_MODE_COPY);
922 #endif
923
924 // Copy src to buffer using selected raster op (none selected
925 // in DrawBitmap, so just use Gxcopy)
926 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
927 0, 0, GR_MODE_COPY);
928
929 // Set masked area in buffer to BLACK (pixel value 0)
930 GrSetGCBackground(gc, WHITE);
931 GrSetGCForeground(gc, BLACK);
932 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
933 0, 0, GR_MODE_AND);
934
935 // set unmasked area in dest to BLACK
936 GrSetGCBackground(gc, BLACK);
937 GrSetGCForeground(gc, WHITE);
938 GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
939 0, 0, GR_MODE_AND);
940
941 // OR buffer to dest
942 GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
943 0, 0, GR_MODE_OR);
944
945 GrDestroyGC(gc);
946 GrDestroyWindow(bufPixmap);
947 }
948 else
949 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
950 (GC) m_penGC, 0, 0, w, h, xx, yy );
951
952 /* remove mask again if any */
953 if (useMask && mask)
954 {
955 if (!m_currentClippingRegion.IsNull())
956 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
957 }
958 }
959
960 #else
961
962 // Normal X11
963 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
964 wxCoord x, wxCoord y,
965 bool useMask )
966 {
967 wxCHECK_RET( Ok(), wxT("invalid window dc") );
968
969 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
970
971 bool is_mono = (bitmap.GetBitmap() != NULL);
972
973 /* scale/translate size and position */
974 int xx = XLOG2DEV(x);
975 int yy = YLOG2DEV(y);
976
977 int w = bitmap.GetWidth();
978 int h = bitmap.GetHeight();
979
980 CalcBoundingBox( x, y );
981 CalcBoundingBox( x + w, y + h );
982
983 if (!m_window) return;
984
985 int ww = XLOG2DEVREL(w);
986 int hh = YLOG2DEVREL(h);
987
988 /* compare to current clipping region */
989 if (!m_currentClippingRegion.IsNull())
990 {
991 wxRegion tmp( xx,yy,ww,hh );
992 tmp.Intersect( m_currentClippingRegion );
993 if (tmp.IsEmpty())
994 return;
995 }
996
997 /* scale bitmap if required */
998 wxBitmap use_bitmap;
999 if ((w != ww) || (h != hh))
1000 {
1001 wxImage image( bitmap );
1002 image.Rescale( ww, hh );
1003 #if 0
1004 if (is_mono)
1005 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1006 else
1007 #endif
1008 use_bitmap = image.ConvertToBitmap();
1009 }
1010 else
1011 {
1012 use_bitmap = bitmap;
1013 }
1014
1015 /* apply mask if any */
1016 WXPixmap mask = NULL;
1017 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1018 {
1019 if (useMask && mask)
1020 {
1021 WXPixmap new_mask = NULL;
1022 #if 0
1023 if (!m_currentClippingRegion.IsNull())
1024 {
1025 GdkColor col;
1026 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1027 GdkGC *gc = gdk_gc_new( new_mask );
1028 col.pixel = 0;
1029 gdk_gc_set_foreground( gc, &col );
1030 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1031 col.pixel = 0;
1032 gdk_gc_set_background( gc, &col );
1033 col.pixel = 1;
1034 gdk_gc_set_foreground( gc, &col );
1035 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1036 gdk_gc_set_clip_origin( gc, -xx, -yy );
1037 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1038 gdk_gc_set_stipple( gc, mask );
1039 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1040 gdk_gc_unref( gc );
1041 }
1042 #endif
1043 if (is_mono)
1044 {
1045 if (new_mask)
1046 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1047 else
1048 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1049 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1050 }
1051 else
1052 {
1053 if (new_mask)
1054 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1055 else
1056 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1057 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1058 }
1059
1060 if (new_mask)
1061 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1062 }
1063 }
1064
1065 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1066 drawing a mono-bitmap (XBitmap) we use the current text GC */
1067 if (is_mono)
1068 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1069 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
1070 else
1071 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1072 (GC) m_penGC, 0, 0, w, h, xx, yy );
1073
1074 /* remove mask again if any */
1075 if (useMask && mask)
1076 {
1077 if (is_mono)
1078 {
1079 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1080 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1081 if (!m_currentClippingRegion.IsNull())
1082 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1083 }
1084 else
1085 {
1086 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1087 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1088 if (!m_currentClippingRegion.IsNull())
1089 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1090 }
1091 }
1092 }
1093 #endif
1094 // wxUSE_NANOX/!wxUSE_NANOX
1095
1096 bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1097 wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
1098 wxCoord xsrcMask, wxCoord ysrcMask )
1099 {
1100 /* this is the nth try to get this utterly useless function to
1101 work. it now completely ignores the scaling or translation
1102 of the source dc, but scales correctly on the target dc and
1103 knows about possible mask information in a memory dc. */
1104
1105 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
1106
1107 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
1108
1109 if (!m_window) return FALSE;
1110
1111 // transform the source DC coords to the device ones
1112 xsrc = source->XLOG2DEV(xsrc);
1113 ysrc = source->YLOG2DEV(ysrc);
1114
1115 wxClientDC *srcDC = (wxClientDC*)source;
1116 wxMemoryDC *memDC = (wxMemoryDC*)source;
1117
1118 bool use_bitmap_method = FALSE;
1119 bool is_mono = FALSE;
1120
1121 /* TODO: use the mask origin when drawing transparently */
1122 if (xsrcMask == -1 && ysrcMask == -1)
1123 {
1124 xsrcMask = xsrc; ysrcMask = ysrc;
1125 }
1126
1127 #if 0
1128 if (srcDC->m_isMemDC)
1129 {
1130 if (!memDC->m_selected.Ok()) return FALSE;
1131
1132 /* we use the "XCopyArea" way to copy a memory dc into
1133 y different window if the memory dc BOTH
1134 a) doesn't have any mask or its mask isn't used
1135 b) it is clipped
1136 c) is not 1-bit */
1137
1138 if (useMask && (memDC->m_selected.GetMask()))
1139 {
1140 /* we HAVE TO use the direct way for memory dcs
1141 that have mask since the XCopyArea doesn't know
1142 about masks */
1143 use_bitmap_method = TRUE;
1144 }
1145 else if (memDC->m_selected.GetDepth() == 1)
1146 {
1147 /* we HAVE TO use the direct way for memory dcs
1148 that are bitmaps because XCopyArea doesn't cope
1149 with different bit depths */
1150 is_mono = TRUE;
1151 use_bitmap_method = TRUE;
1152 }
1153 else if ((xsrc == 0) && (ysrc == 0) &&
1154 (width == memDC->m_selected.GetWidth()) &&
1155 (height == memDC->m_selected.GetHeight()))
1156 {
1157 /* we SHOULD use the direct way if all of the bitmap
1158 in the memory dc is copied in which case XCopyArea
1159 wouldn't be able able to boost performace by reducing
1160 the area to be scaled */
1161 use_bitmap_method = TRUE;
1162 }
1163 else
1164 {
1165 use_bitmap_method = FALSE;
1166 }
1167 }
1168
1169 CalcBoundingBox( xdest, ydest );
1170 CalcBoundingBox( xdest + width, ydest + height );
1171
1172 /* scale/translate size and position */
1173 wxCoord xx = XLOG2DEV(xdest);
1174 wxCoord yy = YLOG2DEV(ydest);
1175
1176 wxCoord ww = XLOG2DEVREL(width);
1177 wxCoord hh = YLOG2DEVREL(height);
1178
1179 /* compare to current clipping region */
1180 if (!m_currentClippingRegion.IsNull())
1181 {
1182 wxRegion tmp( xx,yy,ww,hh );
1183 tmp.Intersect( m_currentClippingRegion );
1184 if (tmp.IsEmpty())
1185 return TRUE;
1186 }
1187
1188 int old_logical_func = m_logicalFunction;
1189 SetLogicalFunction( logical_func );
1190
1191 if (use_bitmap_method)
1192 {
1193 /* scale/translate bitmap size */
1194 wxCoord bm_width = memDC->m_selected.GetWidth();
1195 wxCoord bm_height = memDC->m_selected.GetHeight();
1196
1197 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1198 wxCoord bm_hh = YLOG2DEVREL( bm_height );
1199
1200 /* scale bitmap if required */
1201 wxBitmap use_bitmap;
1202
1203 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1204 {
1205 wxImage image( memDC->m_selected );
1206 image = image.Scale( bm_ww, bm_hh );
1207
1208 if (is_mono)
1209 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1210 else
1211 use_bitmap = image.ConvertToBitmap();
1212 }
1213 else
1214 {
1215 use_bitmap = memDC->m_selected;
1216 }
1217
1218 /* apply mask if any */
1219 GdkBitmap *mask = (GdkBitmap *) NULL;
1220 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1221
1222 if (useMask && mask)
1223 {
1224 GdkBitmap *new_mask = (GdkBitmap*) NULL;
1225 if (!m_currentClippingRegion.IsNull())
1226 {
1227 GdkColor col;
1228 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1229 GdkGC *gc = gdk_gc_new( new_mask );
1230 col.pixel = 0;
1231 gdk_gc_set_foreground( gc, &col );
1232 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1233 col.pixel = 0;
1234 gdk_gc_set_background( gc, &col );
1235 col.pixel = 1;
1236 gdk_gc_set_foreground( gc, &col );
1237 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1238 gdk_gc_set_clip_origin( gc, -xx, -yy );
1239 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1240 gdk_gc_set_stipple( gc, mask );
1241 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1242 gdk_gc_unref( gc );
1243 }
1244
1245 if (is_mono)
1246 {
1247 if (new_mask)
1248 gdk_gc_set_clip_mask( m_textGC, new_mask );
1249 else
1250 gdk_gc_set_clip_mask( m_textGC, mask );
1251 gdk_gc_set_clip_origin( m_textGC, xx, yy );
1252 }
1253 else
1254 {
1255 if (new_mask)
1256 gdk_gc_set_clip_mask( m_penGC, new_mask );
1257 else
1258 gdk_gc_set_clip_mask( m_penGC, mask );
1259 gdk_gc_set_clip_origin( m_penGC, xx, yy );
1260 }
1261 if (new_mask)
1262 gdk_bitmap_unref( new_mask );
1263 }
1264
1265 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1266 drawing a mono-bitmap (XBitmap) we use the current text GC */
1267
1268 if (is_mono)
1269 gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
1270 else
1271 gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
1272
1273 /* remove mask again if any */
1274 if (useMask && mask)
1275 {
1276 if (is_mono)
1277 {
1278 gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL );
1279 gdk_gc_set_clip_origin( m_textGC, 0, 0 );
1280 if (!m_currentClippingRegion.IsNull())
1281 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1282 }
1283 else
1284 {
1285 gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
1286 gdk_gc_set_clip_origin( m_penGC, 0, 0 );
1287 if (!m_currentClippingRegion.IsNull())
1288 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
1289 }
1290 }
1291 }
1292 else /* use_bitmap_method */
1293 {
1294 if ((width != ww) || (height != hh))
1295 {
1296 /* draw source window into a bitmap as we cannot scale
1297 a window in contrast to a bitmap. this would actually
1298 work with memory dcs as well, but we'd lose the mask
1299 information and waste one step in this process since
1300 a memory already has a bitmap. all this is slightly
1301 inefficient as we could take an XImage directly from
1302 an X window, but we'd then also have to care that
1303 the window is not outside the screen (in which case
1304 we'd get a BadMatch or what not).
1305 Is a double XGetImage and combined XGetPixel and
1306 XPutPixel really faster? I'm not sure. look at wxXt
1307 for a different implementation of the same problem. */
1308
1309 wxBitmap bitmap( width, height );
1310
1311 /* copy including child window contents */
1312 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1313 gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
1314 srcDC->GetWindow(),
1315 xsrc, ysrc, width, height );
1316 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1317
1318 /* scale image */
1319 wxImage image( bitmap );
1320 image = image.Scale( ww, hh );
1321
1322 /* convert to bitmap */
1323 bitmap = image.ConvertToBitmap();
1324
1325 /* draw scaled bitmap */
1326 gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
1327
1328 }
1329 else
1330 {
1331 /* No scaling and not a memory dc with a mask either */
1332
1333 /* copy including child window contents */
1334 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1335 gdk_window_copy_area( m_window, m_penGC, xx, yy,
1336 srcDC->GetWindow(),
1337 xsrc, ysrc, width, height );
1338 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1339 }
1340 }
1341
1342 SetLogicalFunction( old_logical_func );
1343 return TRUE;
1344 #endif
1345
1346 return FALSE;
1347 }
1348
1349 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1350 {
1351 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1352
1353 if (!m_window) return;
1354
1355 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1356
1357 wxCHECK_RET( xfont, wxT("invalid font") );
1358
1359 x = XLOG2DEV(x);
1360 y = YLOG2DEV(y);
1361
1362 #if 0
1363 wxCoord width = gdk_string_width( font, text.mbc_str() );
1364 wxCoord height = font->ascent + font->descent;
1365
1366 if ( m_backgroundMode == wxSOLID )
1367 {
1368 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
1369 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
1370 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
1371 }
1372 #endif
1373
1374 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
1375 #if !wxUSE_NANOX
1376 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1377 #endif
1378 {
1379 XDrawString( (Display*) m_display, (Window) m_window,
1380 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1381 }
1382
1383 #if 0
1384 if (m_font.GetUnderlined())
1385 {
1386 wxCoord ul_y = y + XFontStructGetAscent(font);
1387 if (font->descent > 0) ul_y++;
1388 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
1389 }
1390
1391 width = wxCoord(width / m_scaleX);
1392 height = wxCoord(height / m_scaleY);
1393
1394 CalcBoundingBox (x + width, y + height);
1395 CalcBoundingBox (x, y);
1396 #endif
1397 }
1398
1399 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1400 {
1401 // later
1402 }
1403
1404 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1405 wxCoord *descent, wxCoord *externalLeading,
1406 wxFont *font ) const
1407 {
1408 wxCHECK_RET( Ok(), "invalid dc" );
1409
1410 wxFont fontToUse = m_font;
1411 if (font) fontToUse = *font;
1412
1413 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
1414
1415 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1416
1417 wxCHECK_RET( xfont, wxT("invalid font") );
1418
1419 int direction, ascent, descent2;
1420 XCharStruct overall;
1421
1422 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
1423 &ascent, &descent2, &overall);
1424
1425 if (width)
1426 *width = (wxCoord)( overall.width / m_scaleX );
1427 if (height)
1428 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1429 if (descent)
1430 *descent = (wxCoord)(descent2 / m_scaleY );
1431 if (externalLeading)
1432 *externalLeading = 0; // ??
1433 }
1434
1435 wxCoord wxWindowDC::GetCharWidth() const
1436 {
1437 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1438
1439 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1440
1441 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1442
1443 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1444
1445 int direction, ascent, descent;
1446 XCharStruct overall;
1447
1448 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1449
1450 return (wxCoord)(overall.width / m_scaleX);
1451 }
1452
1453 wxCoord wxWindowDC::GetCharHeight() const
1454 {
1455 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1456
1457 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1458
1459 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1460
1461 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1462
1463 int direction, ascent, descent;
1464 XCharStruct overall;
1465
1466 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1467
1468 return (wxCoord)((ascent+descent) / m_scaleY);
1469 }
1470
1471 void wxWindowDC::Clear()
1472 {
1473 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1474
1475 if (!m_window) return;
1476
1477 /* - we either are a memory dc or have a window as the
1478 owner. anything else shouldn't happen.
1479 - we don't use gdk_window_clear() as we don't set
1480 the window's background colour anymore. it is too
1481 much pain to keep the DC's and the window's back-
1482 ground colour in synch. */
1483
1484 if (m_owner)
1485 {
1486 int width,height;
1487 m_owner->GetSize( &width, &height );
1488 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1489 return;
1490 }
1491
1492 if (m_isMemDC)
1493 {
1494 int width,height;
1495 GetSize( &width, &height );
1496 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1497 return;
1498 }
1499 }
1500
1501 void wxWindowDC::SetFont( const wxFont &font )
1502 {
1503 wxCHECK_RET( Ok(), "invalid dc" );
1504
1505 m_font = font;
1506 }
1507
1508 void wxWindowDC::SetPen( const wxPen &pen )
1509 {
1510 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1511
1512 if (m_pen == pen) return;
1513
1514 m_pen = pen;
1515
1516 if (!m_pen.Ok()) return;
1517
1518 if (!m_window) return;
1519
1520 int width = m_pen.GetWidth();
1521 if (width <= 0)
1522 {
1523 // CMB: if width is non-zero scale it with the dc
1524 width = 1;
1525 }
1526 else
1527 {
1528 // X doesn't allow different width in x and y and so we take
1529 // the average
1530 double w = 0.5 +
1531 ( fabs((double) XLOG2DEVREL(width)) +
1532 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1533 width = (int)w;
1534 }
1535
1536 static const wxX11Dash dotted[] = {1, 1};
1537 static const wxX11Dash short_dashed[] = {2, 2};
1538 static const wxX11Dash long_dashed[] = {2, 4};
1539 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1540
1541 // We express dash pattern in pen width unit, so we are
1542 // independent of zoom factor and so on...
1543 int req_nb_dash;
1544 const wxX11Dash *req_dash;
1545
1546 int lineStyle = LineSolid;
1547 switch (m_pen.GetStyle())
1548 {
1549 case wxUSER_DASH:
1550 {
1551 lineStyle = LineOnOffDash;
1552 req_nb_dash = m_pen.GetDashCount();
1553 req_dash = (wxX11Dash*)m_pen.GetDash();
1554 break;
1555 }
1556 case wxDOT:
1557 {
1558 lineStyle = LineOnOffDash;
1559 req_nb_dash = 2;
1560 req_dash = dotted;
1561 break;
1562 }
1563 case wxLONG_DASH:
1564 {
1565 lineStyle = LineOnOffDash;
1566 req_nb_dash = 2;
1567 req_dash = long_dashed;
1568 break;
1569 }
1570 case wxSHORT_DASH:
1571 {
1572 lineStyle = LineOnOffDash;
1573 req_nb_dash = 2;
1574 req_dash = short_dashed;
1575 break;
1576 }
1577 case wxDOT_DASH:
1578 {
1579 // lineStyle = LineDoubleDash;
1580 lineStyle = LineOnOffDash;
1581 req_nb_dash = 4;
1582 req_dash = dotted_dashed;
1583 break;
1584 }
1585
1586 case wxTRANSPARENT:
1587 case wxSTIPPLE_MASK_OPAQUE:
1588 case wxSTIPPLE:
1589 case wxSOLID:
1590 default:
1591 {
1592 lineStyle = LineSolid;
1593 req_dash = (wxX11Dash*)NULL;
1594 req_nb_dash = 0;
1595 break;
1596 }
1597 }
1598
1599 int capStyle = CapRound;
1600 switch (m_pen.GetCap())
1601 {
1602 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1603 case wxCAP_BUTT: { capStyle = CapButt; break; }
1604 case wxCAP_ROUND:
1605 default:
1606 {
1607 if (width <= 1)
1608 {
1609 width = 0;
1610 capStyle = CapNotLast;
1611 }
1612 else
1613 {
1614 capStyle = CapRound;
1615 }
1616 break;
1617 }
1618 }
1619
1620 int joinStyle = JoinRound;
1621 switch (m_pen.GetJoin())
1622 {
1623 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1624 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1625 case wxJOIN_ROUND:
1626 default: { joinStyle = JoinRound; break; }
1627 }
1628
1629 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1630
1631 m_pen.GetColour().CalcPixel( m_cmap );
1632 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1633 }
1634
1635 void wxWindowDC::SetBrush( const wxBrush &brush )
1636 {
1637 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1638
1639 if (m_brush == brush) return;
1640
1641 m_brush = brush;
1642
1643 if (!m_brush.Ok()) return;
1644
1645 if (!m_window) return;
1646
1647 m_brush.GetColour().CalcPixel( m_cmap );
1648 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1649
1650 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1651
1652 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
1653 {
1654 if (m_brush.GetStipple()->GetPixmap())
1655 {
1656 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1657 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1658 }
1659 else
1660 {
1661 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1662 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1663 }
1664 }
1665
1666 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1667 {
1668 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1669 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1670 }
1671
1672 if (IS_HATCH(m_brush.GetStyle()))
1673 {
1674 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1675 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1676 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1677 }
1678 }
1679
1680 void wxWindowDC::SetBackground( const wxBrush &brush )
1681 {
1682 /* CMB 21/7/98: Added SetBackground. Sets background brush
1683 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1684
1685 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1686
1687 if (m_backgroundBrush == brush) return;
1688
1689 m_backgroundBrush = brush;
1690
1691 if (!m_backgroundBrush.Ok()) return;
1692
1693 if (!m_window) return;
1694
1695 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1696 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1697 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1698 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1699 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1700
1701 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
1702
1703 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
1704 {
1705 if (m_backgroundBrush.GetStipple()->GetPixmap())
1706 {
1707 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1708 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
1709 }
1710 else
1711 {
1712 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1713 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1714 }
1715 }
1716
1717 if (IS_HATCH(m_backgroundBrush.GetStyle()))
1718 {
1719 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1720 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1721 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
1722 }
1723 }
1724
1725 void wxWindowDC::SetLogicalFunction( int function )
1726 {
1727 wxCHECK_RET( Ok(), "invalid dc" );
1728
1729 int x_function;
1730
1731 if (m_logicalFunction == function)
1732 return;
1733
1734 // VZ: shouldn't this be a CHECK?
1735 if (!m_window)
1736 return;
1737
1738 switch (function)
1739 {
1740 case wxCLEAR:
1741 x_function = GXclear;
1742 break;
1743 case wxXOR:
1744 x_function = GXxor;
1745 break;
1746 case wxINVERT:
1747 x_function = GXinvert;
1748 break;
1749 case wxOR_REVERSE:
1750 x_function = GXorReverse;
1751 break;
1752 case wxAND_REVERSE:
1753 x_function = GXandReverse;
1754 break;
1755 case wxAND:
1756 x_function = GXand;
1757 break;
1758 case wxOR:
1759 x_function = GXor;
1760 break;
1761 case wxAND_INVERT:
1762 x_function = GXandInverted;
1763 break;
1764 case wxNO_OP:
1765 x_function = GXnoop;
1766 break;
1767 case wxNOR:
1768 x_function = GXnor;
1769 break;
1770 case wxEQUIV:
1771 x_function = GXequiv;
1772 break;
1773 case wxSRC_INVERT:
1774 x_function = GXcopyInverted;
1775 break;
1776 case wxOR_INVERT:
1777 x_function = GXorInverted;
1778 break;
1779 case wxNAND:
1780 x_function = GXnand;
1781 break;
1782 case wxSET:
1783 x_function = GXset;
1784 break;
1785 case wxCOPY:
1786 default:
1787 x_function = GXcopy;
1788 break;
1789 }
1790
1791 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1792 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
1793
1794 // to stay compatible with wxMSW, we don't apply ROPs to the text
1795 // operations (i.e. DrawText/DrawRotatedText).
1796 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1797 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1798
1799 m_logicalFunction = function;
1800 }
1801
1802 void wxWindowDC::SetTextForeground( const wxColour &col )
1803 {
1804 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1805
1806 // don't set m_textForegroundColour to an invalid colour as we'd crash
1807 // later then (we use m_textForegroundColour.GetColor() without checking
1808 // in a few places)
1809 if ( !col.Ok() || (m_textForegroundColour == col) )
1810 return;
1811
1812 m_textForegroundColour = col;
1813
1814 if (m_window)
1815 {
1816 m_textForegroundColour.CalcPixel( m_cmap );
1817 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1818 }
1819 }
1820
1821 void wxWindowDC::SetTextBackground( const wxColour &col )
1822 {
1823 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1824
1825 // same as above
1826 if ( !col.Ok() || (m_textBackgroundColour == col) )
1827 return;
1828
1829 m_textBackgroundColour = col;
1830
1831 if (m_window)
1832 {
1833 m_textBackgroundColour.CalcPixel( m_cmap );
1834 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1835 }
1836 }
1837
1838 void wxWindowDC::SetBackgroundMode( int mode )
1839 {
1840 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1841
1842 m_backgroundMode = mode;
1843
1844 #if wxUSE_NANOX
1845 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1846 #endif
1847
1848 if (!m_window) return;
1849
1850 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1851 // transparent/solid background mode
1852
1853 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1854 {
1855 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1856 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1857 }
1858 }
1859
1860 void wxWindowDC::SetPalette( const wxPalette& palette )
1861 {
1862 #if 0
1863 if (m_window)
1864 {
1865 if (palette.Ok())
1866 /* Use GetXColormap */
1867 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1868 (Colormap) palette.GetXColormap());
1869 else
1870 /* Use wxGetMainColormap */
1871 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1872 (Colormap) wxTheApp->GetMainColormap(m_display));
1873 }
1874 #endif
1875 }
1876
1877 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
1878 {
1879 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1880
1881 if (!m_window) return;
1882
1883 wxRect rect;
1884 rect.x = XLOG2DEV(x);
1885 rect.y = YLOG2DEV(y);
1886 rect.width = XLOG2DEVREL(width);
1887 rect.height = YLOG2DEVREL(height);
1888
1889 if (!m_currentClippingRegion.IsNull())
1890 m_currentClippingRegion.Intersect( rect );
1891 else
1892 m_currentClippingRegion.Union( rect );
1893
1894 #if USE_PAINT_REGION
1895 if (!m_paintClippingRegion.IsNull())
1896 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1897 #endif
1898
1899 wxCoord xx, yy, ww, hh;
1900 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1901 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1902
1903 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1904 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1905 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1906 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1907 }
1908
1909 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1910 {
1911 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1912
1913 if (region.Empty())
1914 {
1915 DestroyClippingRegion();
1916 return;
1917 }
1918
1919 if (!m_window) return;
1920
1921 if (!m_currentClippingRegion.IsNull())
1922 m_currentClippingRegion.Intersect( region );
1923 else
1924 m_currentClippingRegion.Union( region );
1925
1926 #if USE_PAINT_REGION
1927 if (!m_paintClippingRegion.IsNull())
1928 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1929 #endif
1930
1931 wxCoord xx, yy, ww, hh;
1932 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1933 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1934
1935 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1936 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1937 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1938 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1939 }
1940
1941 void wxWindowDC::DestroyClippingRegion()
1942 {
1943 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1944
1945 wxDC::DestroyClippingRegion();
1946
1947 m_currentClippingRegion.Clear();
1948
1949 #if USE_PAINT_REGION
1950 if (!m_paintClippingRegion.IsEmpty())
1951 m_currentClippingRegion.Union( m_paintClippingRegion );
1952 #endif
1953
1954 if (!m_window) return;
1955
1956 if (m_currentClippingRegion.IsEmpty())
1957 {
1958 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1959 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1960 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1961 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1962 }
1963 else
1964 {
1965 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1966 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1967 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1968 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1969 }
1970 }
1971
1972 void wxWindowDC::Destroy()
1973 {
1974 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1975 m_penGC = NULL;
1976 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1977 m_brushGC = NULL;
1978 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1979 m_textGC = NULL;
1980 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1981 m_bgGC = NULL;
1982 }
1983
1984 void wxWindowDC::ComputeScaleAndOrigin()
1985 {
1986 /* CMB: copy scale to see if it changes */
1987 double origScaleX = m_scaleX;
1988 double origScaleY = m_scaleY;
1989
1990 wxDC::ComputeScaleAndOrigin();
1991
1992 /* CMB: if scale has changed call SetPen to recalulate the line width */
1993 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1994 (m_pen.Ok()))
1995 {
1996 /* this is a bit artificial, but we need to force wxDC to think
1997 the pen has changed */
1998 wxPen pen = m_pen;
1999 m_pen = wxNullPen;
2000 SetPen( pen );
2001 }
2002 }
2003
2004 wxSize wxWindowDC::GetPPI() const
2005 {
2006 return wxSize(100, 100);
2007 }
2008
2009 int wxWindowDC::GetDepth() const
2010 {
2011 wxFAIL_MSG(wxT("not implemented"));
2012
2013 return -1;
2014 }
2015
2016 // ----------------------------------------------------------------------------
2017 // wxPaintDC
2018 // ----------------------------------------------------------------------------
2019
2020 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2021
2022 wxPaintDC::wxPaintDC(wxWindow* win)
2023 : wxClientDC(win)
2024 {
2025 #if USE_PAINT_REGION
2026 if (!win->GetClipPaintRegion())
2027 return;
2028
2029 m_paintClippingRegion = win->GetUpdateRegion();
2030 Region region = (Region) m_paintClippingRegion.GetX11Region();
2031 if (region)
2032 {
2033 m_paintClippingRegion = win->GetUpdateRegion();
2034 Region region2 = (Region) m_paintClippingRegion.GetX11Region();
2035 if (region2)
2036 {
2037 m_currentClippingRegion.Union( m_paintClippingRegion );
2038
2039 XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
2040 XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
2041 XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
2042 XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
2043 }
2044 }
2045 #endif // USE_PAINT_REGION
2046 }
2047
2048 //-----------------------------------------------------------------------------
2049 // wxClientDC
2050 //-----------------------------------------------------------------------------
2051
2052 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2053
2054 wxClientDC::wxClientDC( wxWindow *win )
2055 : wxWindowDC( win )
2056 {
2057 wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
2058
2059 #ifdef __WXUNIVERSAL__
2060 wxPoint ptOrigin = win->GetClientAreaOrigin();
2061 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2062 wxSize size = win->GetClientSize();
2063 SetClippingRegion(wxPoint(0, 0), size);
2064 #endif // __WXUNIVERSAL__
2065 }
2066
2067 void wxClientDC::DoGetSize(int *width, int *height) const
2068 {
2069 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2070
2071 m_owner->GetClientSize( width, height );
2072 }
2073
2074 // ----------------------------------------------------------------------------
2075 // wxDCModule
2076 // ----------------------------------------------------------------------------
2077
2078 class wxDCModule : public wxModule
2079 {
2080 public:
2081 bool OnInit();
2082 void OnExit();
2083
2084 private:
2085 DECLARE_DYNAMIC_CLASS(wxDCModule)
2086 };
2087
2088 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2089
2090 bool wxDCModule::OnInit()
2091 {
2092 wxInitGCPool();
2093 return TRUE;
2094 }
2095
2096 void wxDCModule::OnExit()
2097 {
2098 wxCleanUpGCPool();
2099 }