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