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