]> git.saurik.com Git - wxWidgets.git/blame - src/x11/dcclient.cpp
don't define DestroyClippingRegion() any more but simply use the base class version
[wxWidgets.git] / src / x11 / dcclient.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
3cd0b8c5 2// Name: x11/dcclient.cpp
83df96d6 3// Purpose: wxClientDC class
3cd0b8c5 4// Author: Julian Smart, Robert Roebling
83df96d6
JS
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
3cd0b8c5 8// Copyright: (c) Julian Smart, Robert Roebling
83df96d6
JS
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
83df96d6
JS
13 #pragma implementation "dcclient.h"
14#endif
15
16#include "wx/dcclient.h"
17#include "wx/dcmemory.h"
18#include "wx/window.h"
19#include "wx/app.h"
20#include "wx/image.h"
7b35aa40 21#include "wx/module.h"
2b5f62a0 22#include "wx/fontutil.h"
83df96d6 23
3cd0b8c5
RR
24#include "wx/x11/private.h"
25
83df96d6
JS
26#include <math.h>
27
2b5f62a0
VZ
28#if wxUSE_UNICODE
29#include "glib.h"
30#include "pango/pangox.h"
31#include "pango/pangoxft.h"
32
33#include "pango_x.cpp"
34#endif
35
3cd0b8c5
RR
36//-----------------------------------------------------------------------------
37// local defines
38//-----------------------------------------------------------------------------
83df96d6 39
3cd0b8c5 40#define USE_PAINT_REGION 1
83df96d6 41
3cd0b8c5
RR
42//-----------------------------------------------------------------------------
43// local data
44//-----------------------------------------------------------------------------
83df96d6
JS
45
46#include "bdiag.xbm"
47#include "fdiag.xbm"
48#include "cdiag.xbm"
49#include "horiz.xbm"
50#include "verti.xbm"
51#include "cross.xbm"
3cd0b8c5 52#define num_hatches 6
83df96d6 53
3cd0b8c5
RR
54#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
55#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
83df96d6 56
3cd0b8c5
RR
57static Pixmap hatches[num_hatches];
58static Pixmap *hatch_bitmap = (Pixmap *) NULL;
59
60//-----------------------------------------------------------------------------
83df96d6 61// constants
3cd0b8c5 62//-----------------------------------------------------------------------------
83df96d6 63
3cd0b8c5 64const double RAD2DEG = 180.0 / M_PI;
83df96d6
JS
65
66// ----------------------------------------------------------------------------
3cd0b8c5 67// private functions
83df96d6
JS
68// ----------------------------------------------------------------------------
69
3cd0b8c5
RR
70static inline double dmax(double a, double b) { return a > b ? a : b; }
71static inline double dmin(double a, double b) { return a < b ? a : b; }
83df96d6 72
3cd0b8c5
RR
73static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
74
75//-----------------------------------------------------------------------------
76// Implement Pool of Graphic contexts. Creating them takes too much time.
77//-----------------------------------------------------------------------------
78
79#define GC_POOL_SIZE 200
80
81enum wxPoolGCType
82{
83 wxGC_ERROR = 0,
84 wxTEXT_MONO,
85 wxBG_MONO,
86 wxPEN_MONO,
87 wxBRUSH_MONO,
88 wxTEXT_COLOUR,
89 wxBG_COLOUR,
90 wxPEN_COLOUR,
91 wxBRUSH_COLOUR,
92 wxTEXT_SCREEN,
93 wxBG_SCREEN,
94 wxPEN_SCREEN,
95 wxBRUSH_SCREEN
96};
97
98struct wxGC
99{
100 GC m_gc;
101 wxPoolGCType m_type;
102 bool m_used;
103};
104
105static wxGC wxGCPool[GC_POOL_SIZE];
106
107static void wxInitGCPool()
108{
109 memset( wxGCPool, 0, GC_POOL_SIZE*sizeof(wxGC) );
110}
83df96d6 111
3cd0b8c5 112static void wxCleanUpGCPool()
83df96d6 113{
3cd0b8c5
RR
114 for (int i = 0; i < GC_POOL_SIZE; i++)
115 {
116 if (wxGCPool[i].m_gc)
117 XFreeGC( wxGlobalDisplay(), wxGCPool[i].m_gc );
118 }
83df96d6
JS
119}
120
3cd0b8c5 121static GC wxGetPoolGC( Window window, wxPoolGCType type )
83df96d6 122{
3cd0b8c5
RR
123 for (int i = 0; i < GC_POOL_SIZE; i++)
124 {
125 if (!wxGCPool[i].m_gc)
126 {
127 wxGCPool[i].m_gc = XCreateGC( wxGlobalDisplay(), window, 0, NULL );
128 XSetGraphicsExposures( wxGlobalDisplay(), wxGCPool[i].m_gc, FALSE );
129 wxGCPool[i].m_type = type;
130 wxGCPool[i].m_used = FALSE;
131 }
132 if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
133 {
134 wxGCPool[i].m_used = TRUE;
135 return wxGCPool[i].m_gc;
136 }
137 }
138
139 wxFAIL_MSG( wxT("No GC available") );
140
141 return (GC) NULL;
83df96d6
JS
142}
143
3cd0b8c5
RR
144static void wxFreePoolGC( GC gc )
145{
146 for (int i = 0; i < GC_POOL_SIZE; i++)
147 {
148 if (wxGCPool[i].m_gc == gc)
149 {
150 wxGCPool[i].m_used = FALSE;
151 return;
152 }
153 }
154
155 wxFAIL_MSG( wxT("Wrong GC") );
156}
83df96d6
JS
157
158// ----------------------------------------------------------------------------
159// wxWindowDC
160// ----------------------------------------------------------------------------
161
3cd0b8c5
RR
162IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
163
83df96d6
JS
164wxWindowDC::wxWindowDC()
165{
3cd0b8c5
RR
166 m_display = (WXDisplay *) NULL;
167 m_penGC = (WXGC *) NULL;
168 m_brushGC = (WXGC *) NULL;
169 m_textGC = (WXGC *) NULL;
170 m_bgGC = (WXGC *) NULL;
171 m_cmap = (WXColormap *) NULL;
172 m_isMemDC = FALSE;
173 m_isScreenDC = FALSE;
174 m_owner = (wxWindow *)NULL;
2b5f62a0
VZ
175
176#if wxUSE_UNICODE
177 m_context = (PangoContext *)NULL;
178 m_fontdesc = (PangoFontDescription *)NULL;
179#endif
83df96d6
JS
180}
181
182wxWindowDC::wxWindowDC( wxWindow *window )
183{
3cd0b8c5
RR
184 wxASSERT_MSG( window, wxT("DC needs a window") );
185
186 m_display = (WXDisplay *) NULL;
187 m_penGC = (WXGC *) NULL;
188 m_brushGC = (WXGC *) NULL;
189 m_textGC = (WXGC *) NULL;
190 m_bgGC = (WXGC *) NULL;
191 m_cmap = (WXColormap *) NULL;
192 m_owner = (wxWindow *)NULL;
193 m_isMemDC = FALSE;
194 m_isScreenDC = FALSE;
83df96d6 195 m_font = window->GetFont();
83df96d6 196
3cd0b8c5 197 m_window = (WXWindow*) window->GetMainWindow();
83df96d6 198
3cd0b8c5
RR
199 // not realized ?
200 if (!m_window)
201 {
202 // don't report problems
203 m_ok = TRUE;
204
205 return;
206 }
83df96d6 207
3cd0b8c5
RR
208 m_display = (WXDisplay *) wxGlobalDisplay();
209
2b5f62a0
VZ
210#if wxUSE_UNICODE
211 m_context = wxTheApp->GetPangoContext();
212 m_fontdesc = window->GetFont().GetNativeFontInfo()->description;
213#endif
214
3cd0b8c5
RR
215 int screen = DefaultScreen( (Display*) m_display );
216 m_cmap = (WXColormap) DefaultColormap( (Display*) m_display, screen );
83df96d6 217
3cd0b8c5 218 SetUpDC();
83df96d6 219
3cd0b8c5
RR
220 /* this must be done after SetUpDC, bacause SetUpDC calls the
221 repective SetBrush, SetPen, SetBackground etc functions
222 to set up the DC. SetBackground call m_owner->SetBackground
223 and this might not be desired as the standard dc background
224 is white whereas a window might assume gray to be the
225 standard (as e.g. wxStatusBar) */
83df96d6 226
3cd0b8c5 227 m_owner = window;
83df96d6
JS
228}
229
230wxWindowDC::~wxWindowDC()
231{
3cd0b8c5
RR
232 Destroy();
233}
234
235void wxWindowDC::SetUpDC()
236{
237 m_ok = TRUE;
238
239 wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
240
241 if (m_isScreenDC)
242 {
243 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_SCREEN );
244 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_SCREEN );
245 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_SCREEN );
246 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_SCREEN );
247 }
3cd0b8c5
RR
248 else
249 if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
250 {
251 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_MONO );
252 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_MONO );
253 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_MONO );
254 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_MONO );
255 }
3cd0b8c5 256 else
83df96d6 257 {
3cd0b8c5
RR
258 m_penGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxPEN_COLOUR );
259 m_brushGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBRUSH_COLOUR );
260 m_textGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxTEXT_COLOUR );
261 m_bgGC = (WXGC*) wxGetPoolGC( (Window) m_window, wxBG_COLOUR );
83df96d6
JS
262 }
263
3cd0b8c5
RR
264 /* background colour */
265 m_backgroundBrush = *wxWHITE_BRUSH;
266 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
267 unsigned long bg_col = m_backgroundBrush.GetColour().GetPixel();
268
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 );
300
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 );
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
387ebd3e 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
JS
355 col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
356 return TRUE;
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 );
375
376 // XDrawLine( (Display*) m_display, (Window) m_window,
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() );
455
456 XFillArc( (Display*) m_display, (Window) m_window,
457 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
458
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 );
465
466 XFillArc( (Display*) m_display, (Window) m_window,
467 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
468
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 );
475
476 XFillArc( (Display*) m_display, (Window) m_window,
477 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
478
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() );
486
487 XFillArc( (Display*) m_display, (Window) m_window,
488 (GC) m_brushGC, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
489
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 );
503
504 XDrawLine( (Display*) m_display, (Window) m_window,
505 (GC) m_penGC, xx1, yy1, xxc, yyc );
506
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() );
541
542 XFillArc( (Display*) m_display, (Window) m_window,
543 (GC) m_textGC, xx, yy, ww, hh, start, end );
544
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 );
551
552 XFillArc( (Display*) m_display, (Window) m_window,
553 (GC) m_brushGC, xx, yy, ww, hh, start, end );
554
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 );
561
562 XFillArc( (Display*) m_display, (Window) m_window,
563 (GC) m_brushGC, xx, yy, ww, hh, start, end );
564
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() );
572
573 XFillArc( (Display*) m_display, (Window) m_window,
574 (GC) m_brushGC, xx, yy, ww, hh, start, end );
575
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);
619
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);
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 {
648
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() );
654
655 XFillPolygon( (Display*) m_display, (Window) m_window,
656 (GC) m_textGC, xpoints, n, Complex, 0);
657
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 );
664
665 XFillPolygon( (Display*) m_display, (Window) m_window,
666 (GC) m_brushGC, xpoints, n, Complex, 0);
667
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 );
674
675 XFillPolygon( (Display*) m_display, (Window) m_window,
676 (GC) m_brushGC, xpoints, n, Complex, 0);
677
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() );
685
686 XFillPolygon( (Display*) m_display, (Window) m_window,
687 (GC) m_brushGC, xpoints, n, Complex, 0);
688
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; }
726
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() );
736
737 XFillRectangle( (Display*) m_display, (Window) m_window,
738 (GC) m_textGC, xx, yy, ww, hh );
739
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 );
746
747 XFillRectangle( (Display*) m_display, (Window) m_window,
748 (GC) m_brushGC, xx, yy, ww, hh );
749
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 );
756
757 XFillRectangle( (Display*) m_display, (Window) m_window,
758 (GC) m_brushGC, xx, yy, ww, hh );
759
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() );
767
768 XFillRectangle( (Display*) m_display, (Window) m_window,
769 (GC) m_brushGC, xx, yy, ww, hh );
770
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
VZ
793 wxCHECK_RET( Ok(), wxT("invalid window dc") );
794
795 if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
796
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);
802
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; }
806
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 }
815
816 // CMB: draw nothing if transformed w or h is 0
817 if (ww == 0 || hh == 0) return;
818
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 }
826
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;
835
836 if (m_brush.GetStyle() != wxTRANSPARENT)
837 {
838 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
839 {
840 XSetTSOrigin( (Display*) m_display, (GC) m_textGC,
841 m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
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 {
875 XSetTSOrigin( (Display*) m_display, (GC) m_brushGC,
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 }
908
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() );
936
937 XFillArc( (Display*) m_display, (Window) m_window,
938 (GC) m_textGC, xx, yy, ww, hh, 0, 360*64 );
939
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 );
946
947 XFillArc( (Display*) m_display, (Window) m_window,
948 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
949
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 );
956
957 XFillArc( (Display*) m_display, (Window) m_window,
958 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
959
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() );
967
968 XFillArc( (Display*) m_display, (Window) m_window,
969 (GC) m_brushGC, xx, yy, ww, hh, 0, 360*64 );
970
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{
21689736 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") );
1004
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
1076
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);
1087
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
RR
1122 wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
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();
b1633d20 1171
3cd0b8c5
RR
1172 if (useMask && mask)
1173 {
a11672a4
RR
1174 WXPixmap new_mask = NULL;
1175#if 0
3cd0b8c5
RR
1176 if (!m_currentClippingRegion.IsNull())
1177 {
1178 GdkColor col;
1179 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
1180 GdkGC *gc = gdk_gc_new( new_mask );
1181 col.pixel = 0;
1182 gdk_gc_set_foreground( gc, &col );
1183 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1184 col.pixel = 0;
1185 gdk_gc_set_background( gc, &col );
1186 col.pixel = 1;
1187 gdk_gc_set_foreground( gc, &col );
1188 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1189 gdk_gc_set_clip_origin( gc, -xx, -yy );
1190 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1191 gdk_gc_set_stipple( gc, mask );
1192 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
1193 gdk_gc_unref( gc );
1194 }
a11672a4 1195#endif
3cd0b8c5
RR
1196 if (is_mono)
1197 {
1198 if (new_mask)
a11672a4 1199 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1200 else
a11672a4
RR
1201 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1202 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
3cd0b8c5
RR
1203 }
1204 else
1205 {
1206 if (new_mask)
a11672a4 1207 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1208 else
a11672a4
RR
1209 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1210 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
3cd0b8c5 1211 }
a11672a4 1212
3cd0b8c5 1213 if (new_mask)
a11672a4 1214 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1215 }
83df96d6 1216
b1633d20
RR
1217 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1218 // drawing a mono-bitmap (XBitmap) we use the current text GC
3cd0b8c5 1219 if (is_mono)
a11672a4
RR
1220 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1221 (GC) m_textGC, 0, 0, w, h, xx, yy, 1 );
3cd0b8c5 1222 else
a11672a4
RR
1223 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1224 (GC) m_penGC, 0, 0, w, h, xx, yy );
3cd0b8c5 1225
b1633d20 1226 // remove mask again if any
3cd0b8c5 1227 if (useMask && mask)
83df96d6 1228 {
3cd0b8c5 1229 if (is_mono)
83df96d6 1230 {
a11672a4
RR
1231 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1232 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1233 if (!m_currentClippingRegion.IsNull())
a11672a4 1234 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1235 }
1236 else
1237 {
a11672a4
RR
1238 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1239 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1240 if (!m_currentClippingRegion.IsNull())
a11672a4 1241 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6 1242 }
83df96d6 1243 }
83df96d6 1244}
c978d361
JS
1245#endif
1246 // wxUSE_NANOX/!wxUSE_NANOX
83df96d6 1247
83df96d6 1248bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
b1633d20 1249 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func, bool useMask,
83df96d6
JS
1250 wxCoord xsrcMask, wxCoord ysrcMask )
1251{
3cd0b8c5
RR
1252 /* this is the nth try to get this utterly useless function to
1253 work. it now completely ignores the scaling or translation
1254 of the source dc, but scales correctly on the target dc and
1255 knows about possible mask information in a memory dc. */
83df96d6 1256
3cd0b8c5 1257 wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
83df96d6 1258
3cd0b8c5 1259 wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
83df96d6 1260
3cd0b8c5 1261 if (!m_window) return FALSE;
83df96d6 1262
3cd0b8c5
RR
1263 // transform the source DC coords to the device ones
1264 xsrc = source->XLOG2DEV(xsrc);
1265 ysrc = source->YLOG2DEV(ysrc);
83df96d6 1266
3cd0b8c5
RR
1267 wxClientDC *srcDC = (wxClientDC*)source;
1268 wxMemoryDC *memDC = (wxMemoryDC*)source;
83df96d6 1269
3cd0b8c5
RR
1270 bool use_bitmap_method = FALSE;
1271 bool is_mono = FALSE;
83df96d6 1272
b1633d20 1273 // TODO: use the mask origin when drawing transparently
83df96d6
JS
1274 if (xsrcMask == -1 && ysrcMask == -1)
1275 {
b1633d20
RR
1276 xsrcMask = xsrc;
1277 ysrcMask = ysrc;
83df96d6 1278 }
a11672a4 1279
3cd0b8c5 1280 if (srcDC->m_isMemDC)
83df96d6 1281 {
3cd0b8c5 1282 if (!memDC->m_selected.Ok()) return FALSE;
83df96d6 1283
3cd0b8c5
RR
1284 /* we use the "XCopyArea" way to copy a memory dc into
1285 y different window if the memory dc BOTH
1286 a) doesn't have any mask or its mask isn't used
1287 b) it is clipped
1288 c) is not 1-bit */
83df96d6 1289
3cd0b8c5 1290 if (useMask && (memDC->m_selected.GetMask()))
83df96d6 1291 {
3cd0b8c5
RR
1292 /* we HAVE TO use the direct way for memory dcs
1293 that have mask since the XCopyArea doesn't know
1294 about masks */
1295 use_bitmap_method = TRUE;
1296 }
1297 else if (memDC->m_selected.GetDepth() == 1)
1298 {
1299 /* we HAVE TO use the direct way for memory dcs
1300 that are bitmaps because XCopyArea doesn't cope
1301 with different bit depths */
1302 is_mono = TRUE;
1303 use_bitmap_method = TRUE;
1304 }
1305 else if ((xsrc == 0) && (ysrc == 0) &&
1306 (width == memDC->m_selected.GetWidth()) &&
1307 (height == memDC->m_selected.GetHeight()))
1308 {
1309 /* we SHOULD use the direct way if all of the bitmap
1310 in the memory dc is copied in which case XCopyArea
1311 wouldn't be able able to boost performace by reducing
1312 the area to be scaled */
1313 use_bitmap_method = TRUE;
83df96d6
JS
1314 }
1315 else
1316 {
3cd0b8c5 1317 use_bitmap_method = FALSE;
83df96d6
JS
1318 }
1319 }
83df96d6 1320
3cd0b8c5
RR
1321 CalcBoundingBox( xdest, ydest );
1322 CalcBoundingBox( xdest + width, ydest + height );
1323
b1633d20 1324 // scale/translate size and position
3cd0b8c5
RR
1325 wxCoord xx = XLOG2DEV(xdest);
1326 wxCoord yy = YLOG2DEV(ydest);
1327
1328 wxCoord ww = XLOG2DEVREL(width);
1329 wxCoord hh = YLOG2DEVREL(height);
1330
b1633d20 1331 // compare to current clipping region
3cd0b8c5 1332 if (!m_currentClippingRegion.IsNull())
83df96d6 1333 {
3cd0b8c5
RR
1334 wxRegion tmp( xx,yy,ww,hh );
1335 tmp.Intersect( m_currentClippingRegion );
1336 if (tmp.IsEmpty())
1337 return TRUE;
1338 }
83df96d6 1339
3cd0b8c5
RR
1340 int old_logical_func = m_logicalFunction;
1341 SetLogicalFunction( logical_func );
83df96d6 1342
3cd0b8c5
RR
1343 if (use_bitmap_method)
1344 {
b1633d20 1345 // scale/translate bitmap size
3cd0b8c5
RR
1346 wxCoord bm_width = memDC->m_selected.GetWidth();
1347 wxCoord bm_height = memDC->m_selected.GetHeight();
83df96d6 1348
3cd0b8c5
RR
1349 wxCoord bm_ww = XLOG2DEVREL( bm_width );
1350 wxCoord bm_hh = YLOG2DEVREL( bm_height );
83df96d6 1351
b1633d20 1352 // scale bitmap if required
3cd0b8c5 1353 wxBitmap use_bitmap;
83df96d6 1354
3cd0b8c5
RR
1355 if ((bm_width != bm_ww) || (bm_height != bm_hh))
1356 {
2b5f62a0 1357 wxImage image( memDC->m_selected.ConvertToImage() );
3cd0b8c5 1358 image = image.Scale( bm_ww, bm_hh );
83df96d6 1359
b1633d20 1360#if 0
3cd0b8c5
RR
1361 if (is_mono)
1362 use_bitmap = image.ConvertToMonoBitmap(255,255,255);
1363 else
b1633d20 1364#endif
2b5f62a0 1365 use_bitmap = image;
3cd0b8c5
RR
1366 }
1367 else
1368 {
1369 use_bitmap = memDC->m_selected;
1370 }
1371
b1633d20
RR
1372 // apply mask if any
1373 WXPixmap mask = NULL;
3cd0b8c5 1374 if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
83df96d6 1375
3cd0b8c5 1376 if (useMask && mask)
83df96d6 1377 {
b1633d20
RR
1378 WXPixmap new_mask = NULL;
1379#if 0
3cd0b8c5 1380 if (!m_currentClippingRegion.IsNull())
83df96d6 1381 {
3cd0b8c5
RR
1382 GdkColor col;
1383 new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
1384 GdkGC *gc = gdk_gc_new( new_mask );
1385 col.pixel = 0;
1386 gdk_gc_set_foreground( gc, &col );
1387 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1388 col.pixel = 0;
1389 gdk_gc_set_background( gc, &col );
1390 col.pixel = 1;
1391 gdk_gc_set_foreground( gc, &col );
1392 gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
1393 gdk_gc_set_clip_origin( gc, -xx, -yy );
1394 gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED );
1395 gdk_gc_set_stipple( gc, mask );
1396 gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
1397 gdk_gc_unref( gc );
83df96d6 1398 }
b1633d20 1399#endif
3cd0b8c5 1400 if (is_mono)
83df96d6 1401 {
3cd0b8c5 1402 if (new_mask)
b1633d20 1403 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) new_mask );
3cd0b8c5 1404 else
b1633d20
RR
1405 XSetClipMask( (Display*) m_display, (GC) m_textGC, (Pixmap) mask );
1406 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, xx, yy );
83df96d6
JS
1407 }
1408 else
1409 {
3cd0b8c5 1410 if (new_mask)
b1633d20 1411 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) new_mask );
3cd0b8c5 1412 else
b1633d20
RR
1413 XSetClipMask( (Display*) m_display, (GC) m_penGC, (Pixmap) mask );
1414 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, xx, yy );
83df96d6 1415 }
b1633d20 1416
3cd0b8c5 1417 if (new_mask)
b1633d20 1418 XFreePixmap( (Display*) m_display, (Pixmap) new_mask );
3cd0b8c5 1419 }
83df96d6 1420
b1633d20
RR
1421 // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
1422 // drawing a mono-bitmap (XBitmap) we use the current text GC
83df96d6 1423
3cd0b8c5 1424 if (is_mono)
b1633d20
RR
1425 XCopyPlane( (Display*) m_display, (Pixmap) use_bitmap.GetBitmap(), (Window) m_window,
1426 (GC) m_textGC, xsrc, ysrc, width, height, xx, yy, 1 );
83df96d6 1427 else
b1633d20
RR
1428 XCopyArea( (Display*) m_display, (Pixmap) use_bitmap.GetPixmap(), (Window) m_window,
1429 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
83df96d6 1430
b1633d20 1431 // remove mask again if any
3cd0b8c5 1432 if (useMask && mask)
83df96d6 1433 {
3cd0b8c5
RR
1434 if (is_mono)
1435 {
b1633d20
RR
1436 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
1437 XSetClipOrigin( (Display*) m_display, (GC) m_textGC, 0, 0 );
3cd0b8c5 1438 if (!m_currentClippingRegion.IsNull())
b1633d20 1439 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
3cd0b8c5
RR
1440 }
1441 else
83df96d6 1442 {
b1633d20
RR
1443 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
1444 XSetClipOrigin( (Display*) m_display, (GC) m_penGC, 0, 0 );
3cd0b8c5 1445 if (!m_currentClippingRegion.IsNull())
b1633d20 1446 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
1447 }
1448 }
83df96d6 1449 }
b1633d20 1450 else // use_bitmap_method
83df96d6 1451 {
3cd0b8c5 1452 if ((width != ww) || (height != hh))
83df96d6 1453 {
b1633d20 1454 /* Draw source window into a bitmap as we cannot scale
3cd0b8c5
RR
1455 a window in contrast to a bitmap. this would actually
1456 work with memory dcs as well, but we'd lose the mask
1457 information and waste one step in this process since
1458 a memory already has a bitmap. all this is slightly
1459 inefficient as we could take an XImage directly from
1460 an X window, but we'd then also have to care that
1461 the window is not outside the screen (in which case
1462 we'd get a BadMatch or what not).
1463 Is a double XGetImage and combined XGetPixel and
1464 XPutPixel really faster? I'm not sure. look at wxXt
1465 for a different implementation of the same problem. */
1466
1467 wxBitmap bitmap( width, height );
1468
b1633d20
RR
1469 // copy including child window contents
1470 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1471 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) bitmap.GetPixmap(),
1472 (GC) m_penGC, xsrc, ysrc, width, height, 0, 0 );
1473 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1474
b1633d20 1475 // scale image
2b5f62a0 1476 wxImage image( bitmap.ConvertToImage() );
3cd0b8c5
RR
1477 image = image.Scale( ww, hh );
1478
b1633d20 1479 // convert to bitmap
2b5f62a0 1480 bitmap = image;
3cd0b8c5 1481
b1633d20
RR
1482 // draw scaled bitmap
1483 XCopyArea( (Display*) m_display, (Window) bitmap.GetPixmap(), (Window) m_window,
1484 (GC) m_penGC, 0, 0, width, height, xx, yy );
83df96d6
JS
1485 }
1486 else
3cd0b8c5 1487 {
b1633d20
RR
1488 // No scaling and not a memory dc with a mask either
1489
1490 // copy including child window contents
1491 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, IncludeInferiors );
1492 XCopyArea( (Display*) m_display, (Window) srcDC->GetWindow(), (Window) m_window,
1493 (GC) m_penGC, xsrc, ysrc, width, height, xx, yy );
1494 XSetSubwindowMode( (Display*) m_display, (GC) m_penGC, ClipByChildren );
3cd0b8c5 1495 }
83df96d6
JS
1496 }
1497
3cd0b8c5 1498 SetLogicalFunction( old_logical_func );
b1633d20 1499
3cd0b8c5 1500 return TRUE;
83df96d6
JS
1501}
1502
3cd0b8c5 1503void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
83df96d6 1504{
3cd0b8c5 1505 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1506
3cd0b8c5 1507 if (!m_window) return;
83df96d6 1508
3cd0b8c5
RR
1509 x = XLOG2DEV(x);
1510 y = YLOG2DEV(y);
83df96d6 1511
2b5f62a0
VZ
1512#if wxUSE_UNICODE
1513 PangoLayout *layout = pango_layout_new(m_context);
1514 pango_layout_set_font_description(layout, m_fontdesc);
1515
1516 const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
1517 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1518
1519 // Measure layout.
1520 int w,h;
1521 pango_layout_get_pixel_size(layout, &w, &h);
1522 wxCoord width = w;
1523 wxCoord height = h;
1524
1525 // Draw layout.
1526 x11_draw_layout( (Drawable) m_window, (GC) m_textGC, x, y, layout, m_textForegroundColour );
1527
1528 g_object_unref( G_OBJECT( layout ) );
1529
1530 CalcBoundingBox (x + width, y + height);
1531 CalcBoundingBox (x, y);
1532#else
1533 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1534
1535 wxCHECK_RET( xfont, wxT("invalid font") );
1536
ae1daed0
JS
1537 // First draw a rectangle representing the text background, if a text
1538 // background is specified
1539 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
83df96d6 1540 {
ae1daed0
JS
1541 // Since X draws from the baseline of the text, must add the text height
1542 int cx = 0;
1543 int cy = 0;
1544 int ascent = 0;
1545 int slen;
1546 int direction, descent;
1547
1548 slen = strlen(text);
1549 XCharStruct overall_return;
1550
868741e9 1551 (void)XTextExtents(xfont, (char*) text.c_str(), slen, &direction,
ae1daed0
JS
1552 &ascent, &descent, &overall_return);
1553
1554 cx = overall_return.width;
1555 cy = ascent + descent;
1556 m_textBackgroundColour.CalcPixel(m_cmap);
1557 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel());
1558 XFillRectangle( (Display*) m_display, (Window) m_window,
1559 (GC) m_textGC, x, y, cx, cy );
1560 XSetForeground ((Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel());
1561
83df96d6 1562 }
3cd0b8c5
RR
1563
1564 XSetFont( (Display*) m_display, (GC) m_textGC, xfont->fid );
788519c6 1565#if !wxUSE_NANOX
3cd0b8c5 1566 if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
788519c6
JS
1567#endif
1568 {
3cd0b8c5 1569 XDrawString( (Display*) m_display, (Window) m_window,
788519c6
JS
1570 (GC) m_textGC, x, y + XFontStructGetAscent(xfont), text.c_str(), text.Len() );
1571 }
83df96d6
JS
1572
1573#if 0
3cd0b8c5 1574 if (m_font.GetUnderlined())
83df96d6 1575 {
788519c6 1576 wxCoord ul_y = y + XFontStructGetAscent(font);
3cd0b8c5
RR
1577 if (font->descent > 0) ul_y++;
1578 gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
83df96d6 1579 }
83df96d6 1580
3cd0b8c5
RR
1581 width = wxCoord(width / m_scaleX);
1582 height = wxCoord(height / m_scaleY);
1583
1584 CalcBoundingBox (x + width, y + height);
83df96d6 1585 CalcBoundingBox (x, y);
3cd0b8c5 1586#endif
2b5f62a0 1587#endif
83df96d6
JS
1588}
1589
3cd0b8c5 1590void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
83df96d6 1591{
3cd0b8c5 1592 // later
83df96d6
JS
1593}
1594
1595void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1596 wxCoord *descent, wxCoord *externalLeading,
1597 wxFont *font ) const
1598{
54385bdb 1599 wxCHECK_RET( Ok(), wxT("invalid dc") );
83df96d6 1600
2b5f62a0
VZ
1601 if (string.IsEmpty())
1602 {
1603 if (width) (*width) = 0;
1604 if (height) (*height) = 0;
1605 return;
1606 }
1607
1608#if wxUSE_UNICODE
1609 PangoLayout *layout = pango_layout_new( m_context );
1610
1611 if (font)
1612 pango_layout_set_font_description( layout, font->GetNativeFontInfo()->description );
1613 else
1614 pango_layout_set_font_description(layout, m_fontdesc);
1615
1616 const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
1617 pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
1618
1619 // Measure text.
1620 int w,h;
1621 pango_layout_get_pixel_size(layout, &w, &h);
1622
1623 if (width) (*width) = (wxCoord) w;
1624 if (height) (*height) = (wxCoord) h;
1625 if (descent)
1626 {
1627 // Do something about metrics here. TODO.
1628 (*descent) = 0;
1629 }
1630 if (externalLeading) (*externalLeading) = 0; // ??
1631
1632 g_object_unref( G_OBJECT( layout ) );
1633#else
3cd0b8c5
RR
1634 wxFont fontToUse = m_font;
1635 if (font) fontToUse = *font;
83df96d6 1636
54385bdb 1637 wxCHECK_RET( fontToUse.Ok(), wxT("invalid font") );
83df96d6 1638
3cd0b8c5 1639 XFontStruct *xfont = (XFontStruct*) fontToUse.GetFontStruct( m_scaleY, m_display );
83df96d6 1640
3cd0b8c5
RR
1641 wxCHECK_RET( xfont, wxT("invalid font") );
1642
83df96d6
JS
1643 int direction, ascent, descent2;
1644 XCharStruct overall;
83df96d6 1645
788519c6 1646 XTextExtents( xfont, (char*) string.c_str(), string.Len(), &direction,
83df96d6
JS
1647 &ascent, &descent2, &overall);
1648
3cd0b8c5
RR
1649 if (width)
1650 *width = (wxCoord)( overall.width / m_scaleX );
1651 if (height)
1652 *height = (wxCoord)((ascent + descent2) / m_scaleY );
83df96d6 1653 if (descent)
3cd0b8c5 1654 *descent = (wxCoord)(descent2 / m_scaleY );
83df96d6 1655 if (externalLeading)
3cd0b8c5 1656 *externalLeading = 0; // ??
2b5f62a0 1657#endif
83df96d6
JS
1658}
1659
1660wxCoord wxWindowDC::GetCharWidth() const
1661{
54385bdb 1662 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
3cd0b8c5 1663
2b5f62a0
VZ
1664#if wxUSE_UNICODE
1665 PangoLayout *layout = pango_layout_new( m_context );
1666
1667 if (!m_fontdesc)
1668 {
1669 char *crash = NULL;
1670 *crash = 0;
1671 }
1672
1673 pango_layout_set_font_description(layout, m_fontdesc);
1674 pango_layout_set_text(layout, "H", 1 );
1675 int w,h;
1676 pango_layout_get_pixel_size(layout, &w, &h);
1677 g_object_unref( G_OBJECT( layout ) );
1678
1679 return w;
1680#else
54385bdb 1681 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
83df96d6 1682
3cd0b8c5
RR
1683 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1684
1685 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1686
1687 int direction, ascent, descent;
1688 XCharStruct overall;
3cd0b8c5
RR
1689
1690 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1691
1692 return (wxCoord)(overall.width / m_scaleX);
2b5f62a0 1693#endif
83df96d6
JS
1694}
1695
1696wxCoord wxWindowDC::GetCharHeight() const
1697{
54385bdb 1698 wxCHECK_MSG( Ok(), 0, wxT("invalid dc") );
3cd0b8c5 1699
2b5f62a0
VZ
1700#if wxUSE_UNICODE
1701 PangoLayout *layout = pango_layout_new( m_context );
1702
1703 if (!m_fontdesc)
1704 {
1705 char *crash = NULL;
1706 *crash = 0;
1707 }
1708
1709 pango_layout_set_font_description(layout, m_fontdesc);
1710
1711 pango_layout_set_text(layout, "H", 1 );
1712 int w,h;
1713 pango_layout_get_pixel_size(layout, &w, &h);
1714 g_object_unref( G_OBJECT( layout ) );
1715
1716 return h;
1717#else
54385bdb 1718 wxCHECK_MSG( m_font.Ok(), 0, wxT("invalid font") );
83df96d6 1719
3cd0b8c5
RR
1720 XFontStruct *xfont = (XFontStruct*) m_font.GetFontStruct( m_scaleY, m_display );
1721
1722 wxCHECK_MSG( xfont, 0, wxT("invalid font") );
83df96d6
JS
1723
1724 int direction, ascent, descent;
1725 XCharStruct overall;
3cd0b8c5
RR
1726
1727 XTextExtents( xfont, "H", 1, &direction, &ascent, &descent, &overall );
1728
1729 return (wxCoord)((ascent+descent) / m_scaleY);
2b5f62a0 1730#endif
83df96d6
JS
1731}
1732
1733void wxWindowDC::Clear()
1734{
3cd0b8c5 1735 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1736
3cd0b8c5 1737 if (!m_window) return;
83df96d6 1738
3cd0b8c5
RR
1739 /* - we either are a memory dc or have a window as the
1740 owner. anything else shouldn't happen.
1741 - we don't use gdk_window_clear() as we don't set
1742 the window's background colour anymore. it is too
1743 much pain to keep the DC's and the window's back-
1744 ground colour in synch. */
83df96d6 1745
3cd0b8c5
RR
1746 if (m_owner)
1747 {
1748 int width,height;
1749 m_owner->GetSize( &width, &height );
1750 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1751 return;
1752 }
83df96d6 1753
3cd0b8c5
RR
1754 if (m_isMemDC)
1755 {
1756 int width,height;
1757 GetSize( &width, &height );
1758 XFillRectangle( (Display*) m_display, (Window) m_window, (GC) m_bgGC, 0, 0, width, height );
1759 return;
1760 }
83df96d6
JS
1761}
1762
1763void wxWindowDC::SetFont( const wxFont &font )
1764{
54385bdb 1765 wxCHECK_RET( Ok(), wxT("invalid dc") );
83df96d6
JS
1766
1767 m_font = font;
83df96d6
JS
1768}
1769
1770void wxWindowDC::SetPen( const wxPen &pen )
1771{
3cd0b8c5
RR
1772 wxCHECK_RET( Ok(), wxT("invalid window dc") );
1773
1774 if (m_pen == pen) return;
83df96d6
JS
1775
1776 m_pen = pen;
83df96d6 1777
3cd0b8c5 1778 if (!m_pen.Ok()) return;
83df96d6 1779
3cd0b8c5 1780 if (!m_window) return;
83df96d6 1781
3cd0b8c5
RR
1782 int width = m_pen.GetWidth();
1783 if (width <= 0)
1784 {
1785 // CMB: if width is non-zero scale it with the dc
1786 width = 1;
1787 }
1788 else
1789 {
1790 // X doesn't allow different width in x and y and so we take
1791 // the average
1792 double w = 0.5 +
1793 ( fabs((double) XLOG2DEVREL(width)) +
1794 fabs((double) YLOG2DEVREL(width)) ) / 2.0;
1795 width = (int)w;
1796 }
1797
1798 static const wxX11Dash dotted[] = {1, 1};
1799 static const wxX11Dash short_dashed[] = {2, 2};
1800 static const wxX11Dash long_dashed[] = {2, 4};
1801 static const wxX11Dash dotted_dashed[] = {3, 3, 1, 3};
1802
1803 // We express dash pattern in pen width unit, so we are
1804 // independent of zoom factor and so on...
1805 int req_nb_dash;
1806 const wxX11Dash *req_dash;
1807
1808 int lineStyle = LineSolid;
1809 switch (m_pen.GetStyle())
83df96d6 1810 {
83df96d6 1811 case wxUSER_DASH:
3cd0b8c5
RR
1812 {
1813 lineStyle = LineOnOffDash;
1814 req_nb_dash = m_pen.GetDashCount();
1815 req_dash = (wxX11Dash*)m_pen.GetDash();
83df96d6 1816 break;
3cd0b8c5 1817 }
83df96d6 1818 case wxDOT:
3cd0b8c5
RR
1819 {
1820 lineStyle = LineOnOffDash;
83df96d6
JS
1821 req_nb_dash = 2;
1822 req_dash = dotted;
83df96d6 1823 break;
3cd0b8c5 1824 }
83df96d6 1825 case wxLONG_DASH:
3cd0b8c5
RR
1826 {
1827 lineStyle = LineOnOffDash;
83df96d6
JS
1828 req_nb_dash = 2;
1829 req_dash = long_dashed;
83df96d6 1830 break;
3cd0b8c5
RR
1831 }
1832 case wxSHORT_DASH:
1833 {
1834 lineStyle = LineOnOffDash;
1835 req_nb_dash = 2;
1836 req_dash = short_dashed;
1837 break;
1838 }
83df96d6 1839 case wxDOT_DASH:
3cd0b8c5
RR
1840 {
1841// lineStyle = LineDoubleDash;
1842 lineStyle = LineOnOffDash;
83df96d6
JS
1843 req_nb_dash = 4;
1844 req_dash = dotted_dashed;
83df96d6 1845 break;
3cd0b8c5
RR
1846 }
1847
1848 case wxTRANSPARENT:
1849 case wxSTIPPLE_MASK_OPAQUE:
83df96d6
JS
1850 case wxSTIPPLE:
1851 case wxSOLID:
83df96d6 1852 default:
3cd0b8c5
RR
1853 {
1854 lineStyle = LineSolid;
74dc5eb6 1855 req_dash = (wxX11Dash*)NULL;
83df96d6 1856 req_nb_dash = 0;
3cd0b8c5 1857 break;
83df96d6 1858 }
3cd0b8c5 1859 }
83df96d6 1860
3cd0b8c5
RR
1861 int capStyle = CapRound;
1862 switch (m_pen.GetCap())
1863 {
1864 case wxCAP_PROJECTING: { capStyle = CapProjecting; break; }
1865 case wxCAP_BUTT: { capStyle = CapButt; break; }
1866 case wxCAP_ROUND:
1867 default:
83df96d6 1868 {
3cd0b8c5 1869 if (width <= 1)
83df96d6 1870 {
3cd0b8c5
RR
1871 width = 0;
1872 capStyle = CapNotLast;
83df96d6
JS
1873 }
1874 else
1875 {
3cd0b8c5 1876 capStyle = CapRound;
83df96d6 1877 }
83df96d6
JS
1878 break;
1879 }
3cd0b8c5 1880 }
83df96d6 1881
3cd0b8c5
RR
1882 int joinStyle = JoinRound;
1883 switch (m_pen.GetJoin())
1884 {
1885 case wxJOIN_BEVEL: { joinStyle = JoinBevel; break; }
1886 case wxJOIN_MITER: { joinStyle = JoinMiter; break; }
83df96d6 1887 case wxJOIN_ROUND:
3cd0b8c5 1888 default: { joinStyle = JoinRound; break; }
83df96d6
JS
1889 }
1890
3cd0b8c5 1891 XSetLineAttributes( (Display*) m_display, (GC) m_penGC, width, lineStyle, capStyle, joinStyle );
83df96d6 1892
3cd0b8c5
RR
1893 m_pen.GetColour().CalcPixel( m_cmap );
1894 XSetForeground( (Display*) m_display, (GC) m_penGC, m_pen.GetColour().GetPixel() );
1895}
83df96d6 1896
3cd0b8c5
RR
1897void wxWindowDC::SetBrush( const wxBrush &brush )
1898{
1899 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1900
3cd0b8c5 1901 if (m_brush == brush) return;
83df96d6 1902
3cd0b8c5
RR
1903 m_brush = brush;
1904
1905 if (!m_brush.Ok()) return;
83df96d6 1906
3cd0b8c5
RR
1907 if (!m_window) return;
1908
1909 m_brush.GetColour().CalcPixel( m_cmap );
1910 XSetForeground( (Display*) m_display, (GC) m_brushGC, m_brush.GetColour().GetPixel() );
1911
1912 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillSolid );
1913
1914 if ((m_brush.GetStyle() == wxSTIPPLE) && (m_brush.GetStipple()->Ok()))
83df96d6 1915 {
3cd0b8c5 1916 if (m_brush.GetStipple()->GetPixmap())
83df96d6 1917 {
3cd0b8c5
RR
1918 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillTiled );
1919 XSetTile( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetPixmap() );
83df96d6
JS
1920 }
1921 else
1922 {
3cd0b8c5 1923 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
0d1dff01 1924 XSetStipple( (Display*) m_display, (GC) m_brushGC, (Pixmap) m_brush.GetStipple()->GetBitmap() );
83df96d6 1925 }
3cd0b8c5 1926 }
83df96d6 1927
3cd0b8c5
RR
1928 if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
1929 {
1930 XSetFillStyle( (Display*) m_display, (GC) m_textGC, FillOpaqueStippled );
0d1dff01 1931 XSetStipple( (Display*) m_display, (GC) m_textGC, (Pixmap) m_brush.GetStipple()->GetMask()->GetBitmap() );
83df96d6 1932 }
83df96d6 1933
3cd0b8c5
RR
1934 if (IS_HATCH(m_brush.GetStyle()))
1935 {
1936 XSetFillStyle( (Display*) m_display, (GC) m_brushGC, FillStippled );
1937 int num = m_brush.GetStyle() - wxBDIAGONAL_HATCH;
1938 XSetStipple( (Display*) m_display, (GC) m_brushGC, hatches[num] );
1939 }
83df96d6
JS
1940}
1941
3cd0b8c5 1942void wxWindowDC::SetBackground( const wxBrush &brush )
83df96d6 1943{
3cd0b8c5
RR
1944 /* CMB 21/7/98: Added SetBackground. Sets background brush
1945 * for Clear() and bg colour for shapes filled with cross-hatch brush */
83df96d6 1946
3cd0b8c5 1947 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 1948
3cd0b8c5 1949 if (m_backgroundBrush == brush) return;
83df96d6 1950
3cd0b8c5 1951 m_backgroundBrush = brush;
83df96d6 1952
3cd0b8c5 1953 if (!m_backgroundBrush.Ok()) return;
83df96d6 1954
3cd0b8c5 1955 if (!m_window) return;
83df96d6 1956
3cd0b8c5
RR
1957 m_backgroundBrush.GetColour().CalcPixel( m_cmap );
1958 XSetBackground( (Display*) m_display, (GC) m_brushGC, m_backgroundBrush.GetColour().GetPixel() );
1959 XSetBackground( (Display*) m_display, (GC) m_penGC, m_backgroundBrush.GetColour().GetPixel() );
1960 XSetBackground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
1961 XSetForeground( (Display*) m_display, (GC) m_bgGC, m_backgroundBrush.GetColour().GetPixel() );
83df96d6 1962
3cd0b8c5 1963 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillSolid );
83df96d6 1964
3cd0b8c5 1965 if ((m_backgroundBrush.GetStyle() == wxSTIPPLE) && (m_backgroundBrush.GetStipple()->Ok()))
83df96d6 1966 {
3cd0b8c5 1967 if (m_backgroundBrush.GetStipple()->GetPixmap())
83df96d6 1968 {
3cd0b8c5
RR
1969 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillTiled );
1970 XSetTile( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetPixmap() );
83df96d6 1971 }
3cd0b8c5 1972 else
83df96d6 1973 {
3cd0b8c5 1974 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
0d1dff01 1975 XSetStipple( (Display*) m_display, (GC) m_bgGC, (Pixmap) m_backgroundBrush.GetStipple()->GetBitmap() );
83df96d6 1976 }
83df96d6
JS
1977 }
1978
3cd0b8c5 1979 if (IS_HATCH(m_backgroundBrush.GetStyle()))
83df96d6 1980 {
3cd0b8c5
RR
1981 XSetFillStyle( (Display*) m_display, (GC) m_bgGC, FillStippled );
1982 int num = m_backgroundBrush.GetStyle() - wxBDIAGONAL_HATCH;
1983 XSetStipple( (Display*) m_display, (GC) m_bgGC, hatches[num] );
83df96d6 1984 }
83df96d6
JS
1985}
1986
1987void wxWindowDC::SetLogicalFunction( int function )
1988{
54385bdb 1989 wxCHECK_RET( Ok(), wxT("invalid dc") );
83df96d6
JS
1990
1991 int x_function;
1992
83df96d6
JS
1993 if (m_logicalFunction == function)
1994 return;
1995
3cd0b8c5
RR
1996 // VZ: shouldn't this be a CHECK?
1997 if (!m_window)
1998 return;
1999
83df96d6
JS
2000 switch (function)
2001 {
2002 case wxCLEAR:
2003 x_function = GXclear;
2004 break;
2005 case wxXOR:
2006 x_function = GXxor;
2007 break;
2008 case wxINVERT:
2009 x_function = GXinvert;
2010 break;
2011 case wxOR_REVERSE:
2012 x_function = GXorReverse;
2013 break;
2014 case wxAND_REVERSE:
2015 x_function = GXandReverse;
2016 break;
2017 case wxAND:
2018 x_function = GXand;
2019 break;
2020 case wxOR:
2021 x_function = GXor;
2022 break;
2023 case wxAND_INVERT:
2024 x_function = GXandInverted;
2025 break;
2026 case wxNO_OP:
2027 x_function = GXnoop;
2028 break;
2029 case wxNOR:
2030 x_function = GXnor;
2031 break;
2032 case wxEQUIV:
2033 x_function = GXequiv;
2034 break;
2035 case wxSRC_INVERT:
2036 x_function = GXcopyInverted;
2037 break;
2038 case wxOR_INVERT:
2039 x_function = GXorInverted;
2040 break;
2041 case wxNAND:
2042 x_function = GXnand;
2043 break;
2044 case wxSET:
2045 x_function = GXset;
2046 break;
2047 case wxCOPY:
2048 default:
2049 x_function = GXcopy;
2050 break;
2051 }
2052
3cd0b8c5
RR
2053 XSetFunction( (Display*) m_display, (GC) m_penGC, x_function );
2054 XSetFunction( (Display*) m_display, (GC) m_brushGC, x_function );
83df96d6 2055
3cd0b8c5
RR
2056 // to stay compatible with wxMSW, we don't apply ROPs to the text
2057 // operations (i.e. DrawText/DrawRotatedText).
2058 // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
2059 XSetFunction( (Display*) m_display, (GC) m_textGC, x_function );
2060
83df96d6 2061 m_logicalFunction = function;
83df96d6
JS
2062}
2063
2064void wxWindowDC::SetTextForeground( const wxColour &col )
2065{
3cd0b8c5 2066 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2067
3cd0b8c5
RR
2068 // don't set m_textForegroundColour to an invalid colour as we'd crash
2069 // later then (we use m_textForegroundColour.GetColor() without checking
2070 // in a few places)
2071 if ( !col.Ok() || (m_textForegroundColour == col) )
83df96d6
JS
2072 return;
2073
2074 m_textForegroundColour = col;
2075
3cd0b8c5
RR
2076 if (m_window)
2077 {
2078 m_textForegroundColour.CalcPixel( m_cmap );
2079 XSetForeground( (Display*) m_display, (GC) m_textGC, m_textForegroundColour.GetPixel() );
2080 }
83df96d6
JS
2081}
2082
2083void wxWindowDC::SetTextBackground( const wxColour &col )
2084{
3cd0b8c5 2085 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2086
3cd0b8c5
RR
2087 // same as above
2088 if ( !col.Ok() || (m_textBackgroundColour == col) )
83df96d6
JS
2089 return;
2090
2091 m_textBackgroundColour = col;
3cd0b8c5
RR
2092
2093 if (m_window)
2094 {
2095 m_textBackgroundColour.CalcPixel( m_cmap );
2096 XSetBackground( (Display*) m_display, (GC) m_textGC, m_textBackgroundColour.GetPixel() );
2097 }
83df96d6
JS
2098}
2099
2100void wxWindowDC::SetBackgroundMode( int mode )
2101{
3cd0b8c5
RR
2102 wxCHECK_RET( Ok(), wxT("invalid window dc") );
2103
83df96d6 2104 m_backgroundMode = mode;
3cd0b8c5 2105
0b5c0e1a
JS
2106#if wxUSE_NANOX
2107 GrSetGCUseBackground((GC) m_textGC, mode == wxTRANSPARENT ? FALSE : TRUE);
2108#endif
2109
3cd0b8c5
RR
2110 if (!m_window) return;
2111
2112 // CMB 21/7/98: fill style of cross-hatch brushes is affected by
2113 // transparent/solid background mode
2114
2115 if (m_brush.GetStyle() != wxSOLID && m_brush.GetStyle() != wxTRANSPARENT)
2116 {
2117 XSetFillStyle( (Display*) m_display, (GC) m_brushGC,
2118 (m_backgroundMode == wxTRANSPARENT) ? FillStippled : FillOpaqueStippled );
2119 }
83df96d6
JS
2120}
2121
2122void wxWindowDC::SetPalette( const wxPalette& palette )
2123{
3cd0b8c5 2124#if 0
83df96d6
JS
2125 if (m_window)
2126 {
2127 if (palette.Ok())
2128 /* Use GetXColormap */
2129 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2130 (Colormap) palette.GetXColormap());
2131 else
2132 /* Use wxGetMainColormap */
2133 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2134 (Colormap) wxTheApp->GetMainColormap(m_display));
2135 }
3cd0b8c5 2136#endif
83df96d6
JS
2137}
2138
3cd0b8c5 2139void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
83df96d6 2140{
3cd0b8c5 2141 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2142
3cd0b8c5 2143 if (!m_window) return;
83df96d6 2144
3cd0b8c5
RR
2145 wxRect rect;
2146 rect.x = XLOG2DEV(x);
2147 rect.y = YLOG2DEV(y);
2148 rect.width = XLOG2DEVREL(width);
2149 rect.height = YLOG2DEVREL(height);
2150
2151 if (!m_currentClippingRegion.IsNull())
2152 m_currentClippingRegion.Intersect( rect );
83df96d6 2153 else
3cd0b8c5
RR
2154 m_currentClippingRegion.Union( rect );
2155
2156#if USE_PAINT_REGION
2157 if (!m_paintClippingRegion.IsNull())
2158 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2159#endif
2160
2161 wxCoord xx, yy, ww, hh;
2162 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2163 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2164
2165 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2166 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2167 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2168 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2169}
83df96d6 2170
3cd0b8c5
RR
2171void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2172{
2173 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2174
3cd0b8c5 2175 if (region.Empty())
83df96d6 2176 {
3cd0b8c5
RR
2177 DestroyClippingRegion();
2178 return;
83df96d6 2179 }
3cd0b8c5
RR
2180
2181 if (!m_window) return;
2182
2183 if (!m_currentClippingRegion.IsNull())
2184 m_currentClippingRegion.Intersect( region );
83df96d6 2185 else
3cd0b8c5 2186 m_currentClippingRegion.Union( region );
83df96d6 2187
3cd0b8c5
RR
2188#if USE_PAINT_REGION
2189 if (!m_paintClippingRegion.IsNull())
2190 m_currentClippingRegion.Intersect( m_paintClippingRegion );
2191#endif
83df96d6 2192
3cd0b8c5
RR
2193 wxCoord xx, yy, ww, hh;
2194 m_currentClippingRegion.GetBox( xx, yy, ww, hh );
2195 wxDC::DoSetClippingRegion( xx, yy, ww, hh );
2196
2197 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2198 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2199 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2200 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
83df96d6
JS
2201}
2202
3cd0b8c5 2203void wxWindowDC::DestroyClippingRegion()
83df96d6 2204{
3cd0b8c5 2205 wxCHECK_RET( Ok(), wxT("invalid window dc") );
83df96d6 2206
3cd0b8c5 2207 wxDC::DestroyClippingRegion();
83df96d6 2208
3cd0b8c5 2209 m_currentClippingRegion.Clear();
83df96d6 2210
3cd0b8c5
RR
2211#if USE_PAINT_REGION
2212 if (!m_paintClippingRegion.IsEmpty())
2213 m_currentClippingRegion.Union( m_paintClippingRegion );
2214#endif
83df96d6 2215
3cd0b8c5 2216 if (!m_window) return;
83df96d6 2217
3cd0b8c5
RR
2218 if (m_currentClippingRegion.IsEmpty())
2219 {
2220 XSetClipMask( (Display*) m_display, (GC) m_penGC, None );
2221 XSetClipMask( (Display*) m_display, (GC) m_brushGC, None );
2222 XSetClipMask( (Display*) m_display, (GC) m_textGC, None );
2223 XSetClipMask( (Display*) m_display, (GC) m_bgGC, None );
2224 }
2225 else
2226 {
2227 XSetRegion( (Display*) m_display, (GC) m_penGC, (Region) m_currentClippingRegion.GetX11Region() );
2228 XSetRegion( (Display*) m_display, (GC) m_brushGC, (Region) m_currentClippingRegion.GetX11Region() );
2229 XSetRegion( (Display*) m_display, (GC) m_textGC, (Region) m_currentClippingRegion.GetX11Region() );
2230 XSetRegion( (Display*) m_display, (GC) m_bgGC, (Region) m_currentClippingRegion.GetX11Region() );
2231 }
2232}
83df96d6 2233
3cd0b8c5 2234void wxWindowDC::Destroy()
83df96d6 2235{
3cd0b8c5
RR
2236 if (m_penGC) wxFreePoolGC( (GC) m_penGC );
2237 m_penGC = NULL;
2238 if (m_brushGC) wxFreePoolGC( (GC) m_brushGC );
2239 m_brushGC = NULL;
2240 if (m_textGC) wxFreePoolGC( (GC) m_textGC );
2241 m_textGC = NULL;
2242 if (m_bgGC) wxFreePoolGC( (GC) m_bgGC );
2243 m_bgGC = NULL;
2244}
83df96d6 2245
3cd0b8c5
RR
2246void wxWindowDC::ComputeScaleAndOrigin()
2247{
2248 /* CMB: copy scale to see if it changes */
2249 double origScaleX = m_scaleX;
2250 double origScaleY = m_scaleY;
83df96d6 2251
3cd0b8c5 2252 wxDC::ComputeScaleAndOrigin();
83df96d6 2253
3cd0b8c5
RR
2254 /* CMB: if scale has changed call SetPen to recalulate the line width */
2255 if ((m_scaleX != origScaleX || m_scaleY != origScaleY) &&
2256 (m_pen.Ok()))
2257 {
2258 /* this is a bit artificial, but we need to force wxDC to think
2259 the pen has changed */
2260 wxPen pen = m_pen;
2261 m_pen = wxNullPen;
2262 SetPen( pen );
2263 }
83df96d6
JS
2264}
2265
83df96d6
JS
2266wxSize wxWindowDC::GetPPI() const
2267{
2268 return wxSize(100, 100);
2269}
2270
2271int wxWindowDC::GetDepth() const
2272{
3cd0b8c5 2273 wxFAIL_MSG(wxT("not implemented"));
83df96d6 2274
3cd0b8c5
RR
2275 return -1;
2276}
83df96d6 2277
3cd0b8c5
RR
2278//-----------------------------------------------------------------------------
2279// wxClientDC
2280//-----------------------------------------------------------------------------
2281
2282IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
2283
ab6b6b15
RR
2284wxClientDC::wxClientDC( wxWindow *window )
2285 : wxWindowDC( window )
83df96d6 2286{
ab6b6b15 2287 wxCHECK_RET( window, _T("NULL window in wxClientDC::wxClientDC") );
a11672a4 2288
f41bc3e3 2289 m_window = (WXWindow*) window->GetClientAreaWindow();
ab6b6b15 2290
2b5f62a0 2291 // Adjust the client area when the wxWindow is not using 2 X11 windows.
7948c0c2
JS
2292 if (m_window == (WXWindow*) window->GetMainWindow())
2293 {
c2c0dabf
RR
2294 wxPoint ptOrigin = window->GetClientAreaOrigin();
2295 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
2296 wxSize size = window->GetClientSize();
2297 SetClippingRegion(wxPoint(0, 0), size);
7948c0c2 2298 }
83df96d6
JS
2299}
2300
3cd0b8c5 2301void wxClientDC::DoGetSize(int *width, int *height) const
83df96d6 2302{
3cd0b8c5
RR
2303 wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
2304
2305 m_owner->GetClientSize( width, height );
83df96d6
JS
2306}
2307
ab6b6b15
RR
2308// ----------------------------------------------------------------------------
2309// wxPaintDC
2310// ----------------------------------------------------------------------------
2311
2312IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
2313
2314wxPaintDC::wxPaintDC(wxWindow* window)
2315 : wxClientDC(window)
2316{
2317#if USE_PAINT_REGION
2318 if (!window->GetClipPaintRegion())
2319 return;
2320
2321 m_paintClippingRegion = window->GetUpdateRegion();
2322 Region region = (Region) m_paintClippingRegion.GetX11Region();
2323 if (region)
2324 {
2325 m_currentClippingRegion.Union( m_paintClippingRegion );
2326
2327 XSetRegion( (Display*) m_display, (GC) m_penGC, region );
2328 XSetRegion( (Display*) m_display, (GC) m_brushGC, region );
2329 XSetRegion( (Display*) m_display, (GC) m_textGC, region );
2330 XSetRegion( (Display*) m_display, (GC) m_bgGC, region );
2331 }
2332#endif // USE_PAINT_REGION
2333}
2334
83df96d6 2335// ----------------------------------------------------------------------------
3cd0b8c5 2336// wxDCModule
83df96d6
JS
2337// ----------------------------------------------------------------------------
2338
3cd0b8c5 2339class wxDCModule : public wxModule
83df96d6 2340{
3cd0b8c5
RR
2341public:
2342 bool OnInit();
2343 void OnExit();
83df96d6 2344
3cd0b8c5
RR
2345private:
2346 DECLARE_DYNAMIC_CLASS(wxDCModule)
2347};
83df96d6 2348
3cd0b8c5 2349IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
83df96d6 2350
3cd0b8c5
RR
2351bool wxDCModule::OnInit()
2352{
2353 wxInitGCPool();
2354 return TRUE;
83df96d6
JS
2355}
2356
3cd0b8c5 2357void wxDCModule::OnExit()
83df96d6 2358{
3cd0b8c5 2359 wxCleanUpGCPool();
83df96d6 2360}