Some more wxMotif improvements: DrawIcon fixed; generic notebook
[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)
853 {
854 if (!Ok()) return;
855
856 if (!icon.Ok()) return;
857
858 DrawBitmap(icon, x, y, TRUE);
859
860 #if 0
861 // FreeGetPixelCache();
862
863 // Be sure that foreground pixels (1) of
864 // the Icon will be painted with pen colour. [m_pen.SetColour()]
865 // Background pixels (0) will be painted with
866 // last selected background color. [::SetBackground]
867 if (m_pen.Ok() && m_autoSetting)
868 SetPen (m_pen);
869
870 int width, height;
871 Pixmap iconPixmap = (Pixmap) icon.GetPixmap();
872 width = icon.GetWidth();
873 height = icon.GetHeight();
874 if (icon.GetDisplay() == m_display)
875 {
876 if (icon.GetDepth() <= 1)
877 {
878 XCopyPlane ((Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc,
879 0, 0, width, height,
880 (int) XLOG2DEV (x), (int) YLOG2DEV (y), 1);
881 }
882 else
883 {
884 XCopyArea ((Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc,
885 0, 0, width, height,
886 (int) XLOG2DEV (x), (int) YLOG2DEV (y));
887 }
888
889
890 if (m_window && m_window->GetBackingPixmap())
891 {
892 if (icon.GetDepth() <= 1)
893 {
894 XCopyPlane ((Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
895 0, 0, width, height, (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y), 1);
896 }
897 else
898 {
899 XCopyArea ((Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
900 0, 0, width, height,
901 (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y));
902 }
903 }
904 } else { /* Remote copy (different (Display*) m_displays) */
905 XImage *cache = NULL;
906 if (m_window && m_window->GetBackingPixmap())
907 XCopyRemote((Display*) icon.GetDisplay(), (Display*) m_display, iconPixmap, (Pixmap) m_window->GetBackingPixmap(),
908 (GC) m_gcBacking, 0, 0, width, height,
909 (int) XLOG2DEV_2 (x), (int) YLOG2DEV_2 (y), TRUE, &cache);
910 XCopyRemote((Display*) icon.GetDisplay(), (Display*) m_display, iconPixmap, (Pixmap) m_pixmap, (GC) m_gc,
911 0, 0, width, height,
912 (int) XLOG2DEV (x), (int) YLOG2DEV (y), FALSE, &cache);
913 }
914 CalcBoundingBox (x, y);
915 #endif
916 };
917
918 bool wxWindowDC::Blit( long xdest, long ydest, long width, long height,
919 wxDC *source, long xsrc, long ysrc, int rop, bool useMask )
920 {
921 if (!Ok()) return FALSE;
922
923 wxASSERT_MSG( (source->IsKindOf(CLASSINFO(wxWindowDC))), "Blit source DC must be wxWindowDC or derived class." );
924
925 wxWindowDC* sourceDC = (wxWindowDC*) source;
926
927 // FreeGetPixelCache();
928
929 // Be sure that foreground pixels (1) of
930 // the Icon will be painted with pen colour. [m_pen.SetColour()]
931 // Background pixels (0) will be painted with
932 // last selected background color. [::SetBackground]
933 if (m_pen.Ok() && m_autoSetting)
934 SetPen (m_pen);
935
936 if (m_pixmap && sourceDC->m_pixmap)
937 {
938 /* MATTHEW: [9] */
939 int orig = m_logicalFunction;
940
941 SetLogicalFunction (rop);
942
943 if (m_display != sourceDC->m_display)
944 {
945 XImage *cache = NULL;
946
947 if (m_window && m_window->GetBackingPixmap())
948 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display,
949 (Pixmap) sourceDC->m_pixmap, (Pixmap) m_window->GetBackingPixmap(),
950 (GC) m_gcBacking,
951 source->LogicalToDeviceX (xsrc),
952 source->LogicalToDeviceY (ysrc),
953 source->LogicalToDeviceXRel(width),
954 source->LogicalToDeviceYRel(height),
955 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest),
956 TRUE, &cache);
957
958 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
959 {
960 wxMemoryDC *memDC = (wxMemoryDC *)source;
961 wxBitmap& sel = memDC->GetBitmap();
962 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
963 {
964 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
965 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
966 }
967 }
968
969 XCopyRemote((Display*) sourceDC->m_display, (Display*) m_display, (Pixmap) sourceDC->m_pixmap, (Pixmap) m_pixmap, (GC) m_gc,
970 source->LogicalToDeviceX (xsrc),
971 source->LogicalToDeviceY (ysrc),
972 source->LogicalToDeviceXRel(width),
973 source->LogicalToDeviceYRel(height),
974 XLOG2DEV (xdest), YLOG2DEV (ydest),
975 FALSE, &cache);
976
977 if ( useMask )
978 {
979 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
980 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
981 }
982
983 } else
984 {
985 if (m_window && m_window->GetBackingPixmap())
986 {
987 // +++ MARKUS (mho@comnets.rwth-aachen): error on blitting bitmaps with depth 1
988 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) && ((wxMemoryDC*) source)->GetBitmap().GetDepth() == 1)
989 {
990 XCopyPlane ((Display*) m_display, (Pixmap) sourceDC->m_pixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
991 source->LogicalToDeviceX (xsrc),
992 source->LogicalToDeviceY (ysrc),
993 source->LogicalToDeviceXRel(width),
994 source->LogicalToDeviceYRel(height),
995 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest), 1);
996 }
997 else
998 {
999 XCopyArea ((Display*) m_display, (Pixmap) sourceDC->m_pixmap, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1000 source->LogicalToDeviceX (xsrc),
1001 source->LogicalToDeviceY (ysrc),
1002 source->LogicalToDeviceXRel(width),
1003 source->LogicalToDeviceYRel(height),
1004 XLOG2DEV_2 (xdest), YLOG2DEV_2 (ydest));
1005 }
1006 }
1007 if ( useMask && source->IsKindOf(CLASSINFO(wxMemoryDC)) )
1008 {
1009 wxMemoryDC *memDC = (wxMemoryDC *)source;
1010 wxBitmap& sel = memDC->GetBitmap();
1011 if ( sel.Ok() && sel.GetMask() && sel.GetMask()->GetPixmap() )
1012 {
1013 XSetClipMask ((Display*) m_display, (GC) m_gc, (Pixmap) sel.GetMask()->GetPixmap());
1014 XSetClipOrigin ((Display*) m_display, (GC) m_gc, XLOG2DEV (xdest), YLOG2DEV (ydest));
1015 }
1016 }
1017
1018 // Check if we're copying from a mono bitmap
1019 if (source->IsKindOf(CLASSINFO(wxMemoryDC)) &&
1020 ((wxMemoryDC*)source)->GetBitmap().Ok() && (((wxMemoryDC*)source)->GetBitmap().GetDepth () == 1))
1021 {
1022 XCopyPlane ((Display*) m_display, (Pixmap) sourceDC->m_pixmap, (Pixmap) m_pixmap, (GC) m_gc,
1023 source->LogicalToDeviceX (xsrc),
1024 source->LogicalToDeviceY (ysrc),
1025 source->LogicalToDeviceXRel(width),
1026 source->LogicalToDeviceYRel(height),
1027 XLOG2DEV (xdest), YLOG2DEV (ydest), 1);
1028 }
1029 else
1030 {
1031 XCopyArea ((Display*) m_display, (Pixmap) sourceDC->m_pixmap, (Pixmap) m_pixmap, (GC) m_gc,
1032 source->LogicalToDeviceX (xsrc),
1033 source->LogicalToDeviceY (ysrc),
1034 source->LogicalToDeviceXRel(width),
1035 source->LogicalToDeviceYRel(height),
1036 XLOG2DEV (xdest), YLOG2DEV (ydest));
1037
1038 }
1039 if ( useMask )
1040 {
1041 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
1042 XSetClipOrigin ((Display*) m_display, (GC) m_gc, 0, 0);
1043 }
1044
1045 } /* Remote/local (Display*) m_display */
1046 CalcBoundingBox (xdest, ydest);
1047 CalcBoundingBox (xdest + width, ydest + height);
1048
1049 SetLogicalFunction(orig);
1050
1051 return TRUE;
1052 }
1053 return FALSE;
1054 };
1055
1056 /* Helper function for 16-bit fonts */
1057 static int str16len(const char *s)
1058 {
1059 int count = 0;
1060
1061 while (s[0] && s[1]) {
1062 count++;
1063 s += 2;
1064 }
1065
1066 return count;
1067 }
1068
1069 void wxWindowDC::DrawText( const wxString &text, long x, long y, bool use16 )
1070 {
1071 if (!Ok()) return;
1072
1073 // Since X draws from the baseline of the text, must
1074 // add the text height
1075 int cx = 0;
1076 int cy = 0;
1077 int ascent = 0;
1078 int slen;
1079
1080 if (use16)
1081 slen = str16len(text);
1082 else
1083 slen = strlen(text);
1084
1085 if (m_font.Ok())
1086 {
1087 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1088 int direction, descent;
1089 XCharStruct overall_return;
1090 if (use16)
1091 (void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
1092 &ascent, &descent, &overall_return);
1093 else
1094 (void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
1095 &ascent, &descent, &overall_return);
1096 cx = overall_return.width;
1097 cy = ascent + descent;
1098 }
1099
1100 // First draw a rectangle representing the text background,
1101 // if a text background is specified
1102 if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
1103 {
1104 wxColour oldPenColour = m_currentColour;
1105 m_currentColour = m_textBackgroundColour;
1106 bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
1107 (oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
1108 (oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
1109 (oldPenColour.Green () == m_textBackgroundColour.Green ()));
1110
1111 // This separation of the big && test required for gcc2.7/HP UX 9.02
1112 // or pixel value can be corrupted!
1113 sameColour = (sameColour &&
1114 (oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
1115
1116 if (!sameColour || !GetOptimization())
1117 {
1118 int pixel = m_textBackgroundColour.AllocColour(m_display);
1119 m_currentColour = m_textBackgroundColour;
1120
1121 // Set the GC to the required colour
1122 if (pixel > -1)
1123 {
1124 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1125 if (m_window && m_window->GetBackingPixmap())
1126 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1127 }
1128 }
1129 else
1130 m_textBackgroundColour = oldPenColour ;
1131
1132 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
1133 if (m_window && m_window->GetBackingPixmap())
1134 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
1135 XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
1136 }
1137
1138 // Now set the text foreground and draw the text
1139 if (m_textForegroundColour.Ok ())
1140 {
1141 wxColour oldPenColour = m_currentColour;
1142 m_currentColour = m_textForegroundColour;
1143 bool sameColour = (oldPenColour.Ok () && m_currentColour.Ok () &&
1144 (oldPenColour.Red () == m_currentColour.Red ()) &&
1145 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1146 (oldPenColour.Green () == m_currentColour.Green ()) &&
1147 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1148
1149 if (!sameColour || !GetOptimization())
1150 {
1151 int pixel = -1;
1152 if (!m_colour) // Mono display
1153 {
1154 // Unless foreground is really white, draw it in black
1155 unsigned char red = m_textForegroundColour.Red ();
1156 unsigned char blue = m_textForegroundColour.Blue ();
1157 unsigned char green = m_textForegroundColour.Green ();
1158 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1159 && green == (unsigned char) 255)
1160 {
1161 m_currentColour = *wxWHITE;
1162 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1163 m_currentColour.SetPixel(pixel);
1164 m_textForegroundColour.SetPixel(pixel);
1165 }
1166 else
1167 {
1168 m_currentColour = *wxBLACK;
1169 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1170 m_currentColour.SetPixel(pixel);
1171 m_textForegroundColour.SetPixel(pixel);
1172 }
1173 }
1174 else
1175 {
1176 pixel = m_textForegroundColour.AllocColour((Display*) m_display);
1177 m_currentColour.SetPixel(pixel);
1178 }
1179
1180 // Set the GC to the required colour
1181 if (pixel > -1)
1182 {
1183 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1184 if (m_window && m_window->GetBackingPixmap())
1185 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1186 }
1187 }
1188 else
1189 m_textForegroundColour = oldPenColour;
1190 }
1191
1192 // We need to add the ascent, not the whole height, since X draws
1193 // at the point above the descender.
1194 if (use16)
1195 XDrawString16((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1196 (XChar2b *)(char*) (const char*) text, slen);
1197 else
1198 XDrawString((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y) + ascent,
1199 text, slen);
1200
1201 if (m_window && m_window->GetBackingPixmap()) {
1202 if (use16)
1203 XDrawString16((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1204 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent,
1205 (XChar2b *)(char*) (const char*) text, slen);
1206 else
1207 XDrawString((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(), (GC) m_gcBacking,
1208 XLOG2DEV_2 (x), YLOG2DEV_2 (y) + ascent, (char*) (const char*) text, slen);
1209 }
1210
1211 long w, h;
1212 GetTextExtent (text, &w, &h);
1213 CalcBoundingBox (x + w, y + h);
1214 CalcBoundingBox (x, y);
1215 };
1216
1217 bool wxWindowDC::CanGetTextExtent(void) const
1218 {
1219 return TRUE;
1220 };
1221
1222 void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *height,
1223 long *descent, long *externalLeading,
1224 wxFont *font, bool use16 )
1225 {
1226 if (!Ok()) return;
1227
1228 wxFont* theFont = font;
1229 if (!theFont)
1230 theFont = & m_font;
1231
1232 if (!theFont->Ok())
1233 {
1234 // TODO: this should be an error log function
1235 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1236
1237 *width = -1;
1238 *height = -1;
1239 return;
1240 }
1241
1242 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1243
1244 int direction, ascent, descent2;
1245 XCharStruct overall;
1246 int slen;
1247
1248 if (use16) slen = str16len(string); else slen = strlen(string);
1249
1250 if (use16)
1251 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1252 &ascent, &descent2, &overall);
1253 else
1254 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1255 &ascent, &descent2, &overall);
1256
1257 *width = XDEV2LOGREL (overall.width);
1258 *height = YDEV2LOGREL (ascent + descent2);
1259 if (descent)
1260 *descent = descent2;
1261 if (externalLeading)
1262 *externalLeading = 0;
1263 };
1264
1265 long wxWindowDC::GetCharWidth(void)
1266 {
1267 if (!Ok()) return 0;
1268
1269 if (!m_font.Ok())
1270 return 0;
1271
1272 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
1273
1274 int direction, ascent, descent;
1275 XCharStruct overall;
1276 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1277 &descent, &overall);
1278 return XDEV2LOGREL(overall.width);
1279 };
1280
1281 long wxWindowDC::GetCharHeight(void)
1282 {
1283 if (!Ok()) return 0;
1284
1285 if (!m_font.Ok())
1286 return 0;
1287
1288 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1289
1290 int direction, ascent, descent;
1291 XCharStruct overall;
1292 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1293 &descent, &overall);
1294 // return XDEV2LOGREL(overall.ascent + overall.descent);
1295 return XDEV2LOGREL(ascent + descent);
1296 };
1297
1298 void wxWindowDC::Clear(void)
1299 {
1300 if (!Ok()) return;
1301
1302 int w, h;
1303 if (m_window)
1304 {
1305 m_window->GetSize(&w, &h);
1306
1307 if (m_window && m_window->GetBackingPixmap())
1308 {
1309 w = m_window->GetPixmapWidth();
1310 h = m_window->GetPixmapHeight();
1311 }
1312 }
1313 else
1314 {
1315 if (this->IsKindOf(CLASSINFO(wxMemoryDC)))
1316 {
1317 wxMemoryDC* memDC = (wxMemoryDC*) this;
1318 w = memDC->GetBitmap().GetWidth();
1319 h = memDC->GetBitmap().GetHeight();
1320 }
1321 else
1322 return;
1323 }
1324
1325 wxBrush saveBrush = m_brush;
1326 SetBrush (m_backgroundBrush);
1327
1328 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, 0, 0, w, h);
1329
1330 if (m_window && m_window->GetBackingPixmap())
1331 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, 0, 0, w, h);
1332
1333 m_brush = saveBrush;
1334 };
1335
1336 void wxWindowDC::Clear(const wxRect& rect)
1337 {
1338 if (!Ok()) return;
1339
1340 int x = rect.x; int y = rect.y;
1341 int w = rect.width; int h = rect.height;
1342
1343 wxBrush saveBrush = m_brush;
1344 SetBrush (m_backgroundBrush);
1345
1346 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1347
1348 if (m_window && m_window->GetBackingPixmap())
1349 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1350
1351 m_brush = saveBrush;
1352 };
1353
1354 void wxWindowDC::SetFont( const wxFont &font )
1355 {
1356 if (!Ok()) return;
1357
1358 m_font = font;
1359
1360 if (!m_font.Ok())
1361 {
1362 if ((m_oldFont != (WXFont) 0) && ((long) m_oldFont != -1))
1363 {
1364 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1365
1366 if (m_window && m_window->GetBackingPixmap())
1367 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1368 }
1369 return;
1370 }
1371
1372 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
1373
1374 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1375 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1376
1377 if (m_window && m_window->GetBackingPixmap())
1378 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
1379 };
1380
1381 void wxWindowDC::SetPen( const wxPen &pen )
1382 {
1383 if (!Ok()) return;
1384
1385 m_pen = pen;
1386 if (!m_pen.Ok())
1387 return;
1388
1389 wxBitmap oldStipple = m_currentStipple;
1390 int oldStyle = m_currentStyle;
1391 int oldFill = m_currentFill;
1392 int old_pen_width = m_currentPenWidth;
1393 int old_pen_join = m_currentPenJoin;
1394 int old_pen_cap = m_currentPenCap;
1395 int old_pen_nb_dash = m_currentPenDashCount;
1396 char *old_pen_dash = m_currentPenDash;
1397
1398 wxColour oldPenColour = m_currentColour;
1399 m_currentColour = m_pen.GetColour ();
1400 m_currentStyle = m_pen.GetStyle ();
1401 m_currentFill = m_pen.GetStyle (); // TODO?
1402 m_currentPenWidth = m_pen.GetWidth ();
1403 m_currentPenJoin = m_pen.GetJoin ();
1404 m_currentPenCap = m_pen.GetCap ();
1405 m_currentPenDashCount = m_pen.GetDashCount();
1406 m_currentPenDash = m_pen.GetDash();
1407
1408 if (m_currentStyle == wxSTIPPLE)
1409 m_currentStipple = * m_pen.GetStipple ();
1410
1411 bool sameStyle = (oldStyle == m_currentStyle &&
1412 oldFill == m_currentFill &&
1413 old_pen_join == m_currentPenJoin &&
1414 old_pen_cap == m_currentPenCap &&
1415 old_pen_nb_dash == m_currentPenDashCount &&
1416 old_pen_dash == m_currentPenDash &&
1417 old_pen_width == m_currentPenWidth);
1418
1419 bool sameColour = (oldPenColour.Ok () &&
1420 (oldPenColour.Red () == m_currentColour.Red ()) &&
1421 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1422 (oldPenColour.Green () == m_currentColour.Green ()) &&
1423 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1424
1425 if (!sameStyle || !GetOptimization())
1426 {
1427 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1428 if (scaled_width < 0)
1429 scaled_width = 0;
1430
1431 int style;
1432 int join;
1433 int cap;
1434 static char dotted[] =
1435 {2, 5};
1436 static char short_dashed[] =
1437 {4, 4};
1438 static char long_dashed[] =
1439 {4, 8};
1440 static char dotted_dashed[] =
1441 {6, 6, 2, 6};
1442
1443 // We express dash pattern in pen width unit, so we are
1444 // independent of zoom factor and so on...
1445 int req_nb_dash;
1446 char *req_dash;
1447
1448 switch (m_pen.GetStyle ())
1449 {
1450 case wxUSER_DASH:
1451 req_nb_dash = m_currentPenDashCount;
1452 req_dash = m_currentPenDash;
1453 style = LineOnOffDash;
1454 break;
1455 case wxDOT:
1456 req_nb_dash = 2;
1457 req_dash = dotted;
1458 style = LineOnOffDash;
1459 break;
1460 case wxSHORT_DASH:
1461 req_nb_dash = 2;
1462 req_dash = short_dashed;
1463 style = LineOnOffDash;
1464 break;
1465 case wxLONG_DASH:
1466 req_nb_dash = 2;
1467 req_dash = long_dashed;
1468 style = LineOnOffDash;
1469 break;
1470 case wxDOT_DASH:
1471 req_nb_dash = 4;
1472 req_dash = dotted_dashed;
1473 style = LineOnOffDash;
1474 break;
1475 case wxSTIPPLE:
1476 case wxSOLID:
1477 case wxTRANSPARENT:
1478 default:
1479 style = LineSolid;
1480 req_dash = NULL;
1481 req_nb_dash = 0;
1482 }
1483
1484 if (req_dash && req_nb_dash)
1485 {
1486 char *real_req_dash = new char[req_nb_dash];
1487 if (real_req_dash)
1488 {
1489 int factor = scaled_width == 0 ? 1 : scaled_width;
1490 for (int i = 0; i < req_nb_dash; i++)
1491 real_req_dash[i] = req_dash[i] * factor;
1492 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1493
1494 if (m_window && m_window->GetBackingPixmap())
1495 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1496 delete[]real_req_dash;
1497 }
1498 else
1499 {
1500 // No Memory. We use non-scaled dash pattern...
1501 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1502
1503 if (m_window && m_window->GetBackingPixmap())
1504 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1505 }
1506 }
1507
1508 switch (m_pen.GetCap ())
1509 {
1510 case wxCAP_PROJECTING:
1511 cap = CapProjecting;
1512 break;
1513 case wxCAP_BUTT:
1514 cap = CapButt;
1515 break;
1516 case wxCAP_ROUND:
1517 default:
1518 cap = CapRound;
1519 break;
1520 }
1521
1522 switch (m_pen.GetJoin ())
1523 {
1524 case wxJOIN_BEVEL:
1525 join = JoinBevel;
1526 break;
1527 case wxJOIN_MITER:
1528 join = JoinMiter;
1529 break;
1530 case wxJOIN_ROUND:
1531 default:
1532 join = JoinRound;
1533 break;
1534 }
1535
1536 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1537
1538 if (m_window && m_window->GetBackingPixmap())
1539 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1540 }
1541
1542 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1543 {
1544 Pixmap myStipple;
1545
1546 oldStipple = wxNullBitmap; // For later reset!!
1547
1548 switch (m_currentFill)
1549 {
1550 case wxBDIAGONAL_HATCH:
1551 if (bdiag == (Pixmap) 0)
1552 bdiag = XCreateBitmapFromData ((Display*) m_display,
1553 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1554 bdiag_bits, bdiag_width, bdiag_height);
1555 myStipple = bdiag;
1556 break;
1557 case wxFDIAGONAL_HATCH:
1558 if (fdiag == (Pixmap) 0)
1559 fdiag = XCreateBitmapFromData ((Display*) m_display,
1560 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1561 fdiag_bits, fdiag_width, fdiag_height);
1562 myStipple = fdiag;
1563 break;
1564 case wxCROSS_HATCH:
1565 if (cross == (Pixmap) 0)
1566 cross = XCreateBitmapFromData ((Display*) m_display,
1567 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1568 cross_bits, cross_width, cross_height);
1569 myStipple = cross;
1570 break;
1571 case wxHORIZONTAL_HATCH:
1572 if (horiz == (Pixmap) 0)
1573 horiz = XCreateBitmapFromData ((Display*) m_display,
1574 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1575 horiz_bits, horiz_width, horiz_height);
1576 myStipple = horiz;
1577 break;
1578 case wxVERTICAL_HATCH:
1579 if (verti == (Pixmap) 0)
1580 verti = XCreateBitmapFromData ((Display*) m_display,
1581 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1582 verti_bits, verti_width, verti_height);
1583 myStipple = verti;
1584 break;
1585 case wxCROSSDIAG_HATCH:
1586 default:
1587 if (cdiag == (Pixmap) 0)
1588 cdiag = XCreateBitmapFromData ((Display*) m_display,
1589 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1590 cdiag_bits, cdiag_width, cdiag_height);
1591 myStipple = cdiag;
1592 break;
1593 }
1594 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1595
1596 if (m_window && m_window->GetBackingPixmap())
1597 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1598 }
1599 else if (m_currentStipple.Ok()
1600 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1601 {
1602 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1603
1604 if (m_window && m_window->GetBackingPixmap())
1605 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1606 }
1607
1608 if ((m_currentFill != oldFill) || !GetOptimization())
1609 {
1610 int fill_style;
1611
1612 if (m_currentFill == wxSTIPPLE)
1613 fill_style = FillStippled;
1614 else if (IS_HATCH (m_currentFill))
1615 fill_style = FillStippled;
1616 else
1617 fill_style = FillSolid;
1618 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1619 if (m_window && m_window->GetBackingPixmap())
1620 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1621 }
1622
1623 // must test m_logicalFunction, because it involves background!
1624 if (!sameColour || !GetOptimization()
1625 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1626 {
1627 int pixel = -1;
1628 if (m_pen.GetStyle () == wxTRANSPARENT)
1629 pixel = m_backgroundPixel;
1630 else if (!m_colour)
1631 {
1632 unsigned char red = m_pen.GetColour ().Red ();
1633 unsigned char blue = m_pen.GetColour ().Blue ();
1634 unsigned char green = m_pen.GetColour ().Green ();
1635 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1636 && green == (unsigned char) 255)
1637 {
1638 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1639 m_currentColour = *wxWHITE;
1640 m_pen.GetColour().SetPixel(pixel);
1641 m_currentColour.SetPixel(pixel);
1642 }
1643 else
1644 {
1645 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1646 m_currentColour = *wxBLACK;
1647 m_pen.GetColour().SetPixel(pixel);
1648 }
1649 }
1650 else
1651 {
1652 pixel = m_pen.GetColour ().AllocColour(m_display);
1653 m_currentColour.SetPixel(pixel);
1654 }
1655
1656 // Finally, set the GC to the required colour
1657 if (pixel > -1)
1658 {
1659 if (m_logicalFunction == wxXOR)
1660 {
1661 XGCValues values;
1662 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1663 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1664 if (m_window && m_window->GetBackingPixmap())
1665 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1666 }
1667 else
1668 {
1669 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1670 if (m_window && m_window->GetBackingPixmap())
1671 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1672 }
1673 }
1674 }
1675 else
1676 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1677
1678 m_autoSetting = 0;
1679 };
1680
1681 void wxWindowDC::SetBrush( const wxBrush &brush )
1682 {
1683 if (!Ok()) return;
1684
1685 m_brush = brush;
1686
1687 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1688 return;
1689
1690 int oldFill = m_currentFill;
1691 wxBitmap oldStipple = m_currentStipple;
1692
1693 m_autoSetting |= 0x1;
1694
1695 m_currentFill = m_brush.GetStyle ();
1696 if (m_currentFill == wxSTIPPLE)
1697 m_currentStipple = * m_brush.GetStipple ();
1698
1699 wxColour oldBrushColour(m_currentColour);
1700 m_currentColour = m_brush.GetColour ();
1701
1702 bool sameColour = (oldBrushColour.Ok () &&
1703 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1704 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1705 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1706 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1707
1708 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1709 {
1710 switch (brush.GetStyle ())
1711 {
1712 case wxTRANSPARENT:
1713 break;
1714 case wxBDIAGONAL_HATCH:
1715 case wxCROSSDIAG_HATCH:
1716 case wxFDIAGONAL_HATCH:
1717 case wxCROSS_HATCH:
1718 case wxHORIZONTAL_HATCH:
1719 case wxVERTICAL_HATCH:
1720 case wxSTIPPLE:
1721 {
1722 // Chris Breeze 23/07/97: use background mode to determine whether
1723 // fill style should be solid or transparent
1724 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1725 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1726 if (m_window && m_window->GetBackingPixmap())
1727 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1728 }
1729 break;
1730 case wxSOLID:
1731 default:
1732 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1733 if (m_window && m_window->GetBackingPixmap())
1734 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1735 }
1736 }
1737
1738 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1739 {
1740 Pixmap myStipple;
1741
1742 switch (m_currentFill)
1743 {
1744 case wxBDIAGONAL_HATCH:
1745 if (bdiag == (Pixmap) 0)
1746 bdiag = XCreateBitmapFromData ((Display*) m_display,
1747 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1748 bdiag_bits, bdiag_width, bdiag_height);
1749 myStipple = bdiag;
1750 break;
1751 case wxFDIAGONAL_HATCH:
1752 if (fdiag == (Pixmap) 0)
1753 fdiag = XCreateBitmapFromData ((Display*) m_display,
1754 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1755 fdiag_bits, fdiag_width, fdiag_height);
1756 myStipple = fdiag;
1757 break;
1758 case wxCROSS_HATCH:
1759 if (cross == (Pixmap) 0)
1760 cross = XCreateBitmapFromData ((Display*) m_display,
1761 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1762 cross_bits, cross_width, cross_height);
1763 myStipple = cross;
1764 break;
1765 case wxHORIZONTAL_HATCH:
1766 if (horiz == (Pixmap) 0)
1767 horiz = XCreateBitmapFromData ((Display*) m_display,
1768 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1769 horiz_bits, horiz_width, horiz_height);
1770 myStipple = horiz;
1771 break;
1772 case wxVERTICAL_HATCH:
1773 if (verti == (Pixmap) 0)
1774 verti = XCreateBitmapFromData ((Display*) m_display,
1775 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1776 verti_bits, verti_width, verti_height);
1777 myStipple = verti;
1778 break;
1779 case wxCROSSDIAG_HATCH:
1780 default:
1781 if (cdiag == (Pixmap) 0)
1782 cdiag = XCreateBitmapFromData ((Display*) m_display,
1783 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1784 cdiag_bits, cdiag_width, cdiag_height);
1785 myStipple = cdiag;
1786 break;
1787 }
1788 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1789
1790 if (m_window && m_window->GetBackingPixmap())
1791 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1792 }
1793 // X can forget the stipple value when resizing a window (apparently)
1794 // so always set the stipple.
1795 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1796 {
1797 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1798 if (m_window && m_window->GetBackingPixmap())
1799 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1800 }
1801
1802 // must test m_logicalFunction, because it involves background!
1803 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1804 {
1805 int pixel = -1;
1806 if (!m_colour)
1807 {
1808 // Policy - on a monochrome screen, all brushes are white,
1809 // except when they're REALLY black!!!
1810 unsigned char red = m_brush.GetColour ().Red ();
1811 unsigned char blue = m_brush.GetColour ().Blue ();
1812 unsigned char green = m_brush.GetColour ().Green ();
1813
1814 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1815 && green == (unsigned char) 0)
1816 {
1817 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1818 m_currentColour = *wxBLACK;
1819 m_brush.GetColour().SetPixel(pixel);
1820 m_currentColour.SetPixel(pixel);
1821 }
1822 else
1823 {
1824 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1825 m_currentColour = *wxWHITE;
1826 m_brush.GetColour().SetPixel(pixel);
1827 m_currentColour.SetPixel(pixel);
1828 }
1829
1830 // N.B. comment out the above line and uncomment the following lines
1831 // if you want non-white colours to be black on a monochrome display.
1832 /*
1833 if (red == (unsigned char )255 && blue == (unsigned char)255
1834 && green == (unsigned char)255)
1835 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1836 else
1837 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1838 */
1839 }
1840 else if (m_brush.GetStyle () != wxTRANSPARENT)
1841 {
1842 pixel = m_brush.GetColour().AllocColour(m_display);
1843 m_currentColour.SetPixel(pixel);
1844 }
1845 if (pixel > -1)
1846 {
1847 // Finally, set the GC to the required colour
1848 if (m_logicalFunction == wxXOR)
1849 {
1850 XGCValues values;
1851 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1852 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1853 if (m_window && m_window->GetBackingPixmap())
1854 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1855 }
1856 else
1857 {
1858 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1859 if (m_window && m_window->GetBackingPixmap())
1860 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1861 }
1862 }
1863 }
1864 else
1865 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
1866 };
1867
1868 void wxWindowDC::SetBackground( const wxBrush &brush )
1869 {
1870 if (!Ok()) return;
1871
1872 m_backgroundBrush = brush;
1873
1874 if (!m_backgroundBrush.Ok())
1875 return;
1876
1877 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1878
1879 // XSetWindowBackground doesn't work for non-Window pixmaps
1880 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1881 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
1882
1883 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1884 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1885 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
1886 if (m_window && m_window->GetBackingPixmap())
1887 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
1888 };
1889
1890 void wxWindowDC::SetLogicalFunction( int function )
1891 {
1892 int x_function;
1893
1894 /* MATTHEW: [9] */
1895 if (m_logicalFunction == function)
1896 return;
1897
1898 switch (function)
1899 {
1900 case wxCLEAR:
1901 x_function = GXclear;
1902 break;
1903 case wxXOR:
1904 x_function = GXxor;
1905 break;
1906 case wxINVERT:
1907 x_function = GXinvert;
1908 break;
1909 case wxOR_REVERSE:
1910 x_function = GXorReverse;
1911 break;
1912 case wxAND_REVERSE:
1913 x_function = GXandReverse;
1914 break;
1915 case wxAND:
1916 x_function = GXand;
1917 break;
1918 case wxOR:
1919 x_function = GXor;
1920 break;
1921 case wxAND_INVERT:
1922 x_function = GXandInverted;
1923 break;
1924 case wxNO_OP:
1925 x_function = GXnoop;
1926 break;
1927 case wxNOR:
1928 x_function = GXnor;
1929 break;
1930 case wxEQUIV:
1931 x_function = GXequiv;
1932 break;
1933 case wxSRC_INVERT:
1934 x_function = GXcopyInverted;
1935 break;
1936 case wxOR_INVERT:
1937 x_function = GXorInverted;
1938 break;
1939 case wxNAND:
1940 x_function = GXnand;
1941 break;
1942 case wxSET:
1943 x_function = GXset;
1944 break;
1945 case wxCOPY:
1946 default:
1947 x_function = GXcopy;
1948 break;
1949 }
1950
1951 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1952 if (m_window && m_window->GetBackingPixmap())
1953 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
1954
1955 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1956 /* MATTHEW: [9] Need to redo pen simply */
1957 m_autoSetting |= 0x2;
1958
1959 m_logicalFunction = function;
1960
1961 };
1962
1963 void wxWindowDC::SetTextForeground( const wxColour &col )
1964 {
1965 if (!Ok()) return;
1966
1967 if (m_textForegroundColour == col) return;
1968
1969 m_textForegroundColour = col;
1970
1971 };
1972
1973 void wxWindowDC::SetTextBackground( const wxColour &col )
1974 {
1975 if (!Ok()) return;
1976
1977 if (m_textBackgroundColour == col) return;
1978
1979 m_textBackgroundColour = col;
1980 if (!m_textBackgroundColour.Ok()) return;
1981 };
1982
1983 void wxWindowDC::SetBackgroundMode( int mode )
1984 {
1985 m_backgroundMode = mode;
1986
1987 };
1988
1989 void wxWindowDC::SetPalette( const wxPalette& palette )
1990 {
1991 if (m_window)
1992 {
1993 if (palette.Ok())
1994 /* Use GetXColormap */
1995 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1996 (Colormap) palette.GetXColormap());
1997 else
1998 /* Use wxGetMainColormap */
1999 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
2000 (Colormap) wxTheApp->GetMainColormap(m_display));
2001 }
2002 };
2003
2004 // Helper function
2005 void wxWindowDC:: SetDCClipping ()
2006 {
2007 // m_userRegion is the region set by calling SetClippingRegion
2008
2009 if (m_currentRegion)
2010 XDestroyRegion ((Region) m_currentRegion);
2011
2012 // We need to take into account
2013 // clipping imposed on a window by a repaint.
2014 // We'll combine it with the user region. But for now,
2015 // just use the currently-defined user clipping region.
2016 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
2017 m_currentRegion = (WXRegion) XCreateRegion ();
2018 else
2019 m_currentRegion = (WXRegion) NULL;
2020
2021 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2022 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
2023 else if (m_userRegion)
2024 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
2025 else if (m_window && m_window->GetUpdateRegion().Ok())
2026 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
2027 (Region) m_currentRegion);
2028
2029 if (m_currentRegion)
2030 {
2031 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2032 }
2033 else
2034 {
2035 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2036 }
2037
2038 }
2039
2040 void wxWindowDC::SetClippingRegion( long x, long y, long width, long height )
2041 {
2042 wxDC::SetClippingRegion( x, y, width, height );
2043
2044 if (m_userRegion)
2045 XDestroyRegion ((Region) m_userRegion);
2046 m_userRegion = (WXRegion) XCreateRegion ();
2047 XRectangle r;
2048 r.x = XLOG2DEV (x);
2049 r.y = YLOG2DEV (y);
2050 r.width = XLOG2DEVREL(width);
2051 r.height = YLOG2DEVREL(height);
2052 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2053
2054 SetDCClipping ();
2055
2056 // Needs to work differently for Pixmap: without this,
2057 // there's a nasty (Display*) m_display bug. 8/12/94
2058 if (m_window && m_window->GetBackingPixmap())
2059 {
2060 XRectangle rects[1];
2061 rects[0].x = XLOG2DEV_2(x);
2062 rects[0].y = YLOG2DEV_2(y);
2063 rects[0].width = XLOG2DEVREL(width);
2064 rects[0].height = YLOG2DEVREL(height);
2065 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2066 }
2067 };
2068
2069 void wxWindowDC::SetClippingRegion( const wxRegion& region )
2070 {
2071 wxRect box = region.GetBox();
2072
2073 wxDC::SetClippingRegion( box.x, box.y, box.width, box.height );
2074
2075 if (m_userRegion)
2076 XDestroyRegion ((Region) m_userRegion);
2077 m_userRegion = (WXRegion) XCreateRegion ();
2078
2079 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2080
2081 SetDCClipping ();
2082
2083 // Needs to work differently for Pixmap: without this,
2084 // there's a nasty (Display*) m_display bug. 8/12/94
2085 if (m_window && m_window->GetBackingPixmap())
2086 {
2087 XRectangle rects[1];
2088 rects[0].x = XLOG2DEV_2(box.x);
2089 rects[0].y = YLOG2DEV_2(box.y);
2090 rects[0].width = XLOG2DEVREL(box.width);
2091 rects[0].height = YLOG2DEVREL(box.height);
2092 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2093 }
2094 };
2095
2096
2097 void wxWindowDC::DestroyClippingRegion(void)
2098 {
2099 wxDC::DestroyClippingRegion();
2100
2101 if (m_userRegion)
2102 XDestroyRegion ((Region) m_userRegion);
2103 m_userRegion = NULL;
2104
2105 SetDCClipping ();
2106
2107 XGCValues gc_val;
2108 gc_val.clip_mask = None;
2109 if (m_window && m_window->GetBackingPixmap())
2110 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
2111 };
2112
2113 // ----------------------------------- spline code ----------------------------------------
2114
2115 void wx_quadratic_spline(double a1, double b1, double a2, double b2,
2116 double a3, double b3, double a4, double b4);
2117 void wx_clear_stack(void);
2118 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
2119 double *y3, double *x4, double *y4);
2120 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
2121 double x4, double y4);
2122 static bool wx_spline_add_point(double x, double y);
2123 static void wx_spline_draw_point_array(wxDC *dc);
2124
2125 wxList wx_spline_point_list;
2126
2127 #define half(z1, z2) ((z1+z2)/2.0)
2128 #define THRESHOLD 5
2129
2130 /* iterative version */
2131
2132 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
2133 double b4)
2134 {
2135 register double xmid, ymid;
2136 double x1, y1, x2, y2, x3, y3, x4, y4;
2137
2138 wx_clear_stack();
2139 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
2140
2141 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
2142 xmid = (double)half(x2, x3);
2143 ymid = (double)half(y2, y3);
2144 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
2145 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
2146 wx_spline_add_point( x1, y1 );
2147 wx_spline_add_point( xmid, ymid );
2148 } else {
2149 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
2150 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
2151 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
2152 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
2153 }
2154 }
2155 }
2156
2157 /* utilities used by spline drawing routines */
2158
2159 typedef struct wx_spline_stack_struct {
2160 double x1, y1, x2, y2, x3, y3, x4, y4;
2161 } Stack;
2162
2163 #define SPLINE_STACK_DEPTH 20
2164 static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
2165 static Stack *wx_stack_top;
2166 static int wx_stack_count;
2167
2168 void wx_clear_stack(void)
2169 {
2170 wx_stack_top = wx_spline_stack;
2171 wx_stack_count = 0;
2172 }
2173
2174 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
2175 {
2176 wx_stack_top->x1 = x1;
2177 wx_stack_top->y1 = y1;
2178 wx_stack_top->x2 = x2;
2179 wx_stack_top->y2 = y2;
2180 wx_stack_top->x3 = x3;
2181 wx_stack_top->y3 = y3;
2182 wx_stack_top->x4 = x4;
2183 wx_stack_top->y4 = y4;
2184 wx_stack_top++;
2185 wx_stack_count++;
2186 }
2187
2188 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
2189 double *x3, double *y3, double *x4, double *y4)
2190 {
2191 if (wx_stack_count == 0)
2192 return (0);
2193 wx_stack_top--;
2194 wx_stack_count--;
2195 *x1 = wx_stack_top->x1;
2196 *y1 = wx_stack_top->y1;
2197 *x2 = wx_stack_top->x2;
2198 *y2 = wx_stack_top->y2;
2199 *x3 = wx_stack_top->x3;
2200 *y3 = wx_stack_top->y3;
2201 *x4 = wx_stack_top->x4;
2202 *y4 = wx_stack_top->y4;
2203 return (1);
2204 }
2205
2206 static bool wx_spline_add_point(double x, double y)
2207 {
2208 wxPoint *point = new wxPoint ;
2209 point->x = (int) x;
2210 point->y = (int) y;
2211 wx_spline_point_list.Append((wxObject*)point);
2212 return TRUE;
2213 }
2214
2215 static void wx_spline_draw_point_array(wxDC *dc)
2216 {
2217 dc->DrawLines(&wx_spline_point_list, 0, 0 );
2218 wxNode *node = wx_spline_point_list.First();
2219 while (node)
2220 {
2221 wxPoint *point = (wxPoint *)node->Data();
2222 delete point;
2223 delete node;
2224 node = wx_spline_point_list.First();
2225 }
2226 }
2227
2228 void wxWindowDC::DrawSpline( wxList *points )
2229 {
2230 wxPoint *p;
2231 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
2232 double x1, y1, x2, y2;
2233
2234 wxNode *node = points->First();
2235 p = (wxPoint *)node->Data();
2236
2237 x1 = p->x;
2238 y1 = p->y;
2239
2240 node = node->Next();
2241 p = (wxPoint *)node->Data();
2242
2243 x2 = p->x;
2244 y2 = p->y;
2245 cx1 = (double)((x1 + x2) / 2);
2246 cy1 = (double)((y1 + y2) / 2);
2247 cx2 = (double)((cx1 + x2) / 2);
2248 cy2 = (double)((cy1 + y2) / 2);
2249
2250 wx_spline_add_point(x1, y1);
2251
2252 while ((node = node->Next()) != NULL)
2253 {
2254 p = (wxPoint *)node->Data();
2255 x1 = x2;
2256 y1 = y2;
2257 x2 = p->x;
2258 y2 = p->y;
2259 cx4 = (double)(x1 + x2) / 2;
2260 cy4 = (double)(y1 + y2) / 2;
2261 cx3 = (double)(x1 + cx4) / 2;
2262 cy3 = (double)(y1 + cy4) / 2;
2263
2264 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
2265
2266 cx1 = cx4;
2267 cy1 = cy4;
2268 cx2 = (double)(cx1 + x2) / 2;
2269 cy2 = (double)(cy1 + y2) / 2;
2270 }
2271
2272 wx_spline_add_point( cx1, cy1 );
2273 wx_spline_add_point( x2, y2 );
2274
2275 wx_spline_draw_point_array( this );
2276 };
2277
2278 /*
2279 * wxPaintDC
2280 */
2281
2282 wxPaintDC::wxPaintDC(wxWindow* win): wxWindowDC(win)
2283 {
2284 wxRegion* region = NULL;
2285
2286 // Combine all the update rects into a region
2287 if (win->m_updateRects.Number() > 0)
2288 {
2289 int i = 0;
2290 for (i = 0; i < win->m_updateRects.Number(); i++)
2291 {
2292 wxRect* rect = (wxRect*) win->m_updateRects.Nth(i)->Data();
2293 /*
2294 cout << "wxPaintDC. wxRect: " << rect->x << ", " << rect->y << ", ";
2295 cout << rect->width << ", " << rect->height << "\n\n";
2296 */
2297
2298 if (!region)
2299 region = new wxRegion(*rect);
2300 else
2301 // TODO: is this correct? In SetDCClipping above,
2302 // XIntersectRegion is used to combine paint and user
2303 // regions. XIntersectRegion appears to work in that case...
2304 region->Union(*rect);
2305 }
2306 }
2307 else
2308 {
2309 int cw, ch;
2310 win->GetClientSize(&cw, &ch);
2311 region = new wxRegion(wxRect(0, 0, cw, ch));
2312 }
2313
2314 win->m_updateRegion = *region;
2315
2316 // Set the clipping region. Any user-defined region will be combined with this
2317 // one in SetDCClipping.
2318 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2319
2320 delete region;
2321 }
2322
2323 wxPaintDC::~wxPaintDC()
2324 {
2325 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2326 if (m_window)
2327 m_window->m_updateRegion.Clear();
2328 }
2329