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