Sorry folks, a lot of changes to remedy GetFont, GetBrush etc.
[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 const 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 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1233
1234 *width = -1;
1235 *height = -1;
1236 return;
1237 }
1238
1239 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1240
1241 int direction, ascent, descent2;
1242 XCharStruct overall;
1243 int slen;
1244
1245 if (use16) slen = str16len(string); else slen = strlen(string);
1246
1247 if (use16)
1248 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1249 &ascent, &descent2, &overall);
1250 else
1251 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1252 &ascent, &descent2, &overall);
1253
1254 *width = XDEV2LOGREL (overall.width);
1255 *height = YDEV2LOGREL (ascent + descent2);
1256 if (descent)
1257 *descent = descent2;
1258 if (externalLeading)
1259 *externalLeading = 0;
1260 };
1261
1262 long wxWindowDC::GetCharWidth(void)
1263 {
1264 if (!Ok()) return 0;
1265
1266 if (!m_font.Ok())
1267 return 0;
1268
1269 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
1270
1271 int direction, ascent, descent;
1272 XCharStruct overall;
1273 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1274 &descent, &overall);
1275 return XDEV2LOGREL(overall.width);
1276 };
1277
1278 long wxWindowDC::GetCharHeight(void)
1279 {
1280 if (!Ok()) return 0;
1281
1282 if (!m_font.Ok())
1283 return 0;
1284
1285 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1286
1287 int direction, ascent, descent;
1288 XCharStruct overall;
1289 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1290 &descent, &overall);
1291 // return XDEV2LOGREL(overall.ascent + overall.descent);
1292 return XDEV2LOGREL(ascent + descent);
1293 };
1294
1295 void wxWindowDC::Clear(void)
1296 {
1297 if (!Ok()) return;
1298
1299 int w, h;
1300 if (m_window)
1301 {
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::Clear(const wxRect& rect)
1334 {
1335 if (!Ok()) return;
1336
1337 int x = rect.x; int y = rect.y;
1338 int w = rect.width; int h = rect.height;
1339
1340 wxBrush saveBrush = m_brush;
1341 SetBrush (m_backgroundBrush);
1342
1343 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1344
1345 if (m_window && m_window->GetBackingPixmap())
1346 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1347
1348 m_brush = saveBrush;
1349 };
1350
1351 void wxWindowDC::SetFont( const wxFont &font )
1352 {
1353 if (!Ok()) return;
1354
1355 m_font = font;
1356
1357 if (!m_font.Ok())
1358 {
1359 if ((m_oldFont != (WXFont) 0) && ((long) m_oldFont != -1))
1360 {
1361 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1362
1363 if (m_window && m_window->GetBackingPixmap())
1364 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1365 }
1366 return;
1367 }
1368
1369 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1370
1371 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1372 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1373
1374 if (m_window && m_window->GetBackingPixmap())
1375 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1376 };
1377
1378 void wxWindowDC::SetPen( const wxPen &pen )
1379 {
1380 if (!Ok()) return;
1381
1382 m_pen = pen;
1383 if (!m_pen.Ok())
1384 return;
1385
1386 wxBitmap oldStipple = m_currentStipple;
1387 int oldStyle = m_currentStyle;
1388 int oldFill = m_currentFill;
1389 int old_pen_width = m_currentPenWidth;
1390 int old_pen_join = m_currentPenJoin;
1391 int old_pen_cap = m_currentPenCap;
1392 int old_pen_nb_dash = m_currentPenDashCount;
1393 char *old_pen_dash = m_currentPenDash;
1394
1395 wxColour oldPenColour = m_currentColour;
1396 m_currentColour = m_pen.GetColour ();
1397 m_currentStyle = m_pen.GetStyle ();
1398 m_currentFill = m_pen.GetStyle (); // TODO?
1399 m_currentPenWidth = m_pen.GetWidth ();
1400 m_currentPenJoin = m_pen.GetJoin ();
1401 m_currentPenCap = m_pen.GetCap ();
1402 m_currentPenDashCount = m_pen.GetDashCount();
1403 m_currentPenDash = m_pen.GetDash();
1404
1405 if (m_currentStyle == wxSTIPPLE)
1406 m_currentStipple = * m_pen.GetStipple ();
1407
1408 bool sameStyle = (oldStyle == m_currentStyle &&
1409 oldFill == m_currentFill &&
1410 old_pen_join == m_currentPenJoin &&
1411 old_pen_cap == m_currentPenCap &&
1412 old_pen_nb_dash == m_currentPenDashCount &&
1413 old_pen_dash == m_currentPenDash &&
1414 old_pen_width == m_currentPenWidth);
1415
1416 bool sameColour = (oldPenColour.Ok () &&
1417 (oldPenColour.Red () == m_currentColour.Red ()) &&
1418 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1419 (oldPenColour.Green () == m_currentColour.Green ()) &&
1420 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1421
1422 if (!sameStyle || !GetOptimization())
1423 {
1424 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1425 if (scaled_width < 0)
1426 scaled_width = 0;
1427
1428 int style;
1429 int join;
1430 int cap;
1431 static char dotted[] =
1432 {2, 5};
1433 static char short_dashed[] =
1434 {4, 4};
1435 static char long_dashed[] =
1436 {4, 8};
1437 static char dotted_dashed[] =
1438 {6, 6, 2, 6};
1439
1440 // We express dash pattern in pen width unit, so we are
1441 // independent of zoom factor and so on...
1442 int req_nb_dash;
1443 char *req_dash;
1444
1445 switch (m_pen.GetStyle ())
1446 {
1447 case wxUSER_DASH:
1448 req_nb_dash = m_currentPenDashCount;
1449 req_dash = m_currentPenDash;
1450 style = LineOnOffDash;
1451 break;
1452 case wxDOT:
1453 req_nb_dash = 2;
1454 req_dash = dotted;
1455 style = LineOnOffDash;
1456 break;
1457 case wxSHORT_DASH:
1458 req_nb_dash = 2;
1459 req_dash = short_dashed;
1460 style = LineOnOffDash;
1461 break;
1462 case wxLONG_DASH:
1463 req_nb_dash = 2;
1464 req_dash = long_dashed;
1465 style = LineOnOffDash;
1466 break;
1467 case wxDOT_DASH:
1468 req_nb_dash = 4;
1469 req_dash = dotted_dashed;
1470 style = LineOnOffDash;
1471 break;
1472 case wxSTIPPLE:
1473 case wxSOLID:
1474 case wxTRANSPARENT:
1475 default:
1476 style = LineSolid;
1477 req_dash = NULL;
1478 req_nb_dash = 0;
1479 }
1480
1481 if (req_dash && req_nb_dash)
1482 {
1483 char *real_req_dash = new char[req_nb_dash];
1484 if (real_req_dash)
1485 {
1486 int factor = scaled_width == 0 ? 1 : scaled_width;
1487 for (int i = 0; i < req_nb_dash; i++)
1488 real_req_dash[i] = req_dash[i] * factor;
1489 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1490
1491 if (m_window && m_window->GetBackingPixmap())
1492 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1493 delete[]real_req_dash;
1494 }
1495 else
1496 {
1497 // No Memory. We use non-scaled dash pattern...
1498 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1499
1500 if (m_window && m_window->GetBackingPixmap())
1501 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1502 }
1503 }
1504
1505 switch (m_pen.GetCap ())
1506 {
1507 case wxCAP_PROJECTING:
1508 cap = CapProjecting;
1509 break;
1510 case wxCAP_BUTT:
1511 cap = CapButt;
1512 break;
1513 case wxCAP_ROUND:
1514 default:
1515 cap = CapRound;
1516 break;
1517 }
1518
1519 switch (m_pen.GetJoin ())
1520 {
1521 case wxJOIN_BEVEL:
1522 join = JoinBevel;
1523 break;
1524 case wxJOIN_MITER:
1525 join = JoinMiter;
1526 break;
1527 case wxJOIN_ROUND:
1528 default:
1529 join = JoinRound;
1530 break;
1531 }
1532
1533 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1534
1535 if (m_window && m_window->GetBackingPixmap())
1536 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1537 }
1538
1539 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1540 {
1541 Pixmap myStipple;
1542
1543 oldStipple = wxNullBitmap; // For later reset!!
1544
1545 switch (m_currentFill)
1546 {
1547 case wxBDIAGONAL_HATCH:
1548 if (bdiag == (Pixmap) 0)
1549 bdiag = XCreateBitmapFromData ((Display*) m_display,
1550 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1551 bdiag_bits, bdiag_width, bdiag_height);
1552 myStipple = bdiag;
1553 break;
1554 case wxFDIAGONAL_HATCH:
1555 if (fdiag == (Pixmap) 0)
1556 fdiag = XCreateBitmapFromData ((Display*) m_display,
1557 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1558 fdiag_bits, fdiag_width, fdiag_height);
1559 myStipple = fdiag;
1560 break;
1561 case wxCROSS_HATCH:
1562 if (cross == (Pixmap) 0)
1563 cross = XCreateBitmapFromData ((Display*) m_display,
1564 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1565 cross_bits, cross_width, cross_height);
1566 myStipple = cross;
1567 break;
1568 case wxHORIZONTAL_HATCH:
1569 if (horiz == (Pixmap) 0)
1570 horiz = XCreateBitmapFromData ((Display*) m_display,
1571 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1572 horiz_bits, horiz_width, horiz_height);
1573 myStipple = horiz;
1574 break;
1575 case wxVERTICAL_HATCH:
1576 if (verti == (Pixmap) 0)
1577 verti = XCreateBitmapFromData ((Display*) m_display,
1578 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1579 verti_bits, verti_width, verti_height);
1580 myStipple = verti;
1581 break;
1582 case wxCROSSDIAG_HATCH:
1583 default:
1584 if (cdiag == (Pixmap) 0)
1585 cdiag = XCreateBitmapFromData ((Display*) m_display,
1586 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1587 cdiag_bits, cdiag_width, cdiag_height);
1588 myStipple = cdiag;
1589 break;
1590 }
1591 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1592
1593 if (m_window && m_window->GetBackingPixmap())
1594 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1595 }
1596 else if (m_currentStipple.Ok()
1597 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1598 {
1599 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1600
1601 if (m_window && m_window->GetBackingPixmap())
1602 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1603 }
1604
1605 if ((m_currentFill != oldFill) || !GetOptimization())
1606 {
1607 int fill_style;
1608
1609 if (m_currentFill == wxSTIPPLE)
1610 fill_style = FillStippled;
1611 else if (IS_HATCH (m_currentFill))
1612 fill_style = FillStippled;
1613 else
1614 fill_style = FillSolid;
1615 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1616 if (m_window && m_window->GetBackingPixmap())
1617 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1618 }
1619
1620 // must test m_logicalFunction, because it involves background!
1621 if (!sameColour || !GetOptimization()
1622 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1623 {
1624 int pixel = -1;
1625 if (m_pen.GetStyle () == wxTRANSPARENT)
1626 pixel = m_backgroundPixel;
1627 else if (!m_colour)
1628 {
1629 unsigned char red = m_pen.GetColour ().Red ();
1630 unsigned char blue = m_pen.GetColour ().Blue ();
1631 unsigned char green = m_pen.GetColour ().Green ();
1632 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1633 && green == (unsigned char) 255)
1634 {
1635 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1636 m_currentColour = *wxWHITE;
1637 m_pen.GetColour().SetPixel(pixel);
1638 m_currentColour.SetPixel(pixel);
1639 }
1640 else
1641 {
1642 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1643 m_currentColour = *wxBLACK;
1644 m_pen.GetColour().SetPixel(pixel);
1645 }
1646 }
1647 else
1648 {
1649 pixel = m_pen.GetColour ().AllocColour(m_display);
1650 m_currentColour.SetPixel(pixel);
1651 }
1652
1653 // Finally, set the GC to the required colour
1654 if (pixel > -1)
1655 {
1656 if (m_logicalFunction == wxXOR)
1657 {
1658 XGCValues values;
1659 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1660 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1661 if (m_window && m_window->GetBackingPixmap())
1662 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1663 }
1664 else
1665 {
1666 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1667 if (m_window && m_window->GetBackingPixmap())
1668 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1669 }
1670 }
1671 }
1672 else
1673 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1674
1675 m_autoSetting = 0;
1676 };
1677
1678 void wxWindowDC::SetBrush( const wxBrush &brush )
1679 {
1680 if (!Ok()) return;
1681
1682 m_brush = brush;
1683
1684 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1685 return;
1686
1687 int oldFill = m_currentFill;
1688 wxBitmap oldStipple = m_currentStipple;
1689
1690 m_autoSetting |= 0x1;
1691
1692 m_currentFill = m_brush.GetStyle ();
1693 if (m_currentFill == wxSTIPPLE)
1694 m_currentStipple = * m_brush.GetStipple ();
1695
1696 wxColour oldBrushColour(m_currentColour);
1697 m_currentColour = m_brush.GetColour ();
1698
1699 bool sameColour = (oldBrushColour.Ok () &&
1700 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1701 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1702 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1703 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1704
1705 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1706 {
1707 switch (brush.GetStyle ())
1708 {
1709 case wxTRANSPARENT:
1710 break;
1711 case wxBDIAGONAL_HATCH:
1712 case wxCROSSDIAG_HATCH:
1713 case wxFDIAGONAL_HATCH:
1714 case wxCROSS_HATCH:
1715 case wxHORIZONTAL_HATCH:
1716 case wxVERTICAL_HATCH:
1717 case wxSTIPPLE:
1718 {
1719 // Chris Breeze 23/07/97: use background mode to determine whether
1720 // fill style should be solid or transparent
1721 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1722 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1723 if (m_window && m_window->GetBackingPixmap())
1724 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1725 }
1726 break;
1727 case wxSOLID:
1728 default:
1729 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1730 if (m_window && m_window->GetBackingPixmap())
1731 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1732 }
1733 }
1734
1735 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1736 {
1737 Pixmap myStipple;
1738
1739 switch (m_currentFill)
1740 {
1741 case wxBDIAGONAL_HATCH:
1742 if (bdiag == (Pixmap) 0)
1743 bdiag = XCreateBitmapFromData ((Display*) m_display,
1744 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1745 bdiag_bits, bdiag_width, bdiag_height);
1746 myStipple = bdiag;
1747 break;
1748 case wxFDIAGONAL_HATCH:
1749 if (fdiag == (Pixmap) 0)
1750 fdiag = XCreateBitmapFromData ((Display*) m_display,
1751 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1752 fdiag_bits, fdiag_width, fdiag_height);
1753 myStipple = fdiag;
1754 break;
1755 case wxCROSS_HATCH:
1756 if (cross == (Pixmap) 0)
1757 cross = XCreateBitmapFromData ((Display*) m_display,
1758 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1759 cross_bits, cross_width, cross_height);
1760 myStipple = cross;
1761 break;
1762 case wxHORIZONTAL_HATCH:
1763 if (horiz == (Pixmap) 0)
1764 horiz = XCreateBitmapFromData ((Display*) m_display,
1765 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1766 horiz_bits, horiz_width, horiz_height);
1767 myStipple = horiz;
1768 break;
1769 case wxVERTICAL_HATCH:
1770 if (verti == (Pixmap) 0)
1771 verti = XCreateBitmapFromData ((Display*) m_display,
1772 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1773 verti_bits, verti_width, verti_height);
1774 myStipple = verti;
1775 break;
1776 case wxCROSSDIAG_HATCH:
1777 default:
1778 if (cdiag == (Pixmap) 0)
1779 cdiag = XCreateBitmapFromData ((Display*) m_display,
1780 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1781 cdiag_bits, cdiag_width, cdiag_height);
1782 myStipple = cdiag;
1783 break;
1784 }
1785 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1786
1787 if (m_window && m_window->GetBackingPixmap())
1788 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1789 }
1790 // X can forget the stipple value when resizing a window (apparently)
1791 // so always set the stipple.
1792 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1793 {
1794 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1795 if (m_window && m_window->GetBackingPixmap())
1796 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1797 }
1798
1799 // must test m_logicalFunction, because it involves background!
1800 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1801 {
1802 int pixel = -1;
1803 if (!m_colour)
1804 {
1805 // Policy - on a monochrome screen, all brushes are white,
1806 // except when they're REALLY black!!!
1807 unsigned char red = m_brush.GetColour ().Red ();
1808 unsigned char blue = m_brush.GetColour ().Blue ();
1809 unsigned char green = m_brush.GetColour ().Green ();
1810
1811 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1812 && green == (unsigned char) 0)
1813 {
1814 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1815 m_currentColour = *wxBLACK;
1816 m_brush.GetColour().SetPixel(pixel);
1817 m_currentColour.SetPixel(pixel);
1818 }
1819 else
1820 {
1821 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1822 m_currentColour = *wxWHITE;
1823 m_brush.GetColour().SetPixel(pixel);
1824 m_currentColour.SetPixel(pixel);
1825 }
1826
1827 // N.B. comment out the above line and uncomment the following lines
1828 // if you want non-white colours to be black on a monochrome display.
1829 /*
1830 if (red == (unsigned char )255 && blue == (unsigned char)255
1831 && green == (unsigned char)255)
1832 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1833 else
1834 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1835 */
1836 }
1837 else if (m_brush.GetStyle () != wxTRANSPARENT)
1838 {
1839 pixel = m_brush.GetColour().AllocColour(m_display);
1840 m_currentColour.SetPixel(pixel);
1841 }
1842 if (pixel > -1)
1843 {
1844 // Finally, set the GC to the required colour
1845 if (m_logicalFunction == wxXOR)
1846 {
1847 XGCValues values;
1848 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1849 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1850 if (m_window && m_window->GetBackingPixmap())
1851 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1852 }
1853 else
1854 {
1855 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1856 if (m_window && m_window->GetBackingPixmap())
1857 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1858 }
1859 }
1860 }
1861 else
1862 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1863 };
1864
1865 void wxWindowDC::SetBackground( const wxBrush &brush )
1866 {
1867 if (!Ok()) return;
1868
1869 m_backgroundBrush = brush;
1870
1871 if (!m_backgroundBrush.Ok())
1872 return;
1873
1874 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1875
1876 // XSetWindowBackground doesn't work for non-Window pixmaps
1877 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1878 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1879
1880 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1881 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1882 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
1883 if (m_window && m_window->GetBackingPixmap())
1884 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
1885 };
1886
1887 void wxWindowDC::SetLogicalFunction( int function )
1888 {
1889 int x_function;
1890
1891 /* MATTHEW: [9] */
1892 if (m_logicalFunction == function)
1893 return;
1894
1895 switch (function)
1896 {
1897 case wxCLEAR:
1898 x_function = GXclear;
1899 break;
1900 case wxXOR:
1901 x_function = GXxor;
1902 break;
1903 case wxINVERT:
1904 x_function = GXinvert;
1905 break;
1906 case wxOR_REVERSE:
1907 x_function = GXorReverse;
1908 break;
1909 case wxAND_REVERSE:
1910 x_function = GXandReverse;
1911 break;
1912 case wxAND:
1913 x_function = GXand;
1914 break;
1915 case wxOR:
1916 x_function = GXor;
1917 break;
1918 case wxAND_INVERT:
1919 x_function = GXandInverted;
1920 break;
1921 case wxNO_OP:
1922 x_function = GXnoop;
1923 break;
1924 case wxNOR:
1925 x_function = GXnor;
1926 break;
1927 case wxEQUIV:
1928 x_function = GXequiv;
1929 break;
1930 case wxSRC_INVERT:
1931 x_function = GXcopyInverted;
1932 break;
1933 case wxOR_INVERT:
1934 x_function = GXorInverted;
1935 break;
1936 case wxNAND:
1937 x_function = GXnand;
1938 break;
1939 case wxSET:
1940 x_function = GXset;
1941 break;
1942 case wxCOPY:
1943 default:
1944 x_function = GXcopy;
1945 break;
1946 }
1947
1948 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1949 if (m_window && m_window->GetBackingPixmap())
1950 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
1951
1952 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1953 /* MATTHEW: [9] Need to redo pen simply */
1954 m_autoSetting |= 0x2;
1955
1956 m_logicalFunction = function;
1957
1958 };
1959
1960 void wxWindowDC::SetTextForeground( const wxColour &col )
1961 {
1962 if (!Ok()) return;
1963
1964 if (m_textForegroundColour == col) return;
1965
1966 m_textForegroundColour = col;
1967
1968 };
1969
1970 void wxWindowDC::SetTextBackground( const wxColour &col )
1971 {
1972 if (!Ok()) return;
1973
1974 if (m_textBackgroundColour == col) return;
1975
1976 m_textBackgroundColour = col;
1977 if (!m_textBackgroundColour.Ok()) return;
1978 };
1979
1980 void wxWindowDC::SetBackgroundMode( int mode )
1981 {
1982 m_backgroundMode = mode;
1983
1984 };
1985
1986 void wxWindowDC::SetPalette( const wxPalette& palette )
1987 {
1988 if (m_window)
1989 {
1990 if (palette.Ok())
1991 /* Use GetXColormap */
1992 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1993 (Colormap) palette.GetXColormap());
1994 else
1995 /* Use wxGetMainColormap */
1996 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1997 (Colormap) wxTheApp->GetMainColormap(m_display));
1998 }
1999 };
2000
2001 // Helper function
2002 void wxWindowDC:: SetDCClipping ()
2003 {
2004 // m_userRegion is the region set by calling SetClippingRegion
2005
2006 if (m_currentRegion)
2007 XDestroyRegion ((Region) m_currentRegion);
2008
2009 // We need to take into account
2010 // clipping imposed on a window by a repaint.
2011 // We'll combine it with the user region. But for now,
2012 // just use the currently-defined user clipping region.
2013 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2014 m_currentRegion = (WXRegion) XCreateRegion ();
2015 else
2016 m_currentRegion = (WXRegion) NULL;
2017
2018 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2019 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2020 else if (m_userRegion)
2021 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2022 else if (m_window && m_window->GetUpdateRegion().Ok())
2023 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2024 (Region) m_currentRegion);
2025
2026 if (m_currentRegion)
2027 {
2028 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2029 }
2030 else
2031 {
2032 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2033 }
2034
2035 }
2036
2037 void wxWindowDC::SetClippingRegion( long x, long y, long width, long height )
2038 {
2039 wxDC::SetClippingRegion( x, y, width, height );
2040
2041 if (m_userRegion)
2042 XDestroyRegion ((Region) m_userRegion);
2043 m_userRegion = (WXRegion) XCreateRegion ();
2044 XRectangle r;
2045 r.x = XLOG2DEV (x);
2046 r.y = YLOG2DEV (y);
2047 r.width = XLOG2DEVREL(width);
2048 r.height = YLOG2DEVREL(height);
2049 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2050
2051 SetDCClipping ();
2052
2053 // Needs to work differently for Pixmap: without this,
2054 // there's a nasty (Display*) m_display bug. 8/12/94
2055 if (m_window && m_window->GetBackingPixmap())
2056 {
2057 XRectangle rects[1];
2058 rects[0].x = XLOG2DEV_2(x);
2059 rects[0].y = YLOG2DEV_2(y);
2060 rects[0].width = XLOG2DEVREL(width);
2061 rects[0].height = YLOG2DEVREL(height);
2062 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2063 }
2064 };
2065
2066 void wxWindowDC::SetClippingRegion( const wxRegion& region )
2067 {
2068 wxRect box = region.GetBox();
2069
2070 wxDC::SetClippingRegion( box.x, box.y, box.width, box.height );
2071
2072 if (m_userRegion)
2073 XDestroyRegion ((Region) m_userRegion);
2074 m_userRegion = (WXRegion) XCreateRegion ();
2075
2076 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2077
2078 SetDCClipping ();
2079
2080 // Needs to work differently for Pixmap: without this,
2081 // there's a nasty (Display*) m_display bug. 8/12/94
2082 if (m_window && m_window->GetBackingPixmap())
2083 {
2084 XRectangle rects[1];
2085 rects[0].x = XLOG2DEV_2(box.x);
2086 rects[0].y = YLOG2DEV_2(box.y);
2087 rects[0].width = XLOG2DEVREL(box.width);
2088 rects[0].height = YLOG2DEVREL(box.height);
2089 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2090 }
2091 };
2092
2093
2094 void wxWindowDC::DestroyClippingRegion(void)
2095 {
2096 wxDC::DestroyClippingRegion();
2097
2098 if (m_userRegion)
2099 XDestroyRegion ((Region) m_userRegion);
2100 m_userRegion = NULL;
2101
2102 SetDCClipping ();
2103
2104 XGCValues gc_val;
2105 gc_val.clip_mask = None;
2106 if (m_window && m_window->GetBackingPixmap())
2107 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
2108 };
2109
2110 // ----------------------------------- spline code ----------------------------------------
2111
2112 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
2113 double a3, double b3, double a4, double b4);
2114 void wx_clear_stack(void);
2115 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
2116 double *y3, double *x4, double *y4);
2117 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
2118 double x4, double y4);
2119 static bool wx_spline_add_point(double x, double y);
2120 static void wx_spline_draw_point_array(wxDC *dc);
2121
2122 wxList wx_spline_point_list;
2123
2124 #define half(z1, z2) ((z1+z2)/2.0)
2125 #define THRESHOLD 5
2126
2127 /* iterative version */
2128
2129 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
2130 double b4)
2131 {
2132 register double xmid, ymid;
2133 double x1, y1, x2, y2, x3, y3, x4, y4;
2134
2135 wx_clear_stack();
2136 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
2137
2138 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
2139 xmid = (double)half(x2, x3);
2140 ymid = (double)half(y2, y3);
2141 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
2142 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
2143 wx_spline_add_point( x1, y1 );
2144 wx_spline_add_point( xmid, ymid );
2145 } else {
2146 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
2147 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
2148 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
2149 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
2150 }
2151 }
2152 }
2153
2154 /* utilities used by spline drawing routines */
2155
2156 typedef struct wx_spline_stack_struct {
2157 double x1, y1, x2, y2, x3, y3, x4, y4;
2158 } Stack;
2159
2160 #define SPLINE_STACK_DEPTH 20
2161 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
2162 static Stack *wx_stack_top;
2163 static int wx_stack_count;
2164
2165 void wx_clear_stack(void)
2166 {
2167 wx_stack_top = wx_spline_stack;
2168 wx_stack_count = 0;
2169 }
2170
2171 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
2172 {
2173 wx_stack_top->x1 = x1;
2174 wx_stack_top->y1 = y1;
2175 wx_stack_top->x2 = x2;
2176 wx_stack_top->y2 = y2;
2177 wx_stack_top->x3 = x3;
2178 wx_stack_top->y3 = y3;
2179 wx_stack_top->x4 = x4;
2180 wx_stack_top->y4 = y4;
2181 wx_stack_top++;
2182 wx_stack_count++;
2183 }
2184
2185 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
2186 double *x3, double *y3, double *x4, double *y4)
2187 {
2188 if (wx_stack_count == 0)
2189 return (0);
2190 wx_stack_top--;
2191 wx_stack_count--;
2192 *x1 = wx_stack_top->x1;
2193 *y1 = wx_stack_top->y1;
2194 *x2 = wx_stack_top->x2;
2195 *y2 = wx_stack_top->y2;
2196 *x3 = wx_stack_top->x3;
2197 *y3 = wx_stack_top->y3;
2198 *x4 = wx_stack_top->x4;
2199 *y4 = wx_stack_top->y4;
2200 return (1);
2201 }
2202
2203 static bool wx_spline_add_point(double x, double y)
2204 {
2205 wxPoint *point = new wxPoint ;
2206 point->x = (int) x;
2207 point->y = (int) y;
2208 wx_spline_point_list.Append((wxObject*)point);
2209 return TRUE;
2210 }
2211
2212 static void wx_spline_draw_point_array(wxDC *dc)
2213 {
2214 dc->DrawLines(&wx_spline_point_list, 0, 0 );
2215 wxNode *node = wx_spline_point_list.First();
2216 while (node)
2217 {
2218 wxPoint *point = (wxPoint *)node->Data();
2219 delete point;
2220 delete node;
2221 node = wx_spline_point_list.First();
2222 }
2223 }
2224
2225 void wxWindowDC::DrawSpline( wxList *points )
2226 {
2227 wxPoint *p;
2228 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
2229 double x1, y1, x2, y2;
2230
2231 wxNode *node = points->First();
2232 p = (wxPoint *)node->Data();
2233
2234 x1 = p->x;
2235 y1 = p->y;
2236
2237 node = node->Next();
2238 p = (wxPoint *)node->Data();
2239
2240 x2 = p->x;
2241 y2 = p->y;
2242 cx1 = (double)((x1 + x2) / 2);
2243 cy1 = (double)((y1 + y2) / 2);
2244 cx2 = (double)((cx1 + x2) / 2);
2245 cy2 = (double)((cy1 + y2) / 2);
2246
2247 wx_spline_add_point(x1, y1);
2248
2249 while ((node = node->Next()) != NULL)
2250 {
2251 p = (wxPoint *)node->Data();
2252 x1 = x2;
2253 y1 = y2;
2254 x2 = p->x;
2255 y2 = p->y;
2256 cx4 = (double)(x1 + x2) / 2;
2257 cy4 = (double)(y1 + y2) / 2;
2258 cx3 = (double)(x1 + cx4) / 2;
2259 cy3 = (double)(y1 + cy4) / 2;
2260
2261 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
2262
2263 cx1 = cx4;
2264 cy1 = cy4;
2265 cx2 = (double)(cx1 + x2) / 2;
2266 cy2 = (double)(cy1 + y2) / 2;
2267 }
2268
2269 wx_spline_add_point( cx1, cy1 );
2270 wx_spline_add_point( x2, y2 );
2271
2272 wx_spline_draw_point_array( this );
2273 };
2274
2275 /*
2276 * wxPaintDC
2277 */
2278
2279 wxPaintDC::wxPaintDC(wxWindow* win): wxWindowDC(win)
2280 {
2281 wxRegion* region = NULL;
2282
2283 // Combine all the update rects into a region
2284 if (win->m_updateRects.Number() > 0)
2285 {
2286 int i = 0;
2287 for (i = 0; i < win->m_updateRects.Number(); i++)
2288 {
2289 wxRect* rect = (wxRect*) win->m_updateRects.Nth(i)->Data();
2290 /*
2291 cout << "wxPaintDC. wxRect: " << rect->x << ", " << rect->y << ", ";
2292 cout << rect->width << ", " << rect->height << "\n\n";
2293 */
2294
2295 if (!region)
2296 region = new wxRegion(*rect);
2297 else
2298 // TODO: is this correct? In SetDCClipping above,
2299 // XIntersectRegion is used to combine paint and user
2300 // regions. XIntersectRegion appears to work in that case...
2301 region->Union(*rect);
2302 }
2303 }
2304 else
2305 {
2306 int cw, ch;
2307 win->GetClientSize(&cw, &ch);
2308 region = new wxRegion(wxRect(0, 0, cw, ch));
2309 }
2310
2311 win->m_updateRegion = *region;
2312
2313 // Set the clipping region. Any user-defined region will be combined with this
2314 // one in SetDCClipping.
2315 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2316
2317 delete region;
2318 }
2319
2320 wxPaintDC::~wxPaintDC()
2321 {
2322 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2323 if (m_window)
2324 m_window->m_updateRegion.Clear();
2325 }
2326