More changes for better redraw flow under X11.
[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 DoDrawBitmap(icon, x, y, TRUE);
842 }
843
844 #if wxUSE_NANOX
845 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
846 wxCoord x, wxCoord y,
847 bool useMask )
848 {
849 wxCHECK_RET( Ok(), wxT("invalid window dc") );
850
851 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
852
853 bool is_mono = (bitmap.GetBitmap() != NULL);
854
855 /* scale/translate size and position */
856 int xx = XLOG2DEV(x);
857 int yy = YLOG2DEV(y);
858
859 int w = bitmap.GetWidth();
860 int h = bitmap.GetHeight();
861
862 CalcBoundingBox( x, y );
863 CalcBoundingBox( x + w, y + h );
864
865 if (!m_window) return;
866
867 int ww = XLOG2DEVREL(w);
868 int hh = YLOG2DEVREL(h);
869
870 /* compare to current clipping region */
871 if (!m_currentClippingRegion.IsNull())
872 {
873 wxRegion tmp( xx,yy,ww,hh );
874 tmp.Intersect( m_currentClippingRegion );
875 if (tmp.IsEmpty())
876 return;
877 }
878
879 /* scale bitmap if required */
880 wxBitmap use_bitmap;
881 if ((w != ww) || (h != hh))
882 {
883 wxImage image( bitmap );
884 image.Rescale( ww, hh );
885 #if 0
886 if (is_mono)
887 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
888 else
889 #endif
890 use_bitmap = image.ConvertToBitmap();
891 }
892 else
893 {
894 use_bitmap = bitmap;
895 }
896
897 /* apply mask if any */
898 WXPixmap mask = NULL;
899 if (use_bitmap.GetMask())
900 mask = use_bitmap.GetMask()->GetBitmap();
901
902 if (useMask && mask)
903 {
904 Pixmap pixmap = (Pixmap) use_bitmap.GetPixmap() ;
905 Pixmap maskPixmap = (Pixmap) use_bitmap.GetMask()->GetBitmap() ;
906 Pixmap bufPixmap = GrNewPixmap(w, h, 0);
907 GC gc = GrNewGC();
908 GrSetGCUseBackground(gc, FALSE);
909 GrSetGCMode(gc, GR_MODE_COPY);
910
911 // This code assumes that background and foreground
912 // colours are used in ROPs, like in MSW.
913 // Not sure if this is true.
914
915 // Copy destination to buffer.
916 // In DoBlit, we need this step because Blit has
917 // a ROP argument. Here, we don't need it.
918 // In DoBlit, we may be able to eliminate this step
919 // if we check if the rop = copy
920 #if 0
921 GrCopyArea(bufPixmap, gc, 0, 0, w, h, (Window) m_window,
922 0, 0, GR_MODE_COPY);
923 #endif
924
925 // Copy src to buffer using selected raster op (none selected
926 // in DrawBitmap, so just use Gxcopy)
927 GrCopyArea(bufPixmap, gc, 0, 0, w, h, pixmap,
928 0, 0, GR_MODE_COPY);
929
930 // Set masked area in buffer to BLACK (pixel value 0)
931 GrSetGCBackground(gc, WHITE);
932 GrSetGCForeground(gc, BLACK);
933 GrCopyArea(bufPixmap, gc, 0, 0, w, h, maskPixmap,
934 0, 0, GR_MODE_AND);
935
936 // set unmasked area in dest to BLACK
937 GrSetGCBackground(gc, BLACK);
938 GrSetGCForeground(gc, WHITE);
939 GrCopyArea((Window) m_window, gc, xx, yy, w, h, maskPixmap,
940 0, 0, GR_MODE_AND);
941
942 // OR buffer to dest
943 GrCopyArea((Window) m_window, gc, xx, yy, w, h, bufPixmap,
944 0, 0, GR_MODE_OR);
945
946 GrDestroyGC(gc);
947 GrDestroyWindow(bufPixmap);
948 }
949 else
950 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
951 (GC) m_penGC, 0, 0, w, h, xx, yy );
952
953 /* remove mask again if any */
954 if (useMask && mask)
955 {
956 if (!m_currentClippingRegion.IsNull())
957 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
958 }
959 }
960
961 #else
962
963 // Normal X11
964 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
965 wxCoord x, wxCoord y,
966 bool useMask )
967 {
968 wxCHECK_RET( Ok(), wxT("invalid window dc") );
969
970 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
971
972 bool is_mono = (bitmap.GetBitmap() != NULL);
973
974 // scale/translate size and position
975 int xx = XLOG2DEV(x);
976 int yy = YLOG2DEV(y);
977
978 int w = bitmap.GetWidth();
979 int h = bitmap.GetHeight();
980
981 CalcBoundingBox( x, y );
982 CalcBoundingBox( x + w, y + h );
983
984 if (!m_window) return;
985
986 int ww = XLOG2DEVREL(w);
987 int hh = YLOG2DEVREL(h);
988
989 // compare to current clipping region
990 if (!m_currentClippingRegion.IsNull())
991 {
992 wxRegion tmp( xx,yy,ww,hh );
993 tmp.Intersect( m_currentClippingRegion );
994 if (tmp.IsEmpty())
995 return;
996 }
997
998 // scale bitmap if required
999 wxBitmap use_bitmap;
1000 if ((w != ww) || (h != hh))
1001 {
1002 wxImage image( bitmap );
1003 image.Rescale( ww, hh );
1004 #if 0
1005 if (is_mono)
1006 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1007 else
1008 #endif
1009 use_bitmap = image.ConvertToBitmap();
1010 }
1011 else
1012 {
1013 use_bitmap = bitmap;
1014 }
1015
1016 // apply mask if any
1017 WXPixmap mask = NULL;
1018 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1019
1020 if (useMask && mask)
1021 {
1022 WXPixmap new_mask = NULL;
1023 #if 0
1024 if (!m_currentClippingRegion.IsNull())
1025 {
1026 GdkColor col;
1027 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1028 GdkGC *gc = gdk_gc_new( new_mask );
1029 col.pixel = 0;
1030 gdk_gc_set_foreground( gc, &col );
1031 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1032 col.pixel = 0;
1033 gdk_gc_set_background( gc, &col );
1034 col.pixel = 1;
1035 gdk_gc_set_foreground( gc, &col );
1036 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1037 gdk_gc_set_clip_origin( gc, -xx, -yy );
1038 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1039 gdk_gc_set_stipple( gc, mask );
1040 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1041 gdk_gc_unref( gc );
1042 }
1043 #endif
1044 if (is_mono)
1045 {
1046 if (new_mask)
1047 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1048 else
1049 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1050 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1051 }
1052 else
1053 {
1054 if (new_mask)
1055 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1056 else
1057 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1058 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1059 }
1060
1061 if (new_mask)
1062 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
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 logical_func, 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;
1125 ysrcMask = ysrc;
1126 }
1127
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 0
1209 if (is_mono)
1210 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1211 else
1212 #endif
1213 use_bitmap = image.ConvertToBitmap();
1214 }
1215 else
1216 {
1217 use_bitmap = memDC->m_selected;
1218 }
1219
1220 // apply mask if any
1221 WXPixmap mask = NULL;
1222 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
1223
1224 if (useMask && mask)
1225 {
1226 WXPixmap new_mask = NULL;
1227 #if 0
1228 if (!m_currentClippingRegion.IsNull())
1229 {
1230 GdkColor col;
1231 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1232 GdkGC *gc = gdk_gc_new( new_mask );
1233 col.pixel = 0;
1234 gdk_gc_set_foreground( gc, &col );
1235 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1236 col.pixel = 0;
1237 gdk_gc_set_background( gc, &col );
1238 col.pixel = 1;
1239 gdk_gc_set_foreground( gc, &col );
1240 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1241 gdk_gc_set_clip_origin( gc, -xx, -yy );
1242 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1243 gdk_gc_set_stipple( gc, mask );
1244 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1245 gdk_gc_unref( gc );
1246 }
1247 #endif
1248 if (is_mono)
1249 {
1250 if (new_mask)
1251 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
1252 else
1253 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1254 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
1255 }
1256 else
1257 {
1258 if (new_mask)
1259 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
1260 else
1261 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1262 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
1263 }
1264
1265 if (new_mask)
1266 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
1267 }
1268
1269 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1270 // drawing a mono-bitmap (XBitmap) we use the current text GC
1271
1272 if (is_mono)
1273 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1274 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
1275 else
1276 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1277 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1278
1279 // remove mask again if any
1280 if (useMask && mask)
1281 {
1282 if (is_mono)
1283 {
1284 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1285 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
1286 if (!m_currentClippingRegion.IsNull())
1287 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1288 }
1289 else
1290 {
1291 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1292 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
1293 if (!m_currentClippingRegion.IsNull())
1294 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1295 }
1296 }
1297 }
1298 else // use_bitmap_method
1299 {
1300 if ((width != ww) || (height != hh))
1301 {
1302 /* Draw source window into a bitmap as we cannot scale
1303 a window in contrast to a bitmap. this would actually
1304 work with memory dcs as well, but we'd lose the mask
1305 information and waste one step in this process since
1306 a memory already has a bitmap. all this is slightly
1307 inefficient as we could take an XImage directly from
1308 an X window, but we'd then also have to care that
1309 the window is not outside the screen (in which case
1310 we'd get a BadMatch or what not).
1311 Is a double XGetImage and combined XGetPixel and
1312 XPutPixel really faster? I'm not sure. look at wxXt
1313 for a different implementation of the same problem. */
1314
1315 wxBitmap bitmap( width, height );
1316
1317 // copy including child window contents
1318 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1319 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1320 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1321 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1322
1323 // scale image
1324 wxImage image( bitmap );
1325 image = image.Scale( ww, hh );
1326
1327 // convert to bitmap
1328 bitmap = image.ConvertToBitmap();
1329
1330 // draw scaled bitmap
1331 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1332 (GC) m_penGC, 0, 0, width, height, xx, yy );
1333 }
1334 else
1335 {
1336 // No scaling and not a memory dc with a mask either
1337
1338 // copy including child window contents
1339 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1340 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1341 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1342 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
1343 }
1344 }
1345
1346 SetLogicalFunction( old_logical_func );
1347
1348 return TRUE;
1349 }
1350
1351 void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1352 {
1353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1354
1355 if (!m_window) return;
1356
1357 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1358
1359 wxCHECK_RET( xfont, wxT("invalid font") );
1360
1361 x = XLOG2DEV(x);
1362 y = YLOG2DEV(y);
1363
1364 // First draw a rectangle representing the text background, if a text
1365 // background is specified
1366 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1367 {
1368 // Since X draws from the baseline of the text, must add the text height
1369 int cx = 0;
1370 int cy = 0;
1371 int ascent = 0;
1372 int slen;
1373 int direction, descent;
1374
1375 slen = strlen(text);
1376 XCharStruct overall_return;
1377
1378 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
1379 &ascent, &descent, &overall_return);
1380
1381 cx = overall_return.width;
1382 cy = ascent + descent;
1383 m_textBackgroundColour.CalcPixel(m_cmap);
1384 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
1385 XFillRectangle( (Display*) m_display, (Window) m_window,
1386 (GC) m_textGC, x, y, cx, cy );
1387 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1388
1389 }
1390
1391 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
1392 #if !wxUSE_NANOX
1393 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
1394 #endif
1395 {
1396 XDrawString( (Display*) m_display, (Window) m_window,
1397 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1398 }
1399
1400 #if 0
1401 if (m_font.GetUnderlined())
1402 {
1403 wxCoord ul_y = y + XFontStructGetAscent(font);
1404 if (font->descent > 0) ul_y++;
1405 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
1406 }
1407
1408 width = wxCoord(width / m_scaleX);
1409 height = wxCoord(height / m_scaleY);
1410
1411 CalcBoundingBox (x + width, y + height);
1412 CalcBoundingBox (x, y);
1413 #endif
1414 }
1415
1416 void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
1417 {
1418 // later
1419 }
1420
1421 void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1422 wxCoord *descent, wxCoord *externalLeading,
1423 wxFont *font ) const
1424 {
1425 wxCHECK_RET( Ok(), "invalid dc" );
1426
1427 wxFont fontToUse = m_font;
1428 if (font) fontToUse = *font;
1429
1430 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
1431
1432 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
1433
1434 wxCHECK_RET( xfont, wxT("invalid font") );
1435
1436 int direction, ascent, descent2;
1437 XCharStruct overall;
1438
1439 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
1440 &ascent, &descent2, &overall);
1441
1442 if (width)
1443 *width = (wxCoord)( overall.width / m_scaleX );
1444 if (height)
1445 *height = (wxCoord)((ascent + descent2) / m_scaleY );
1446 if (descent)
1447 *descent = (wxCoord)(descent2 / m_scaleY );
1448 if (externalLeading)
1449 *externalLeading = 0; // ??
1450 }
1451
1452 wxCoord wxWindowDC::GetCharWidth() const
1453 {
1454 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1455
1456 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1457
1458 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1459
1460 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1461
1462 int direction, ascent, descent;
1463 XCharStruct overall;
1464
1465 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1466
1467 return (wxCoord)(overall.width / m_scaleX);
1468 }
1469
1470 wxCoord wxWindowDC::GetCharHeight() const
1471 {
1472 wxCHECK_MSG( Ok(), 0, "invalid dc" );
1473
1474 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1475
1476 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1477
1478 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
1479
1480 int direction, ascent, descent;
1481 XCharStruct overall;
1482
1483 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1484
1485 return (wxCoord)((ascent+descent) / m_scaleY);
1486 }
1487
1488 void wxWindowDC::Clear()
1489 {
1490 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1491
1492 if (!m_window) return;
1493
1494 /* - we either are a memory dc or have a window as the
1495 owner. anything else shouldn't happen.
1496 - we don't use gdk_window_clear() as we don't set
1497 the window's background colour anymore. it is too
1498 much pain to keep the DC's and the window's back-
1499 ground colour in synch. */
1500
1501 if (m_owner)
1502 {
1503 int width,height;
1504 m_owner->GetSize( &width, &height );
1505 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1506 return;
1507 }
1508
1509 if (m_isMemDC)
1510 {
1511 int width,height;
1512 GetSize( &width, &height );
1513 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1514 return;
1515 }
1516 }
1517
1518 void wxWindowDC::SetFont( const wxFont &font )
1519 {
1520 wxCHECK_RET( Ok(), "invalid dc" );
1521
1522 m_font = font;
1523 }
1524
1525 void wxWindowDC::SetPen( const wxPen &pen )
1526 {
1527 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1528
1529 if (m_pen == pen) return;
1530
1531 m_pen = pen;
1532
1533 if (!m_pen.Ok()) return;
1534
1535 if (!m_window) return;
1536
1537 int width = m_pen.GetWidth();
1538 if (width <= 0)
1539 {
1540 // CMB: if width is non-zero scale it with the dc
1541 width = 1;
1542 }
1543 else
1544 {
1545 // X doesn't allow different width in x and y and so we take
1546 // the average
1547 double w = 0.5 +
1548 ( fabs((double) XLOG2DEVREL(width)) +
1549 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1550 width = (int)w;
1551 }
1552
1553 static const wxX11Dash dotted[] = {1, 1};
1554 static const wxX11Dash short_dashed[] = {2, 2};
1555 static const wxX11Dash long_dashed[] = {2, 4};
1556 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1557
1558 // We express dash pattern in pen width unit, so we are
1559 // independent of zoom factor and so on...
1560 int req_nb_dash;
1561 const wxX11Dash *req_dash;
1562
1563 int lineStyle = LineSolid;
1564 switch (m_pen.GetStyle())
1565 {
1566 case wxUSER_DASH:
1567 {
1568 lineStyle = LineOnOffDash;
1569 req_nb_dash = m_pen.GetDashCount();
1570 req_dash = (wxX11Dash*)m_pen.GetDash();
1571 break;
1572 }
1573 case wxDOT:
1574 {
1575 lineStyle = LineOnOffDash;
1576 req_nb_dash = 2;
1577 req_dash = dotted;
1578 break;
1579 }
1580 case wxLONG_DASH:
1581 {
1582 lineStyle = LineOnOffDash;
1583 req_nb_dash = 2;
1584 req_dash = long_dashed;
1585 break;
1586 }
1587 case wxSHORT_DASH:
1588 {
1589 lineStyle = LineOnOffDash;
1590 req_nb_dash = 2;
1591 req_dash = short_dashed;
1592 break;
1593 }
1594 case wxDOT_DASH:
1595 {
1596 // lineStyle = LineDoubleDash;
1597 lineStyle = LineOnOffDash;
1598 req_nb_dash = 4;
1599 req_dash = dotted_dashed;
1600 break;
1601 }
1602
1603 case wxTRANSPARENT:
1604 case wxSTIPPLE_MASK_OPAQUE:
1605 case wxSTIPPLE:
1606 case wxSOLID:
1607 default:
1608 {
1609 lineStyle = LineSolid;
1610 req_dash = (wxX11Dash*)NULL;
1611 req_nb_dash = 0;
1612 break;
1613 }
1614 }
1615
1616 int capStyle = CapRound;
1617 switch (m_pen.GetCap())
1618 {
1619 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1620 case wxCAP_BUTT: { capStyle = CapButt; break; }
1621 case wxCAP_ROUND:
1622 default:
1623 {
1624 if (width <= 1)
1625 {
1626 width = 0;
1627 capStyle = CapNotLast;
1628 }
1629 else
1630 {
1631 capStyle = CapRound;
1632 }
1633 break;
1634 }
1635 }
1636
1637 int joinStyle = JoinRound;
1638 switch (m_pen.GetJoin())
1639 {
1640 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1641 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
1642 case wxJOIN_ROUND:
1643 default: { joinStyle = JoinRound; break; }
1644 }
1645
1646 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
1647
1648 m_pen.GetColour().CalcPixel( m_cmap );
1649 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1650 }
1651
1652 void wxWindowDC::SetBrush( const wxBrush &brush )
1653 {
1654 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1655
1656 if (m_brush == brush) return;
1657
1658 m_brush = brush;
1659
1660 if (!m_brush.Ok()) return;
1661
1662 if (!m_window) return;
1663
1664 m_brush.GetColour().CalcPixel( m_cmap );
1665 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1666
1667 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1668
1669 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
1670 {
1671 if (m_brush.GetStipple()->GetPixmap())
1672 {
1673 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1674 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
1675 }
1676 else
1677 {
1678 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1679 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
1680 }
1681 }
1682
1683 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1684 {
1685 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
1686 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
1687 }
1688
1689 if (IS_HATCH(m_brush.GetStyle()))
1690 {
1691 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1692 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1693 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1694 }
1695 }
1696
1697 void wxWindowDC::SetBackground( const wxBrush &brush )
1698 {
1699 /* CMB 21/7/98: Added SetBackground. Sets background brush
1700 * for Clear() and bg colour for shapes filled with cross-hatch brush */
1701
1702 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1703
1704 if (m_backgroundBrush == brush) return;
1705
1706 m_backgroundBrush = brush;
1707
1708 if (!m_backgroundBrush.Ok()) return;
1709
1710 if (!m_window) return;
1711
1712 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1713 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1714 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1715 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1716 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1717
1718 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
1719
1720 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
1721 {
1722 if (m_backgroundBrush.GetStipple()->GetPixmap())
1723 {
1724 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1725 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
1726 }
1727 else
1728 {
1729 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1730 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
1731 }
1732 }
1733
1734 if (IS_HATCH(m_backgroundBrush.GetStyle()))
1735 {
1736 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1737 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1738 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
1739 }
1740 }
1741
1742 void wxWindowDC::SetLogicalFunction( int function )
1743 {
1744 wxCHECK_RET( Ok(), "invalid dc" );
1745
1746 int x_function;
1747
1748 if (m_logicalFunction == function)
1749 return;
1750
1751 // VZ: shouldn't this be a CHECK?
1752 if (!m_window)
1753 return;
1754
1755 switch (function)
1756 {
1757 case wxCLEAR:
1758 x_function = GXclear;
1759 break;
1760 case wxXOR:
1761 x_function = GXxor;
1762 break;
1763 case wxINVERT:
1764 x_function = GXinvert;
1765 break;
1766 case wxOR_REVERSE:
1767 x_function = GXorReverse;
1768 break;
1769 case wxAND_REVERSE:
1770 x_function = GXandReverse;
1771 break;
1772 case wxAND:
1773 x_function = GXand;
1774 break;
1775 case wxOR:
1776 x_function = GXor;
1777 break;
1778 case wxAND_INVERT:
1779 x_function = GXandInverted;
1780 break;
1781 case wxNO_OP:
1782 x_function = GXnoop;
1783 break;
1784 case wxNOR:
1785 x_function = GXnor;
1786 break;
1787 case wxEQUIV:
1788 x_function = GXequiv;
1789 break;
1790 case wxSRC_INVERT:
1791 x_function = GXcopyInverted;
1792 break;
1793 case wxOR_INVERT:
1794 x_function = GXorInverted;
1795 break;
1796 case wxNAND:
1797 x_function = GXnand;
1798 break;
1799 case wxSET:
1800 x_function = GXset;
1801 break;
1802 case wxCOPY:
1803 default:
1804 x_function = GXcopy;
1805 break;
1806 }
1807
1808 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1809 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
1810
1811 // to stay compatible with wxMSW, we don't apply ROPs to the text
1812 // operations (i.e. DrawText/DrawRotatedText).
1813 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1814 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1815
1816 m_logicalFunction = function;
1817 }
1818
1819 void wxWindowDC::SetTextForeground( const wxColour &col )
1820 {
1821 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1822
1823 // don't set m_textForegroundColour to an invalid colour as we'd crash
1824 // later then (we use m_textForegroundColour.GetColor() without checking
1825 // in a few places)
1826 if ( !col.Ok() || (m_textForegroundColour == col) )
1827 return;
1828
1829 m_textForegroundColour = col;
1830
1831 if (m_window)
1832 {
1833 m_textForegroundColour.CalcPixel( m_cmap );
1834 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1835 }
1836 }
1837
1838 void wxWindowDC::SetTextBackground( const wxColour &col )
1839 {
1840 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1841
1842 // same as above
1843 if ( !col.Ok() || (m_textBackgroundColour == col) )
1844 return;
1845
1846 m_textBackgroundColour = col;
1847
1848 if (m_window)
1849 {
1850 m_textBackgroundColour.CalcPixel( m_cmap );
1851 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1852 }
1853 }
1854
1855 void wxWindowDC::SetBackgroundMode( int mode )
1856 {
1857 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1858
1859 m_backgroundMode = mode;
1860
1861 #if wxUSE_NANOX
1862 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1863 #endif
1864
1865 if (!m_window) return;
1866
1867 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1868 // transparent/solid background mode
1869
1870 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1871 {
1872 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1873 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1874 }
1875 }
1876
1877 void wxWindowDC::SetPalette( const wxPalette& palette )
1878 {
1879 #if 0
1880 if (m_window)
1881 {
1882 if (palette.Ok())
1883 /* Use GetXColormap */
1884 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1885 (Colormap) palette.GetXColormap());
1886 else
1887 /* Use wxGetMainColormap */
1888 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1889 (Colormap) wxTheApp->GetMainColormap(m_display));
1890 }
1891 #endif
1892 }
1893
1894 void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
1895 {
1896 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1897
1898 if (!m_window) return;
1899
1900 wxRect rect;
1901 rect.x = XLOG2DEV(x);
1902 rect.y = YLOG2DEV(y);
1903 rect.width = XLOG2DEVREL(width);
1904 rect.height = YLOG2DEVREL(height);
1905
1906 if (!m_currentClippingRegion.IsNull())
1907 m_currentClippingRegion.Intersect( rect );
1908 else
1909 m_currentClippingRegion.Union( rect );
1910
1911 #if USE_PAINT_REGION
1912 if (!m_paintClippingRegion.IsNull())
1913 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1914 #endif
1915
1916 wxCoord xx, yy, ww, hh;
1917 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1918 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1919
1920 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1921 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1922 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1923 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1924 }
1925
1926 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1927 {
1928 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1929
1930 if (region.Empty())
1931 {
1932 DestroyClippingRegion();
1933 return;
1934 }
1935
1936 if (!m_window) return;
1937
1938 if (!m_currentClippingRegion.IsNull())
1939 m_currentClippingRegion.Intersect( region );
1940 else
1941 m_currentClippingRegion.Union( region );
1942
1943 #if USE_PAINT_REGION
1944 if (!m_paintClippingRegion.IsNull())
1945 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1946 #endif
1947
1948 wxCoord xx, yy, ww, hh;
1949 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1950 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1951
1952 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1953 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1954 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1955 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1956 }
1957
1958 void wxWindowDC::DestroyClippingRegion()
1959 {
1960 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1961
1962 wxDC::DestroyClippingRegion();
1963
1964 m_currentClippingRegion.Clear();
1965
1966 #if USE_PAINT_REGION
1967 if (!m_paintClippingRegion.IsEmpty())
1968 m_currentClippingRegion.Union( m_paintClippingRegion );
1969 #endif
1970
1971 if (!m_window) return;
1972
1973 if (m_currentClippingRegion.IsEmpty())
1974 {
1975 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1976 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1977 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1978 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1979 }
1980 else
1981 {
1982 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1983 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1984 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1985 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1986 }
1987 }
1988
1989 void wxWindowDC::Destroy()
1990 {
1991 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1992 m_penGC = NULL;
1993 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1994 m_brushGC = NULL;
1995 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1996 m_textGC = NULL;
1997 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1998 m_bgGC = NULL;
1999 }
2000
2001 void wxWindowDC::ComputeScaleAndOrigin()
2002 {
2003 /* CMB: copy scale to see if it changes */
2004 double origScaleX = m_scaleX;
2005 double origScaleY = m_scaleY;
2006
2007 wxDC::ComputeScaleAndOrigin();
2008
2009 /* CMB: if scale has changed call SetPen to recalulate the line width */
2010 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2011 (m_pen.Ok()))
2012 {
2013 /* this is a bit artificial, but we need to force wxDC to think
2014 the pen has changed */
2015 wxPen pen = m_pen;
2016 m_pen = wxNullPen;
2017 SetPen( pen );
2018 }
2019 }
2020
2021 wxSize wxWindowDC::GetPPI() const
2022 {
2023 return wxSize(100, 100);
2024 }
2025
2026 int wxWindowDC::GetDepth() const
2027 {
2028 wxFAIL_MSG(wxT("not implemented"));
2029
2030 return -1;
2031 }
2032
2033 //-----------------------------------------------------------------------------
2034 // wxClientDC
2035 //-----------------------------------------------------------------------------
2036
2037 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2038
2039 wxClientDC::wxClientDC( wxWindow *window )
2040 : wxWindowDC( window )
2041 {
2042 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
2043
2044 m_window = (WXWindow*) window->GetClientWindow();
2045
2046 #if wxUSE_TWO_WINDOWS
2047 #else
2048 wxPoint ptOrigin = window->GetClientAreaOrigin();
2049 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2050 wxSize size = window->GetClientSize();
2051 SetClippingRegion(wxPoint(0, 0), size);
2052 #endif
2053 }
2054
2055 void wxClientDC::DoGetSize(int *width, int *height) const
2056 {
2057 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2058
2059 m_owner->GetClientSize( width, height );
2060 }
2061
2062 // ----------------------------------------------------------------------------
2063 // wxPaintDC
2064 // ----------------------------------------------------------------------------
2065
2066 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2067
2068 wxPaintDC::wxPaintDC(wxWindow* window)
2069 : wxClientDC(window)
2070 {
2071 #if USE_PAINT_REGION
2072 if (!window->GetClipPaintRegion())
2073 return;
2074
2075 m_paintClippingRegion = window->GetUpdateRegion();
2076 Region region = (Region) m_paintClippingRegion.GetX11Region();
2077 if (region)
2078 {
2079 m_currentClippingRegion.Union( m_paintClippingRegion );
2080
2081 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2082 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2083 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2084 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2085 }
2086 #endif // USE_PAINT_REGION
2087 }
2088
2089 // ----------------------------------------------------------------------------
2090 // wxDCModule
2091 // ----------------------------------------------------------------------------
2092
2093 class wxDCModule : public wxModule
2094 {
2095 public:
2096 bool OnInit();
2097 void OnExit();
2098
2099 private:
2100 DECLARE_DYNAMIC_CLASS(wxDCModule)
2101 };
2102
2103 IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
2104
2105 bool wxDCModule::OnInit()
2106 {
2107 wxInitGCPool();
2108 return TRUE;
2109 }
2110
2111 void wxDCModule::OnExit()
2112 {
2113 wxCleanUpGCPool();
2114 }