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