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