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