]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
Fixed compilation error.
[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 }
3cd0b8c5
RR
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 }
3cd0b8c5 236 else
83df96d6 237 {
3cd0b8c5
RR
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 );
83df96d6
JS
242 }
243
3cd0b8c5
RR
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
0b5c0e1a
JS
258#if wxUSE_NANOX
259 // By default, draw transparently
260 GrSetGCUseBackground((GC) m_textGC, FALSE);
261#endif
262
3cd0b8c5
RR
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 );
83df96d6 293
3cd0b8c5
RR
294 if (!hatch_bitmap)
295 {
1180fb81
RR
296 int xscreen = DefaultScreen( (Display*) m_display );
297 Window xroot = RootWindow( (Display*) m_display, xscreen );
298
3cd0b8c5 299 hatch_bitmap = hatches;
1180fb81
RR
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 );
3cd0b8c5
RR
306 }
307}
83df96d6 308
3cd0b8c5
RR
309void wxWindowDC::DoGetSize( int* width, int* height ) const
310{
311 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
83df96d6 312
3cd0b8c5 313 m_owner->GetSize(width, height);
83df96d6
JS
314}
315
316void wxWindowDC::DoFloodFill( wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
317 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
318{
319 wxFAIL_MSG("not implemented");
320}
321
322bool 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
336void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
337{
3cd0b8c5 338 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 339
3cd0b8c5
RR
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) );
83df96d6 345
3cd0b8c5
RR
346 CalcBoundingBox(x1, y1);
347 CalcBoundingBox(x2, y2);
348 }
83df96d6
JS
349}
350
351void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
352{
3cd0b8c5 353 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 354
3cd0b8c5
RR
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 }
83df96d6
JS
370}
371
372void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
373{
3cd0b8c5
RR
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;
83df96d6
JS
386 double radius1, radius2;
387
388 if (xx1 == xx2 && yy1 == yy2)
389 {
390 radius1 = 0.0;
391 radius2 = 360.0;
392 }
83df96d6 393 else
3cd0b8c5 394 if (radius == 0.0)
83df96d6 395 {
3cd0b8c5 396 radius1 = radius2 = 0.0;
83df96d6 397 }
3cd0b8c5 398 else
83df96d6 399 {
3cd0b8c5
RR
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;
83df96d6 406 }
3cd0b8c5
RR
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;
83df96d6 411
3cd0b8c5 412 if (m_window)
83df96d6 413 {
3cd0b8c5
RR
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 }
83df96d6 476 }
3cd0b8c5 477
83df96d6
JS
478 CalcBoundingBox (x1, y1);
479 CalcBoundingBox (x2, y2);
480}
481
482void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
483{
3cd0b8c5 484 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 485
3cd0b8c5
RR
486 wxCoord xx = XLOG2DEV(x);
487 wxCoord yy = YLOG2DEV(y);
488 wxCoord ww = m_signX * XLOG2DEVREL(width);
489 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 490
3cd0b8c5
RR
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; }
83df96d6 494
3cd0b8c5 495 if (m_window)
83df96d6 496 {
3cd0b8c5
RR
497 wxCoord start = wxCoord(sa * 64.0);
498 wxCoord end = wxCoord((ea-sa) * 64.0);
83df96d6 499
3cd0b8c5
RR
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 }
83df96d6 550
3cd0b8c5
RR
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 }
83df96d6 556 }
3cd0b8c5 557
83df96d6
JS
558 CalcBoundingBox (x, y);
559 CalcBoundingBox (x + width, y + height);
560}
561
562void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
563{
3cd0b8c5 564 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 565
3cd0b8c5
RR
566 if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
567 XDrawPoint( (Display*) m_display, (Window) m_window,
568 (GC) m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
83df96d6 569
83df96d6
JS
570 CalcBoundingBox (x, y);
571}
572
573void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
574{
3cd0b8c5 575 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 576
3cd0b8c5
RR
577 if (m_pen.GetStyle() == wxTRANSPARENT) return;
578 if (n <= 0) return;
83df96d6 579
3cd0b8c5
RR
580 XPoint *xpoints = new XPoint[n];
581 for (int i = 0; i < n; i++)
83df96d6 582 {
3cd0b8c5
RR
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 );
83df96d6 587 }
3cd0b8c5
RR
588 XDrawLines( (Display*) m_display, (Window) m_window, (GC) m_penGC, xpoints, n, 0 );
589
590 delete[] xpoints;
83df96d6
JS
591}
592
593void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
594 wxCoord xoffset, wxCoord yoffset, int fillStyle )
595{
3cd0b8c5 596 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 597
3cd0b8c5 598 if (n <= 0) return;
83df96d6 599
3cd0b8c5 600 XPoint *xpoints = new XPoint[n + 1];
83df96d6
JS
601 int i;
602 for (i = 0; i < n; i++)
603 {
3cd0b8c5
RR
604 xpoints[i].x = XLOG2DEV (points[i].x + xoffset);
605 xpoints[i].y = YLOG2DEV (points[i].y + yoffset);
606
83df96d6
JS
607 CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
608 }
609
3cd0b8c5 610 if (m_window)
83df96d6 611 {
3cd0b8c5
RR
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 }
83df96d6 663
3cd0b8c5
RR
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 }
83df96d6
JS
672 }
673
3cd0b8c5 674 delete[] xpoints;
83df96d6
JS
675}
676
677void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
678{
3cd0b8c5 679 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 680
3cd0b8c5
RR
681 wxCoord xx = XLOG2DEV(x);
682 wxCoord yy = YLOG2DEV(y);
683 wxCoord ww = m_signX * XLOG2DEVREL(width);
684 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 685
3cd0b8c5
RR
686 // CMB: draw nothing if transformed w or h is 0
687 if (ww == 0 || hh == 0) return;
83df96d6 688
3cd0b8c5
RR
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)
83df96d6 694 {
3cd0b8c5
RR
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 }
83df96d6 745
3cd0b8c5
RR
746 if (m_pen.GetStyle () != wxTRANSPARENT)
747 {
748 XDrawRectangle( (Display*) m_display, (Window) m_window,
887dd52f 749 (GC) m_penGC, xx, yy, ww-1, hh-1 );
3cd0b8c5 750 }
83df96d6 751 }
3cd0b8c5
RR
752
753 CalcBoundingBox( x, y );
754 CalcBoundingBox( x + width, y + height );
83df96d6
JS
755}
756
757void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
758{
3cd0b8c5
RR
759 // later
760}
83df96d6 761
3cd0b8c5
RR
762void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
763{
764 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 765
3cd0b8c5
RR
766 wxCoord xx = XLOG2DEV(x);
767 wxCoord yy = YLOG2DEV(y);
768 wxCoord ww = m_signX * XLOG2DEVREL(width);
769 wxCoord hh = m_signY * YLOG2DEVREL(height);
83df96d6 770
3cd0b8c5
RR
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; }
83df96d6 774
3cd0b8c5 775 if (m_window)
83df96d6 776 {
3cd0b8c5
RR
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 }
83df96d6 827
3cd0b8c5
RR
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 }
83df96d6 833 }
83df96d6 834
3cd0b8c5
RR
835 CalcBoundingBox( x, y );
836 CalcBoundingBox( x + width, y + height );
837}
83df96d6 838
3cd0b8c5
RR
839void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y)
840{
83df96d6
JS
841}
842
3cd0b8c5
RR
843void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
844 wxCoord x, wxCoord y,
845 bool useMask )
83df96d6 846{
3cd0b8c5 847 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 848
3cd0b8c5
RR
849 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
850
3cd0b8c5 851 bool is_mono = (bitmap.GetBitmap() != NULL);
83df96d6 852
3cd0b8c5
RR
853 /* scale/translate size and position */
854 int xx = XLOG2DEV(x);
855 int yy = YLOG2DEV(y);
83df96d6 856
3cd0b8c5
RR
857 int w = bitmap.GetWidth();
858 int h = bitmap.GetHeight();
83df96d6 859
3cd0b8c5
RR
860 CalcBoundingBox( x, y );
861 CalcBoundingBox( x + w, y + h );
83df96d6 862
3cd0b8c5 863 if (!m_window) return;
83df96d6 864
3cd0b8c5
RR
865 int ww = XLOG2DEVREL(w);
866 int hh = YLOG2DEVREL(h);
83df96d6 867
3cd0b8c5
RR
868 /* compare to current clipping region */
869 if (!m_currentClippingRegion.IsNull())
83df96d6 870 {
3cd0b8c5
RR
871 wxRegion tmp( xx,yy,ww,hh );
872 tmp.Intersect( m_currentClippingRegion );
873 if (tmp.IsEmpty())
874 return;
83df96d6
JS
875 }
876
3cd0b8c5
RR
877 /* scale bitmap if required */
878 wxBitmap use_bitmap;
879 if ((w != ww) || (h != hh))
83df96d6 880 {
3cd0b8c5
RR
881 wxImage image( bitmap );
882 image.Rescale( ww, hh );
a11672a4 883#if 0
3cd0b8c5
RR
884 if (is_mono)
885 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
886 else
a11672a4 887#endif
3cd0b8c5
RR
888 use_bitmap = image.ConvertToBitmap();
889 }
890 else
891 {
892 use_bitmap = bitmap;
83df96d6 893 }
83df96d6 894
3cd0b8c5 895 /* apply mask if any */
a11672a4 896 WXPixmap mask = NULL;
3cd0b8c5 897 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
a11672a4 898 {
3cd0b8c5
RR
899 if (useMask && mask)
900 {
a11672a4
RR
901 WXPixmap new_mask = NULL;
902#if 0
3cd0b8c5
RR
903 if (!m_currentClippingRegion.IsNull())
904 {
905 GdkColor col;
906 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
907 GdkGC *gc = gdk_gc_new( new_mask );
908 col.pixel = 0;
909 gdk_gc_set_foreground( gc, &col );
910 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
911 col.pixel = 0;
912 gdk_gc_set_background( gc, &col );
913 col.pixel = 1;
914 gdk_gc_set_foreground( gc, &col );
915 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
916 gdk_gc_set_clip_origin( gc, -xx, -yy );
917 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
918 gdk_gc_set_stipple( gc, mask );
919 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
920 gdk_gc_unref( gc );
921 }
a11672a4 922#endif
3cd0b8c5
RR
923 if (is_mono)
924 {
925 if (new_mask)
a11672a4 926 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 927 else
a11672a4
RR
928 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
929 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
3cd0b8c5
RR
930 }
931 else
932 {
933 if (new_mask)
a11672a4 934 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 935 else
a11672a4
RR
936 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
937 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
3cd0b8c5 938 }
a11672a4 939
3cd0b8c5 940 if (new_mask)
a11672a4 941 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 942 }
a11672a4 943 }
83df96d6 944
3cd0b8c5
RR
945 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
946 drawing a mono-bitmap (XBitmap) we use the current text GC */
947 if (is_mono)
a11672a4
RR
948 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
949 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
3cd0b8c5 950 else
a11672a4
RR
951 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
952 (GC) m_penGC, 0, 0, w, h, xx, yy );
3cd0b8c5
RR
953
954 /* remove mask again if any */
955 if (useMask && mask)
83df96d6 956 {
3cd0b8c5 957 if (is_mono)
83df96d6 958 {
a11672a4
RR
959 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
960 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 961 if (!m_currentClippingRegion.IsNull())
a11672a4 962 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
963 }
964 else
965 {
a11672a4
RR
966 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
967 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 968 if (!m_currentClippingRegion.IsNull())
a11672a4 969 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6 970 }
83df96d6 971 }
83df96d6 972}
83df96d6 973
83df96d6
JS
974bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
975 wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop, bool useMask,
976 wxCoord xsrcMask, wxCoord ysrcMask )
977{
3cd0b8c5
RR
978 /* this is the nth try to get this utterly useless function to
979 work. it now completely ignores the scaling or translation
980 of the source dc, but scales correctly on the target dc and
981 knows about possible mask information in a memory dc. */
83df96d6 982
3cd0b8c5 983 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
83df96d6 984
3cd0b8c5 985 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
83df96d6 986
3cd0b8c5 987 if (!m_window) return FALSE;
83df96d6 988
3cd0b8c5
RR
989 // transform the source DC coords to the device ones
990 xsrc = source->XLOG2DEV(xsrc);
991 ysrc = source->YLOG2DEV(ysrc);
83df96d6 992
3cd0b8c5
RR
993 wxClientDC *srcDC = (wxClientDC*)source;
994 wxMemoryDC *memDC = (wxMemoryDC*)source;
83df96d6 995
3cd0b8c5
RR
996 bool use_bitmap_method = FALSE;
997 bool is_mono = FALSE;
83df96d6
JS
998
999 /* TODO: use the mask origin when drawing transparently */
1000 if (xsrcMask == -1 && ysrcMask == -1)
1001 {
1002 xsrcMask = xsrc; ysrcMask = ysrc;
1003 }
a11672a4 1004
3cd0b8c5
RR
1005#if 0
1006 if (srcDC->m_isMemDC)
83df96d6 1007 {
3cd0b8c5 1008 if (!memDC->m_selected.Ok()) return FALSE;
83df96d6 1009
3cd0b8c5
RR
1010 /* we use the "XCopyArea" way to copy a memory dc into
1011 y different window if the memory dc BOTH
1012 a) doesn't have any mask or its mask isn't used
1013 b) it is clipped
1014 c) is not 1-bit */
83df96d6 1015
3cd0b8c5 1016 if (useMask && (memDC->m_selected.GetMask()))
83df96d6 1017 {
3cd0b8c5
RR
1018 /* we HAVE TO use the direct way for memory dcs
1019 that have mask since the XCopyArea doesn't know
1020 about masks */
1021 use_bitmap_method = TRUE;
1022 }
1023 else if (memDC->m_selected.GetDepth() == 1)
1024 {
1025 /* we HAVE TO use the direct way for memory dcs
1026 that are bitmaps because XCopyArea doesn't cope
1027 with different bit depths */
1028 is_mono = TRUE;
1029 use_bitmap_method = TRUE;
1030 }
1031 else if ((xsrc == 0) && (ysrc == 0) &&
1032 (width == memDC->m_selected.GetWidth()) &&
1033 (height == memDC->m_selected.GetHeight()))
1034 {
1035 /* we SHOULD use the direct way if all of the bitmap
1036 in the memory dc is copied in which case XCopyArea
1037 wouldn't be able able to boost performace by reducing
1038 the area to be scaled */
1039 use_bitmap_method = TRUE;
83df96d6
JS
1040 }
1041 else
1042 {
3cd0b8c5 1043 use_bitmap_method = FALSE;
83df96d6
JS
1044 }
1045 }
83df96d6 1046
3cd0b8c5
RR
1047 CalcBoundingBox( xdest, ydest );
1048 CalcBoundingBox( xdest + width, ydest + height );
1049
1050 /* scale/translate size and position */
1051 wxCoord xx = XLOG2DEV(xdest);
1052 wxCoord yy = YLOG2DEV(ydest);
1053
1054 wxCoord ww = XLOG2DEVREL(width);
1055 wxCoord hh = YLOG2DEVREL(height);
1056
1057 /* compare to current clipping region */
1058 if (!m_currentClippingRegion.IsNull())
83df96d6 1059 {
3cd0b8c5
RR
1060 wxRegion tmp( xx,yy,ww,hh );
1061 tmp.Intersect( m_currentClippingRegion );
1062 if (tmp.IsEmpty())
1063 return TRUE;
1064 }
83df96d6 1065
3cd0b8c5
RR
1066 int old_logical_func = m_logicalFunction;
1067 SetLogicalFunction( logical_func );
83df96d6 1068
3cd0b8c5
RR
1069 if (use_bitmap_method)
1070 {
1071 /* scale/translate bitmap size */
1072 wxCoord bm_width = memDC->m_selected.GetWidth();
1073 wxCoord bm_height = memDC->m_selected.GetHeight();
83df96d6 1074
3cd0b8c5
RR
1075 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1076 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1077
3cd0b8c5
RR
1078 /* scale bitmap if required */
1079 wxBitmap use_bitmap;
83df96d6 1080
3cd0b8c5
RR
1081 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1082 {
1083 wxImage image( memDC->m_selected );
1084 image = image.Scale( bm_ww, bm_hh );
83df96d6 1085
3cd0b8c5
RR
1086 if (is_mono)
1087 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1088 else
1089 use_bitmap = image.ConvertToBitmap();
1090 }
1091 else
1092 {
1093 use_bitmap = memDC->m_selected;
1094 }
1095
1096 /* apply mask if any */
1097 GdkBitmap *mask = (GdkBitmap *) NULL;
1098 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1099
3cd0b8c5 1100 if (useMask && mask)
83df96d6 1101 {
3cd0b8c5
RR
1102 GdkBitmap *new_mask = (GdkBitmap*) NULL;
1103 if (!m_currentClippingRegion.IsNull())
83df96d6 1104 {
3cd0b8c5
RR
1105 GdkColor col;
1106 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1107 GdkGC *gc = gdk_gc_new( new_mask );
1108 col.pixel = 0;
1109 gdk_gc_set_foreground( gc, &col );
1110 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1111 col.pixel = 0;
1112 gdk_gc_set_background( gc, &col );
1113 col.pixel = 1;
1114 gdk_gc_set_foreground( gc, &col );
1115 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1116 gdk_gc_set_clip_origin( gc, -xx, -yy );
1117 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1118 gdk_gc_set_stipple( gc, mask );
1119 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1120 gdk_gc_unref( gc );
83df96d6
JS
1121 }
1122
3cd0b8c5 1123 if (is_mono)
83df96d6 1124 {
3cd0b8c5
RR
1125 if (new_mask)
1126 gdk_gc_set_clip_mask( m_textGC, new_mask );
1127 else
1128 gdk_gc_set_clip_mask( m_textGC, mask );
1129 gdk_gc_set_clip_origin( m_textGC, xx, yy );
83df96d6
JS
1130 }
1131 else
1132 {
3cd0b8c5
RR
1133 if (new_mask)
1134 gdk_gc_set_clip_mask( m_penGC, new_mask );
1135 else
1136 gdk_gc_set_clip_mask( m_penGC, mask );
1137 gdk_gc_set_clip_origin( m_penGC, xx, yy );
83df96d6 1138 }
3cd0b8c5
RR
1139 if (new_mask)
1140 gdk_bitmap_unref( new_mask );
1141 }
83df96d6 1142
3cd0b8c5
RR
1143 /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1144 drawing a mono-bitmap (XBitmap) we use the current text GC */
83df96d6 1145
3cd0b8c5
RR
1146 if (is_mono)
1147 gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
83df96d6 1148 else
3cd0b8c5 1149 gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
83df96d6 1150
3cd0b8c5
RR
1151 /* remove mask again if any */
1152 if (useMask && mask)
83df96d6 1153 {
3cd0b8c5
RR
1154 if (is_mono)
1155 {
1156 gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL );
1157 gdk_gc_set_clip_origin( m_textGC, 0, 0 );
1158 if (!m_currentClippingRegion.IsNull())
1159 gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
1160 }
1161 else
83df96d6 1162 {
3cd0b8c5
RR
1163 gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
1164 gdk_gc_set_clip_origin( m_penGC, 0, 0 );
1165 if (!m_currentClippingRegion.IsNull())
1166 gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
83df96d6
JS
1167 }
1168 }
83df96d6 1169 }
3cd0b8c5 1170 else /* use_bitmap_method */
83df96d6 1171 {
3cd0b8c5 1172 if ((width != ww) || (height != hh))
83df96d6 1173 {
3cd0b8c5
RR
1174 /* draw source window into a bitmap as we cannot scale
1175 a window in contrast to a bitmap. this would actually
1176 work with memory dcs as well, but we'd lose the mask
1177 information and waste one step in this process since
1178 a memory already has a bitmap. all this is slightly
1179 inefficient as we could take an XImage directly from
1180 an X window, but we'd then also have to care that
1181 the window is not outside the screen (in which case
1182 we'd get a BadMatch or what not).
1183 Is a double XGetImage and combined XGetPixel and
1184 XPutPixel really faster? I'm not sure. look at wxXt
1185 for a different implementation of the same problem. */
1186
1187 wxBitmap bitmap( width, height );
1188
1189 /* copy including child window contents */
1190 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1191 gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
1192 srcDC->GetWindow(),
1193 xsrc, ysrc, width, height );
1194 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1195
1196 /* scale image */
1197 wxImage image( bitmap );
1198 image = image.Scale( ww, hh );
1199
1200 /* convert to bitmap */
1201 bitmap = image.ConvertToBitmap();
1202
1203 /* draw scaled bitmap */
1204 gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
83df96d6 1205
83df96d6
JS
1206 }
1207 else
3cd0b8c5
RR
1208 {
1209 /* No scaling and not a memory dc with a mask either */
1210
1211 /* copy including child window contents */
1212 gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
1213 gdk_window_copy_area( m_window, m_penGC, xx, yy,
1214 srcDC->GetWindow(),
1215 xsrc, ysrc, width, height );
1216 gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
1217 }
83df96d6
JS
1218 }
1219
3cd0b8c5
RR
1220 SetLogicalFunction( old_logical_func );
1221 return TRUE;
1222#endif
83df96d6 1223
3cd0b8c5 1224 return FALSE;
83df96d6
JS
1225}
1226
3cd0b8c5 1227void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1228{
3cd0b8c5 1229 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1230
3cd0b8c5 1231 if (!m_window) return;
83df96d6 1232
3cd0b8c5 1233 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
83df96d6 1234
3cd0b8c5 1235 wxCHECK_RET( xfont, wxT("invalid font") );
83df96d6 1236
3cd0b8c5
RR
1237 x = XLOG2DEV(x);
1238 y = YLOG2DEV(y);
83df96d6 1239
3cd0b8c5
RR
1240#if 0
1241 wxCoord width = gdk_string_width( font, text.mbc_str() );
1242 wxCoord height = font->ascent + font->descent;
83df96d6 1243
3cd0b8c5 1244 if ( m_backgroundMode == wxSOLID )
83df96d6 1245 {
3cd0b8c5
RR
1246 gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
1247 gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
1248 gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
83df96d6 1249 }
3cd0b8c5
RR
1250#endif
1251
1252 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1253#if !wxUSE_NANOX
3cd0b8c5 1254 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1255#endif
1256 {
3cd0b8c5 1257 XDrawString( (Display*) m_display, (Window) m_window,
788519c6
JS
1258 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1259 }
83df96d6
JS
1260
1261#if 0
3cd0b8c5 1262 if (m_font.GetUnderlined())
83df96d6 1263 {
788519c6 1264 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5
RR
1265 if (font->descent > 0) ul_y++;
1266 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1267 }
83df96d6 1268
3cd0b8c5
RR
1269 width = wxCoord(width / m_scaleX);
1270 height = wxCoord(height / m_scaleY);
1271
1272 CalcBoundingBox (x + width, y + height);
83df96d6 1273 CalcBoundingBox (x, y);
3cd0b8c5 1274#endif
83df96d6
JS
1275}
1276
3cd0b8c5 1277void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
83df96d6 1278{
3cd0b8c5 1279 // later
83df96d6
JS
1280}
1281
1282void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1283 wxCoord *descent, wxCoord *externalLeading,
1284 wxFont *font ) const
1285{
1286 wxCHECK_RET( Ok(), "invalid dc" );
1287
3cd0b8c5
RR
1288 wxFont fontToUse = m_font;
1289 if (font) fontToUse = *font;
83df96d6 1290
3cd0b8c5 1291 wxCHECK_RET( fontToUse.Ok(), "invalid font" );
83df96d6 1292
3cd0b8c5 1293 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1294
3cd0b8c5
RR
1295 wxCHECK_RET( xfont, wxT("invalid font") );
1296
83df96d6
JS
1297 int direction, ascent, descent2;
1298 XCharStruct overall;
83df96d6 1299
788519c6 1300 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
83df96d6
JS
1301 &ascent, &descent2, &overall);
1302
3cd0b8c5
RR
1303 if (width)
1304 *width = (wxCoord)( overall.width / m_scaleX );
1305 if (height)
1306 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1307 if (descent)
3cd0b8c5 1308 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1309 if (externalLeading)
3cd0b8c5 1310 *externalLeading = 0; // ??
83df96d6
JS
1311}
1312
1313wxCoord wxWindowDC::GetCharWidth() const
1314{
1315 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1316
83df96d6
JS
1317 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1318
3cd0b8c5
RR
1319 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1320
1321 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1322
1323 int direction, ascent, descent;
1324 XCharStruct overall;
3cd0b8c5
RR
1325
1326 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1327
1328 return (wxCoord)(overall.width / m_scaleX);
83df96d6
JS
1329}
1330
1331wxCoord wxWindowDC::GetCharHeight() const
1332{
1333 wxCHECK_MSG( Ok(), 0, "invalid dc" );
3cd0b8c5 1334
83df96d6
JS
1335 wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1336
3cd0b8c5
RR
1337 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1338
1339 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1340
1341 int direction, ascent, descent;
1342 XCharStruct overall;
3cd0b8c5
RR
1343
1344 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1345
1346 return (wxCoord)((ascent+descent) / m_scaleY);
83df96d6
JS
1347}
1348
1349void wxWindowDC::Clear()
1350{
3cd0b8c5 1351 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1352
3cd0b8c5 1353 if (!m_window) return;
83df96d6 1354
3cd0b8c5
RR
1355 /* - we either are a memory dc or have a window as the
1356 owner. anything else shouldn't happen.
1357 - we don't use gdk_window_clear() as we don't set
1358 the window's background colour anymore. it is too
1359 much pain to keep the DC's and the window's back-
1360 ground colour in synch. */
83df96d6 1361
3cd0b8c5
RR
1362 if (m_owner)
1363 {
1364 int width,height;
1365 m_owner->GetSize( &width, &height );
1366 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1367 return;
1368 }
83df96d6 1369
3cd0b8c5
RR
1370 if (m_isMemDC)
1371 {
1372 int width,height;
1373 GetSize( &width, &height );
1374 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1375 return;
1376 }
83df96d6
JS
1377}
1378
1379void wxWindowDC::SetFont( const wxFont &font )
1380{
1381 wxCHECK_RET( Ok(), "invalid dc" );
1382
1383 m_font = font;
83df96d6
JS
1384}
1385
1386void wxWindowDC::SetPen( const wxPen &pen )
1387{
3cd0b8c5
RR
1388 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1389
1390 if (m_pen == pen) return;
83df96d6
JS
1391
1392 m_pen = pen;
83df96d6 1393
3cd0b8c5 1394 if (!m_pen.Ok()) return;
83df96d6 1395
3cd0b8c5 1396 if (!m_window) return;
83df96d6 1397
3cd0b8c5
RR
1398 int width = m_pen.GetWidth();
1399 if (width <= 0)
1400 {
1401 // CMB: if width is non-zero scale it with the dc
1402 width = 1;
1403 }
1404 else
1405 {
1406 // X doesn't allow different width in x and y and so we take
1407 // the average
1408 double w = 0.5 +
1409 ( fabs((double) XLOG2DEVREL(width)) +
1410 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1411 width = (int)w;
1412 }
1413
1414 static const wxX11Dash dotted[] = {1, 1};
1415 static const wxX11Dash short_dashed[] = {2, 2};
1416 static const wxX11Dash long_dashed[] = {2, 4};
1417 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1418
1419 // We express dash pattern in pen width unit, so we are
1420 // independent of zoom factor and so on...
1421 int req_nb_dash;
1422 const wxX11Dash *req_dash;
1423
1424 int lineStyle = LineSolid;
1425 switch (m_pen.GetStyle())
83df96d6 1426 {
83df96d6 1427 case wxUSER_DASH:
3cd0b8c5
RR
1428 {
1429 lineStyle = LineOnOffDash;
1430 req_nb_dash = m_pen.GetDashCount();
1431 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1432 break;
3cd0b8c5 1433 }
83df96d6 1434 case wxDOT:
3cd0b8c5
RR
1435 {
1436 lineStyle = LineOnOffDash;
83df96d6
JS
1437 req_nb_dash = 2;
1438 req_dash = dotted;
83df96d6 1439 break;
3cd0b8c5 1440 }
83df96d6 1441 case wxLONG_DASH:
3cd0b8c5
RR
1442 {
1443 lineStyle = LineOnOffDash;
83df96d6
JS
1444 req_nb_dash = 2;
1445 req_dash = long_dashed;
83df96d6 1446 break;
3cd0b8c5
RR
1447 }
1448 case wxSHORT_DASH:
1449 {
1450 lineStyle = LineOnOffDash;
1451 req_nb_dash = 2;
1452 req_dash = short_dashed;
1453 break;
1454 }
83df96d6 1455 case wxDOT_DASH:
3cd0b8c5
RR
1456 {
1457// lineStyle = LineDoubleDash;
1458 lineStyle = LineOnOffDash;
83df96d6
JS
1459 req_nb_dash = 4;
1460 req_dash = dotted_dashed;
83df96d6 1461 break;
3cd0b8c5
RR
1462 }
1463
1464 case wxTRANSPARENT:
1465 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1466 case wxSTIPPLE:
1467 case wxSOLID:
83df96d6 1468 default:
3cd0b8c5
RR
1469 {
1470 lineStyle = LineSolid;
74dc5eb6 1471 req_dash = (wxX11Dash*)NULL;
83df96d6 1472 req_nb_dash = 0;
3cd0b8c5 1473 break;
83df96d6 1474 }
3cd0b8c5 1475 }
83df96d6 1476
3cd0b8c5
RR
1477 int capStyle = CapRound;
1478 switch (m_pen.GetCap())
1479 {
1480 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1481 case wxCAP_BUTT: { capStyle = CapButt; break; }
1482 case wxCAP_ROUND:
1483 default:
83df96d6 1484 {
3cd0b8c5 1485 if (width <= 1)
83df96d6 1486 {
3cd0b8c5
RR
1487 width = 0;
1488 capStyle = CapNotLast;
83df96d6
JS
1489 }
1490 else
1491 {
3cd0b8c5 1492 capStyle = CapRound;
83df96d6 1493 }
83df96d6
JS
1494 break;
1495 }
3cd0b8c5 1496 }
83df96d6 1497
3cd0b8c5
RR
1498 int joinStyle = JoinRound;
1499 switch (m_pen.GetJoin())
1500 {
1501 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1502 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1503 case wxJOIN_ROUND:
3cd0b8c5 1504 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1505 }
1506
3cd0b8c5 1507 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1508
3cd0b8c5
RR
1509 m_pen.GetColour().CalcPixel( m_cmap );
1510 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1511}
83df96d6 1512
3cd0b8c5
RR
1513void wxWindowDC::SetBrush( const wxBrush &brush )
1514{
1515 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1516
3cd0b8c5 1517 if (m_brush == brush) return;
83df96d6 1518
3cd0b8c5
RR
1519 m_brush = brush;
1520
1521 if (!m_brush.Ok()) return;
83df96d6 1522
3cd0b8c5
RR
1523 if (!m_window) return;
1524
1525 m_brush.GetColour().CalcPixel( m_cmap );
1526 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1527
1528 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1529
1530 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1531 {
3cd0b8c5 1532 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1533 {
3cd0b8c5
RR
1534 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1535 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1536 }
1537 else
1538 {
3cd0b8c5 1539 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1540 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1541 }
3cd0b8c5 1542 }
83df96d6 1543
3cd0b8c5
RR
1544 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1545 {
1546 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1547 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1548 }
83df96d6 1549
3cd0b8c5
RR
1550 if (IS_HATCH(m_brush.GetStyle()))
1551 {
1552 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1553 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1554 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1555 }
83df96d6
JS
1556}
1557
3cd0b8c5 1558void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1559{
3cd0b8c5
RR
1560 /* CMB 21/7/98: Added SetBackground. Sets background brush
1561 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1562
3cd0b8c5 1563 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1564
3cd0b8c5 1565 if (m_backgroundBrush == brush) return;
83df96d6 1566
3cd0b8c5 1567 m_backgroundBrush = brush;
83df96d6 1568
3cd0b8c5 1569 if (!m_backgroundBrush.Ok()) return;
83df96d6 1570
3cd0b8c5 1571 if (!m_window) return;
83df96d6 1572
3cd0b8c5
RR
1573 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1574 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1575 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1576 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1577 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1578
3cd0b8c5 1579 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1580
3cd0b8c5 1581 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1582 {
3cd0b8c5 1583 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1584 {
3cd0b8c5
RR
1585 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1586 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1587 }
3cd0b8c5 1588 else
83df96d6 1589 {
3cd0b8c5 1590 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1591 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1592 }
83df96d6
JS
1593 }
1594
3cd0b8c5 1595 if (IS_HATCH(m_backgroundBrush.GetStyle()))
83df96d6 1596 {
3cd0b8c5
RR
1597 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1598 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1599 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1600 }
83df96d6
JS
1601}
1602
1603void wxWindowDC::SetLogicalFunction( int function )
1604{
1605 wxCHECK_RET( Ok(), "invalid dc" );
1606
1607 int x_function;
1608
83df96d6
JS
1609 if (m_logicalFunction == function)
1610 return;
1611
3cd0b8c5
RR
1612 // VZ: shouldn't this be a CHECK?
1613 if (!m_window)
1614 return;
1615
83df96d6
JS
1616 switch (function)
1617 {
1618 case wxCLEAR:
1619 x_function = GXclear;
1620 break;
1621 case wxXOR:
1622 x_function = GXxor;
1623 break;
1624 case wxINVERT:
1625 x_function = GXinvert;
1626 break;
1627 case wxOR_REVERSE:
1628 x_function = GXorReverse;
1629 break;
1630 case wxAND_REVERSE:
1631 x_function = GXandReverse;
1632 break;
1633 case wxAND:
1634 x_function = GXand;
1635 break;
1636 case wxOR:
1637 x_function = GXor;
1638 break;
1639 case wxAND_INVERT:
1640 x_function = GXandInverted;
1641 break;
1642 case wxNO_OP:
1643 x_function = GXnoop;
1644 break;
1645 case wxNOR:
1646 x_function = GXnor;
1647 break;
1648 case wxEQUIV:
1649 x_function = GXequiv;
1650 break;
1651 case wxSRC_INVERT:
1652 x_function = GXcopyInverted;
1653 break;
1654 case wxOR_INVERT:
1655 x_function = GXorInverted;
1656 break;
1657 case wxNAND:
1658 x_function = GXnand;
1659 break;
1660 case wxSET:
1661 x_function = GXset;
1662 break;
1663 case wxCOPY:
1664 default:
1665 x_function = GXcopy;
1666 break;
1667 }
1668
3cd0b8c5
RR
1669 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
1670 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 1671
3cd0b8c5
RR
1672 // to stay compatible with wxMSW, we don't apply ROPs to the text
1673 // operations (i.e. DrawText/DrawRotatedText).
1674 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
1675 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
1676
83df96d6 1677 m_logicalFunction = function;
83df96d6
JS
1678}
1679
1680void wxWindowDC::SetTextForeground( const wxColour &col )
1681{
3cd0b8c5 1682 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1683
3cd0b8c5
RR
1684 // don't set m_textForegroundColour to an invalid colour as we'd crash
1685 // later then (we use m_textForegroundColour.GetColor() without checking
1686 // in a few places)
1687 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
1688 return;
1689
1690 m_textForegroundColour = col;
1691
3cd0b8c5
RR
1692 if (m_window)
1693 {
1694 m_textForegroundColour.CalcPixel( m_cmap );
1695 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
1696 }
83df96d6
JS
1697}
1698
1699void wxWindowDC::SetTextBackground( const wxColour &col )
1700{
3cd0b8c5 1701 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1702
3cd0b8c5
RR
1703 // same as above
1704 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
1705 return;
1706
1707 m_textBackgroundColour = col;
3cd0b8c5
RR
1708
1709 if (m_window)
1710 {
1711 m_textBackgroundColour.CalcPixel( m_cmap );
1712 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
1713 }
83df96d6
JS
1714}
1715
1716void wxWindowDC::SetBackgroundMode( int mode )
1717{
3cd0b8c5
RR
1718 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1719
83df96d6 1720 m_backgroundMode = mode;
3cd0b8c5 1721
0b5c0e1a
JS
1722#if wxUSE_NANOX
1723 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
1724#endif
1725
3cd0b8c5
RR
1726 if (!m_window) return;
1727
1728 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
1729 // transparent/solid background mode
1730
1731 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
1732 {
1733 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
1734 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
1735 }
83df96d6
JS
1736}
1737
1738void wxWindowDC::SetPalette( const wxPalette& palette )
1739{
3cd0b8c5 1740#if 0
83df96d6
JS
1741 if (m_window)
1742 {
1743 if (palette.Ok())
1744 /* Use GetXColormap */
1745 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1746 (Colormap) palette.GetXColormap());
1747 else
1748 /* Use wxGetMainColormap */
1749 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1750 (Colormap) wxTheApp->GetMainColormap(m_display));
1751 }
3cd0b8c5 1752#endif
83df96d6
JS
1753}
1754
3cd0b8c5 1755void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 1756{
3cd0b8c5 1757 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1758
3cd0b8c5 1759 if (!m_window) return;
83df96d6 1760
3cd0b8c5
RR
1761 wxRect rect;
1762 rect.x = XLOG2DEV(x);
1763 rect.y = YLOG2DEV(y);
1764 rect.width = XLOG2DEVREL(width);
1765 rect.height = YLOG2DEVREL(height);
1766
1767 if (!m_currentClippingRegion.IsNull())
1768 m_currentClippingRegion.Intersect( rect );
83df96d6 1769 else
3cd0b8c5
RR
1770 m_currentClippingRegion.Union( rect );
1771
1772#if USE_PAINT_REGION
1773 if (!m_paintClippingRegion.IsNull())
1774 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1775#endif
1776
1777 wxCoord xx, yy, ww, hh;
1778 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1779 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1780
1781 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1782 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1783 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1784 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1785}
83df96d6 1786
3cd0b8c5
RR
1787void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
1788{
1789 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1790
3cd0b8c5 1791 if (region.Empty())
83df96d6 1792 {
3cd0b8c5
RR
1793 DestroyClippingRegion();
1794 return;
83df96d6 1795 }
3cd0b8c5
RR
1796
1797 if (!m_window) return;
1798
1799 if (!m_currentClippingRegion.IsNull())
1800 m_currentClippingRegion.Intersect( region );
83df96d6 1801 else
3cd0b8c5 1802 m_currentClippingRegion.Union( region );
83df96d6 1803
3cd0b8c5
RR
1804#if USE_PAINT_REGION
1805 if (!m_paintClippingRegion.IsNull())
1806 m_currentClippingRegion.Intersect( m_paintClippingRegion );
1807#endif
83df96d6 1808
3cd0b8c5
RR
1809 wxCoord xx, yy, ww, hh;
1810 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
1811 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
1812
1813 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1814 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1815 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1816 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1817}
1818
3cd0b8c5 1819void wxWindowDC::DestroyClippingRegion()
83df96d6 1820{
3cd0b8c5 1821 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1822
3cd0b8c5 1823 wxDC::DestroyClippingRegion();
83df96d6 1824
3cd0b8c5 1825 m_currentClippingRegion.Clear();
83df96d6 1826
3cd0b8c5
RR
1827#if USE_PAINT_REGION
1828 if (!m_paintClippingRegion.IsEmpty())
1829 m_currentClippingRegion.Union( m_paintClippingRegion );
1830#endif
83df96d6 1831
3cd0b8c5 1832 if (!m_window) return;
83df96d6 1833
3cd0b8c5
RR
1834 if (m_currentClippingRegion.IsEmpty())
1835 {
1836 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1837 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
1838 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1839 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
1840 }
1841 else
1842 {
1843 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
1844 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
1845 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
1846 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
1847 }
1848}
83df96d6 1849
3cd0b8c5 1850void wxWindowDC::Destroy()
83df96d6 1851{
3cd0b8c5
RR
1852 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
1853 m_penGC = NULL;
1854 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
1855 m_brushGC = NULL;
1856 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
1857 m_textGC = NULL;
1858 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
1859 m_bgGC = NULL;
1860}
83df96d6 1861
3cd0b8c5
RR
1862void wxWindowDC::ComputeScaleAndOrigin()
1863{
1864 /* CMB: copy scale to see if it changes */
1865 double origScaleX = m_scaleX;
1866 double origScaleY = m_scaleY;
83df96d6 1867
3cd0b8c5 1868 wxDC::ComputeScaleAndOrigin();
83df96d6 1869
3cd0b8c5
RR
1870 /* CMB: if scale has changed call SetPen to recalulate the line width */
1871 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
1872 (m_pen.Ok()))
1873 {
1874 /* this is a bit artificial, but we need to force wxDC to think
1875 the pen has changed */
1876 wxPen pen = m_pen;
1877 m_pen = wxNullPen;
1878 SetPen( pen );
1879 }
83df96d6
JS
1880}
1881
83df96d6
JS
1882wxSize wxWindowDC::GetPPI() const
1883{
1884 return wxSize(100, 100);
1885}
1886
1887int wxWindowDC::GetDepth() const
1888{
3cd0b8c5 1889 wxFAIL_MSG(wxT("not implemented"));
83df96d6 1890
3cd0b8c5
RR
1891 return -1;
1892}
83df96d6
JS
1893
1894// ----------------------------------------------------------------------------
1895// wxPaintDC
1896// ----------------------------------------------------------------------------
1897
3cd0b8c5
RR
1898IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
1899
1934d291 1900wxPaintDC::wxPaintDC(wxWindow* win)
3cd0b8c5
RR
1901 : wxClientDC(win)
1902{
1903#if USE_PAINT_REGION
1904 if (!win->GetClipPaintRegion())
1905 return;
1906
1907 m_paintClippingRegion = win->GetUpdateRegion();
1908 Region region = (Region) m_paintClippingRegion.GetX11Region();
1909 if (region)
1910 {
1911 m_paintClippingRegion = win->GetUpdateRegion();
1912 Region region2 = (Region) m_paintClippingRegion.GetX11Region();
1913 if (region2)
1914 {
1915 m_currentClippingRegion.Union( m_paintClippingRegion );
1916
1917 XSetRegion( (Display*) m_display, (GC) m_penGC, region2 );
1918 XSetRegion( (Display*) m_display, (GC) m_brushGC, region2 );
1919 XSetRegion( (Display*) m_display, (GC) m_textGC, region2 );
1920 XSetRegion( (Display*) m_display, (GC) m_bgGC, region2 );
1921 }
1922 }
1923#endif // USE_PAINT_REGION
1924}
1925
1926//-----------------------------------------------------------------------------
1927// wxClientDC
1928//-----------------------------------------------------------------------------
1929
1930IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
1931
1932wxClientDC::wxClientDC( wxWindow *win )
1933 : wxWindowDC( win )
83df96d6 1934{
3cd0b8c5 1935 wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
a11672a4
RR
1936
1937#ifdef __WXUNIVERSAL__
1938 wxPoint ptOrigin = win->GetClientAreaOrigin();
1939 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
1940 wxSize size = win->GetClientSize();
1941 SetClippingRegion(wxPoint(0, 0), size);
1942#endif // __WXUNIVERSAL__
83df96d6
JS
1943}
1944
3cd0b8c5 1945void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 1946{
3cd0b8c5
RR
1947 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
1948
1949 m_owner->GetClientSize( width, height );
83df96d6
JS
1950}
1951
1952// ----------------------------------------------------------------------------
3cd0b8c5 1953// wxDCModule
83df96d6
JS
1954// ----------------------------------------------------------------------------
1955
3cd0b8c5 1956class wxDCModule : public wxModule
83df96d6 1957{
3cd0b8c5
RR
1958public:
1959 bool OnInit();
1960 void OnExit();
83df96d6 1961
3cd0b8c5
RR
1962private:
1963 DECLARE_DYNAMIC_CLASS(wxDCModule)
1964};
83df96d6 1965
3cd0b8c5 1966IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 1967
3cd0b8c5
RR
1968bool wxDCModule::OnInit()
1969{
1970 wxInitGCPool();
1971 return TRUE;
83df96d6
JS
1972}
1973
3cd0b8c5 1974void wxDCModule::OnExit()
83df96d6 1975{
3cd0b8c5 1976 wxCleanUpGCPool();
83df96d6 1977}