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