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