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