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