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