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