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