1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/motif/dcclient.cpp
3// Purpose:     wxClientDC class
4// Author:      Julian Smart
5// Modified by:
6// Created:     01/02/97
7// RCS-ID:      $Id: dcclient.cpp 42787 2006-10-30 22:58:02Z VZ $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12/*
13  About pens, brushes, and the m_autoSetting flag:
14
15  Under X, pens and brushes control some of the same X drawing
16  parameters.  Therefore, it is impossible to independently maintain
17  the current pen and the current brush. Also, some settings depend on
18  the current logical function. The m_currentFill, etc. instance
19  variables remember state across the brush and pen.
20
21  Since pens are used more than brushes, the m_autoSetting flag is used to
22  indicate that a brush was recently used, and SetPen must be called to
23  reinstall the current pen's parameters. If m_autoSetting includes 0x2, then the
24  pens color may need to be set based on XOR.
25
26  There is, unfortunately, some confusion between setting the current pen/brush
27  and actually installing the brush/pen parameters. Both functionalies are
28  perform by SetPen and SetBrush. C'est la vie.
29*/
30
31// ============================================================================
32// declarations
33// ============================================================================
34
35// ----------------------------------------------------------------------------
36// headers
37// ----------------------------------------------------------------------------
38
39// For compilers that support precompilation, includes "wx.h".
40#include "wx/wxprec.h"
41
42#include "wx/dcclient.h"
43
44#ifndef WX_PRECOMP
45    #include "wx/log.h"
46    #include "wx/app.h"
47    #include "wx/window.h"
48    #include "wx/dcmemory.h"
49    #include "wx/math.h"
50    #include "wx/image.h"
51#endif
52
53#ifdef __VMS__
54#pragma message disable nosimpint
55#endif
56#include <Xm/Xm.h>
57#ifdef __VMS__
58#pragma message enable nosimpint
59#endif
60
61#include "wx/motif/private.h"
62
63#ifdef __EMX__
64    #include <float.h>          // for M_PI
65#endif // __EMX__
66
67#include "bdiag.xbm"
68#include "fdiag.xbm"
69#include "cdiag.xbm"
70#include "horiz.xbm"
71#include "verti.xbm"
72#include "cross.xbm"
73
74static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti;
75
76// ----------------------------------------------------------------------------
77// constants
78// ----------------------------------------------------------------------------
79
80// Fudge factor (VZ: what??)
81#define WX_GC_CF 1
82
83// ----------------------------------------------------------------------------
84// macros
85// ----------------------------------------------------------------------------
86
87IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
88IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
89IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
90
91#ifndef IS_HATCH
92    // IS_HATCH exists for WXWIN_COMPATIBILITY_2_4 only
93    // but wxMotif needs it for its internals here
94    #define IS_HATCH(s)    ((s)>=wxFIRST_HATCH && (s)<=wxLAST_HATCH)
95#endif
96
97// FIXME: left over after removal of wxDC::GetOptimization()
98#define GET_OPTIMIZATION false
99
100// ----------------------------------------------------------------------------
101// prototypes
102// ----------------------------------------------------------------------------
103
104static void XCopyRemote(Display *src_display, Display *dest_display,
105                        Drawable src, Drawable dest,
106                        GC destgc,
107                        int srcx, int srcy,
108                        unsigned int w, unsigned int h,
109                        int destx, int desty,
110                        bool more, XImage **cache);
111
112// ============================================================================
113// implementation
114// ============================================================================
115
116/*
117 * compare two doubles and return the larger rounded
118 * to the nearest int
119 */
120static int roundmax(double a, double b)
121{
122    return (int)((a > b ? a : b) + 0.5);
123}
124
125/*
126 * compare two doubles and return the smaller rounded
127 * to the nearest int
128 */
129static int roundmin(double a, double b)
130{
131    return (int)((a < b ? a : b) - 0.5);
132}
133
134
135// ----------------------------------------------------------------------------
136// wxWindowDC
137// ----------------------------------------------------------------------------
138
139void wxWindowDC::Init()
140{
141    m_gc = (WXGC) 0;
142    m_gcBacking = (WXGC) 0;
143    m_window = NULL;
144    m_backgroundPixel = -1;
145    m_currentPenWidth = 1;
146    m_currentPenJoin = -1;
147    m_currentPenDashCount = -1;
148    m_currentPenDash = (wxX11Dash*) NULL;
149    m_currentStyle = -1;
150    m_currentFill = -1;
151    m_colour = wxColourDisplay();
152    m_display = (WXDisplay*) NULL;
153    m_pixmap = (WXPixmap) 0;
154    m_autoSetting = 0;
155    m_ok = false;
156    m_clipRegion = (WXRegion) 0;
157}
158
159wxWindowDC::wxWindowDC()
160{
161    Init();
162}
163
164wxWindowDC::wxWindowDC( wxWindow *window )
165{
166    wxASSERT_MSG( (window != (wxWindow*) NULL), "You must pass a valid wxWindow to wxWindowDC/wxClientDC/wxPaintDC constructor." );
167
168    Init();
169
170    m_window = window;
171    m_font = window->GetFont();
172    m_ok = true;
173
174    m_display = window->GetXDisplay();
175    m_pixmap = window->GetXWindow();
176    Display* display = (Display*) m_display;
177
178    XSetWindowColormap (display, (Pixmap) m_pixmap, (Colormap) wxTheApp->GetMainColormap(m_display));
179
180    XGCValues gcvalues;
181    gcvalues.foreground = BlackPixel (display, DefaultScreen (display));
182    gcvalues.background = WhitePixel (display, DefaultScreen (display));
183    gcvalues.graphics_exposures = False;
184    gcvalues.subwindow_mode = IncludeInferiors;
185    gcvalues.line_width = 1;
186    m_gc = (WXGC) XCreateGC (display, RootWindow (display, DefaultScreen (display)),
187        GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode,
188        &gcvalues);
189
190    if (m_window->GetBackingPixmap())
191    {
192        m_gcBacking = (WXGC) XCreateGC (display, RootWindow (display,
193            DefaultScreen (display)),
194            GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode,
195            &gcvalues);
196    }
197
198    m_backgroundPixel = gcvalues.background;
199
200    SetBackground(wxBrush(m_window->GetBackgroundColour(), wxSOLID));
201}
202
203wxWindowDC::~wxWindowDC()
204{
205    if (m_gc)
206        XFreeGC ((Display*) m_display, (GC) m_gc);
207    m_gc = (WXGC) 0;
208
209    if (m_gcBacking)
210        XFreeGC ((Display*) m_display, (GC) m_gcBacking);
211    m_gcBacking = (WXGC) 0;
212
213    if (m_clipRegion)
214        XDestroyRegion ((Region) m_clipRegion);
215    m_clipRegion = (WXRegion) 0;
216}
217
218extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
219                          const wxColour & col, int style);
220
221bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y,
222                             const wxColour& col, int style)
223{
224    return wxDoFloodFill(this, x, y, col, style);
225}
226
227bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
228{
229    // Generic (and therefore rather inefficient) method.
230    // Could be improved.
231    wxMemoryDC memdc;
232    wxBitmap bitmap(1, 1);
233    memdc.SelectObject(bitmap);
234    memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
235    memdc.SelectObject(wxNullBitmap);
236    wxImage image = bitmap.ConvertToImage();
237    col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
238    return true;
239}
240
241void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
242{
243    wxCHECK_RET( Ok(), "invalid dc" );
244
245    int x1d, y1d, x2d, y2d;
246
247    x1d = XLOG2DEV(x1);
248    y1d = YLOG2DEV(y1);
249    x2d = XLOG2DEV(x2);
250    y2d = YLOG2DEV(y2);
251
252    if (m_autoSetting)
253        SetPen (m_pen);
254
255    XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x1d, y1d, x2d, y2d);
256
257    if (m_window && m_window->GetBackingPixmap())
258        XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
259        XLOG2DEV_2(x1), YLOG2DEV_2(y1),
260        XLOG2DEV_2(x2), YLOG2DEV_2(y2));
261
262    CalcBoundingBox(x1, y1);
263    CalcBoundingBox(x2, y2);
264}
265
266void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
267{
268    wxCHECK_RET( Ok(), "invalid dc" );
269
270    if (m_autoSetting)
271        SetPen (m_pen);
272
273    int xx = XLOG2DEV (x);
274    int yy = YLOG2DEV (y);
275    int ww, hh;
276    wxDisplaySize (&ww, &hh);
277    XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, yy,
278        ww, yy);
279    XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xx, 0,
280        xx, hh);
281
282    if (m_window && m_window->GetBackingPixmap())
283    {
284        xx = XLOG2DEV_2 (x);
285        yy = YLOG2DEV_2 (y);
286        XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
287            0, yy,
288            ww, yy);
289        XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
290            xx, 0,
291            xx, hh);
292    }
293}
294
295void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
296{
297    wxCHECK_RET( Ok(), "invalid dc" );
298
299    int xx1 = XLOG2DEV (x1);
300    int yy1 = YLOG2DEV (y1);
301    int xx2 = XLOG2DEV (x2);
302    int yy2 = YLOG2DEV (y2);
303    int xxc = XLOG2DEV (xc);
304    int yyc = YLOG2DEV (yc);
305    int xxc_2 = XLOG2DEV_2 (xc);
306    int yyc_2 = YLOG2DEV_2 (yc);
307
308    wxCoord dx = xx1 - xxc;
309    wxCoord dy = yy1 - yyc;
310    double radius = sqrt ((double)(dx * dx + dy * dy));
311    wxCoord r = (wxCoord) radius;
312
313    double radius1, radius2;
314
315    if (xx1 == xx2 && yy1 == yy2)
316    {
317        radius1 = 0.0;
318        radius2 = 360.0;
319    }
320    else if (radius == 0.0)
321        radius1 = radius2 = 0.0;
322    else
323    {
324        if (xx1 - xxc == 0)
325            if (yy1 - yyc < 0)
326                radius1 = 90.0;
327            else
328                radius1 = -90.0;
329            else
330                radius1 = -atan2 ((double) (yy1 - yyc), (double) (xx1 - xxc)) * 360.0 / (2 * M_PI);
331
332            if (xx2 - xxc == 0)
333                if (yy2 - yyc < 0)
334                    radius2 = 90.0;
335                else
336                    radius2 = -90.0;
337                else
338                    radius2 = -atan2 ((double) (yy2 - yyc), (double) (xx2 - xxc)) * 360.0 / (2 * M_PI);
339    }
340    radius1 *= 64.0;
341    radius2 *= 64.0;
342    int alpha1 = (int) radius1;
343    int alpha2 = (int) (radius2 - radius1);
344    while (alpha2 <= 0)
345        alpha2 += 360 * 64;
346    while (alpha2 > 360 * 64)
347        alpha2 -= 360 * 64;
348
349    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
350    {
351        SetBrush (m_brush);
352        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) (GC) m_gc,
353            xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2);
354
355        if (m_window && m_window->GetBackingPixmap())
356            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
357            xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2);
358
359    }
360
361    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
362    {
363        if (m_autoSetting)
364            SetPen (m_pen);
365        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc,
366            xxc - r, yyc - r, 2 * r, 2 * r, alpha1, alpha2);
367
368        if (m_window && m_window->GetBackingPixmap())
369            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
370            xxc_2 - r, yyc_2 - r, 2 * r, 2 * r, alpha1, alpha2);
371    }
372    CalcBoundingBox (x1, y1);
373    CalcBoundingBox (x2, y2);
374}
375
376void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
377{
378    wxCHECK_RET( Ok(), "invalid dc" );
379
380    int xd, yd, wd, hd;
381
382    xd = XLOG2DEV(x);
383    yd = YLOG2DEV(y);
384    wd = XLOG2DEVREL(width);
385    hd = YLOG2DEVREL(height);
386
387    if (sa>=360 || sa<=-360) sa=sa-int(sa/360)*360;
388    if (ea>=360 || ea<=-360) ea=ea-int(ea/360)*360;
389    int start = int(sa*64);
390    int end   = int(ea*64);
391    if (start<0) start+=360*64;
392    if (end  <0) end  +=360*64;
393    if (end>start) end-=start;
394    else end+=360*64-start;
395
396    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
397    {
398        m_autoSetting = true;    // must be reset
399
400        SetBrush (m_brush);
401        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start, end);
402
403        if (m_window && m_window->GetBackingPixmap())
404            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
405            XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end);
406    }
407
408    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
409    {
410        if (m_autoSetting)
411            SetPen (m_pen);
412        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, start,end);
413        if (m_window && m_window->GetBackingPixmap())
414            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
415            XLOG2DEV_2 (x), YLOG2DEV_2 (y),wd,hd,start,end);
416    }
417    CalcBoundingBox (x, y);
418    CalcBoundingBox (x + width, y + height);
419}
420
421void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
422{
423    wxCHECK_RET( Ok(), "invalid dc" );
424
425    if (m_pen.Ok() && m_autoSetting)
426        SetPen (m_pen);
427
428    XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y));
429    if (m_window && m_window->GetBackingPixmap())
430        XDrawPoint ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, XLOG2DEV_2 (x), YLOG2DEV_2 (y));
431
432    CalcBoundingBox (x, y);
433}
434
435void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
436{
437    wxCHECK_RET( Ok(), "invalid dc" );
438
439    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
440    {
441        if (m_autoSetting)
442            SetPen (m_pen);
443
444        XPoint *xpoints = new XPoint[n];
445        int i;
446
447        for (i = 0; i < n; i++)
448        {
449            xpoints[i].x = (short)XLOG2DEV (points[i].x + xoffset);
450            xpoints[i].y = (short)YLOG2DEV (points[i].y + yoffset);
451        }
452        XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints, n, 0);
453
454        if (m_window && m_window->GetBackingPixmap())
455        {
456            for (i = 0; i < n; i++)
457            {
458                xpoints[i].x = (short)XLOG2DEV_2 (points[i].x + xoffset);
459                xpoints[i].y = (short)YLOG2DEV_2 (points[i].y + yoffset);
460            }
461            XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints, n, 0);
462        }
463        delete[]xpoints;
464    }
465}
466
467void wxWindowDC::DoDrawPolygon( int n, wxPoint points[],
468                                wxCoord xoffset, wxCoord yoffset, int fillStyle )
469{
470    wxCHECK_RET( Ok(), "invalid dc" );
471
472    XPoint *xpoints1 = new XPoint[n + 1];
473    XPoint *xpoints2 = new XPoint[n + 1];
474    int i;
475    for (i = 0; i < n; i++)
476    {
477        xpoints1[i].x = (short)XLOG2DEV (points[i].x + xoffset);
478        xpoints1[i].y = (short)YLOG2DEV (points[i].y + yoffset);
479        xpoints2[i].x = (short)XLOG2DEV_2 (points[i].x + xoffset);
480        xpoints2[i].y = (short)YLOG2DEV_2 (points[i].y + yoffset);
481        CalcBoundingBox (points[i].x + xoffset, points[i].y + yoffset);
482    }
483
484    // Close figure for XDrawLines (not needed for XFillPolygon)
485    xpoints1[i].x = xpoints1[0].x;
486    xpoints1[i].y = xpoints1[0].y;
487    xpoints2[i].x = xpoints2[0].x;
488    xpoints2[i].y = xpoints2[0].y;
489
490    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
491    {
492        SetBrush (m_brush);
493        XSetFillRule ((Display*) m_display, (GC) m_gc, fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule);
494        XFillPolygon ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n, Complex, 0);
495        XSetFillRule ((Display*) m_display, (GC) m_gc, EvenOddRule);    // default mode
496        if (m_window && m_window->GetBackingPixmap())
497        {
498            XSetFillRule ((Display*) m_display,(GC) m_gcBacking,
499                fillStyle == wxODDEVEN_RULE ? EvenOddRule : WindingRule);
500            XFillPolygon ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n, Complex, 0);
501            XSetFillRule ((Display*) m_display,(GC) m_gcBacking, EvenOddRule);    // default mode
502        }
503    }
504
505    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
506    {
507        if (m_autoSetting)
508            SetPen (m_pen);
509        XDrawLines ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xpoints1, n + 1, 0);
510
511        if (m_window && m_window->GetBackingPixmap())
512            XDrawLines ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, xpoints2, n + 1, 0);
513    }
514
515    delete[]xpoints1;
516    delete[]xpoints2;
517}
518
519void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
520{
521    wxCHECK_RET( Ok(), "invalid dc" );
522
523    int xd, yd, wfd, hfd, wd, hd;
524
525    xd = XLOG2DEV(x);
526    yd = YLOG2DEV(y);
527    wfd = XLOG2DEVREL(width);
528    wd = wfd - WX_GC_CF;
529    hfd = YLOG2DEVREL(height);
530    hd = hfd - WX_GC_CF;
531
532    if (wfd == 0 || hfd == 0) return;
533    if (wd < 0) { wd = - wd; xd = xd - wd; }
534    if (hd < 0) { hd = - hd; yd = yd - hd; }
535
536    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
537    {
538        SetBrush (m_brush);
539        XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wfd, hfd);
540
541        if (m_window && m_window->GetBackingPixmap())
542            XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
543            XLOG2DEV_2 (x), YLOG2DEV_2 (y),
544            wfd, hfd);
545    }
546
547    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
548    {
549        if (m_autoSetting)
550            SetPen (m_pen);
551        XDrawRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd);
552
553        if (m_window && m_window->GetBackingPixmap())
554            XDrawRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
555            XLOG2DEV_2 (x), YLOG2DEV_2 (y),
556            wd, hd);
557    }
558    CalcBoundingBox (x, y);
559    CalcBoundingBox (x + width, y + height);
560}
561
562void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
563{
564    wxCHECK_RET( Ok(), "invalid dc" );
565
566    // If radius is negative, it's a proportion of the smaller dimension.
567
568    if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
569
570    int xd = XLOG2DEV (x);
571    int yd = YLOG2DEV (y);
572    int rd = XLOG2DEVREL ((long) radius);
573    int wd = XLOG2DEVREL (width) - WX_GC_CF;
574    int hd = YLOG2DEVREL (height) - WX_GC_CF;
575
576    int rw_d = rd * 2;
577    int rh_d = rw_d;
578
579    // If radius is zero use DrawRectangle() instead to avoid
580    // X drawing errors with small radii
581    if (rd == 0)
582    {
583        DrawRectangle( x, y, width, height );
584        return;
585    }
586
587    // Draw nothing if transformed w or h is 0
588    if (wd == 0 || hd == 0) return;
589
590    // CMB: adjust size if outline is drawn otherwise the result is
591    // 1 pixel too wide and high
592    if (m_pen.GetStyle() != wxTRANSPARENT)
593    {
594        wd--;
595        hd--;
596    }
597
598    // CMB: ensure dd is not larger than rectangle otherwise we
599    // get an hour glass shape
600    if (rw_d > wd) rw_d = wd;
601    if (rw_d > hd) rw_d = hd;
602    rd = rw_d / 2;
603
604    // For backing pixmap
605    int xd2 = XLOG2DEV_2 (x);
606    int yd2 = YLOG2DEV_2 (y);
607    int rd2 = XLOG2DEVREL ((long) radius);
608    int wd2 = XLOG2DEVREL (width) ;
609    int hd2 = YLOG2DEVREL (height) ;
610
611    int rw_d2 = rd2 * 2;
612    int rh_d2 = rw_d2;
613
614    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
615    {
616        SetBrush (m_brush);
617
618        XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd,
619            wd - rw_d, hd);
620        XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd,
621            wd, hd - rh_d);
622
623        // Arcs start from 3 o'clock, positive angles anticlockwise
624        // Top-left
625        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd,
626            rw_d, rh_d, 90 * 64, 90 * 64);
627        // Top-right
628        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd,
629            //        rw_d, rh_d, 0, 90 * 64);
630            rw_d, rh_d, 0, 91 * 64);
631        // Bottom-right
632        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d,
633            yd + hd - rh_d,
634            //        rw_d, rh_d, 270 * 64, 90 * 64);
635            rw_d, rh_d, 269 * 64, 92 * 64);
636        // Bottom-left
637        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d,
638            rw_d, rh_d, 180 * 64, 90 * 64);
639
640        if (m_window && m_window->GetBackingPixmap())
641        {
642            XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
643                xd2 + rd2, yd2, wd2 - rw_d2, hd2);
644            XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
645                xd2, yd2 + rd2, wd2, hd2 - rh_d2);
646
647            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
648                xd2, yd2, rw_d2, rh_d2, 90 * 64, 90 * 64);
649            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
650                xd2 + wd2 - rw_d2, yd2,
651                //            rw_d2, rh_d2, 0, 90 * 64);
652                rw_d2, rh_d2, 0, 91 * 64);
653            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
654                xd2 + wd2 - rw_d2,
655                yd2 + hd2 - rh_d2,
656                //            rw_d2, rh_d2, 270 * 64, 90 * 64);
657                rw_d2, rh_d2, 269 * 64, 92 * 64);
658            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
659                xd2, yd2 + hd2 - rh_d2,
660                rw_d2, rh_d2, 180 * 64, 90 * 64);
661        }
662    }
663
664    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
665    {
666        SetPen (m_pen);
667        XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd,
668            xd + wd - rd + 1, yd);
669        XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + rd, yd + hd,
670            xd + wd - rd, yd + hd);
671
672        XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + rd,
673            xd, yd + hd - rd);
674        XDrawLine ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd, yd + rd,
675            xd + wd, yd + hd - rd + 1);
676        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd,
677            rw_d, rh_d, 90 * 64, 90 * 64);
678        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d, yd,
679            //        rw_d, rh_d, 0, 90 * 64);
680            rw_d, rh_d, 0, 91 * 64);
681        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd + wd - rw_d,
682            yd + hd - rh_d,
683            rw_d, rh_d, 269 * 64, 92 * 64);
684        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd + hd - rh_d,
685            rw_d, rh_d, 180 * 64, 90 * 64);
686
687        if (m_window && m_window->GetBackingPixmap())
688        {
689            XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
690                xd2 + rd2, yd2,
691                xd2 + wd2 - rd2 + 1, yd2);
692            XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
693                xd2 + rd2, yd2 + hd2,
694                xd2 + wd2 - rd2, yd2 + hd2);
695
696            XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
697                xd2, yd2 + rd2,
698                xd2, yd2 + hd2 - rd2);
699            XDrawLine ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
700                xd2 + wd2, yd2 + rd2,
701                xd2 + wd2, yd2 + hd2 - rd2 + 1);
702            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
703                xd2, yd2,
704                rw_d2, rh_d2, 90 * 64, 90 * 64);
705            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
706                xd2 + wd2 - rw_d2, yd2,
707                //            rw_d2, rh_d2, 0, 90 * 64);
708                rw_d2, rh_d2, 0, 91 * 64);
709            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
710                xd2 + wd2 - rw_d2,
711                yd2 + hd2 - rh_d2,
712                rw_d2, rh_d2, 269 * 64, 92 * 64);
713            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
714                xd2, yd2 + hd2 - rh_d2,
715                rw_d2, rh_d2, 180 * 64, 90 * 64);
716        }
717    }
718    CalcBoundingBox (x, y);
719    CalcBoundingBox (x + width, y + height);
720}
721
722void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
723{
724    wxCHECK_RET( Ok(), "invalid dc" );
725
726    // Check for negative width and height
727    if (height < 0)
728    {
729        y = y + height;
730        height = - height ;
731    }
732
733    if (width < 0)
734    {
735        x = x + width;
736        width = - width ;
737    }
738
739    static const int angle = 23040;
740
741    int xd, yd, wd, hd;
742
743    xd = XLOG2DEV(x);
744    yd = YLOG2DEV(y);
745    wd = XLOG2DEVREL(width) ;
746    hd = YLOG2DEVREL(height) ;
747
748    if (m_brush.Ok() && m_brush.GetStyle () != wxTRANSPARENT)
749    {
750        SetBrush (m_brush);
751        XFillArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle);
752        if (m_window && m_window->GetBackingPixmap())
753            XFillArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
754            XLOG2DEV_2 (x), YLOG2DEV_2 (y),
755            XLOG2DEVREL (width) - WX_GC_CF,
756            YLOG2DEVREL (height) - WX_GC_CF, 0, angle);
757    }
758
759    if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
760    {
761        if (m_autoSetting)
762            SetPen (m_pen);
763        XDrawArc ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, xd, yd, wd, hd, 0, angle);
764        if (m_window && m_window->GetBackingPixmap())
765            XDrawArc ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
766            XLOG2DEV_2 (x), YLOG2DEV_2 (y),
767            XLOG2DEVREL (width) - WX_GC_CF,
768            YLOG2DEVREL (height) - WX_GC_CF, 0, angle);
769    }
770    CalcBoundingBox (x, y);
771    CalcBoundingBox (x + width, y + height);
772
773}
774
775bool wxWindowDC::CanDrawBitmap() const
776{
777    wxCHECK_MSG( Ok(), false, "invalid dc" );
778
779    return true;
780}
781
782// TODO: use scaled Blit e.g. as per John Price's implementation
783// in Contrib/Utilities
784bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
785                         wxCoord width, wxCoord height,
786                         wxDC *source, wxCoord xsrc, wxCoord ysrc,
787                         int rop, bool useMask,
788                         wxCoord xsrcMask, wxCoord ysrcMask )
789{
790    wxCHECK_MSG( Ok(), false, "invalid dc" );
791
792    wxWindowDC* sourceDC = wxDynamicCast(source, wxWindowDC);
793
794    wxASSERT_MSG( sourceDC, "Blit source DC must be wxWindowDC or derived class." );
795
796    // Be sure that foreground pixels (1) of the Icon will be painted with
797    // foreground colour. [m_textForegroundColour] Background pixels (0)
798    // will be painted with backgound colour (m_textBackgroundColour)
799    // Using ::SetPen is horribly slow, so avoid doing it
800    WXPixel oldBackgroundPixel = -1;
801    WXPixel oldForegroundPixel = -1;
802
803    if (m_textBackgroundColour.Ok())
804    {
805        oldBackgroundPixel = m_backgroundPixel;
806        WXPixel pixel = m_textBackgroundColour.AllocColour(m_display);
807
808        XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
809        if (m_window && m_window->GetBackingPixmap())
810            XSetBackground ((Display*) m_display,(GC) m_gcBacking,
811                            pixel);
812    }
813    if (m_textForegroundColour.Ok())
814    {
815        oldForegroundPixel = m_currentColour.GetPixel();
816
817        if( m_textForegroundColour.GetPixel() <= -1 )
818            CalculatePixel( m_textForegroundColour,
819                            m_textForegroundColour, true);
820
821        WXPixel pixel = m_textForegroundColour.GetPixel();
822        if (pixel > -1)
823            SetForegroundPixelWithLogicalFunction(pixel);
824    }
825
826    // Do bitmap scaling if necessary
827
828    wxBitmap *scaledBitmap = (wxBitmap*) NULL;
829    Pixmap sourcePixmap = (Pixmap) NULL;
830    double scaleX, scaleY;
831    GetUserScale(& scaleX, & scaleY);
832    bool retVal = false;
833
834    /* TODO: use the mask origin when drawing transparently */
835    if (xsrcMask == -1 && ysrcMask == -1)
836    {
837        xsrcMask = xsrc; ysrcMask = ysrc;
838    }
839
840    // Sorry, can't scale masks just yet
841    if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC)))
842    {
843        wxMemoryDC* memDC = (wxMemoryDC*) sourceDC;
844        wxBitmap& bitmap = memDC->GetBitmap();
845
846        wxASSERT_MSG( (bitmap.Ok()), "Bad source bitmap in wxWindowDC::Blit");
847
848        wxImage image = bitmap.ConvertToImage();
849        if (!image.Ok())
850        {
851            sourcePixmap = (Pixmap) bitmap.GetDrawable();
852        }
853        else
854        {
855            int scaledW = (int) (bitmap.GetWidth() * scaleX);
856            int scaledH = (int) (bitmap.GetHeight() * scaleY);
857
858            image = image.Scale(scaledW, scaledH);
859            scaledBitmap = new wxBitmap(image);
860            sourcePixmap = (Pixmap) scaledBitmap->GetDrawable();
861        }
862    }
863    else
864        sourcePixmap = (Pixmap) sourceDC->m_pixmap;
865
866    if (m_pixmap && sourcePixmap)
867    {
868        /* MATTHEW: [9] */
869        int orig = m_logicalFunction;
870
871        SetLogicalFunction (rop);
872
873        if (m_display != sourceDC->m_display)
874        {
875            XImage *cache = NULL;
876
877            if (m_window && m_window->GetBackingPixmap())
878                XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display,
879                (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),
880                (GC) m_gcBacking,
881                source->LogicalToDeviceX (xsrc),
882                source->LogicalToDeviceY (ysrc),
883                source->LogicalToDeviceXRel(width),
884                source->LogicalToDeviceYRel(height),
885                XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
886                True, &cache);
887
888            if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
889            {
890                wxMemoryDC *memDC = (wxMemoryDC *)source;
891                wxBitmap& sel = memDC->GetBitmap();
892                if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() )
893                {
894                    XSetClipMask   ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
895                    XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
896                }
897            }
898
899            XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
900                source->LogicalToDeviceX (xsrc),
901                source->LogicalToDeviceY (ysrc),
902                source->LogicalToDeviceXRel(width),
903                source->LogicalToDeviceYRel(height),
904                XLOG2DEV (xdest), YLOG2DEV (ydest),
905                False, &cache);
906
907            if ( useMask )
908            {
909                if ( m_clipRegion )
910                    XSetRegion ((Display*) m_display, (GC) m_gc,
911                                (Region) m_clipRegion);
912                else
913                    XSetClipMask   ((Display*) m_display, (GC) m_gc, None);
914
915                XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
916            }
917
918        } else
919        {        //XGCValues values;
920        //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
921
922            if (m_window && m_window->GetBackingPixmap())
923            {
924                // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
925                if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1)
926                {
927                    XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
928                        source->LogicalToDeviceX (xsrc),
929                        source->LogicalToDeviceY (ysrc),
930                        source->LogicalToDeviceXRel(width),
931                        source->LogicalToDeviceYRel(height),
932                        XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
933                }
934                else
935                {
936                    XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
937                        source->LogicalToDeviceX (xsrc),
938                        source->LogicalToDeviceY (ysrc),
939                        source->LogicalToDeviceXRel(width),
940                        source->LogicalToDeviceYRel(height),
941                        XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
942                }
943            }
944            if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
945            {
946                wxMemoryDC *memDC = (wxMemoryDC *)source;
947                wxBitmap& sel = memDC->GetBitmap();
948                if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetBitmap() )
949                {
950                    XSetClipMask   ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
951                    XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
952                }
953            }
954
955            // Check if we're copying from a mono bitmap
956            if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
957                ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1))
958            {
959                XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
960                    source->LogicalToDeviceX (xsrc),
961                    source->LogicalToDeviceY (ysrc),
962                    source->LogicalToDeviceXRel(width),
963                    source->LogicalToDeviceYRel(height),
964                    XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
965            }
966            else
967            {
968                XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
969                    source->LogicalToDeviceX (xsrc),
970                    source->LogicalToDeviceY (ysrc),
971                    source->LogicalToDeviceXRel(width),
972                    source->LogicalToDeviceYRel(height),
973                    XLOG2DEV (xdest), YLOG2DEV (ydest));
974
975            }
976            if ( useMask )
977            {
978                if ( m_clipRegion )
979                    XSetRegion ((Display*) m_display, (GC) m_gc,
980                                (Region) m_clipRegion);
981                else
982                    XSetClipMask   ((Display*) m_display, (GC) m_gc, None);
983
984                XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
985            }
986
987        } /* Remote/local (Display*) m_display */
988        CalcBoundingBox (xdest, ydest);
989        CalcBoundingBox (xdest + width, ydest + height);
990
991        SetLogicalFunction(orig);
992
993        retVal = true;
994  }
995  if (scaledBitmap) delete scaledBitmap;
996
997  if (oldBackgroundPixel > -1)
998  {
999      XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
1000      if (m_window && m_window->GetBackingPixmap())
1001          XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1002                          oldBackgroundPixel);
1003  }
1004  if (oldForegroundPixel > -1)
1005  {
1006      XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1007      if (m_window && m_window->GetBackingPixmap())
1008          XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1009                          oldForegroundPixel);
1010  }
1011
1012  return retVal;
1013}
1014
1015void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1016{
1017    wxCHECK_RET( Ok(), "invalid dc" );
1018
1019    // Since X draws from the baseline of the text, must add the text height
1020    int cx = 0;
1021    int cy = 0;
1022    int ascent = 0;
1023    int slen = text.length();
1024
1025    // Set FillStyle, otherwise X will use current stipple!
1026    XGCValues gcV, gcBackingV;
1027
1028    XGetGCValues ((Display*) m_display, (GC)m_gc, GCFillStyle, &gcV);
1029    XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1030    if (m_window && m_window->GetBackingPixmap())
1031    {
1032        XGetGCValues ((Display*) m_display, (GC)m_gcBacking, GCFillStyle,
1033                      &gcBackingV );
1034        XSetFillStyle ((Display*) m_display, (GC) m_gcBacking, FillSolid);
1035    }
1036
1037    if (m_font.Ok())
1038        wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1039                         text, &cx, &cy, &ascent, NULL);
1040
1041    // First draw a rectangle representing the text background, if a text
1042    // background is specified
1043    if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1044    {
1045        wxColour oldPenColour = m_currentColour;
1046        m_currentColour = m_textBackgroundColour;
1047        bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1048            (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1049            (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1050            (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1051
1052        // This separation of the big && test required for gcc2.7/HP UX 9.02
1053        // or pixel value can be corrupted!
1054        sameColour = (sameColour &&
1055            (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1056
1057        if (!sameColour || !GET_OPTIMIZATION)
1058        {
1059            WXPixel pixel = m_textBackgroundColour.AllocColour(m_display);
1060            m_currentColour = m_textBackgroundColour;
1061
1062            // Set the GC to the required colour
1063            if (pixel > -1)
1064            {
1065                XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1066                if (m_window && m_window->GetBackingPixmap())
1067                    XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1068            }
1069        }
1070        else
1071            m_textBackgroundColour = oldPenColour ;
1072
1073        XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1074        if (m_window && m_window->GetBackingPixmap())
1075            XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1076            XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1077    }
1078
1079    // Now set the text foreground and draw the text
1080    if (m_textForegroundColour.Ok ())
1081    {
1082        wxColour oldPenColour = m_currentColour;
1083        m_currentColour = m_textForegroundColour;
1084        bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1085            (oldPenColour.Red () == m_currentColour.Red ()) &&
1086            (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1087            (oldPenColour.Green () == m_currentColour.Green ()) &&
1088            (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1089
1090        if (!sameColour || !GET_OPTIMIZATION)
1091        {
1092            WXPixel pixel = CalculatePixel(m_textForegroundColour,
1093                                           m_currentColour, false);
1094
1095            // Set the GC to the required colour
1096            if (pixel > -1)
1097            {
1098                XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1099                if (m_window && m_window->GetBackingPixmap())
1100                    XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1101            }
1102        }
1103        else
1104            m_textForegroundColour = oldPenColour;
1105    }
1106
1107    // We need to add the ascent, not the whole height, since X draws at the
1108    // point above the descender.
1109#if 0
1110    if (use16)
1111        XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1112        (XChar2b *)(char*) (const char*) text, slen);
1113    else
1114#endif // 0
1115#if wxMOTIF_NEW_FONT_HANDLING
1116        XFontSet fset = (XFontSet) m_font.GetFontSet (m_userScaleY * m_logicalScaleY, m_display);
1117        XmbDrawString((Display*) m_display, (Pixmap) m_pixmap, fset, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1118#else
1119        XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1120#endif
1121
1122    if (m_window && m_window->GetBackingPixmap()) {
1123#if 0
1124        if (use16)
1125            XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1126            XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1127            (XChar2b *)(char*) (const char*) text, slen);
1128        else
1129#endif // 0
1130#if wxMOTIF_NEW_FONT_HANDLING
1131            XmbDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), fset, (GC) m_gcBacking,
1132            XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1133                        wxConstCast(text.c_str(), char), slen);
1134#else
1135            XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1136            XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1137                        wxConstCast(text.c_str(), char), slen);
1138#endif
1139    }
1140
1141    // restore fill style
1142    XSetFillStyle ((Display*) m_display, (GC) m_gc, gcV.fill_style);
1143    if (m_window && m_window->GetBackingPixmap())
1144        XSetFillStyle ((Display*) m_display, (GC) m_gcBacking,
1145                       gcBackingV.fill_style);
1146
1147    wxCoord w, h;
1148    GetTextExtent (text, &w, &h);
1149    CalcBoundingBox (x + w, y + h);
1150    CalcBoundingBox (x, y);
1151}
1152
1153void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y,
1154                                    double angle )
1155{
1156    if (angle == 0.0)
1157    {
1158        DrawText(text, x, y);
1159        return;
1160    }
1161
1162    wxCHECK_RET( Ok(), "invalid dc" );
1163
1164    WXPixel oldBackgroundPixel = -1;
1165    WXPixel oldForegroundPixel = -1;
1166    WXPixel foregroundPixel = -1;
1167    WXPixel backgroundPixel = -1;
1168
1169    if (m_textBackgroundColour.Ok())
1170    {
1171        oldBackgroundPixel = m_backgroundPixel;
1172        backgroundPixel = m_textBackgroundColour.AllocColour(m_display);
1173    }
1174    if (m_textForegroundColour.Ok())
1175    {
1176        oldForegroundPixel = m_currentColour.GetPixel();
1177
1178        if( m_textForegroundColour.GetPixel() <= -1 )
1179            CalculatePixel( m_textForegroundColour,
1180                            m_textForegroundColour, true);
1181
1182        foregroundPixel = m_textForegroundColour.GetPixel();
1183    }
1184
1185    // Since X draws from the baseline of the text, must add the text height
1186    int cx = 0;
1187    int cy = 0;
1188    int ascent = 0;
1189
1190    if (m_font.Ok())
1191        wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1192                         text, &cx, &cy, &ascent, NULL);
1193
1194    wxBitmap src(cx, cy);
1195    wxMemoryDC dc;
1196    dc.SelectObject(src);
1197    dc.SetFont(GetFont());
1198    dc.SetBackground(*wxWHITE_BRUSH);
1199    dc.SetBrush(*wxBLACK_BRUSH);
1200    dc.Clear();
1201    dc.DrawText(text, 0, 0);
1202    dc.SetFont(wxNullFont);
1203
1204    // Calculate the size of the rotated bounding box.
1205    double dx = cos(angle / 180.0 * M_PI);
1206    double dy = sin(angle / 180.0 * M_PI);
1207    double x4 = cy * dy;
1208    double y4 = cy * dx;
1209    double x3 = cx * dx;
1210    double y3 = -cx * dy;
1211    double x2 = x3 + x4;
1212    double y2 = y3 + y4;
1213    double x1 = x;
1214    double y1 = y;
1215
1216    // Create image from the source bitmap after writing the text into it.
1217    wxImage  image = src.ConvertToImage();
1218
1219    int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1220    int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1221    int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1222    int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1223
1224    bool lastFore = false, lastBack = false;
1225
1226    // This rotates counterclockwise around the top left corner.
1227    for (int rx = minx; rx < maxx; rx++)
1228    {
1229        for (int ry = miny; ry < maxy; ry++)
1230        {
1231            // transform dest coords to source coords
1232            int sx = (int) (rx * dx - ry * dy + 0.5);
1233            int sy = - (int) (-ry * dx - rx * dy + 0.5);
1234            if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1235            {
1236                bool textPixel = image.GetRed(sx, sy) == 0;
1237
1238                if (!textPixel && m_backgroundMode != wxSOLID)
1239                    continue;
1240
1241                wxCoord ox = (wxCoord) (x1 + rx),
1242                        oy = (wxCoord) (y1 + ry);
1243                // draw black pixels, ignore white ones (i.e. transparent b/g)
1244                if (textPixel && !lastFore)
1245                {
1246                    XSetForeground ((Display*) m_display, (GC) m_gc,
1247                                    foregroundPixel);
1248                    lastFore = true;
1249                    lastBack = false;
1250                }
1251                else if (!textPixel && !lastBack)
1252                {
1253                    XSetForeground ((Display*) m_display, (GC) m_gc,
1254                                    backgroundPixel);
1255                    lastFore = false;
1256                    lastBack = true;
1257                }
1258
1259                XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap,
1260                            (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy));
1261                if (m_window && m_window->GetBackingPixmap())
1262                    XDrawPoint ((Display*) m_display,
1263                                (Pixmap) m_window->GetBackingPixmap(),
1264                                (GC) m_gcBacking,
1265                                XLOG2DEV_2 (ox), YLOG2DEV_2 (oy));
1266            }
1267        }
1268    }
1269
1270    if (oldBackgroundPixel > -1)
1271    {
1272        XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
1273        if (m_window && m_window->GetBackingPixmap())
1274            XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1275                            oldBackgroundPixel);
1276    }
1277    if (oldForegroundPixel > -1)
1278    {
1279        XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1280        if (m_window && m_window->GetBackingPixmap())
1281            XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1282                            oldForegroundPixel);
1283    }
1284
1285    CalcBoundingBox (minx, miny);
1286    CalcBoundingBox (maxx, maxy);
1287}
1288
1289bool wxWindowDC::CanGetTextExtent() const
1290{
1291    return true;
1292}
1293
1294void wxWindowDC::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1295                                wxCoord *descent, wxCoord *externalLeading,
1296                                wxFont *font ) const
1297{
1298    wxCHECK_RET( Ok(), "invalid dc" );
1299
1300    const wxFont* theFont = font ? font : &m_font;
1301
1302    if (!theFont->Ok())
1303    {
1304        // TODO: this should be an error log function
1305        wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1306
1307        if (width) *width = -1;
1308        if (height) *height = -1;
1309        return;
1310    }
1311
1312    wxGetTextExtent(m_display, *theFont, m_userScaleY * m_logicalScaleY,
1313                    string, width, height, NULL, descent);
1314
1315    if (width) *width = XDEV2LOGREL (*width);
1316    if (height) *height = YDEV2LOGREL (*height);
1317    if (externalLeading)
1318        *externalLeading = 0;
1319}
1320
1321wxCoord wxWindowDC::GetCharWidth() const
1322{
1323    wxCHECK_MSG( Ok(), 0, "invalid dc" );
1324    wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1325
1326    int width;
1327
1328    wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1329                     "x", &width, NULL, NULL, NULL);
1330
1331    return XDEV2LOGREL(width);
1332}
1333
1334wxCoord wxWindowDC::GetCharHeight() const
1335{
1336    wxCHECK_MSG( Ok(), 0, "invalid dc" );
1337    wxCHECK_MSG( m_font.Ok(), 0, "invalid font" );
1338
1339    int height;
1340
1341    wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1342                     "x", NULL, &height, NULL, NULL);
1343
1344    return XDEV2LOGREL(height);
1345}
1346
1347void wxWindowDC::DoGetSize( int *width, int *height ) const
1348{
1349    int w = 0, h = 0;
1350
1351    if( m_window )
1352    {
1353        if( m_window->GetBackingPixmap() )
1354        {
1355            w = m_window->GetPixmapWidth();
1356            h = m_window->GetPixmapHeight();
1357        }
1358        else
1359            m_window->GetSize( &w, &h );
1360    }
1361
1362    if( width ) *width = w;
1363    if( height ) *height = h;
1364}
1365
1366void wxWindowDC::Clear()
1367{
1368    wxCHECK_RET( Ok(), "invalid dc" );
1369
1370    wxRect rect( GetSize() );
1371    Clear( rect );
1372}
1373
1374void wxWindowDC::Clear(const wxRect& rect)
1375{
1376    wxCHECK_RET( Ok(), "invalid dc" );
1377
1378    int x = rect.x; int y = rect.y;
1379    int w = rect.width; int h = rect.height;
1380
1381    wxBrush saveBrush = m_brush;
1382    SetBrush (m_backgroundBrush);
1383
1384    XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc,
1385                    x, y, w, h);
1386
1387    if (m_window && m_window->GetBackingPixmap())
1388        XFillRectangle ((Display*) m_display,
1389                        (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1390                        x, y, w, h);
1391
1392    m_brush = saveBrush;
1393}
1394
1395void wxWindowDC::SetFont( const wxFont &font )
1396{
1397    wxCHECK_RET( Ok(), "invalid dc" );
1398
1399    m_font = font;
1400
1401    if (!m_font.Ok())
1402    {
1403        return;
1404    }
1405
1406#if !wxMOTIF_NEW_FONT_HANDLING
1407    WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1408
1409    Font fontId = ((XFontStruct*)pFontStruct)->fid;
1410    XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1411
1412    if (m_window && m_window->GetBackingPixmap())
1413        XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1414#endif
1415}
1416
1417void wxWindowDC::SetForegroundPixelWithLogicalFunction(WXPixel pixel)
1418{
1419    if (m_logicalFunction == wxXOR)
1420    {
1421        XGCValues values;
1422        XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1423        XSetForeground ((Display*) m_display, (GC) m_gc,
1424                        pixel ^ values.background);
1425        if (m_window && m_window->GetBackingPixmap())
1426            XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1427                            pixel ^ values.background);
1428    }
1429    else
1430    {
1431        XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1432        if (m_window && m_window->GetBackingPixmap())
1433            XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1434    }
1435}
1436
1437WXPixel wxWindowDC::CalculatePixel(wxColour& colour, wxColour& curCol,
1438                               bool roundToWhite) const
1439{
1440    const unsigned char wp = (unsigned char)255;
1441
1442    WXPixel pixel = -1;
1443    if(!m_colour) // Mono display
1444    {
1445        unsigned char red = colour.Red ();
1446        unsigned char blue = colour.Blue ();
1447        unsigned char green = colour.Green ();
1448        // white
1449        if((red == wp && blue == wp && green == wp) ||
1450           // not black and roundToWhite was specified
1451           ((red != 0 || blue != 0 || green != 0) && roundToWhite))
1452        {
1453            curCol = *wxWHITE;
1454            pixel = WhitePixel((Display*) m_display,
1455                               DefaultScreen((Display*) m_display));
1456            curCol.SetPixel(pixel);
1457            colour.SetPixel(pixel);
1458        }
1459        else
1460        {
1461            curCol = *wxBLACK;
1462            pixel = BlackPixel((Display*) m_display,
1463                               DefaultScreen((Display*) m_display));
1464            curCol.SetPixel(pixel);
1465            colour.SetPixel(pixel);
1466        }
1467    }
1468    else
1469    {
1470        curCol = colour;
1471        pixel = colour.AllocColour((Display*) m_display);
1472        curCol.SetPixel(pixel);
1473    }
1474
1475    return pixel;
1476}
1477
1478void wxWindowDC::SetPen( const wxPen &pen )
1479{
1480    wxCHECK_RET( Ok(), "invalid dc" );
1481
1482    m_pen = pen;
1483    if (!m_pen.Ok())
1484        return;
1485
1486    wxBitmap oldStipple = m_currentStipple;
1487    int oldStyle = m_currentStyle;
1488    int oldFill = m_currentFill;
1489    int old_pen_width = m_currentPenWidth;
1490    int old_pen_join = m_currentPenJoin;
1491    int old_pen_cap = m_currentPenCap;
1492    int old_pen_nb_dash = m_currentPenDashCount;
1493    wxX11Dash *old_pen_dash = m_currentPenDash;
1494
1495    wxColour oldPenColour = m_currentColour;
1496    m_currentColour = m_pen.GetColour ();
1497    m_currentStyle = m_pen.GetStyle ();
1498    m_currentFill = m_pen.GetStyle (); // TODO?
1499    m_currentPenWidth = m_pen.GetWidth ();
1500    m_currentPenJoin = m_pen.GetJoin ();
1501    m_currentPenCap = m_pen.GetCap ();
1502    m_currentPenDashCount = m_pen.GetDashCount();
1503    m_currentPenDash = (wxX11Dash*)m_pen.GetDash();
1504
1505    if (m_currentStyle == wxSTIPPLE)
1506        m_currentStipple = * m_pen.GetStipple ();
1507
1508    bool sameStyle = (oldStyle == m_currentStyle &&
1509        oldFill == m_currentFill &&
1510        old_pen_join == m_currentPenJoin &&
1511        old_pen_cap == m_currentPenCap &&
1512        old_pen_nb_dash == m_currentPenDashCount &&
1513        old_pen_dash == m_currentPenDash &&
1514        old_pen_width == m_currentPenWidth);
1515
1516    bool sameColour = (oldPenColour.Ok () &&
1517        (oldPenColour.Red () == m_currentColour.Red ()) &&
1518        (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1519        (oldPenColour.Green () == m_currentColour.Green ()) &&
1520        (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1521
1522    if (!sameStyle || !GET_OPTIMIZATION)
1523    {
1524        int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1525        if (scaled_width < 0)
1526            scaled_width = 0;
1527
1528        int style;
1529        int join;
1530        int cap;
1531        static const wxX11Dash dotted[] = {2, 5};
1532        static const wxX11Dash short_dashed[] = {4, 4};
1533        static const wxX11Dash long_dashed[] = {4, 8};
1534        static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6};
1535
1536        // We express dash pattern in pen width unit, so we are
1537        // independent of zoom factor and so on...
1538        int req_nb_dash;
1539        const wxX11Dash *req_dash;
1540
1541        switch (m_pen.GetStyle ())
1542        {
1543        case wxUSER_DASH:
1544            req_nb_dash = m_currentPenDashCount;
1545            req_dash = m_currentPenDash;
1546            style = LineOnOffDash;
1547            break;
1548        case wxDOT:
1549            req_nb_dash = 2;
1550            req_dash = dotted;
1551            style = LineOnOffDash;
1552            break;
1553        case wxSHORT_DASH:
1554            req_nb_dash = 2;
1555            req_dash = short_dashed;
1556            style = LineOnOffDash;
1557            break;
1558        case wxLONG_DASH:
1559            req_nb_dash = 2;
1560            req_dash = long_dashed;
1561            style = LineOnOffDash;
1562            break;
1563        case wxDOT_DASH:
1564            req_nb_dash = 4;
1565            req_dash = dotted_dashed;
1566            style = LineOnOffDash;
1567            break;
1568        case wxSTIPPLE:
1569        case wxSOLID:
1570        case wxTRANSPARENT:
1571        default:
1572            style = LineSolid;
1573            req_dash = (wxX11Dash*)NULL;
1574            req_nb_dash = 0;
1575        }
1576
1577        if (req_dash && req_nb_dash)
1578        {
1579            wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash];
1580            if (real_req_dash)
1581            {
1582                int factor = scaled_width == 0 ? 1 : scaled_width;
1583                for (int i = 0; i < req_nb_dash; i++)
1584                    real_req_dash[i] = (wxX11Dash)(req_dash[i] * factor);
1585                XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1586
1587                if (m_window && m_window->GetBackingPixmap())
1588                    XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1589                delete[]real_req_dash;
1590            }
1591            else
1592            {
1593                // No Memory. We use non-scaled dash pattern...
1594                XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1595
1596                if (m_window && m_window->GetBackingPixmap())
1597                    XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1598            }
1599        }
1600
1601        switch (m_pen.GetCap ())
1602        {
1603        case wxCAP_PROJECTING:
1604            cap = CapProjecting;
1605            break;
1606        case wxCAP_BUTT:
1607            cap = CapButt;
1608            break;
1609        case wxCAP_ROUND:
1610        default:
1611            cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1612            break;
1613        }
1614
1615        switch (m_pen.GetJoin ())
1616        {
1617        case wxJOIN_BEVEL:
1618            join = JoinBevel;
1619            break;
1620        case wxJOIN_MITER:
1621            join = JoinMiter;
1622            break;
1623        case wxJOIN_ROUND:
1624        default:
1625            join = JoinRound;
1626            break;
1627        }
1628
1629        XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1630
1631        if (m_window && m_window->GetBackingPixmap())
1632            XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1633    }
1634
1635    if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
1636    {
1637        Pixmap myStipple;
1638
1639        oldStipple = wxNullBitmap;    // For later reset!!
1640
1641        switch (m_currentFill)
1642        {
1643        case wxBDIAGONAL_HATCH:
1644            if (bdiag == (Pixmap) 0)
1645                bdiag = XCreateBitmapFromData ((Display*) m_display,
1646                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1647                bdiag_bits, bdiag_width, bdiag_height);
1648            myStipple = bdiag;
1649            break;
1650        case wxFDIAGONAL_HATCH:
1651            if (fdiag == (Pixmap) 0)
1652                fdiag = XCreateBitmapFromData ((Display*) m_display,
1653                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1654                fdiag_bits, fdiag_width, fdiag_height);
1655            myStipple = fdiag;
1656            break;
1657        case wxCROSS_HATCH:
1658            if (cross == (Pixmap) 0)
1659                cross = XCreateBitmapFromData ((Display*) m_display,
1660                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1661                cross_bits, cross_width, cross_height);
1662            myStipple = cross;
1663            break;
1664        case wxHORIZONTAL_HATCH:
1665            if (horiz == (Pixmap) 0)
1666                horiz = XCreateBitmapFromData ((Display*) m_display,
1667                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1668                horiz_bits, horiz_width, horiz_height);
1669            myStipple = horiz;
1670            break;
1671        case wxVERTICAL_HATCH:
1672            if (verti == (Pixmap) 0)
1673                verti = XCreateBitmapFromData ((Display*) m_display,
1674                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1675                verti_bits, verti_width, verti_height);
1676            myStipple = verti;
1677            break;
1678        case wxCROSSDIAG_HATCH:
1679        default:
1680            if (cdiag == (Pixmap) 0)
1681                cdiag = XCreateBitmapFromData ((Display*) m_display,
1682                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1683                cdiag_bits, cdiag_width, cdiag_height);
1684            myStipple = cdiag;
1685            break;
1686        }
1687        XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1688
1689        if (m_window && m_window->GetBackingPixmap())
1690            XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1691    }
1692    else if (m_currentStipple.Ok()
1693        && ((!m_currentStipple.IsSameAs(oldStipple)) || !GET_OPTIMIZATION))
1694    {
1695        XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetDrawable());
1696
1697        if (m_window && m_window->GetBackingPixmap())
1698            XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetDrawable());
1699    }
1700
1701    if ((m_currentFill != oldFill) || !GET_OPTIMIZATION)
1702    {
1703        int fill_style;
1704
1705        if (m_currentFill == wxSTIPPLE)
1706            fill_style = FillStippled;
1707        else if (IS_HATCH (m_currentFill))
1708            fill_style = FillStippled;
1709        else
1710            fill_style = FillSolid;
1711        XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1712        if (m_window && m_window->GetBackingPixmap())
1713            XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1714    }
1715
1716    // must test m_logicalFunction, because it involves background!
1717    if (!sameColour || !GET_OPTIMIZATION
1718        || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1719    {
1720        WXPixel pixel = -1;
1721        if (m_pen.GetStyle () == wxTRANSPARENT)
1722            pixel = m_backgroundPixel;
1723        else
1724        {
1725            pixel = CalculatePixel(m_pen.GetColour(), m_currentColour, false);
1726        }
1727
1728        // Finally, set the GC to the required colour
1729        if (pixel > -1)
1730            SetForegroundPixelWithLogicalFunction(pixel);
1731    }
1732    else
1733        m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1734
1735    m_autoSetting = 0;
1736}
1737
1738void wxWindowDC::SetBrush( const wxBrush &brush )
1739{
1740    wxCHECK_RET( Ok(), "invalid dc" );
1741
1742    m_brush = brush;
1743
1744    if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1745        return;
1746
1747    int oldFill = m_currentFill;
1748    wxBitmap oldStipple = m_currentStipple;
1749
1750    m_autoSetting |= 0x1;
1751
1752    m_currentFill = m_brush.GetStyle ();
1753    if (m_currentFill == wxSTIPPLE)
1754        m_currentStipple = * m_brush.GetStipple ();
1755
1756    wxColour oldBrushColour(m_currentColour);
1757    m_currentColour = m_brush.GetColour ();
1758
1759    bool sameColour = (oldBrushColour.Ok () &&
1760        (oldBrushColour.Red () == m_currentColour.Red ()) &&
1761        (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1762        (oldBrushColour.Green () == m_currentColour.Green ()) &&
1763        (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1764
1765    int stippleDepth = -1;
1766
1767    if ((oldFill != m_brush.GetStyle ()) || !GET_OPTIMIZATION)
1768    {
1769        switch (brush.GetStyle ())
1770        {
1771        case wxTRANSPARENT:
1772            break;
1773        case wxSTIPPLE:
1774            stippleDepth = m_currentStipple.GetDepth();
1775            // fall through!
1776        case wxBDIAGONAL_HATCH:
1777        case wxCROSSDIAG_HATCH:
1778        case wxFDIAGONAL_HATCH:
1779        case wxCROSS_HATCH:
1780        case wxHORIZONTAL_HATCH:
1781        case wxVERTICAL_HATCH:
1782            {
1783                if (stippleDepth == -1) stippleDepth = 1;
1784
1785                // Chris Breeze 23/07/97: use background mode to
1786                // determine whether fill style should be solid or
1787                // transparent
1788                int style = stippleDepth == 1 ?
1789                    (m_backgroundMode == wxSOLID ?
1790                     FillOpaqueStippled : FillStippled) :
1791                    FillTiled;
1792                XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1793                if (m_window && m_window->GetBackingPixmap())
1794                    XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1795            }
1796            break;
1797        case wxSOLID:
1798        default:
1799            XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1800            if (m_window && m_window->GetBackingPixmap())
1801                XSetFillStyle ((Display*) m_display,(GC) m_gcBacking,
1802                               FillSolid);
1803        }
1804    }
1805
1806    if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
1807    {
1808        Pixmap myStipple;
1809
1810        switch (m_currentFill)
1811        {
1812        case wxBDIAGONAL_HATCH:
1813            if (bdiag == (Pixmap) 0)
1814                bdiag = XCreateBitmapFromData ((Display*) m_display,
1815                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1816                bdiag_bits, bdiag_width, bdiag_height);
1817            myStipple = bdiag;
1818            break;
1819        case wxFDIAGONAL_HATCH:
1820            if (fdiag == (Pixmap) 0)
1821                fdiag = XCreateBitmapFromData ((Display*) m_display,
1822                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1823                fdiag_bits, fdiag_width, fdiag_height);
1824            myStipple = fdiag;
1825            break;
1826        case wxCROSS_HATCH:
1827            if (cross == (Pixmap) 0)
1828                cross = XCreateBitmapFromData ((Display*) m_display,
1829                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1830                cross_bits, cross_width, cross_height);
1831            myStipple = cross;
1832            break;
1833        case wxHORIZONTAL_HATCH:
1834            if (horiz == (Pixmap) 0)
1835                horiz = XCreateBitmapFromData ((Display*) m_display,
1836                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1837                horiz_bits, horiz_width, horiz_height);
1838            myStipple = horiz;
1839            break;
1840        case wxVERTICAL_HATCH:
1841            if (verti == (Pixmap) 0)
1842                verti = XCreateBitmapFromData ((Display*) m_display,
1843                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1844                verti_bits, verti_width, verti_height);
1845            myStipple = verti;
1846            break;
1847        case wxCROSSDIAG_HATCH:
1848        default:
1849            if (cdiag == (Pixmap) 0)
1850                cdiag = XCreateBitmapFromData ((Display*) m_display,
1851                RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1852                cdiag_bits, cdiag_width, cdiag_height);
1853            myStipple = cdiag;
1854            break;
1855        }
1856        XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1857
1858        if (m_window && m_window->GetBackingPixmap())
1859            XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1860    }
1861    // X can forget the stipple value when resizing a window (apparently)
1862    // so always set the stipple.
1863    else if (m_currentFill != wxSOLID && m_currentFill != wxTRANSPARENT &&
1864             m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1865    {
1866        if (m_currentStipple.GetDepth() == 1)
1867        {
1868            XSetStipple ((Display*) m_display, (GC) m_gc,
1869                         (Pixmap) m_currentStipple.GetDrawable());
1870        if (m_window && m_window->GetBackingPixmap())
1871                XSetStipple ((Display*) m_display,(GC) m_gcBacking,
1872                             (Pixmap) m_currentStipple.GetDrawable());
1873        }
1874        else
1875        {
1876            XSetTile ((Display*) m_display, (GC) m_gc,
1877                      (Pixmap) m_currentStipple.GetDrawable());
1878            if (m_window && m_window->GetBackingPixmap())
1879                XSetTile ((Display*) m_display,(GC) m_gcBacking,
1880                          (Pixmap) m_currentStipple.GetDrawable());
1881        }
1882    }
1883
1884    // must test m_logicalFunction, because it involves background!
1885    if (!sameColour || !GET_OPTIMIZATION || m_logicalFunction == wxXOR)
1886    {
1887        WXPixel pixel = CalculatePixel(m_brush.GetColour(), m_currentColour, true);
1888
1889        if (pixel > -1)
1890            SetForegroundPixelWithLogicalFunction(pixel);
1891    }
1892    else
1893        m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1894}
1895
1896void wxWindowDC::SetBackground( const wxBrush &brush )
1897{
1898    wxCHECK_RET( Ok(), "invalid dc" );
1899
1900    m_backgroundBrush = brush;
1901
1902    if (!m_backgroundBrush.Ok())
1903        return;
1904
1905    m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1906
1907    // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1908    // And Blit,... (Any fct that use XCopyPlane, in fact.)
1909    XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel);
1910    if (m_window && m_window->GetBackingPixmap())
1911        XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1912                        m_backgroundPixel);
1913}
1914
1915void wxWindowDC::SetLogicalFunction( int function )
1916{
1917    wxCHECK_RET( Ok(), "invalid dc" );
1918
1919    int x_function;
1920
1921    /* MATTHEW: [9] */
1922    if (m_logicalFunction == function)
1923        return;
1924
1925    switch (function)
1926    {
1927    case wxCLEAR:
1928        x_function = GXclear;
1929        break;
1930    case wxXOR:
1931        x_function = GXxor;
1932        break;
1933    case wxINVERT:
1934        x_function = GXinvert;
1935        break;
1936    case wxOR_REVERSE:
1937        x_function = GXorReverse;
1938        break;
1939    case wxAND_REVERSE:
1940        x_function = GXandReverse;
1941        break;
1942    case wxAND:
1943        x_function = GXand;
1944        break;
1945    case wxOR:
1946        x_function = GXor;
1947        break;
1948    case wxAND_INVERT:
1949        x_function = GXandInverted;
1950        break;
1951    case wxNO_OP:
1952        x_function = GXnoop;
1953        break;
1954    case wxNOR:
1955        x_function = GXnor;
1956        break;
1957    case wxEQUIV:
1958        x_function = GXequiv;
1959        break;
1960    case wxSRC_INVERT:
1961        x_function = GXcopyInverted;
1962        break;
1963    case wxOR_INVERT:
1964        x_function = GXorInverted;
1965        break;
1966    case wxNAND:
1967        x_function = GXnand;
1968        break;
1969    case wxSET:
1970        x_function = GXset;
1971        break;
1972    case wxCOPY:
1973    default:
1974        x_function = GXcopy;
1975        break;
1976    }
1977
1978    XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1979    if (m_window && m_window->GetBackingPixmap())
1980        XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
1981
1982    if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1983        /* MATTHEW: [9] Need to redo pen simply */
1984        m_autoSetting |= 0x2;
1985
1986    m_logicalFunction = function;
1987
1988}
1989
1990void wxWindowDC::SetTextForeground( const wxColour &col )
1991{
1992    wxCHECK_RET( Ok(), "invalid dc" );
1993
1994    m_textForegroundColour = col;
1995}
1996
1997void wxWindowDC::SetTextBackground( const wxColour &col )
1998{
1999    wxCHECK_RET( Ok(), "invalid dc" );
2000
2001    m_textBackgroundColour = col;
2002}
2003
2004void wxWindowDC::SetBackgroundMode( int mode )
2005{
2006    m_backgroundMode = mode;
2007}
2008
2009void wxWindowDC::SetPalette( const wxPalette& palette )
2010{
2011    if (m_window)
2012    {
2013        if (palette.Ok())
2014            /* Use GetXColormap */
2015            XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2016            (Colormap) palette.GetXColormap());
2017        else
2018            /* Use wxGetMainColormap */
2019            XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2020            (Colormap) wxTheApp->GetMainColormap(m_display));
2021    }
2022}
2023
2024static void wxCopyRegion( WXRegion src, WXRegion& dst )
2025{
2026    if( !dst )
2027        dst = XCreateRegion();
2028    XUnionRegion( (Region)src, (Region)src, (Region)dst );
2029}
2030
2031// Helper function; userRegion is the region set by calling SetClippingRegion
2032void wxWindowDC::SetDCClipping( WXRegion userRegion )
2033{
2034    bool hasUpdateRegion = m_window && m_window->GetUpdateRegion().Ok();
2035    // this means that we should start the clip region from scratch,
2036    // or from the update region, if any
2037    if( !userRegion )
2038    {
2039        if( m_clipRegion )
2040            XDestroyRegion( (Region)m_clipRegion );
2041        m_clipRegion = (WXRegion)NULL;
2042
2043        if( hasUpdateRegion )
2044            wxCopyRegion( m_window->GetUpdateRegion().GetX11Region(),
2045                          m_clipRegion );
2046    }
2047    // intersect the user region, if any, with the
2048    // exisiting clip region
2049    else // if( userRegion )
2050    {
2051        if( !m_clipRegion )
2052            wxCopyRegion( userRegion, m_clipRegion );
2053        else
2054            XIntersectRegion( (Region)m_clipRegion,
2055                              (Region)userRegion, (Region)m_clipRegion );
2056    }
2057
2058    if( m_clipRegion )
2059        XSetRegion( (Display*)m_display, (GC)m_gc, (Region)m_clipRegion );
2060    else
2061        XSetClipMask( (Display*)m_display, (GC)m_gc, None );
2062}
2063
2064void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y,
2065                                      wxCoord width, wxCoord height )
2066{
2067    wxDC::DoSetClippingRegion( x, y, width, height );
2068
2069    wxRegion temp(XLOG2DEV(x), YLOG2DEV(y),
2070                  XLOG2DEVREL(width), YLOG2DEVREL(height));
2071
2072    SetDCClipping(temp.GetX11Region());
2073
2074    // Needs to work differently for Pixmap: without this,
2075    // there's a nasty (Display*) m_display bug. 8/12/94
2076    if (m_window && m_window->GetBackingPixmap())
2077    {
2078        XRectangle rects[1];
2079        rects[0].x = (short)XLOG2DEV_2(x);
2080        rects[0].y = (short)YLOG2DEV_2(y);
2081        rects[0].width = (unsigned short)XLOG2DEVREL(width);
2082        rects[0].height = (unsigned short)YLOG2DEVREL(height);
2083        XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2084                           0, 0, rects, 1, Unsorted);
2085    }
2086}
2087
2088void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion& region )
2089{
2090    SetDCClipping(region.GetX11Region());
2091
2092    // Needs to work differently for Pixmap: without this,
2093    // there's a nasty (Display*) m_display bug. 8/12/94
2094    if (m_window && m_window->GetBackingPixmap())
2095    {
2096        wxRect box = region.GetBox();
2097
2098        XRectangle rects[1];
2099        rects[0].x = (short)XLOG2DEV_2(box.x);
2100        rects[0].y = (short)YLOG2DEV_2(box.y);
2101        rects[0].width = (unsigned short)XLOG2DEVREL(box.width);
2102        rects[0].height = (unsigned short)YLOG2DEVREL(box.height);
2103        XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2104                           0, 0, rects, 1, Unsorted);
2105    }
2106}
2107
2108
2109void wxWindowDC::DestroyClippingRegion()
2110{
2111    wxDC::DestroyClippingRegion();
2112
2113    SetDCClipping(NULL);
2114
2115    if (m_window && m_window->GetBackingPixmap())
2116        XSetClipMask ((Display*) m_display, (GC) m_gcBacking, None);
2117}
2118
2119// Resolution in pixels per logical inch
2120wxSize wxWindowDC::GetPPI() const
2121{
2122    // TODO
2123    return wxSize(100, 100);
2124}
2125
2126int wxWindowDC::GetDepth() const
2127{
2128    // TODO
2129    return 24;
2130}
2131
2132
2133
2134
2135// ----------------------------------------------------------------------------
2136// wxPaintDC
2137// ----------------------------------------------------------------------------
2138
2139wxPaintDC::wxPaintDC(wxWindow* win) : wxWindowDC(win)
2140{
2141    // Set the clipping region.to the update region
2142    SetDCClipping((WXRegion)NULL);
2143}
2144
2145wxPaintDC::~wxPaintDC()
2146{
2147    if (m_window)
2148        m_window->ClearUpdateRegion();
2149    SetDCClipping((WXRegion)NULL);
2150}
2151
2152// ----------------------------------------------------------------------------
2153// private functions
2154// ----------------------------------------------------------------------------
2155
2156/*
2157   Used when copying between drawables on different (Display*) m_displays. Not
2158   very fast, but better than giving up.
2159*/
2160
2161static void XCopyRemote(Display *src_display, Display *dest_display,
2162                        Drawable src, Drawable dest,
2163                        GC destgc,
2164                        int srcx, int srcy,
2165                        unsigned int w, unsigned int h,
2166                        int destx, int desty,
2167                        bool more, XImage **cache)
2168{
2169    XImage *image, *destimage;
2170    Colormap destcm, srccm;
2171    static const int CACHE_SIZE = 256;
2172
2173    unsigned int i, j;
2174    Pixel cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2175    int k, cache_pos, all_cache;
2176
2177    if (!cache || !*cache)
2178        image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2179    else
2180        image = *cache;
2181
2182    destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2183
2184    srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2185    destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2186
2187    cache_pos = 0;
2188    all_cache = False;
2189
2190    for (i = 0; i < w; i++)
2191        for (j = 0; j < h; j++) {
2192            Pixel pixel;
2193            XColor xcol;
2194
2195            pixel = XGetPixel(image, i, j);
2196            for (k = cache_pos; k--; )
2197                if (cachesrc[k] == pixel) {
2198                    pixel = cachedest[k];
2199                    goto install;
2200                }
2201                if (all_cache)
2202                    for (k = CACHE_SIZE; k-- > cache_pos; )
2203                        if (cachesrc[k] == pixel) {
2204                            pixel = cachedest[k];
2205                            goto install;
2206                        }
2207
2208                        cachesrc[cache_pos] = xcol.pixel = pixel;
2209                        XQueryColor(src_display, srccm, &xcol);
2210                        if (!XAllocColor(dest_display, destcm, &xcol))
2211                            xcol.pixel = 0;
2212                        cachedest[cache_pos] = pixel = xcol.pixel;
2213
2214                        if (++cache_pos >= CACHE_SIZE) {
2215                            cache_pos = 0;
2216                            all_cache = true;
2217                        }
2218
2219install:
2220                        XPutPixel(destimage, i, j, pixel);
2221        }
2222
2223        XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2224        XDestroyImage(destimage);
2225
2226        if (more)
2227            *cache = image;
2228        else
2229            XDestroyImage(image);
2230}
2231
2232#if 0
2233
2234/* Helper function for 16-bit fonts */
2235static int str16len(const char *s)
2236{
2237    int count = 0;
2238
2239    while (s[0] && s[1]) {
2240        count++;
2241        s += 2;
2242    }
2243
2244    return count;
2245}
2246
2247#endif // 0
2248