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