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