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