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