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