]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
cursor setting corrected
[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
e66faf3d
RR
1673 if (m_fontdesc)
1674 pango_layout_set_font_description(layout, m_fontdesc);
1675 else
1676 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1677
2b5f62a0
VZ
1678 pango_layout_set_text(layout, "H", 1 );
1679 int w,h;
1680 pango_layout_get_pixel_size(layout, &w, &h);
1681 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1682
2b5f62a0
VZ
1683 return w;
1684#else
54385bdb 1685 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
83df96d6 1686
3cd0b8c5
RR
1687 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1688
1689 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1690
1691 int direction, ascent, descent;
1692 XCharStruct overall;
ab9d0a8c 1693
3cd0b8c5 1694 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1695
3cd0b8c5 1696 return (wxCoord)(overall.width / m_scaleX);
2b5f62a0 1697#endif
83df96d6
JS
1698}
1699
1700wxCoord wxWindowDC::GetCharHeight() const
1701{
54385bdb 1702 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
ab9d0a8c 1703
2b5f62a0
VZ
1704#if wxUSE_UNICODE
1705 PangoLayout *layout = pango_layout_new( m_context );
ab9d0a8c 1706
e66faf3d
RR
1707 if (m_fontdesc)
1708 pango_layout_set_font_description(layout, m_fontdesc);
1709 else
1710 pango_layout_set_font_description(layout, this->GetFont().GetNativeFontInfo()->description);
1711
2b5f62a0
VZ
1712 pango_layout_set_text(layout, "H", 1 );
1713 int w,h;
1714 pango_layout_get_pixel_size(layout, &w, &h);
1715 g_object_unref( G_OBJECT( layout ) );
ab9d0a8c 1716
2b5f62a0
VZ
1717 return h;
1718#else
54385bdb 1719 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
83df96d6 1720
3cd0b8c5
RR
1721 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1722
1723 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1724
1725 int direction, ascent, descent;
1726 XCharStruct overall;
ab9d0a8c 1727
3cd0b8c5 1728 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
ab9d0a8c 1729
3cd0b8c5 1730 return (wxCoord)((ascent+descent) / m_scaleY);
2b5f62a0 1731#endif
83df96d6
JS
1732}
1733
1734void wxWindowDC::Clear()
1735{
3cd0b8c5 1736 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1737
3cd0b8c5 1738 if (!m_window) return;
83df96d6 1739
3cd0b8c5
RR
1740 /* - we either are a memory dc or have a window as the
1741 owner. anything else shouldn't happen.
1742 - we don't use gdk_window_clear() as we don't set
1743 the window's background colour anymore. it is too
1744 much pain to keep the DC's and the window's back-
1745 ground colour in synch. */
83df96d6 1746
3cd0b8c5
RR
1747 if (m_owner)
1748 {
1749 int width,height;
1750 m_owner->GetSize( &width, &height );
1751 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1752 return;
1753 }
83df96d6 1754
3cd0b8c5
RR
1755 if (m_isMemDC)
1756 {
1757 int width,height;
1758 GetSize( &width, &height );
1759 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1760 return;
1761 }
83df96d6
JS
1762}
1763
1764void wxWindowDC::SetFont( const wxFont &font )
1765{
54385bdb 1766 wxCHECK_RET( Ok(), wxT("invalid dc") );
83df96d6
JS
1767
1768 m_font = font;
1175aa4e 1769
e66faf3d
RR
1770 return;
1771
1175aa4e 1772#if wxUSE_UNICODE
e66faf3d 1773 m_fontdesc = font.GetNativeFontInfo()->description;
1175aa4e 1774#endif
83df96d6
JS
1775}
1776
1777void wxWindowDC::SetPen( const wxPen &pen )
1778{
3cd0b8c5
RR
1779 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1780
1781 if (m_pen == pen) return;
83df96d6
JS
1782
1783 m_pen = pen;
83df96d6 1784
3cd0b8c5 1785 if (!m_pen.Ok()) return;
83df96d6 1786
3cd0b8c5 1787 if (!m_window) return;
83df96d6 1788
3cd0b8c5
RR
1789 int width = m_pen.GetWidth();
1790 if (width <= 0)
1791 {
1792 // CMB: if width is non-zero scale it with the dc
1793 width = 1;
1794 }
1795 else
1796 {
1797 // X doesn't allow different width in x and y and so we take
1798 // the average
1799 double w = 0.5 +
1800 ( fabs((double) XLOG2DEVREL(width)) +
1801 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1802 width = (int)w;
1803 }
1804
1805 static const wxX11Dash dotted[] = {1, 1};
1806 static const wxX11Dash short_dashed[] = {2, 2};
1807 static const wxX11Dash long_dashed[] = {2, 4};
1808 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1809
1810 // We express dash pattern in pen width unit, so we are
1811 // independent of zoom factor and so on...
1812 int req_nb_dash;
1813 const wxX11Dash *req_dash;
1814
1815 int lineStyle = LineSolid;
1816 switch (m_pen.GetStyle())
83df96d6 1817 {
83df96d6 1818 case wxUSER_DASH:
3cd0b8c5
RR
1819 {
1820 lineStyle = LineOnOffDash;
1821 req_nb_dash = m_pen.GetDashCount();
1822 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1823 break;
3cd0b8c5 1824 }
83df96d6 1825 case wxDOT:
3cd0b8c5
RR
1826 {
1827 lineStyle = LineOnOffDash;
83df96d6
JS
1828 req_nb_dash = 2;
1829 req_dash = dotted;
83df96d6 1830 break;
3cd0b8c5 1831 }
83df96d6 1832 case wxLONG_DASH:
3cd0b8c5
RR
1833 {
1834 lineStyle = LineOnOffDash;
83df96d6
JS
1835 req_nb_dash = 2;
1836 req_dash = long_dashed;
83df96d6 1837 break;
3cd0b8c5
RR
1838 }
1839 case wxSHORT_DASH:
1840 {
1841 lineStyle = LineOnOffDash;
1842 req_nb_dash = 2;
1843 req_dash = short_dashed;
1844 break;
1845 }
83df96d6 1846 case wxDOT_DASH:
3cd0b8c5
RR
1847 {
1848// lineStyle = LineDoubleDash;
1849 lineStyle = LineOnOffDash;
83df96d6
JS
1850 req_nb_dash = 4;
1851 req_dash = dotted_dashed;
83df96d6 1852 break;
3cd0b8c5
RR
1853 }
1854
1855 case wxTRANSPARENT:
1856 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1857 case wxSTIPPLE:
1858 case wxSOLID:
83df96d6 1859 default:
3cd0b8c5
RR
1860 {
1861 lineStyle = LineSolid;
74dc5eb6 1862 req_dash = (wxX11Dash*)NULL;
83df96d6 1863 req_nb_dash = 0;
3cd0b8c5 1864 break;
83df96d6 1865 }
3cd0b8c5 1866 }
83df96d6 1867
3cd0b8c5
RR
1868 int capStyle = CapRound;
1869 switch (m_pen.GetCap())
1870 {
1871 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1872 case wxCAP_BUTT: { capStyle = CapButt; break; }
1873 case wxCAP_ROUND:
1874 default:
83df96d6 1875 {
3cd0b8c5 1876 if (width <= 1)
83df96d6 1877 {
3cd0b8c5
RR
1878 width = 0;
1879 capStyle = CapNotLast;
83df96d6
JS
1880 }
1881 else
1882 {
3cd0b8c5 1883 capStyle = CapRound;
83df96d6 1884 }
83df96d6
JS
1885 break;
1886 }
3cd0b8c5 1887 }
83df96d6 1888
3cd0b8c5
RR
1889 int joinStyle = JoinRound;
1890 switch (m_pen.GetJoin())
1891 {
1892 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1893 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1894 case wxJOIN_ROUND:
3cd0b8c5 1895 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1896 }
1897
3cd0b8c5 1898 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1899
3cd0b8c5
RR
1900 m_pen.GetColour().CalcPixel( m_cmap );
1901 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1902}
83df96d6 1903
3cd0b8c5
RR
1904void wxWindowDC::SetBrush( const wxBrush &brush )
1905{
1906 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1907
3cd0b8c5 1908 if (m_brush == brush) return;
83df96d6 1909
3cd0b8c5
RR
1910 m_brush = brush;
1911
1912 if (!m_brush.Ok()) return;
83df96d6 1913
3cd0b8c5
RR
1914 if (!m_window) return;
1915
1916 m_brush.GetColour().CalcPixel( m_cmap );
1917 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
ab9d0a8c 1918
3cd0b8c5
RR
1919 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1920
1921 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1922 {
3cd0b8c5 1923 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1924 {
3cd0b8c5
RR
1925 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1926 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1927 }
1928 else
1929 {
3cd0b8c5 1930 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1931 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1932 }
3cd0b8c5 1933 }
83df96d6 1934
3cd0b8c5
RR
1935 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1936 {
1937 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1938 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1939 }
83df96d6 1940
ab9d0a8c 1941 if (m_brush.IsHatch())
3cd0b8c5
RR
1942 {
1943 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1944 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1945 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1946 }
83df96d6
JS
1947}
1948
3cd0b8c5 1949void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1950{
3cd0b8c5
RR
1951 /* CMB 21/7/98: Added SetBackground. Sets background brush
1952 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1953
3cd0b8c5 1954 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1955
3cd0b8c5 1956 if (m_backgroundBrush == brush) return;
83df96d6 1957
3cd0b8c5 1958 m_backgroundBrush = brush;
83df96d6 1959
3cd0b8c5 1960 if (!m_backgroundBrush.Ok()) return;
83df96d6 1961
3cd0b8c5 1962 if (!m_window) return;
83df96d6 1963
3cd0b8c5
RR
1964 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1965 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1966 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1967 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1968 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1969
3cd0b8c5 1970 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1971
3cd0b8c5 1972 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1973 {
3cd0b8c5 1974 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1975 {
3cd0b8c5
RR
1976 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1977 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1978 }
3cd0b8c5 1979 else
83df96d6 1980 {
3cd0b8c5 1981 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1982 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1983 }
83df96d6
JS
1984 }
1985
ab9d0a8c 1986 if (m_backgroundBrush.IsHatch())
83df96d6 1987 {
3cd0b8c5
RR
1988 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1989 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1990 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1991 }
83df96d6
JS
1992}
1993
1994void wxWindowDC::SetLogicalFunction( int function )
1995{
54385bdb 1996 wxCHECK_RET( Ok(), wxT("invalid dc") );
83df96d6
JS
1997
1998 int x_function;
1999
83df96d6
JS
2000 if (m_logicalFunction == function)
2001 return;
2002
3cd0b8c5
RR
2003 // VZ: shouldn't this be a CHECK?
2004 if (!m_window)
2005 return;
ab9d0a8c 2006
83df96d6
JS
2007 switch (function)
2008 {
2009 case wxCLEAR:
2010 x_function = GXclear;
2011 break;
2012 case wxXOR:
2013 x_function = GXxor;
2014 break;
2015 case wxINVERT:
2016 x_function = GXinvert;
2017 break;
2018 case wxOR_REVERSE:
2019 x_function = GXorReverse;
2020 break;
2021 case wxAND_REVERSE:
2022 x_function = GXandReverse;
2023 break;
2024 case wxAND:
2025 x_function = GXand;
2026 break;
2027 case wxOR:
2028 x_function = GXor;
2029 break;
2030 case wxAND_INVERT:
2031 x_function = GXandInverted;
2032 break;
2033 case wxNO_OP:
2034 x_function = GXnoop;
2035 break;
2036 case wxNOR:
2037 x_function = GXnor;
2038 break;
2039 case wxEQUIV:
2040 x_function = GXequiv;
2041 break;
2042 case wxSRC_INVERT:
2043 x_function = GXcopyInverted;
2044 break;
2045 case wxOR_INVERT:
2046 x_function = GXorInverted;
2047 break;
2048 case wxNAND:
2049 x_function = GXnand;
2050 break;
2051 case wxSET:
2052 x_function = GXset;
2053 break;
2054 case wxCOPY:
2055 default:
2056 x_function = GXcopy;
2057 break;
2058 }
2059
3cd0b8c5
RR
2060 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2061 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 2062
3cd0b8c5
RR
2063 // to stay compatible with wxMSW, we don't apply ROPs to the text
2064 // operations (i.e. DrawText/DrawRotatedText).
2065 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2066 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
ab9d0a8c 2067
83df96d6 2068 m_logicalFunction = function;
83df96d6
JS
2069}
2070
2071void wxWindowDC::SetTextForeground( const wxColour &col )
2072{
3cd0b8c5 2073 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2074
3cd0b8c5
RR
2075 // don't set m_textForegroundColour to an invalid colour as we'd crash
2076 // later then (we use m_textForegroundColour.GetColor() without checking
2077 // in a few places)
2078 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
2079 return;
2080
2081 m_textForegroundColour = col;
2082
3cd0b8c5
RR
2083 if (m_window)
2084 {
2085 m_textForegroundColour.CalcPixel( m_cmap );
2086 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2087 }
83df96d6
JS
2088}
2089
2090void wxWindowDC::SetTextBackground( const wxColour &col )
2091{
3cd0b8c5 2092 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2093
3cd0b8c5
RR
2094 // same as above
2095 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
2096 return;
2097
2098 m_textBackgroundColour = col;
3cd0b8c5
RR
2099
2100 if (m_window)
2101 {
2102 m_textBackgroundColour.CalcPixel( m_cmap );
2103 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2104 }
83df96d6
JS
2105}
2106
2107void wxWindowDC::SetBackgroundMode( int mode )
2108{
3cd0b8c5
RR
2109 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2110
83df96d6 2111 m_backgroundMode = mode;
3cd0b8c5 2112
0b5c0e1a
JS
2113#if wxUSE_NANOX
2114 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2115#endif
2116
3cd0b8c5
RR
2117 if (!m_window) return;
2118
2119 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2120 // transparent/solid background mode
2121
2122 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2123 {
2124 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2125 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2126 }
83df96d6
JS
2127}
2128
2129void wxWindowDC::SetPalette( const wxPalette& palette )
2130{
3cd0b8c5 2131#if 0
83df96d6
JS
2132 if (m_window)
2133 {
2134 if (palette.Ok())
2135 /* Use GetXColormap */
2136 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2137 (Colormap) palette.GetXColormap());
2138 else
2139 /* Use wxGetMainColormap */
2140 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2141 (Colormap) wxTheApp->GetMainColormap(m_display));
2142 }
3cd0b8c5 2143#endif
83df96d6
JS
2144}
2145
3cd0b8c5 2146void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 2147{
3cd0b8c5 2148 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2149
3cd0b8c5 2150 if (!m_window) return;
83df96d6 2151
3cd0b8c5
RR
2152 wxRect rect;
2153 rect.x = XLOG2DEV(x);
2154 rect.y = YLOG2DEV(y);
2155 rect.width = XLOG2DEVREL(width);
2156 rect.height = YLOG2DEVREL(height);
2157
2158 if (!m_currentClippingRegion.IsNull())
2159 m_currentClippingRegion.Intersect( rect );
83df96d6 2160 else
3cd0b8c5
RR
2161 m_currentClippingRegion.Union( rect );
2162
2163#if USE_PAINT_REGION
2164 if (!m_paintClippingRegion.IsNull())
2165 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2166#endif
2167
2168 wxCoord xx, yy, ww, hh;
2169 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2170 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2171
2172 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2173 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2174 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2175 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2176}
83df96d6 2177
3cd0b8c5
RR
2178void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2179{
2180 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2181
3cd0b8c5 2182 if (region.Empty())
83df96d6 2183 {
3cd0b8c5
RR
2184 DestroyClippingRegion();
2185 return;
83df96d6 2186 }
3cd0b8c5
RR
2187
2188 if (!m_window) return;
2189
2190 if (!m_currentClippingRegion.IsNull())
2191 m_currentClippingRegion.Intersect( region );
83df96d6 2192 else
3cd0b8c5 2193 m_currentClippingRegion.Union( region );
83df96d6 2194
3cd0b8c5
RR
2195#if USE_PAINT_REGION
2196 if (!m_paintClippingRegion.IsNull())
2197 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2198#endif
83df96d6 2199
3cd0b8c5
RR
2200 wxCoord xx, yy, ww, hh;
2201 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2202 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2203
2204 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2205 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2206 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2207 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
2208}
2209
3cd0b8c5 2210void wxWindowDC::DestroyClippingRegion()
83df96d6 2211{
3cd0b8c5 2212 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2213
3cd0b8c5 2214 wxDC::DestroyClippingRegion();
83df96d6 2215
3cd0b8c5 2216 m_currentClippingRegion.Clear();
83df96d6 2217
3cd0b8c5
RR
2218#if USE_PAINT_REGION
2219 if (!m_paintClippingRegion.IsEmpty())
2220 m_currentClippingRegion.Union( m_paintClippingRegion );
2221#endif
83df96d6 2222
3cd0b8c5 2223 if (!m_window) return;
83df96d6 2224
3cd0b8c5
RR
2225 if (m_currentClippingRegion.IsEmpty())
2226 {
2227 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2228 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2229 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2230 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2231 }
2232 else
2233 {
2234 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2235 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2236 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2237 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2238 }
2239}
83df96d6 2240
3cd0b8c5 2241void wxWindowDC::Destroy()
83df96d6 2242{
3cd0b8c5
RR
2243 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2244 m_penGC = NULL;
2245 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2246 m_brushGC = NULL;
2247 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2248 m_textGC = NULL;
2249 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2250 m_bgGC = NULL;
2251}
83df96d6 2252
3cd0b8c5
RR
2253void wxWindowDC::ComputeScaleAndOrigin()
2254{
2255 /* CMB: copy scale to see if it changes */
2256 double origScaleX = m_scaleX;
2257 double origScaleY = m_scaleY;
83df96d6 2258
3cd0b8c5 2259 wxDC::ComputeScaleAndOrigin();
83df96d6 2260
3cd0b8c5
RR
2261 /* CMB: if scale has changed call SetPen to recalulate the line width */
2262 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2263 (m_pen.Ok()))
2264 {
2265 /* this is a bit artificial, but we need to force wxDC to think
2266 the pen has changed */
2267 wxPen pen = m_pen;
2268 m_pen = wxNullPen;
2269 SetPen( pen );
2270 }
83df96d6
JS
2271}
2272
83df96d6
JS
2273wxSize wxWindowDC::GetPPI() const
2274{
2275 return wxSize(100, 100);
2276}
2277
2278int wxWindowDC::GetDepth() const
2279{
3cd0b8c5 2280 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2281
3cd0b8c5
RR
2282 return -1;
2283}
83df96d6 2284
3cd0b8c5
RR
2285//-----------------------------------------------------------------------------
2286// wxClientDC
2287//-----------------------------------------------------------------------------
2288
2289IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2290
ab6b6b15
RR
2291wxClientDC::wxClientDC( wxWindow *window )
2292 : wxWindowDC( window )
83df96d6 2293{
ab6b6b15 2294 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
ab9d0a8c 2295
f41bc3e3 2296 m_window = (WXWindow*) window->GetClientAreaWindow();
ab9d0a8c 2297
2b5f62a0 2298 // Adjust the client area when the wxWindow is not using 2 X11 windows.
7948c0c2
JS
2299 if (m_window == (WXWindow*) window->GetMainWindow())
2300 {
c2c0dabf
RR
2301 wxPoint ptOrigin = window->GetClientAreaOrigin();
2302 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2303 wxSize size = window->GetClientSize();
2304 SetClippingRegion(wxPoint(0, 0), size);
7948c0c2 2305 }
83df96d6
JS
2306}
2307
3cd0b8c5 2308void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 2309{
3cd0b8c5
RR
2310 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2311
2312 m_owner->GetClientSize( width, height );
83df96d6
JS
2313}
2314
ab6b6b15
RR
2315// ----------------------------------------------------------------------------
2316// wxPaintDC
2317// ----------------------------------------------------------------------------
2318
2319IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2320
2321wxPaintDC::wxPaintDC(wxWindow* window)
2322 : wxClientDC(window)
2323{
2324#if USE_PAINT_REGION
2325 if (!window->GetClipPaintRegion())
2326 return;
2327
2328 m_paintClippingRegion = window->GetUpdateRegion();
2329 Region region = (Region) m_paintClippingRegion.GetX11Region();
2330 if (region)
2331 {
2332 m_currentClippingRegion.Union( m_paintClippingRegion );
2333
2334 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2335 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2336 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2337 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2338 }
2339#endif // USE_PAINT_REGION
2340}
2341
83df96d6 2342// ----------------------------------------------------------------------------
3cd0b8c5 2343// wxDCModule
83df96d6
JS
2344// ----------------------------------------------------------------------------
2345
3cd0b8c5 2346class wxDCModule : public wxModule
83df96d6 2347{
3cd0b8c5
RR
2348public:
2349 bool OnInit();
2350 void OnExit();
83df96d6 2351
3cd0b8c5
RR
2352private:
2353 DECLARE_DYNAMIC_CLASS(wxDCModule)
2354};
83df96d6 2355
3cd0b8c5 2356IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2357
3cd0b8c5
RR
2358bool wxDCModule::OnInit()
2359{
2360 wxInitGCPool();
ab9d0a8c 2361 return true;
83df96d6
JS
2362}
2363
3cd0b8c5 2364void wxDCModule::OnExit()
83df96d6 2365{
3cd0b8c5 2366 wxCleanUpGCPool();
83df96d6 2367}