1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/motif/dcclient.cpp
3 // Purpose:     wxClientDCImpl class
4 // Author:      Julian Smart
5 // Modified by:
6 // Created:     01/02/97
7 // Copyright:   (c) Julian Smart
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 /*
12   About pens, brushes, and the m_autoSetting flag:
13 
14   Under X, pens and brushes control some of the same X drawing
15   parameters.  Therefore, it is impossible to independently maintain
16   the current pen and the current brush. Also, some settings depend on
17   the current logical function. The m_currentFill, etc. instance
18   variables remember state across the brush and pen.
19 
20   Since pens are used more than brushes, the m_autoSetting flag is used to
21   indicate that a brush was recently used, and SetPen must be called to
22   reinstall the current pen's parameters. If m_autoSetting includes 0x2, then the
23   pens color may need to be set based on XOR.
24 
25   There is, unfortunately, some confusion between setting the current pen/brush
26   and actually installing the brush/pen parameters. Both functionalies are
27   perform by SetPen and SetBrush. C'est la vie.
28 */
29 
30 // ============================================================================
31 // declarations
32 // ============================================================================
33 
34 // ----------------------------------------------------------------------------
35 // headers
36 // ----------------------------------------------------------------------------
37 
38 // For compilers that support precompilation, includes "wx.h".
39 #include "wx/wxprec.h"
40 
41 #ifndef WX_PRECOMP
42     #include "wx/log.h"
43     #include "wx/app.h"
44     #include "wx/window.h"
45     #include "wx/dcmemory.h"
46     #include "wx/math.h"
47     #include "wx/image.h"
48     #include "wx/dcclient.h"
49 #endif
50 
51 #ifdef __VMS__
52 #pragma message disable nosimpint
53 #endif
54 #include <Xm/Xm.h>
55 #ifdef __VMS__
56 #pragma message enable nosimpint
57 #endif
58 
59 #include "wx/motif/private.h"
60 #include "wx/motif/dcclient.h"
61 
62 #include "bdiag.xbm"
63 #include "fdiag.xbm"
64 #include "cdiag.xbm"
65 #include "horiz.xbm"
66 #include "verti.xbm"
67 #include "cross.xbm"
68 
69 static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti;
70 
71 // ----------------------------------------------------------------------------
72 // constants
73 // ----------------------------------------------------------------------------
74 
75 // Fudge factor (VZ: what??)
76 #define WX_GC_CF 1
77 
78 // ----------------------------------------------------------------------------
79 // macros
80 // ----------------------------------------------------------------------------
81 
82 wxIMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl);
83 wxIMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxWindowDCImpl);
84 wxIMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxMotifDCImpl);
85 
86 #define IS_HATCH(s)    ((s)>=wxHATCHSTYLE_FIRST && (s)<=wxHATCHSTYLE_LAST)
87 
88 // FIXME: left over after removal of wxDC::GetOptimization()
89 #define GET_OPTIMIZATION false
90 
91 // ----------------------------------------------------------------------------
92 // prototypes
93 // ----------------------------------------------------------------------------
94 
95 static void XCopyRemote(Display *src_display, Display *dest_display,
96                         Drawable src, Drawable dest,
97                         GC destgc,
98                         int srcx, int srcy,
99                         unsigned int w, unsigned int h,
100                         int destx, int desty,
101                         bool more, XImage **cache);
102 
103 // ============================================================================
104 // implementation
105 // ============================================================================
106 
107 /*
108  * compare two doubles and return the larger rounded
109  * to the nearest int
110  */
roundmax(double a,double b)111 static int roundmax(double a, double b)
112 {
113     return (int)((a > b ? a : b) + 0.5);
114 }
115 
116 /*
117  * compare two doubles and return the smaller rounded
118  * to the nearest int
119  */
roundmin(double a,double b)120 static int roundmin(double a, double b)
121 {
122     return (int)((a < b ? a : b) - 0.5);
123 }
124 
125 
126 // ----------------------------------------------------------------------------
127 // wxWindowDCImpl
128 // ----------------------------------------------------------------------------
129 
Init()130 void wxWindowDCImpl::Init()
131 {
132     m_gc = (WXGC) 0;
133     m_gcBacking = (WXGC) 0;
134     m_window = NULL;
135     m_backgroundPixel = -1;
136     m_currentPenWidth = 1;
137     m_currentPenJoin = -1;
138     m_currentPenDashCount = -1;
139     m_currentPenDash = NULL;
140     m_currentStyle = -1;
141     m_currentFill = -1;
142     m_display = NULL;
143     m_pixmap = (WXPixmap) 0;
144     m_autoSetting = 0;
145     m_ok = false;
146     m_clipRegion = (WXRegion) 0;
147 }
148 
wxWindowDCImpl(wxDC * owner)149 wxWindowDCImpl::wxWindowDCImpl(wxDC *owner)
150               : wxMotifDCImpl(owner)
151 {
152     Init();
153 }
154 
wxWindowDCImpl(wxDC * owner,wxWindow * window)155 wxWindowDCImpl::wxWindowDCImpl(wxDC *owner, wxWindow *window)
156               : wxMotifDCImpl(owner)
157 {
158     wxASSERT_MSG( (window != NULL), "You must pass a valid wxWindow to wxWindowDCImpl/wxClientDCImpl/wxPaintDCImpl constructor." );
159 
160     Init();
161 
162     m_window = window;
163     m_font = window->GetFont();
164     m_ok = true;
165 
166     m_display = window->GetXDisplay();
167     m_pixmap = window->GetXWindow();
168     Display* display = (Display*) m_display;
169 
170     XSetWindowColormap (display, (Pixmap) m_pixmap, (Colormap) wxTheApp->GetMainColormap(m_display));
171 
172     XGCValues gcvalues;
173     gcvalues.foreground = BlackPixel (display, DefaultScreen (display));
174     gcvalues.background = WhitePixel (display, DefaultScreen (display));
175     gcvalues.graphics_exposures = False;
176     gcvalues.subwindow_mode = IncludeInferiors;
177     gcvalues.line_width = 1;
178 #if !wxMOTIF_NEW_FONT_HANDLING
179     WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
180     gcvalues.font = ((XFontStruct*)pFontStruct)->fid;
181 #endif
182     m_gc = (WXGC) XCreateGC (display, RootWindow (display, DefaultScreen (display)),
183         GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth | GCSubwindowMode
184 #if !wxMOTIF_NEW_FONT_HANDLING
185         | GCFont
186 #endif
187                              ,
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(), wxBRUSHSTYLE_SOLID));
201 }
202 
~wxWindowDCImpl()203 wxWindowDCImpl::~wxWindowDCImpl()
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 
218 extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
219                           const wxColour & col, wxFloodFillStyle style);
220 
DoFloodFill(wxCoord x,wxCoord y,const wxColour & col,wxFloodFillStyle style)221 bool wxWindowDCImpl::DoFloodFill(wxCoord x, wxCoord y,
222                              const wxColour& col, wxFloodFillStyle style)
223 {
224     return wxDoFloodFill(GetOwner(), x, y, col, style);
225 }
226 
DoGetPixel(wxCoord x1,wxCoord y1,wxColour * col) const227 bool wxWindowDCImpl::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, GetOwner(), 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 
DoDrawLine(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2)241 void wxWindowDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
242 {
243     wxCHECK_RET( IsOk(), "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 
DoCrossHair(wxCoord x,wxCoord y)266 void wxWindowDCImpl::DoCrossHair( wxCoord x, wxCoord y )
267 {
268     wxCHECK_RET( IsOk(), "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 
DoDrawArc(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2,wxCoord xc,wxCoord yc)295 void wxWindowDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc )
296 {
297     wxCHECK_RET( IsOk(), "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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord width,wxCoord height,double sa,double ea)376 void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
377 {
378     wxCHECK_RET( IsOk(), "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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawPoint(wxCoord x,wxCoord y)421 void wxWindowDCImpl::DoDrawPoint( wxCoord x, wxCoord y )
422 {
423     wxCHECK_RET( IsOk(), "invalid dc" );
424 
425     if (m_pen.IsOk() && 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 
DoDrawLines(int n,const wxPoint points[],wxCoord xoffset,wxCoord yoffset)435 void wxWindowDCImpl::DoDrawLines( int n, const wxPoint points[], wxCoord xoffset, wxCoord yoffset )
436 {
437     wxCHECK_RET( IsOk(), "invalid dc" );
438 
439     if (m_pen.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawPolygon(int n,const wxPoint points[],wxCoord xoffset,wxCoord yoffset,wxPolygonFillMode fillStyle)467 void wxWindowDCImpl::DoDrawPolygon( int n, const wxPoint points[],
468                                 wxCoord xoffset, wxCoord yoffset, wxPolygonFillMode fillStyle )
469 {
470     wxCHECK_RET( IsOk(), "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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawRectangle(wxCoord x,wxCoord y,wxCoord width,wxCoord height)519 void wxWindowDCImpl::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
520 {
521     wxCHECK_RET( IsOk(), "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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawRoundedRectangle(wxCoord x,wxCoord y,wxCoord width,wxCoord height,double radius)562 void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
563 {
564     wxCHECK_RET( IsOk(), "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         DoDrawRectangle( 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() != wxPENSTYLE_TRANSPARENT)
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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
DoDrawEllipse(wxCoord x,wxCoord y,wxCoord width,wxCoord height)722 void wxWindowDCImpl::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
723 {
724     wxCHECK_RET( IsOk(), "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.IsOk() && m_brush.GetStyle () != wxBRUSHSTYLE_TRANSPARENT)
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.IsOk() && m_pen.GetStyle () != wxPENSTYLE_TRANSPARENT)
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 
CanDrawBitmap() const775 bool wxWindowDCImpl::CanDrawBitmap() const
776 {
777     wxCHECK_MSG( IsOk(), 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
DoBlit(wxCoord xdest,wxCoord ydest,wxCoord width,wxCoord height,wxDC * source,wxCoord xsrc,wxCoord ysrc,wxRasterOperationMode rop,bool useMask,wxCoord xsrcMask,wxCoord ysrcMask)784 bool wxWindowDCImpl::DoBlit( wxCoord xdest, wxCoord ydest,
785                          wxCoord width, wxCoord height,
786                          wxDC *source, wxCoord xsrc, wxCoord ysrc,
787                          wxRasterOperationMode rop, bool useMask,
788                          wxCoord xsrcMask, wxCoord ysrcMask )
789 {
790     wxCHECK_MSG( IsOk(), false, "invalid dc" );
791 
792     wxWindowDC const * sourceDC = wxDynamicCast(source, wxWindowDC);
793     wxCHECK_MSG( sourceDC, false, "Blit source DC must be wxWindowDCImpl or derived class." );
794 
795     // cast is safe in virtue of the above wxCHECK_MSG()
796     const wxWindowDCImpl * const
797         srcImpl = static_cast<const wxWindowDCImpl *>(sourceDC->GetImpl());
798     WXDisplay * const srcDpy = srcImpl->m_display;
799 
800 
801     // Be sure that foreground pixels (1) of the Icon will be painted with
802     // foreground colour. [m_textForegroundColour] Background pixels (0)
803     // will be painted with backgound colour (m_textBackgroundColour)
804     // Using ::SetPen is horribly slow, so avoid doing it
805     WXPixel oldBackgroundPixel = -1;
806     WXPixel oldForegroundPixel = -1;
807 
808     if (m_textBackgroundColour.IsOk())
809     {
810         oldBackgroundPixel = m_backgroundPixel;
811         WXPixel pixel = m_textBackgroundColour.AllocColour(m_display);
812 
813         XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
814         if (m_window && m_window->GetBackingPixmap())
815             XSetBackground ((Display*) m_display,(GC) m_gcBacking,
816                             pixel);
817     }
818     if (m_textForegroundColour.IsOk())
819     {
820         oldForegroundPixel = m_currentColour.GetPixel();
821 
822         if( m_textForegroundColour.GetPixel() <= -1 )
823             CalculatePixel( m_textForegroundColour,
824                             m_textForegroundColour, true);
825 
826         WXPixel pixel = m_textForegroundColour.GetPixel();
827         if (pixel > -1)
828             SetForegroundPixelWithLogicalFunction(pixel);
829     }
830 
831     // Do bitmap scaling if necessary
832 
833     wxBitmap *scaledBitmap = NULL;
834     Pixmap sourcePixmap = (Pixmap) NULL;
835     double scaleX, scaleY;
836     GetUserScale(& scaleX, & scaleY);
837     bool retVal = false;
838 
839     /* TODO: use the mask origin when drawing transparently */
840     if (xsrcMask == -1 && ysrcMask == -1)
841     {
842         xsrcMask = xsrc; ysrcMask = ysrc;
843     }
844 
845     // Sorry, can't scale masks just yet
846     if (!useMask && (scaleX != 1.0 || scaleY != 1.0) && sourceDC->IsKindOf(CLASSINFO(wxMemoryDC)))
847     {
848         wxMemoryDC* memDC = (wxMemoryDC*) sourceDC;
849         wxBitmap& bitmap = memDC->GetSelectedBitmap();
850 
851         wxASSERT_MSG( (bitmap.IsOk()), "Bad source bitmap in wxWindowDCImpl::Blit");
852 
853         wxImage image = bitmap.ConvertToImage();
854         if (!image.IsOk())
855         {
856             sourcePixmap = (Pixmap) bitmap.GetDrawable();
857         }
858         else
859         {
860             int scaledW = (int) (bitmap.GetWidth() * scaleX);
861             int scaledH = (int) (bitmap.GetHeight() * scaleY);
862 
863             image = image.Scale(scaledW, scaledH);
864             scaledBitmap = new wxBitmap(image);
865             sourcePixmap = (Pixmap) scaledBitmap->GetDrawable();
866         }
867     }
868     else
869     {
870         sourcePixmap = (Pixmap) srcImpl->m_pixmap;
871     }
872 
873     if (m_pixmap && sourcePixmap)
874     {
875         /* MATTHEW: [9] */
876         wxRasterOperationMode orig = m_logicalFunction;
877 
878         SetLogicalFunction (rop);
879 
880         if (m_display != srcDpy)
881         {
882             XImage *cache = NULL;
883 
884             if (m_window && m_window->GetBackingPixmap())
885                 XCopyRemote((Display*) srcDpy, (Display*) m_display,
886                 (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),
887                 (GC) m_gcBacking,
888                 source->LogicalToDeviceX (xsrc),
889                 source->LogicalToDeviceY (ysrc),
890                 source->LogicalToDeviceXRel(width),
891                 source->LogicalToDeviceYRel(height),
892                 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
893                 True, &cache);
894 
895             if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
896             {
897                 wxMemoryDC *memDC = (wxMemoryDC *)source;
898                 wxBitmap& sel = memDC->GetSelectedBitmap();
899                 if ( sel.IsOk() && sel.GetMask() && sel.GetMask()->GetBitmap() )
900                 {
901                     XSetClipMask   ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
902                     XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
903                 }
904             }
905 
906             XCopyRemote((Display*) srcDpy, (Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
907                 source->LogicalToDeviceX (xsrc),
908                 source->LogicalToDeviceY (ysrc),
909                 source->LogicalToDeviceXRel(width),
910                 source->LogicalToDeviceYRel(height),
911                 XLOG2DEV (xdest), YLOG2DEV (ydest),
912                 False, &cache);
913 
914             if ( useMask )
915             {
916                 if ( m_clipRegion )
917                     XSetRegion ((Display*) m_display, (GC) m_gc,
918                                 (Region) m_clipRegion);
919                 else
920                     XSetClipMask   ((Display*) m_display, (GC) m_gc, None);
921 
922                 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
923             }
924 
925         } else
926         {        //XGCValues values;
927         //XGetGCValues((Display*)m_display, (GC)m_gc, GCForeground, &values);
928 
929             if (m_window && m_window->GetBackingPixmap())
930             {
931                 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
932                 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetSelectedBitmap().GetDepth() == 1)
933                 {
934                     XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
935                         source->LogicalToDeviceX (xsrc),
936                         source->LogicalToDeviceY (ysrc),
937                         source->LogicalToDeviceXRel(width),
938                         source->LogicalToDeviceYRel(height),
939                         XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
940                 }
941                 else
942                 {
943                     XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
944                         source->LogicalToDeviceX (xsrc),
945                         source->LogicalToDeviceY (ysrc),
946                         source->LogicalToDeviceXRel(width),
947                         source->LogicalToDeviceYRel(height),
948                         XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
949                 }
950             }
951             if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
952             {
953                 wxMemoryDC *memDC = (wxMemoryDC *)source;
954                 wxBitmap& sel = memDC->GetSelectedBitmap();
955                 if ( sel.IsOk() && sel.GetMask() && sel.GetMask()->GetBitmap() )
956                 {
957                     XSetClipMask   ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetBitmap());
958                     XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
959                 }
960             }
961 
962             // Check if we're copying from a mono bitmap
963             if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
964                 ((wxMemoryDC*)source)->GetSelectedBitmap().IsOk() &&
965                 (((wxMemoryDC*)source)->GetSelectedBitmap().GetDepth () == 1))
966             {
967                 XCopyPlane ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
968                     source->LogicalToDeviceX (xsrc),
969                     source->LogicalToDeviceY (ysrc),
970                     source->LogicalToDeviceXRel(width),
971                     source->LogicalToDeviceYRel(height),
972                     XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
973             }
974             else
975             {
976                 XCopyArea ((Display*) m_display, (Pixmap) sourcePixmap, (Pixmap) m_pixmap, (GC) m_gc,
977                     source->LogicalToDeviceX (xsrc),
978                     source->LogicalToDeviceY (ysrc),
979                     source->LogicalToDeviceXRel(width),
980                     source->LogicalToDeviceYRel(height),
981                     XLOG2DEV (xdest), YLOG2DEV (ydest));
982 
983             }
984             if ( useMask )
985             {
986                 if ( m_clipRegion )
987                     XSetRegion ((Display*) m_display, (GC) m_gc,
988                                 (Region) m_clipRegion);
989                 else
990                     XSetClipMask   ((Display*) m_display, (GC) m_gc, None);
991 
992                 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
993             }
994 
995         } /* Remote/local (Display*) m_display */
996         CalcBoundingBox (xdest, ydest);
997         CalcBoundingBox (xdest + width, ydest + height);
998 
999         SetLogicalFunction(orig);
1000 
1001         retVal = true;
1002   }
1003   if (scaledBitmap) delete scaledBitmap;
1004 
1005   if (oldBackgroundPixel > -1)
1006   {
1007       XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
1008       if (m_window && m_window->GetBackingPixmap())
1009           XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1010                           oldBackgroundPixel);
1011   }
1012   if (oldForegroundPixel > -1)
1013   {
1014       XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1015       if (m_window && m_window->GetBackingPixmap())
1016           XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1017                           oldForegroundPixel);
1018   }
1019 
1020   return retVal;
1021 }
1022 
DoDrawText(const wxString & text,wxCoord x,wxCoord y)1023 void wxWindowDCImpl::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
1024 {
1025     wxCHECK_RET( IsOk(), "invalid dc" );
1026 
1027     // Since X draws from the baseline of the text, must add the text height
1028     int cx = 0;
1029     int cy = 0;
1030     int ascent = 0;
1031     int slen = text.length();
1032 
1033     // Set FillStyle, otherwise X will use current stipple!
1034     XGCValues gcV, gcBackingV;
1035 
1036     XGetGCValues ((Display*) m_display, (GC)m_gc, GCFillStyle, &gcV);
1037     XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1038     if (m_window && m_window->GetBackingPixmap())
1039     {
1040         XGetGCValues ((Display*) m_display, (GC)m_gcBacking, GCFillStyle,
1041                       &gcBackingV );
1042         XSetFillStyle ((Display*) m_display, (GC) m_gcBacking, FillSolid);
1043     }
1044 
1045     if (m_font.IsOk())
1046         wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1047                          text, &cx, &cy, &ascent, NULL);
1048 
1049     // First draw a rectangle representing the text background, if a text
1050     // background is specified
1051     if (m_textBackgroundColour.IsOk () && (m_backgroundMode != wxBRUSHSTYLE_TRANSPARENT))
1052     {
1053         wxColour oldPenColour = m_currentColour;
1054         m_currentColour = m_textBackgroundColour;
1055         bool sameColour = (oldPenColour.IsOk () && m_textBackgroundColour.IsOk () &&
1056             (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1057             (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1058             (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1059 
1060         // This separation of the big && test required for gcc2.7/HP UX 9.02
1061         // or pixel value can be corrupted!
1062         sameColour = (sameColour &&
1063             (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1064 
1065         if (!sameColour || !GET_OPTIMIZATION)
1066         {
1067             WXPixel pixel = m_textBackgroundColour.AllocColour(m_display);
1068             m_currentColour = m_textBackgroundColour;
1069 
1070             // Set the GC to the required colour
1071             if (pixel > -1)
1072             {
1073                 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1074                 if (m_window && m_window->GetBackingPixmap())
1075                     XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1076             }
1077         }
1078         else
1079             m_textBackgroundColour = oldPenColour ;
1080 
1081         XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1082         if (m_window && m_window->GetBackingPixmap())
1083             XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1084             XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1085     }
1086 
1087     // Now set the text foreground and draw the text
1088     if (m_textForegroundColour.IsOk ())
1089     {
1090         wxColour oldPenColour = m_currentColour;
1091         m_currentColour = m_textForegroundColour;
1092         bool sameColour = (oldPenColour.IsOk () && m_currentColour.IsOk () &&
1093             (oldPenColour.Red () == m_currentColour.Red ()) &&
1094             (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1095             (oldPenColour.Green () == m_currentColour.Green ()) &&
1096             (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1097 
1098         if (!sameColour || !GET_OPTIMIZATION)
1099         {
1100             WXPixel pixel = CalculatePixel(m_textForegroundColour,
1101                                            m_currentColour, false);
1102 
1103             // Set the GC to the required colour
1104             if (pixel > -1)
1105             {
1106                 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1107                 if (m_window && m_window->GetBackingPixmap())
1108                     XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1109             }
1110         }
1111         else
1112             m_textForegroundColour = oldPenColour;
1113     }
1114 
1115     // We need to add the ascent, not the whole height, since X draws at the
1116     // point above the descender.
1117 #if 0
1118     if (use16)
1119         XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1120         (XChar2b *)(char*) (const char*) text, slen);
1121     else
1122 #endif // 0
1123 #if wxMOTIF_NEW_FONT_HANDLING
1124         XFontSet fset = (XFontSet) m_font.GetFontSet (m_userScaleY * m_logicalScaleY, m_display);
1125         XmbDrawString((Display*) m_display, (Pixmap) m_pixmap, fset, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1126 #else
1127         XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent, text, slen);
1128 #endif
1129 
1130     if (m_window && m_window->GetBackingPixmap()) {
1131 #if 0
1132         if (use16)
1133             XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1134             XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1135             (XChar2b *)(char*) (const char*) text, slen);
1136         else
1137 #endif // 0
1138 #if wxMOTIF_NEW_FONT_HANDLING
1139             XmbDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), fset, (GC) m_gcBacking,
1140             XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1141                         text.mb_str(), slen);
1142 #else
1143             XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1144             XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1145                         text.mb_str(), slen);
1146 #endif
1147     }
1148 
1149     // restore fill style
1150     XSetFillStyle ((Display*) m_display, (GC) m_gc, gcV.fill_style);
1151     if (m_window && m_window->GetBackingPixmap())
1152         XSetFillStyle ((Display*) m_display, (GC) m_gcBacking,
1153                        gcBackingV.fill_style);
1154 
1155     wxCoord w, h;
1156     DoGetTextExtent (text, &w, &h);
1157     CalcBoundingBox (x + w, y + h);
1158     CalcBoundingBox (x, y);
1159 }
1160 
DoDrawRotatedText(const wxString & text,wxCoord x,wxCoord y,double angle)1161 void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y,
1162                                     double angle )
1163 {
1164     if (angle == 0.0)
1165     {
1166         DoDrawText(text, x, y);
1167         return;
1168     }
1169 
1170     wxCHECK_RET( IsOk(), "invalid dc" );
1171 
1172     WXPixel oldBackgroundPixel = -1;
1173     WXPixel oldForegroundPixel = -1;
1174     WXPixel foregroundPixel = -1;
1175     WXPixel backgroundPixel = -1;
1176 
1177     if (m_textBackgroundColour.IsOk())
1178     {
1179         oldBackgroundPixel = m_backgroundPixel;
1180         backgroundPixel = m_textBackgroundColour.AllocColour(m_display);
1181     }
1182     if (m_textForegroundColour.IsOk())
1183     {
1184         oldForegroundPixel = m_currentColour.GetPixel();
1185 
1186         if( m_textForegroundColour.GetPixel() <= -1 )
1187             CalculatePixel( m_textForegroundColour,
1188                             m_textForegroundColour, true);
1189 
1190         foregroundPixel = m_textForegroundColour.GetPixel();
1191     }
1192 
1193     // Since X draws from the baseline of the text, must add the text height
1194     int cx = 0;
1195     int cy = 0;
1196     int ascent = 0;
1197 
1198     if (m_font.IsOk())
1199         wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1200                          text, &cx, &cy, &ascent, NULL);
1201 
1202     wxBitmap src(cx, cy);
1203     wxMemoryDC dc;
1204     dc.SelectObject(src);
1205     dc.SetFont(GetFont());
1206     dc.SetBackground(*wxWHITE_BRUSH);
1207     dc.SetBrush(*wxBLACK_BRUSH);
1208     dc.Clear();
1209     dc.DrawText(text, 0, 0);
1210     dc.SetFont(wxNullFont);
1211 
1212     // Calculate the size of the rotated bounding box.
1213     double dx = cos(angle / 180.0 * M_PI);
1214     double dy = sin(angle / 180.0 * M_PI);
1215     double x4 = cy * dy;
1216     double y4 = cy * dx;
1217     double x3 = cx * dx;
1218     double y3 = -cx * dy;
1219     double x2 = x3 + x4;
1220     double y2 = y3 + y4;
1221     double x1 = x;
1222     double y1 = y;
1223 
1224     // Create image from the source bitmap after writing the text into it.
1225     wxImage  image = src.ConvertToImage();
1226 
1227     int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
1228     int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
1229     int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
1230     int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
1231 
1232     bool lastFore = false, lastBack = false;
1233 
1234     // This rotates counterclockwise around the top left corner.
1235     for (int rx = minx; rx < maxx; rx++)
1236     {
1237         for (int ry = miny; ry < maxy; ry++)
1238         {
1239             // transform dest coords to source coords
1240             int sx = (int) (rx * dx - ry * dy + 0.5);
1241             int sy = - (int) (-ry * dx - rx * dy + 0.5);
1242             if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
1243             {
1244                 bool textPixel = image.GetRed(sx, sy) == 0;
1245 
1246                 if (!textPixel && m_backgroundMode != wxBRUSHSTYLE_SOLID)
1247                     continue;
1248 
1249                 wxCoord ox = (wxCoord) (x1 + rx),
1250                         oy = (wxCoord) (y1 + ry);
1251                 // draw black pixels, ignore white ones (i.e. transparent b/g)
1252                 if (textPixel && !lastFore)
1253                 {
1254                     XSetForeground ((Display*) m_display, (GC) m_gc,
1255                                     foregroundPixel);
1256                     lastFore = true;
1257                     lastBack = false;
1258                 }
1259                 else if (!textPixel && !lastBack)
1260                 {
1261                     XSetForeground ((Display*) m_display, (GC) m_gc,
1262                                     backgroundPixel);
1263                     lastFore = false;
1264                     lastBack = true;
1265                 }
1266 
1267                 XDrawPoint ((Display*) m_display, (Pixmap) m_pixmap,
1268                             (GC) m_gc, XLOG2DEV (ox), YLOG2DEV (oy));
1269                 if (m_window && m_window->GetBackingPixmap())
1270                     XDrawPoint ((Display*) m_display,
1271                                 (Pixmap) m_window->GetBackingPixmap(),
1272                                 (GC) m_gcBacking,
1273                                 XLOG2DEV_2 (ox), YLOG2DEV_2 (oy));
1274             }
1275         }
1276     }
1277 
1278     if (oldBackgroundPixel > -1)
1279     {
1280         XSetBackground ((Display*) m_display, (GC) m_gc, oldBackgroundPixel);
1281         if (m_window && m_window->GetBackingPixmap())
1282             XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1283                             oldBackgroundPixel);
1284     }
1285     if (oldForegroundPixel > -1)
1286     {
1287         XSetForeground ((Display*) m_display, (GC) m_gc, oldForegroundPixel);
1288         if (m_window && m_window->GetBackingPixmap())
1289             XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1290                             oldForegroundPixel);
1291     }
1292 
1293     CalcBoundingBox (minx, miny);
1294     CalcBoundingBox (maxx, maxy);
1295 }
1296 
CanGetTextExtent() const1297 bool wxWindowDCImpl::CanGetTextExtent() const
1298 {
1299     return true;
1300 }
1301 
DoGetTextExtent(const wxString & string,wxCoord * width,wxCoord * height,wxCoord * descent,wxCoord * externalLeading,const wxFont * font) const1302 void wxWindowDCImpl::DoGetTextExtent( const wxString &string, wxCoord *width, wxCoord *height,
1303                                 wxCoord *descent, wxCoord *externalLeading,
1304                                 const wxFont *font ) const
1305 {
1306     wxCHECK_RET( IsOk(), "invalid dc" );
1307 
1308     const wxFont* theFont = font ? font : &m_font;
1309 
1310     if (!theFont->IsOk())
1311     {
1312         // TODO: this should be an error log function
1313         wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1314 
1315         if (width) *width = -1;
1316         if (height) *height = -1;
1317         return;
1318     }
1319 
1320     wxGetTextExtent(m_display, *theFont, m_userScaleY * m_logicalScaleY,
1321                     string, width, height, NULL, descent);
1322 
1323     if (width) *width = XDEV2LOGREL (*width);
1324     if (height) *height = YDEV2LOGREL (*height);
1325     if (externalLeading)
1326         *externalLeading = 0;
1327 }
1328 
GetCharWidth() const1329 wxCoord wxWindowDCImpl::GetCharWidth() const
1330 {
1331     wxCHECK_MSG( IsOk(), 0, "invalid dc" );
1332     wxCHECK_MSG( m_font.IsOk(), 0, "invalid font" );
1333 
1334     int width;
1335 
1336     wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1337                      "x", &width, NULL, NULL, NULL);
1338 
1339     return XDEV2LOGREL(width);
1340 }
1341 
GetCharHeight() const1342 wxCoord wxWindowDCImpl::GetCharHeight() const
1343 {
1344     wxCHECK_MSG( IsOk(), 0, "invalid dc" );
1345     wxCHECK_MSG( m_font.IsOk(), 0, "invalid font" );
1346 
1347     int height;
1348 
1349     wxGetTextExtent (m_display, m_font, m_userScaleY * m_logicalScaleY,
1350                      "x", NULL, &height, NULL, NULL);
1351 
1352     return XDEV2LOGREL(height);
1353 }
1354 
DoGetSize(int * width,int * height) const1355 void wxWindowDCImpl::DoGetSize( int *width, int *height ) const
1356 {
1357     int w = 0, h = 0;
1358 
1359     if( m_window )
1360     {
1361         if( m_window->GetBackingPixmap() )
1362         {
1363             w = m_window->GetPixmapWidth();
1364             h = m_window->GetPixmapHeight();
1365         }
1366         else
1367             m_window->GetSize( &w, &h );
1368     }
1369 
1370     if( width ) *width = w;
1371     if( height ) *height = h;
1372 }
1373 
Clear()1374 void wxWindowDCImpl::Clear()
1375 {
1376     wxCHECK_RET( IsOk(), "invalid dc" );
1377 
1378     wxRect rect( GetSize() );
1379     Clear( rect );
1380 }
1381 
Clear(const wxRect & rect)1382 void wxWindowDCImpl::Clear(const wxRect& rect)
1383 {
1384     wxCHECK_RET( IsOk(), "invalid dc" );
1385 
1386     int x = rect.x; int y = rect.y;
1387     int w = rect.width; int h = rect.height;
1388 
1389     wxBrush saveBrush = m_brush;
1390     SetBrush (m_backgroundBrush);
1391 
1392     XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc,
1393                     x, y, w, h);
1394 
1395     if (m_window && m_window->GetBackingPixmap())
1396         XFillRectangle ((Display*) m_display,
1397                         (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1398                         x, y, w, h);
1399 
1400     m_brush = saveBrush;
1401 }
1402 
SetFont(const wxFont & font)1403 void wxWindowDCImpl::SetFont( const wxFont &font )
1404 {
1405     wxCHECK_RET( IsOk(), "invalid dc" );
1406 
1407     m_font = font;
1408 
1409     if (!m_font.IsOk())
1410     {
1411         return;
1412     }
1413 
1414 #if !wxMOTIF_NEW_FONT_HANDLING
1415     WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1416 
1417     Font fontId = ((XFontStruct*)pFontStruct)->fid;
1418     XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1419 
1420     if (m_window && m_window->GetBackingPixmap())
1421         XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1422 #endif
1423 }
1424 
SetForegroundPixelWithLogicalFunction(WXPixel pixel)1425 void wxWindowDCImpl::SetForegroundPixelWithLogicalFunction(WXPixel pixel)
1426 {
1427     if (m_logicalFunction == wxXOR)
1428     {
1429         XGCValues values;
1430         XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1431         XSetForeground ((Display*) m_display, (GC) m_gc,
1432                         pixel ^ values.background);
1433         if (m_window && m_window->GetBackingPixmap())
1434             XSetForeground ((Display*) m_display,(GC) m_gcBacking,
1435                             pixel ^ values.background);
1436     }
1437     else
1438     {
1439         XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1440         if (m_window && m_window->GetBackingPixmap())
1441             XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1442     }
1443 }
1444 
CalculatePixel(wxColour & colour,wxColour & curCol,bool roundToWhite) const1445 WXPixel wxWindowDCImpl::CalculatePixel(wxColour& colour, wxColour& curCol,
1446                                bool roundToWhite) const
1447 {
1448     const unsigned char wp = (unsigned char)255;
1449 
1450     WXPixel pixel = -1;
1451     if(!m_colour) // Mono display
1452     {
1453         unsigned char red = colour.Red ();
1454         unsigned char blue = colour.Blue ();
1455         unsigned char green = colour.Green ();
1456         // white
1457         if((red == wp && blue == wp && green == wp) ||
1458            // not black and roundToWhite was specified
1459            ((red != 0 || blue != 0 || green != 0) && roundToWhite))
1460         {
1461             curCol = *wxWHITE;
1462             pixel = WhitePixel((Display*) m_display,
1463                                DefaultScreen((Display*) m_display));
1464             curCol.SetPixel(pixel);
1465             colour.SetPixel(pixel);
1466         }
1467         else
1468         {
1469             curCol = *wxBLACK;
1470             pixel = BlackPixel((Display*) m_display,
1471                                DefaultScreen((Display*) m_display));
1472             curCol.SetPixel(pixel);
1473             colour.SetPixel(pixel);
1474         }
1475     }
1476     else
1477     {
1478         curCol = colour;
1479         pixel = colour.AllocColour((Display*) m_display);
1480         curCol.SetPixel(pixel);
1481     }
1482 
1483     return pixel;
1484 }
1485 
SetPen(const wxPen & pen)1486 void wxWindowDCImpl::SetPen( const wxPen &pen )
1487 {
1488     wxCHECK_RET( IsOk(), "invalid dc" );
1489 
1490     m_pen = pen;
1491     if (!m_pen.IsOk())
1492         return;
1493 
1494     wxBitmap oldStipple = m_currentStipple;
1495     int oldStyle = m_currentStyle;
1496     int oldFill = m_currentFill;
1497     int old_pen_width = m_currentPenWidth;
1498     int old_pen_join = m_currentPenJoin;
1499     int old_pen_cap = m_currentPenCap;
1500     int old_pen_nb_dash = m_currentPenDashCount;
1501     wxX11Dash *old_pen_dash = m_currentPenDash;
1502 
1503     wxColour oldPenColour = m_currentColour;
1504     m_currentColour = m_pen.GetColour ();
1505     m_currentStyle = m_pen.GetStyle ();
1506     m_currentFill = m_pen.GetStyle (); // TODO?
1507     m_currentPenWidth = m_pen.GetWidth ();
1508     m_currentPenJoin = m_pen.GetJoin ();
1509     m_currentPenCap = m_pen.GetCap ();
1510     m_currentPenDashCount = m_pen.GetDashCount();
1511     m_currentPenDash = (wxX11Dash*)m_pen.GetDash();
1512 
1513     if (m_currentStyle == wxPENSTYLE_STIPPLE)
1514         m_currentStipple = * m_pen.GetStipple ();
1515 
1516     bool sameStyle = (oldStyle == m_currentStyle &&
1517         oldFill == m_currentFill &&
1518         old_pen_join == m_currentPenJoin &&
1519         old_pen_cap == m_currentPenCap &&
1520         old_pen_nb_dash == m_currentPenDashCount &&
1521         old_pen_dash == m_currentPenDash &&
1522         old_pen_width == m_currentPenWidth);
1523 
1524     bool sameColour = (oldPenColour.IsOk () &&
1525         (oldPenColour.Red () == m_currentColour.Red ()) &&
1526         (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1527         (oldPenColour.Green () == m_currentColour.Green ()) &&
1528         (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1529 
1530     if (!sameStyle || !GET_OPTIMIZATION)
1531     {
1532         int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1533         if (scaled_width < 0)
1534             scaled_width = 0;
1535 
1536         int style;
1537         int join;
1538         int cap;
1539         static const wxX11Dash dotted[] = {2, 5};
1540         static const wxX11Dash short_dashed[] = {4, 4};
1541         static const wxX11Dash long_dashed[] = {4, 8};
1542         static const wxX11Dash dotted_dashed[] = {6, 6, 2, 6};
1543 
1544         // We express dash pattern in pen width unit, so we are
1545         // independent of zoom factor and so on...
1546         int req_nb_dash;
1547         const wxX11Dash *req_dash;
1548 
1549         switch (m_pen.GetStyle ())
1550         {
1551         case wxPENSTYLE_USER_DASH:
1552             req_nb_dash = m_currentPenDashCount;
1553             req_dash = m_currentPenDash;
1554             style = LineOnOffDash;
1555             break;
1556         case wxPENSTYLE_DOT:
1557             req_nb_dash = 2;
1558             req_dash = dotted;
1559             style = LineOnOffDash;
1560             break;
1561         case wxPENSTYLE_SHORT_DASH:
1562             req_nb_dash = 2;
1563             req_dash = short_dashed;
1564             style = LineOnOffDash;
1565             break;
1566         case wxPENSTYLE_LONG_DASH:
1567             req_nb_dash = 2;
1568             req_dash = long_dashed;
1569             style = LineOnOffDash;
1570             break;
1571         case wxPENSTYLE_DOT_DASH:
1572             req_nb_dash = 4;
1573             req_dash = dotted_dashed;
1574             style = LineOnOffDash;
1575             break;
1576         case wxPENSTYLE_STIPPLE:
1577         case wxPENSTYLE_SOLID:
1578         case wxPENSTYLE_TRANSPARENT:
1579         default:
1580             style = LineSolid;
1581             req_dash = NULL;
1582             req_nb_dash = 0;
1583         }
1584 
1585         if (req_dash && req_nb_dash)
1586         {
1587             wxX11Dash *real_req_dash = new wxX11Dash[req_nb_dash];
1588             if (real_req_dash)
1589             {
1590                 int factor = scaled_width == 0 ? 1 : scaled_width;
1591                 for (int i = 0; i < req_nb_dash; i++)
1592                     real_req_dash[i] = (wxX11Dash)(req_dash[i] * factor);
1593                 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1594 
1595                 if (m_window && m_window->GetBackingPixmap())
1596                     XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1597                 delete[]real_req_dash;
1598             }
1599             else
1600             {
1601                 // No Memory. We use non-scaled dash pattern...
1602                 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1603 
1604                 if (m_window && m_window->GetBackingPixmap())
1605                     XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1606             }
1607         }
1608 
1609         switch (m_pen.GetCap ())
1610         {
1611         case wxCAP_PROJECTING:
1612             cap = CapProjecting;
1613             break;
1614         case wxCAP_BUTT:
1615             cap = CapButt;
1616             break;
1617         case wxCAP_ROUND:
1618         default:
1619             cap = (scaled_width <= 1) ? CapNotLast : CapRound;
1620             break;
1621         }
1622 
1623         switch (m_pen.GetJoin ())
1624         {
1625         case wxJOIN_BEVEL:
1626             join = JoinBevel;
1627             break;
1628         case wxJOIN_MITER:
1629             join = JoinMiter;
1630             break;
1631         case wxJOIN_ROUND:
1632         default:
1633             join = JoinRound;
1634             break;
1635         }
1636 
1637         XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1638 
1639         if (m_window && m_window->GetBackingPixmap())
1640             XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1641     }
1642 
1643     if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
1644     {
1645         Pixmap myStipple;
1646 
1647         oldStipple = wxNullBitmap;    // For later reset!!
1648 
1649         switch (m_currentFill)
1650         {
1651         case wxHATCHSTYLE_BDIAGONAL:
1652             if (bdiag == (Pixmap) 0)
1653                 bdiag = XCreateBitmapFromData ((Display*) m_display,
1654                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1655                 reinterpret_cast<const char*>(bdiag_bits), bdiag_width, bdiag_height);
1656             myStipple = bdiag;
1657             break;
1658         case wxHATCHSTYLE_FDIAGONAL:
1659             if (fdiag == (Pixmap) 0)
1660                 fdiag = XCreateBitmapFromData ((Display*) m_display,
1661                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1662                 reinterpret_cast<const char*>(fdiag_bits), fdiag_width, fdiag_height);
1663             myStipple = fdiag;
1664             break;
1665         case wxHATCHSTYLE_CROSS:
1666             if (cross == (Pixmap) 0)
1667                 cross = XCreateBitmapFromData ((Display*) m_display,
1668                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1669                 reinterpret_cast<const char*>(cross_bits), cross_width, cross_height);
1670             myStipple = cross;
1671             break;
1672         case wxHATCHSTYLE_HORIZONTAL:
1673             if (horiz == (Pixmap) 0)
1674                 horiz = XCreateBitmapFromData ((Display*) m_display,
1675                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1676                 reinterpret_cast<const char*>(horiz_bits), horiz_width, horiz_height);
1677             myStipple = horiz;
1678             break;
1679         case wxHATCHSTYLE_VERTICAL:
1680             if (verti == (Pixmap) 0)
1681                 verti = XCreateBitmapFromData ((Display*) m_display,
1682                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1683                 reinterpret_cast<const char*>(verti_bits), verti_width, verti_height);
1684             myStipple = verti;
1685             break;
1686         case wxHATCHSTYLE_CROSSDIAG:
1687         default:
1688             if (cdiag == (Pixmap) 0)
1689                 cdiag = XCreateBitmapFromData ((Display*) m_display,
1690                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1691                 reinterpret_cast<const char*>(cdiag_bits), cdiag_width, cdiag_height);
1692             myStipple = cdiag;
1693             break;
1694         }
1695         XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1696 
1697         if (m_window && m_window->GetBackingPixmap())
1698             XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1699     }
1700     else if (m_currentStyle == wxPENSTYLE_STIPPLE && m_currentStipple.IsOk()
1701         && ((!m_currentStipple.IsSameAs(oldStipple)) || !GET_OPTIMIZATION))
1702     {
1703         XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetDrawable());
1704 
1705         if (m_window && m_window->GetBackingPixmap())
1706             XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetDrawable());
1707     }
1708 
1709     if ((m_currentFill != oldFill) || !GET_OPTIMIZATION)
1710     {
1711         int fill_style;
1712 
1713         if (m_currentFill == wxBRUSHSTYLE_STIPPLE)
1714             fill_style = FillStippled;
1715         else if (IS_HATCH (m_currentFill))
1716             fill_style = FillStippled;
1717         else
1718             fill_style = FillSolid;
1719         XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1720         if (m_window && m_window->GetBackingPixmap())
1721             XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1722     }
1723 
1724     // must test m_logicalFunction, because it involves background!
1725     if (!sameColour || !GET_OPTIMIZATION
1726         || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1727     {
1728         WXPixel pixel = -1;
1729         if (m_pen.GetStyle () == wxPENSTYLE_TRANSPARENT)
1730             pixel = m_backgroundPixel;
1731         else
1732         {
1733             wxColour penClr = m_pen.GetColour();
1734             pixel = CalculatePixel( penClr, m_currentColour, false);
1735             m_pen.SetColour(penClr);
1736         }
1737 
1738         // Finally, set the GC to the required colour
1739         if (pixel > -1)
1740             SetForegroundPixelWithLogicalFunction(pixel);
1741     }
1742     else
1743         m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1744 
1745     m_autoSetting = 0;
1746 }
1747 
SetBrush(const wxBrush & brush)1748 void wxWindowDCImpl::SetBrush( const wxBrush &brush )
1749 {
1750     wxCHECK_RET( IsOk(), "invalid dc" );
1751 
1752     m_brush = brush;
1753 
1754     if (!m_brush.IsOk() || m_brush.GetStyle () == wxBRUSHSTYLE_TRANSPARENT)
1755         return;
1756 
1757     int oldFill = m_currentFill;
1758     wxBitmap oldStipple = m_currentStipple;
1759 
1760     m_autoSetting |= 0x1;
1761 
1762     m_currentFill = m_brush.GetStyle ();
1763     if (m_currentFill == wxBRUSHSTYLE_STIPPLE)
1764         m_currentStipple = * m_brush.GetStipple ();
1765 
1766     wxColour oldBrushColour(m_currentColour);
1767     m_currentColour = m_brush.GetColour ();
1768 
1769     bool sameColour = (oldBrushColour.IsOk () &&
1770         (oldBrushColour.Red () == m_currentColour.Red ()) &&
1771         (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1772         (oldBrushColour.Green () == m_currentColour.Green ()) &&
1773         (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1774 
1775     int stippleDepth = -1;
1776 
1777     if ((oldFill != m_brush.GetStyle ()) || !GET_OPTIMIZATION)
1778     {
1779         switch (brush.GetStyle ())
1780         {
1781         case wxBRUSHSTYLE_TRANSPARENT:
1782             break;
1783         case wxBRUSHSTYLE_STIPPLE:
1784             stippleDepth = m_currentStipple.GetDepth();
1785             // fall through!
1786         case wxBRUSHSTYLE_BDIAGONAL_HATCH:
1787         case wxBRUSHSTYLE_CROSSDIAG_HATCH:
1788         case wxBRUSHSTYLE_FDIAGONAL_HATCH:
1789         case wxBRUSHSTYLE_CROSS_HATCH:
1790         case wxBRUSHSTYLE_HORIZONTAL_HATCH:
1791         case wxBRUSHSTYLE_VERTICAL_HATCH:
1792             {
1793                 if (stippleDepth == -1) stippleDepth = 1;
1794 
1795                 // Chris Breeze 23/07/97: use background mode to
1796                 // determine whether fill style should be solid or
1797                 // transparent
1798                 int style = stippleDepth == 1 ?
1799                     (m_backgroundMode == wxBRUSHSTYLE_SOLID ?
1800                      FillOpaqueStippled : FillStippled) :
1801                     FillTiled;
1802                 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1803                 if (m_window && m_window->GetBackingPixmap())
1804                     XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1805             }
1806             break;
1807         case wxBRUSHSTYLE_SOLID:
1808         default:
1809             XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1810             if (m_window && m_window->GetBackingPixmap())
1811                 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking,
1812                                FillSolid);
1813         }
1814     }
1815 
1816     if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GET_OPTIMIZATION))
1817     {
1818         Pixmap myStipple;
1819 
1820         switch (m_currentFill)
1821         {
1822         case wxHATCHSTYLE_BDIAGONAL:
1823             if (bdiag == (Pixmap) 0)
1824                 bdiag = XCreateBitmapFromData ((Display*) m_display,
1825                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1826                 reinterpret_cast<const char*>(bdiag_bits), bdiag_width, bdiag_height);
1827             myStipple = bdiag;
1828             break;
1829         case wxHATCHSTYLE_FDIAGONAL:
1830             if (fdiag == (Pixmap) 0)
1831                 fdiag = XCreateBitmapFromData ((Display*) m_display,
1832                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1833                 reinterpret_cast<const char*>(fdiag_bits), fdiag_width, fdiag_height);
1834             myStipple = fdiag;
1835             break;
1836         case wxHATCHSTYLE_CROSS:
1837             if (cross == (Pixmap) 0)
1838                 cross = XCreateBitmapFromData ((Display*) m_display,
1839                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1840                 reinterpret_cast<const char*>(cross_bits), cross_width, cross_height);
1841             myStipple = cross;
1842             break;
1843         case wxHATCHSTYLE_HORIZONTAL:
1844             if (horiz == (Pixmap) 0)
1845                 horiz = XCreateBitmapFromData ((Display*) m_display,
1846                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1847                 reinterpret_cast<const char*>(horiz_bits), horiz_width, horiz_height);
1848             myStipple = horiz;
1849             break;
1850         case wxHATCHSTYLE_VERTICAL:
1851             if (verti == (Pixmap) 0)
1852                 verti = XCreateBitmapFromData ((Display*) m_display,
1853                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1854                 reinterpret_cast<const char*>(verti_bits), verti_width, verti_height);
1855             myStipple = verti;
1856             break;
1857         case wxHATCHSTYLE_CROSSDIAG:
1858         default:
1859             if (cdiag == (Pixmap) 0)
1860                 cdiag = XCreateBitmapFromData ((Display*) m_display,
1861                 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1862                 reinterpret_cast<const char*>(cdiag_bits), cdiag_width, cdiag_height);
1863             myStipple = cdiag;
1864             break;
1865         }
1866         XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1867 
1868         if (m_window && m_window->GetBackingPixmap())
1869             XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1870     }
1871     // X can forget the stipple value when resizing a window (apparently)
1872     // so always set the stipple.
1873     else if (m_currentFill != wxBRUSHSTYLE_SOLID && m_currentFill != wxBRUSHSTYLE_TRANSPARENT &&
1874              m_currentStipple.IsOk()) // && m_currentStipple != oldStipple)
1875     {
1876         if (m_currentStipple.GetDepth() == 1)
1877         {
1878             XSetStipple ((Display*) m_display, (GC) m_gc,
1879                          (Pixmap) m_currentStipple.GetDrawable());
1880         if (m_window && m_window->GetBackingPixmap())
1881                 XSetStipple ((Display*) m_display,(GC) m_gcBacking,
1882                              (Pixmap) m_currentStipple.GetDrawable());
1883         }
1884         else
1885         {
1886             XSetTile ((Display*) m_display, (GC) m_gc,
1887                       (Pixmap) m_currentStipple.GetDrawable());
1888             if (m_window && m_window->GetBackingPixmap())
1889                 XSetTile ((Display*) m_display,(GC) m_gcBacking,
1890                           (Pixmap) m_currentStipple.GetDrawable());
1891         }
1892     }
1893 
1894     // must test m_logicalFunction, because it involves background!
1895     if (!sameColour || !GET_OPTIMIZATION || m_logicalFunction == wxXOR)
1896     {
1897         wxColour brushClr = m_brush.GetColour();
1898         WXPixel pixel = CalculatePixel( brushClr, m_currentColour, true);
1899         m_brush.SetColour(brushClr);
1900 
1901         if (pixel > -1)
1902             SetForegroundPixelWithLogicalFunction(pixel);
1903     }
1904     else
1905         m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1906 }
1907 
SetBackground(const wxBrush & brush)1908 void wxWindowDCImpl::SetBackground( const wxBrush &brush )
1909 {
1910     wxCHECK_RET( IsOk(), "invalid dc" );
1911 
1912     m_backgroundBrush = brush;
1913 
1914     if (!m_backgroundBrush.IsOk())
1915         return;
1916 
1917     m_backgroundPixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1918 
1919     // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1920     // And Blit,... (Any fct that use XCopyPlane, in fact.)
1921     XSetBackground ((Display*) m_display, (GC) m_gc, m_backgroundPixel);
1922     if (m_window && m_window->GetBackingPixmap())
1923         XSetBackground ((Display*) m_display,(GC) m_gcBacking,
1924                         m_backgroundPixel);
1925 }
1926 
SetLogicalFunction(wxRasterOperationMode function)1927 void wxWindowDCImpl::SetLogicalFunction( wxRasterOperationMode function )
1928 {
1929     wxCHECK_RET( IsOk(), "invalid dc" );
1930 
1931     int x_function;
1932 
1933     /* MATTHEW: [9] */
1934     if (m_logicalFunction == function)
1935         return;
1936 
1937     switch (function)
1938     {
1939     case wxCLEAR:
1940         x_function = GXclear;
1941         break;
1942     case wxXOR:
1943         x_function = GXxor;
1944         break;
1945     case wxINVERT:
1946         x_function = GXinvert;
1947         break;
1948     case wxOR_REVERSE:
1949         x_function = GXorReverse;
1950         break;
1951     case wxAND_REVERSE:
1952         x_function = GXandReverse;
1953         break;
1954     case wxAND:
1955         x_function = GXand;
1956         break;
1957     case wxOR:
1958         x_function = GXor;
1959         break;
1960     case wxAND_INVERT:
1961         x_function = GXandInverted;
1962         break;
1963     case wxNO_OP:
1964         x_function = GXnoop;
1965         break;
1966     case wxNOR:
1967         x_function = GXnor;
1968         break;
1969     case wxEQUIV:
1970         x_function = GXequiv;
1971         break;
1972     case wxSRC_INVERT:
1973         x_function = GXcopyInverted;
1974         break;
1975     case wxOR_INVERT:
1976         x_function = GXorInverted;
1977         break;
1978     case wxNAND:
1979         x_function = GXnand;
1980         break;
1981     case wxSET:
1982         x_function = GXset;
1983         break;
1984     case wxCOPY:
1985     default:
1986         x_function = GXcopy;
1987         break;
1988     }
1989 
1990     XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1991     if (m_window && m_window->GetBackingPixmap())
1992         XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
1993 
1994     if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1995         /* MATTHEW: [9] Need to redo pen simply */
1996         m_autoSetting |= 0x2;
1997 
1998     m_logicalFunction = function;
1999 
2000 }
2001 
SetTextForeground(const wxColour & col)2002 void wxWindowDCImpl::SetTextForeground( const wxColour &col )
2003 {
2004     wxCHECK_RET( IsOk(), "invalid dc" );
2005 
2006     m_textForegroundColour = col;
2007 }
2008 
SetTextBackground(const wxColour & col)2009 void wxWindowDCImpl::SetTextBackground( const wxColour &col )
2010 {
2011     wxCHECK_RET( IsOk(), "invalid dc" );
2012 
2013     m_textBackgroundColour = col;
2014 }
2015 
SetBackgroundMode(int mode)2016 void wxWindowDCImpl::SetBackgroundMode( int mode )
2017 {
2018     m_backgroundMode = mode;
2019 }
2020 
SetPalette(const wxPalette & palette)2021 void wxWindowDCImpl::SetPalette( const wxPalette& palette )
2022 {
2023     if (m_window)
2024     {
2025         if (palette.IsOk())
2026             /* Use GetXColormap */
2027             XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2028             (Colormap) palette.GetXColormap());
2029         else
2030             /* Use wxGetMainColormap */
2031             XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2032             (Colormap) wxTheApp->GetMainColormap(m_display));
2033     }
2034 }
2035 
wxCopyRegion(WXRegion src,WXRegion & dst)2036 static void wxCopyRegion( WXRegion src, WXRegion& dst )
2037 {
2038     if( !dst )
2039         dst = XCreateRegion();
2040     XUnionRegion( (Region)src, (Region)src, (Region)dst );
2041 }
2042 
2043 // Helper function; userRegion is the region set by calling SetClippingRegion
SetDCClipping(WXRegion userRegion)2044 void wxWindowDCImpl::SetDCClipping( WXRegion userRegion )
2045 {
2046     bool hasUpdateRegion = m_window && m_window->GetUpdateRegion().IsOk();
2047     // this means that we should start the clip region from scratch,
2048     // or from the update region, if any
2049     if( !userRegion )
2050     {
2051         if( m_clipRegion )
2052             XDestroyRegion( (Region)m_clipRegion );
2053         m_clipRegion = (WXRegion)NULL;
2054 
2055         if( hasUpdateRegion )
2056             wxCopyRegion( m_window->GetUpdateRegion().GetX11Region(),
2057                           m_clipRegion );
2058     }
2059     // intersect the user region, if any, with the
2060     // existing clip region
2061     else // if( userRegion )
2062     {
2063         if( !m_clipRegion )
2064             wxCopyRegion( userRegion, m_clipRegion );
2065         else
2066             XIntersectRegion( (Region)m_clipRegion,
2067                               (Region)userRegion, (Region)m_clipRegion );
2068     }
2069 
2070     if( m_clipRegion )
2071         XSetRegion( (Display*)m_display, (GC)m_gc, (Region)m_clipRegion );
2072     else
2073         XSetClipMask( (Display*)m_display, (GC)m_gc, None );
2074 }
2075 
DoSetClippingRegion(wxCoord x,wxCoord y,wxCoord width,wxCoord height)2076 void wxWindowDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y,
2077                                       wxCoord width, wxCoord height )
2078 {
2079     wxMotifDCImpl::DoSetClippingRegion( x, y, width, height );
2080 
2081     wxRegion temp(XLOG2DEV(x), YLOG2DEV(y),
2082                   XLOG2DEVREL(width), YLOG2DEVREL(height));
2083 
2084     SetDCClipping(temp.GetX11Region());
2085 
2086     // Needs to work differently for Pixmap: without this,
2087     // there's a nasty (Display*) m_display bug. 8/12/94
2088     if (m_window && m_window->GetBackingPixmap())
2089     {
2090         XRectangle rects[1];
2091         rects[0].x = (short)XLOG2DEV_2(x);
2092         rects[0].y = (short)YLOG2DEV_2(y);
2093         rects[0].width = (unsigned short)XLOG2DEVREL(width);
2094         rects[0].height = (unsigned short)YLOG2DEVREL(height);
2095         XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2096                            0, 0, rects, 1, Unsorted);
2097     }
2098 }
2099 
DoSetDeviceClippingRegion(const wxRegion & region)2100 void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion& region )
2101 {
2102     SetDCClipping(region.GetX11Region());
2103 
2104     // Needs to work differently for Pixmap: without this,
2105     // there's a nasty (Display*) m_display bug. 8/12/94
2106     if (m_window && m_window->GetBackingPixmap())
2107     {
2108         wxRect box = region.GetBox();
2109 
2110         XRectangle rects[1];
2111         rects[0].x = (short)box.x;
2112         rects[0].y = (short)box.y;
2113         rects[0].width = (unsigned short)box.width;
2114         rects[0].height = (unsigned short)box.height;
2115         XSetClipRectangles((Display*) m_display, (GC) m_gcBacking,
2116                            0, 0, rects, 1, Unsorted);
2117     }
2118 }
2119 
2120 
DestroyClippingRegion()2121 void wxWindowDCImpl::DestroyClippingRegion()
2122 {
2123     wxMotifDCImpl::DestroyClippingRegion();
2124 
2125     SetDCClipping(NULL);
2126 
2127     if (m_window && m_window->GetBackingPixmap())
2128         XSetClipMask ((Display*) m_display, (GC) m_gcBacking, None);
2129 }
2130 
2131 // Resolution in pixels per logical inch
GetPPI() const2132 wxSize wxWindowDCImpl::GetPPI() const
2133 {
2134     // TODO
2135     return wxSize(100, 100);
2136 }
2137 
GetDepth() const2138 int wxWindowDCImpl::GetDepth() const
2139 {
2140     // TODO
2141     return 24;
2142 }
2143 
2144 
2145 
2146 
2147 // ----------------------------------------------------------------------------
2148 // wxPaintDCImpl
2149 // ----------------------------------------------------------------------------
2150 
wxPaintDCImpl(wxDC * owner,wxWindow * win)2151 wxPaintDCImpl::wxPaintDCImpl(wxDC *owner, wxWindow* win)
2152              : wxWindowDCImpl(owner, win)
2153 {
2154     // Set the clipping region.to the update region
2155     SetDCClipping((WXRegion)NULL);
2156 }
2157 
~wxPaintDCImpl()2158 wxPaintDCImpl::~wxPaintDCImpl()
2159 {
2160     if (m_window)
2161         m_window->ClearUpdateRegion();
2162     SetDCClipping((WXRegion)NULL);
2163 }
2164 
2165 // ----------------------------------------------------------------------------
2166 // private functions
2167 // ----------------------------------------------------------------------------
2168 
2169 /*
2170    Used when copying between drawables on different (Display*) m_displays. Not
2171    very fast, but better than giving up.
2172 */
2173 
XCopyRemote(Display * src_display,Display * dest_display,Drawable src,Drawable dest,GC destgc,int srcx,int srcy,unsigned int w,unsigned int h,int destx,int desty,bool more,XImage ** cache)2174 static void XCopyRemote(Display *src_display, Display *dest_display,
2175                         Drawable src, Drawable dest,
2176                         GC destgc,
2177                         int srcx, int srcy,
2178                         unsigned int w, unsigned int h,
2179                         int destx, int desty,
2180                         bool more, XImage **cache)
2181 {
2182     XImage *image, *destimage;
2183     Colormap destcm, srccm;
2184     static const int CACHE_SIZE = 256;
2185 
2186     unsigned int i, j;
2187     Pixel cachesrc[CACHE_SIZE], cachedest[CACHE_SIZE];
2188     int k, cache_pos, all_cache;
2189 
2190     if (!cache || !*cache)
2191         image = XGetImage(src_display, src, srcx, srcy, w, h, AllPlanes, ZPixmap);
2192     else
2193         image = *cache;
2194 
2195     destimage = XGetImage(dest_display, dest, destx, desty, w, h, AllPlanes, ZPixmap);
2196 
2197     srccm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) src_display);
2198     destcm = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dest_display);
2199 
2200     cache_pos = 0;
2201     all_cache = False;
2202 
2203     for (i = 0; i < w; i++)
2204         for (j = 0; j < h; j++) {
2205             Pixel pixel;
2206             XColor xcol;
2207 
2208             pixel = XGetPixel(image, i, j);
2209             for (k = cache_pos; k--; )
2210                 if (cachesrc[k] == pixel) {
2211                     pixel = cachedest[k];
2212                     goto install;
2213                 }
2214             if (all_cache)
2215                 for (k = CACHE_SIZE; k-- > cache_pos; )
2216                     if (cachesrc[k] == pixel) {
2217                         pixel = cachedest[k];
2218                         goto install;
2219                     }
2220 
2221             cachesrc[cache_pos] = xcol.pixel = pixel;
2222             XQueryColor(src_display, srccm, &xcol);
2223             if (!XAllocColor(dest_display, destcm, &xcol))
2224                 xcol.pixel = 0;
2225             cachedest[cache_pos] = pixel = xcol.pixel;
2226 
2227             if (++cache_pos >= CACHE_SIZE) {
2228                 cache_pos = 0;
2229                 all_cache = true;
2230             }
2231 
2232 install:
2233             XPutPixel(destimage, i, j, pixel);
2234         }
2235 
2236         XPutImage(dest_display, dest, destgc, destimage, 0, 0, destx, desty, w, h);
2237         XDestroyImage(destimage);
2238 
2239         if (more && cache)
2240             *cache = image;
2241         else
2242             XDestroyImage(image);
2243 }
2244 
2245