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