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