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