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