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