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