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