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