]> git.saurik.com Git - wxWidgets.git/blame - src/motif/dcclient.cpp
* Fixes
[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),
a367b9b3 175 const wxColour& WXUNUSED(col), int WXUNUSED(style) )
4bb6408c 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
45d49251 357 if (m_pen.Ok() && m_pen.GetStyle () != wxTRANSPARENT)
16c1f7f3
JS
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
a367b9b3
JS
1232 wxFAIL_MSG("set a valid font before calling GetTextExtent!");
1233
16c1f7f3
JS
1234 *width = -1;
1235 *height = -1;
1236 return;
1237 }
1238
f97c9854 1239 WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
16c1f7f3
JS
1240
1241 int direction, ascent, descent2;
1242 XCharStruct overall;
1243 int slen;
1244
1245 if (use16) slen = str16len(string); else slen = strlen(string);
1246
1247 if (use16)
1248 XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *) (char*) (const char*) string, slen, &direction,
1249 &ascent, &descent2, &overall);
1250 else
1251 XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) string, slen, &direction,
1252 &ascent, &descent2, &overall);
1253
1254 *width = XDEV2LOGREL (overall.width);
1255 *height = YDEV2LOGREL (ascent + descent2);
1256 if (descent)
1257 *descent = descent2;
1258 if (externalLeading)
1259 *externalLeading = 0;
4bb6408c
JS
1260};
1261
dfc54541 1262long wxWindowDC::GetCharWidth(void)
4bb6408c
JS
1263{
1264 if (!Ok()) return 0;
16c1f7f3
JS
1265
1266 if (!m_font.Ok())
1267 return 0;
1268
f97c9854 1269 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display);
16c1f7f3
JS
1270
1271 int direction, ascent, descent;
1272 XCharStruct overall;
1273 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1274 &descent, &overall);
1275 return XDEV2LOGREL(overall.width);
4bb6408c
JS
1276};
1277
dfc54541 1278long wxWindowDC::GetCharHeight(void)
4bb6408c
JS
1279{
1280 if (!Ok()) return 0;
16c1f7f3
JS
1281
1282 if (!m_font.Ok())
1283 return 0;
1284
f97c9854 1285 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
16c1f7f3
JS
1286
1287 int direction, ascent, descent;
1288 XCharStruct overall;
1289 XTextExtents ((XFontStruct*) pFontStruct, "x", 1, &direction, &ascent,
1290 &descent, &overall);
1291// return XDEV2LOGREL(overall.ascent + overall.descent);
1292 return XDEV2LOGREL(ascent + descent);
4bb6408c
JS
1293};
1294
dfc54541 1295void wxWindowDC::Clear(void)
4bb6408c
JS
1296{
1297 if (!Ok()) return;
1298
16c1f7f3
JS
1299 int w, h;
1300 if (m_window)
1301 {
16c1f7f3
JS
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
a367b9b3
JS
1333void wxWindowDC::Clear(const wxRect& rect)
1334{
1335 if (!Ok()) return;
1336
1337 int x = rect.x; int y = rect.y;
1338 int w = rect.width; int h = rect.height;
1339
1340 wxBrush saveBrush = m_brush;
1341 SetBrush (m_backgroundBrush);
1342
1343 XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, x, y, w, h);
1344
1345 if (m_window && m_window->GetBackingPixmap())
1346 XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking, x, y, w, h);
1347
1348 m_brush = saveBrush;
1349};
1350
dfc54541 1351void wxWindowDC::SetFont( const wxFont &font )
4bb6408c
JS
1352{
1353 if (!Ok()) return;
1354
1355 m_font = font;
16c1f7f3
JS
1356
1357 if (!m_font.Ok())
e97f20a0
JS
1358 {
1359 if ((m_oldFont != (WXFont) 0) && ((long) m_oldFont != -1))
1360 {
1361 XSetFont ((Display*) m_display, (GC) m_gc, (Font) m_oldFont);
1362
1363 if (m_window && m_window->GetBackingPixmap())
1364 XSetFont ((Display*) m_display,(GC) m_gcBacking, (Font) m_oldFont);
1365 }
16c1f7f3 1366 return;
e97f20a0 1367 }
16c1f7f3 1368
f97c9854 1369 WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
16c1f7f3
JS
1370
1371 Font fontId = ((XFontStruct*)pFontStruct)->fid;
1372 XSetFont ((Display*) m_display, (GC) m_gc, fontId);
1373
1374 if (m_window && m_window->GetBackingPixmap())
1375 XSetFont ((Display*) m_display,(GC) m_gcBacking, fontId);
4bb6408c
JS
1376};
1377
dfc54541 1378void wxWindowDC::SetPen( const wxPen &pen )
4bb6408c
JS
1379{
1380 if (!Ok()) return;
1381
4bb6408c 1382 m_pen = pen;
e97f20a0 1383 if (!m_pen.Ok())
16c1f7f3
JS
1384 return;
1385
1386 wxBitmap oldStipple = m_currentStipple;
1387 int oldStyle = m_currentStyle;
1388 int oldFill = m_currentFill;
1389 int old_pen_width = m_currentPenWidth;
1390 int old_pen_join = m_currentPenJoin;
1391 int old_pen_cap = m_currentPenCap;
1392 int old_pen_nb_dash = m_currentPenDashCount;
1393 char *old_pen_dash = m_currentPenDash;
1394
1395 wxColour oldPenColour = m_currentColour;
1396 m_currentColour = m_pen.GetColour ();
1397 m_currentStyle = m_pen.GetStyle ();
1398 m_currentFill = m_pen.GetStyle (); // TODO?
1399 m_currentPenWidth = m_pen.GetWidth ();
1400 m_currentPenJoin = m_pen.GetJoin ();
1401 m_currentPenCap = m_pen.GetCap ();
1402 m_currentPenDashCount = m_pen.GetDashCount();
1403 m_currentPenDash = m_pen.GetDash();
1404
1405 if (m_currentStyle == wxSTIPPLE)
c0ed460c 1406 m_currentStipple = * m_pen.GetStipple ();
16c1f7f3
JS
1407
1408 bool sameStyle = (oldStyle == m_currentStyle &&
1409 oldFill == m_currentFill &&
1410 old_pen_join == m_currentPenJoin &&
1411 old_pen_cap == m_currentPenCap &&
1412 old_pen_nb_dash == m_currentPenDashCount &&
1413 old_pen_dash == m_currentPenDash &&
1414 old_pen_width == m_currentPenWidth);
1415
1416 bool sameColour = (oldPenColour.Ok () &&
1417 (oldPenColour.Red () == m_currentColour.Red ()) &&
1418 (oldPenColour.Blue () == m_currentColour.Blue ()) &&
1419 (oldPenColour.Green () == m_currentColour.Green ()) &&
1420 (oldPenColour.GetPixel() == m_currentColour.GetPixel()));
1421
1422 if (!sameStyle || !GetOptimization())
1423 {
1424 int scaled_width = (int) XLOG2DEVREL (m_pen.GetWidth ());
1425 if (scaled_width < 0)
1426 scaled_width = 0;
1427
1428 int style;
1429 int join;
1430 int cap;
1431 static char dotted[] =
1432 {2, 5};
1433 static char short_dashed[] =
1434 {4, 4};
1435 static char long_dashed[] =
1436 {4, 8};
1437 static char dotted_dashed[] =
1438 {6, 6, 2, 6};
1439
1440 // We express dash pattern in pen width unit, so we are
1441 // independent of zoom factor and so on...
1442 int req_nb_dash;
1443 char *req_dash;
1444
1445 switch (m_pen.GetStyle ())
1446 {
1447 case wxUSER_DASH:
1448 req_nb_dash = m_currentPenDashCount;
1449 req_dash = m_currentPenDash;
1450 style = LineOnOffDash;
1451 break;
1452 case wxDOT:
1453 req_nb_dash = 2;
1454 req_dash = dotted;
1455 style = LineOnOffDash;
1456 break;
1457 case wxSHORT_DASH:
1458 req_nb_dash = 2;
1459 req_dash = short_dashed;
1460 style = LineOnOffDash;
1461 break;
1462 case wxLONG_DASH:
1463 req_nb_dash = 2;
1464 req_dash = long_dashed;
1465 style = LineOnOffDash;
1466 break;
1467 case wxDOT_DASH:
1468 req_nb_dash = 4;
1469 req_dash = dotted_dashed;
1470 style = LineOnOffDash;
1471 break;
1472 case wxSTIPPLE:
1473 case wxSOLID:
1474 case wxTRANSPARENT:
1475 default:
1476 style = LineSolid;
1477 req_dash = NULL;
1478 req_nb_dash = 0;
1479 }
1480
1481 if (req_dash && req_nb_dash)
1482 {
1483 char *real_req_dash = new char[req_nb_dash];
1484 if (real_req_dash)
1485 {
1486 int factor = scaled_width == 0 ? 1 : scaled_width;
1487 for (int i = 0; i < req_nb_dash; i++)
1488 real_req_dash[i] = req_dash[i] * factor;
1489 XSetDashes ((Display*) m_display, (GC) m_gc, 0, real_req_dash, req_nb_dash);
1490
1491 if (m_window && m_window->GetBackingPixmap())
1492 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, real_req_dash, req_nb_dash);
1493 delete[]real_req_dash;
1494 }
1495 else
1496 {
1497 // No Memory. We use non-scaled dash pattern...
1498 XSetDashes ((Display*) m_display, (GC) m_gc, 0, req_dash, req_nb_dash);
1499
1500 if (m_window && m_window->GetBackingPixmap())
1501 XSetDashes ((Display*) m_display,(GC) m_gcBacking, 0, req_dash, req_nb_dash);
1502 }
1503 }
1504
1505 switch (m_pen.GetCap ())
1506 {
1507 case wxCAP_PROJECTING:
1508 cap = CapProjecting;
1509 break;
1510 case wxCAP_BUTT:
1511 cap = CapButt;
1512 break;
1513 case wxCAP_ROUND:
1514 default:
1515 cap = CapRound;
1516 break;
1517 }
1518
1519 switch (m_pen.GetJoin ())
1520 {
1521 case wxJOIN_BEVEL:
1522 join = JoinBevel;
1523 break;
1524 case wxJOIN_MITER:
1525 join = JoinMiter;
1526 break;
1527 case wxJOIN_ROUND:
1528 default:
1529 join = JoinRound;
1530 break;
1531 }
1532
1533 XSetLineAttributes ((Display*) m_display, (GC) m_gc, scaled_width, style, cap, join);
1534
1535 if (m_window && m_window->GetBackingPixmap())
1536 XSetLineAttributes ((Display*) m_display,(GC) m_gcBacking, scaled_width, style, cap, join);
1537 }
1538
1539 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1540 {
1541 Pixmap myStipple;
1542
c0ed460c 1543 oldStipple = wxNullBitmap; // For later reset!!
16c1f7f3
JS
1544
1545 switch (m_currentFill)
1546 {
1547 case wxBDIAGONAL_HATCH:
1548 if (bdiag == (Pixmap) 0)
1549 bdiag = XCreateBitmapFromData ((Display*) m_display,
1550 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1551 bdiag_bits, bdiag_width, bdiag_height);
1552 myStipple = bdiag;
1553 break;
1554 case wxFDIAGONAL_HATCH:
1555 if (fdiag == (Pixmap) 0)
1556 fdiag = XCreateBitmapFromData ((Display*) m_display,
1557 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1558 fdiag_bits, fdiag_width, fdiag_height);
1559 myStipple = fdiag;
1560 break;
1561 case wxCROSS_HATCH:
1562 if (cross == (Pixmap) 0)
1563 cross = XCreateBitmapFromData ((Display*) m_display,
1564 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1565 cross_bits, cross_width, cross_height);
1566 myStipple = cross;
1567 break;
1568 case wxHORIZONTAL_HATCH:
1569 if (horiz == (Pixmap) 0)
1570 horiz = XCreateBitmapFromData ((Display*) m_display,
1571 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1572 horiz_bits, horiz_width, horiz_height);
1573 myStipple = horiz;
1574 break;
1575 case wxVERTICAL_HATCH:
1576 if (verti == (Pixmap) 0)
1577 verti = XCreateBitmapFromData ((Display*) m_display,
1578 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1579 verti_bits, verti_width, verti_height);
1580 myStipple = verti;
1581 break;
1582 case wxCROSSDIAG_HATCH:
1583 default:
1584 if (cdiag == (Pixmap) 0)
1585 cdiag = XCreateBitmapFromData ((Display*) m_display,
1586 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1587 cdiag_bits, cdiag_width, cdiag_height);
1588 myStipple = cdiag;
1589 break;
1590 }
1591 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1592
1593 if (m_window && m_window->GetBackingPixmap())
1594 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1595 }
1596 else if (m_currentStipple.Ok()
1597 && ((m_currentStipple != oldStipple) || !GetOptimization()))
1598 {
1599 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1600
1601 if (m_window && m_window->GetBackingPixmap())
1602 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1603 }
1604
1605 if ((m_currentFill != oldFill) || !GetOptimization())
1606 {
1607 int fill_style;
1608
1609 if (m_currentFill == wxSTIPPLE)
1610 fill_style = FillStippled;
1611 else if (IS_HATCH (m_currentFill))
1612 fill_style = FillStippled;
1613 else
1614 fill_style = FillSolid;
1615 XSetFillStyle ((Display*) m_display, (GC) m_gc, fill_style);
1616 if (m_window && m_window->GetBackingPixmap())
1617 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, fill_style);
1618 }
1619
1620 // must test m_logicalFunction, because it involves background!
1621 if (!sameColour || !GetOptimization()
1622 || ((m_logicalFunction == wxXOR) || (m_autoSetting & 0x2)))
1623 {
1624 int pixel = -1;
1625 if (m_pen.GetStyle () == wxTRANSPARENT)
1626 pixel = m_backgroundPixel;
1627 else if (!m_colour)
1628 {
1629 unsigned char red = m_pen.GetColour ().Red ();
1630 unsigned char blue = m_pen.GetColour ().Blue ();
1631 unsigned char green = m_pen.GetColour ().Green ();
1632 if (red == (unsigned char) 255 && blue == (unsigned char) 255
1633 && green == (unsigned char) 255)
1634 {
1635 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1636 m_currentColour = *wxWHITE;
1637 m_pen.GetColour().SetPixel(pixel);
1638 m_currentColour.SetPixel(pixel);
1639 }
1640 else
1641 {
1642 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1643 m_currentColour = *wxBLACK;
1644 m_pen.GetColour().SetPixel(pixel);
1645 }
1646 }
1647 else
1648 {
1649 pixel = m_pen.GetColour ().AllocColour(m_display);
1650 m_currentColour.SetPixel(pixel);
1651 }
1652
1653 // Finally, set the GC to the required colour
1654 if (pixel > -1)
1655 {
1656 if (m_logicalFunction == wxXOR)
1657 {
1658 XGCValues values;
1659 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1660 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1661 if (m_window && m_window->GetBackingPixmap())
1662 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1663 }
1664 else
1665 {
1666 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1667 if (m_window && m_window->GetBackingPixmap())
1668 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1669 }
1670 }
1671 }
1672 else
1673 m_pen.GetColour().SetPixel(oldPenColour.GetPixel());
1674
1675 m_autoSetting = 0;
4bb6408c
JS
1676};
1677
dfc54541 1678void wxWindowDC::SetBrush( const wxBrush &brush )
4bb6408c
JS
1679{
1680 if (!Ok()) return;
1681
4bb6408c 1682 m_brush = brush;
16c1f7f3
JS
1683
1684 if (!m_brush.Ok() || m_brush.GetStyle () == wxTRANSPARENT)
1685 return;
1686
1687 int oldFill = m_currentFill;
1688 wxBitmap oldStipple = m_currentStipple;
1689
1690 m_autoSetting |= 0x1;
1691
1692 m_currentFill = m_brush.GetStyle ();
1693 if (m_currentFill == wxSTIPPLE)
c0ed460c 1694 m_currentStipple = * m_brush.GetStipple ();
16c1f7f3
JS
1695
1696 wxColour oldBrushColour(m_currentColour);
1697 m_currentColour = m_brush.GetColour ();
1698
1699 bool sameColour = (oldBrushColour.Ok () &&
1700 (oldBrushColour.Red () == m_currentColour.Red ()) &&
1701 (oldBrushColour.Blue () == m_currentColour.Blue ()) &&
1702 (oldBrushColour.Green () == m_currentColour.Green ()) &&
1703 (oldBrushColour.GetPixel() == m_currentColour.GetPixel()));
1704
1705 if ((oldFill != m_brush.GetStyle ()) || !GetOptimization())
1706 {
1707 switch (brush.GetStyle ())
1708 {
1709 case wxTRANSPARENT:
1710 break;
1711 case wxBDIAGONAL_HATCH:
1712 case wxCROSSDIAG_HATCH:
1713 case wxFDIAGONAL_HATCH:
1714 case wxCROSS_HATCH:
1715 case wxHORIZONTAL_HATCH:
1716 case wxVERTICAL_HATCH:
1717 case wxSTIPPLE:
1718 {
1719 // Chris Breeze 23/07/97: use background mode to determine whether
1720 // fill style should be solid or transparent
1721 int style = (m_backgroundMode == wxSOLID ? FillOpaqueStippled : FillStippled);
1722 XSetFillStyle ((Display*) m_display, (GC) m_gc, style);
1723 if (m_window && m_window->GetBackingPixmap())
1724 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, style);
1725 }
1726 break;
1727 case wxSOLID:
1728 default:
1729 XSetFillStyle ((Display*) m_display, (GC) m_gc, FillSolid);
1730 if (m_window && m_window->GetBackingPixmap())
1731 XSetFillStyle ((Display*) m_display,(GC) m_gcBacking, FillSolid);
1732 }
1733 }
1734
1735 if (IS_HATCH(m_currentFill) && ((m_currentFill != oldFill) || !GetOptimization()))
1736 {
1737 Pixmap myStipple;
1738
1739 switch (m_currentFill)
1740 {
1741 case wxBDIAGONAL_HATCH:
1742 if (bdiag == (Pixmap) 0)
1743 bdiag = XCreateBitmapFromData ((Display*) m_display,
1744 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1745 bdiag_bits, bdiag_width, bdiag_height);
1746 myStipple = bdiag;
1747 break;
1748 case wxFDIAGONAL_HATCH:
1749 if (fdiag == (Pixmap) 0)
1750 fdiag = XCreateBitmapFromData ((Display*) m_display,
1751 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1752 fdiag_bits, fdiag_width, fdiag_height);
1753 myStipple = fdiag;
1754 break;
1755 case wxCROSS_HATCH:
1756 if (cross == (Pixmap) 0)
1757 cross = XCreateBitmapFromData ((Display*) m_display,
1758 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1759 cross_bits, cross_width, cross_height);
1760 myStipple = cross;
1761 break;
1762 case wxHORIZONTAL_HATCH:
1763 if (horiz == (Pixmap) 0)
1764 horiz = XCreateBitmapFromData ((Display*) m_display,
1765 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1766 horiz_bits, horiz_width, horiz_height);
1767 myStipple = horiz;
1768 break;
1769 case wxVERTICAL_HATCH:
1770 if (verti == (Pixmap) 0)
1771 verti = XCreateBitmapFromData ((Display*) m_display,
1772 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1773 verti_bits, verti_width, verti_height);
1774 myStipple = verti;
1775 break;
1776 case wxCROSSDIAG_HATCH:
1777 default:
1778 if (cdiag == (Pixmap) 0)
1779 cdiag = XCreateBitmapFromData ((Display*) m_display,
1780 RootWindow ((Display*) m_display, DefaultScreen ((Display*) m_display)),
1781 cdiag_bits, cdiag_width, cdiag_height);
1782 myStipple = cdiag;
1783 break;
1784 }
1785 XSetStipple ((Display*) m_display, (GC) m_gc, myStipple);
1786
1787 if (m_window && m_window->GetBackingPixmap())
1788 XSetStipple ((Display*) m_display,(GC) m_gcBacking, myStipple);
1789 }
1790 // X can forget the stipple value when resizing a window (apparently)
1791 // so always set the stipple.
1792 else if (m_currentStipple.Ok()) // && m_currentStipple != oldStipple)
1793 {
1794 XSetStipple ((Display*) m_display, (GC) m_gc, (Pixmap) m_currentStipple.GetPixmap());
1795 if (m_window && m_window->GetBackingPixmap())
1796 XSetStipple ((Display*) m_display,(GC) m_gcBacking, (Pixmap) m_currentStipple.GetPixmap());
1797 }
1798
1799 // must test m_logicalFunction, because it involves background!
1800 if (!sameColour || !GetOptimization() || m_logicalFunction == wxXOR)
1801 {
1802 int pixel = -1;
1803 if (!m_colour)
1804 {
1805 // Policy - on a monochrome screen, all brushes are white,
1806 // except when they're REALLY black!!!
1807 unsigned char red = m_brush.GetColour ().Red ();
1808 unsigned char blue = m_brush.GetColour ().Blue ();
1809 unsigned char green = m_brush.GetColour ().Green ();
1810
1811 if (red == (unsigned char) 0 && blue == (unsigned char) 0
1812 && green == (unsigned char) 0)
1813 {
1814 pixel = (int) BlackPixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1815 m_currentColour = *wxBLACK;
1816 m_brush.GetColour().SetPixel(pixel);
1817 m_currentColour.SetPixel(pixel);
1818 }
1819 else
1820 {
1821 pixel = (int) WhitePixel ((Display*) m_display, DefaultScreen ((Display*) m_display));
1822 m_currentColour = *wxWHITE;
1823 m_brush.GetColour().SetPixel(pixel);
1824 m_currentColour.SetPixel(pixel);
1825 }
1826
1827 // N.B. comment out the above line and uncomment the following lines
1828 // if you want non-white colours to be black on a monochrome display.
1829 /*
1830 if (red == (unsigned char )255 && blue == (unsigned char)255
1831 && green == (unsigned char)255)
1832 pixel = (int)WhitePixel((Display*) m_display, DefaultScreen((Display*) m_display));
1833 else
1834 pixel = (int)BlackPixel((Display*) m_display, DefaultScreen((Display*) m_display));
1835 */
1836 }
1837 else if (m_brush.GetStyle () != wxTRANSPARENT)
1838 {
1839 pixel = m_brush.GetColour().AllocColour(m_display);
1840 m_currentColour.SetPixel(pixel);
1841 }
1842 if (pixel > -1)
1843 {
1844 // Finally, set the GC to the required colour
1845 if (m_logicalFunction == wxXOR)
1846 {
1847 XGCValues values;
1848 XGetGCValues ((Display*) m_display, (GC) m_gc, GCBackground, &values);
1849 XSetForeground ((Display*) m_display, (GC) m_gc, pixel ^ values.background);
1850 if (m_window && m_window->GetBackingPixmap())
1851 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel ^ values.background);
1852 }
1853 else
1854 {
1855 XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
1856 if (m_window && m_window->GetBackingPixmap())
1857 XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
1858 }
1859 }
1860 }
1861 else
1862 m_brush.GetColour().SetPixel(oldBrushColour.GetPixel());
4bb6408c
JS
1863};
1864
dfc54541 1865void wxWindowDC::SetBackground( const wxBrush &brush )
4bb6408c
JS
1866{
1867 if (!Ok()) return;
1868
4bb6408c 1869 m_backgroundBrush = brush;
16c1f7f3
JS
1870
1871 if (!m_backgroundBrush.Ok())
1872 return;
1873
1874 int pixel = m_backgroundBrush.GetColour().AllocColour(m_display);
1875
0d57be45
JS
1876 // XSetWindowBackground doesn't work for non-Window pixmaps
1877 if (!this->IsKindOf(CLASSINFO(wxMemoryDC)))
1878 XSetWindowBackground ((Display*) m_display, (Pixmap) m_pixmap, pixel);
16c1f7f3
JS
1879
1880 // Necessary for ::DrawIcon, which use fg/bg pixel or the GC.
1881 // And Blit,... (Any fct that use XCopyPlane, in fact.)
1882 XSetBackground ((Display*) m_display, (GC) m_gc, pixel);
1883 if (m_window && m_window->GetBackingPixmap())
1884 XSetBackground ((Display*) m_display,(GC) m_gcBacking, pixel);
4bb6408c
JS
1885};
1886
dfc54541 1887void wxWindowDC::SetLogicalFunction( int function )
4bb6408c 1888{
16c1f7f3
JS
1889 int x_function;
1890
1891 /* MATTHEW: [9] */
1892 if (m_logicalFunction == function)
1893 return;
1894
1895 switch (function)
1896 {
1897 case wxCLEAR:
1898 x_function = GXclear;
1899 break;
1900 case wxXOR:
1901 x_function = GXxor;
1902 break;
1903 case wxINVERT:
1904 x_function = GXinvert;
1905 break;
1906 case wxOR_REVERSE:
1907 x_function = GXorReverse;
1908 break;
1909 case wxAND_REVERSE:
1910 x_function = GXandReverse;
1911 break;
1912 case wxAND:
1913 x_function = GXand;
1914 break;
1915 case wxOR:
1916 x_function = GXor;
1917 break;
1918 case wxAND_INVERT:
1919 x_function = GXandInverted;
1920 break;
1921 case wxNO_OP:
1922 x_function = GXnoop;
1923 break;
1924 case wxNOR:
1925 x_function = GXnor;
1926 break;
1927 case wxEQUIV:
1928 x_function = GXequiv;
1929 break;
1930 case wxSRC_INVERT:
1931 x_function = GXcopyInverted;
1932 break;
1933 case wxOR_INVERT:
1934 x_function = GXorInverted;
1935 break;
1936 case wxNAND:
1937 x_function = GXnand;
1938 break;
1939 case wxSET:
1940 x_function = GXset;
1941 break;
1942 case wxCOPY:
1943 default:
1944 x_function = GXcopy;
1945 break;
1946 }
1947
1948 XSetFunction((Display*) m_display, (GC) m_gc, x_function);
1949 if (m_window && m_window->GetBackingPixmap())
1950 XSetFunction((Display*) m_display, (GC) m_gcBacking, x_function);
1951
1952 if ((m_logicalFunction == wxXOR) != (function == wxXOR))
1953 /* MATTHEW: [9] Need to redo pen simply */
1954 m_autoSetting |= 0x2;
1955
1956 m_logicalFunction = function;
1957
4bb6408c
JS
1958};
1959
dfc54541 1960void wxWindowDC::SetTextForeground( const wxColour &col )
4bb6408c
JS
1961{
1962 if (!Ok()) return;
1963
1964 if (m_textForegroundColour == col) return;
1965
1966 m_textForegroundColour = col;
16c1f7f3 1967
4bb6408c
JS
1968};
1969
dfc54541 1970void wxWindowDC::SetTextBackground( const wxColour &col )
4bb6408c
JS
1971{
1972 if (!Ok()) return;
1973
1974 if (m_textBackgroundColour == col) return;
1975
1976 m_textBackgroundColour = col;
1977 if (!m_textBackgroundColour.Ok()) return;
1978};
1979
dfc54541 1980void wxWindowDC::SetBackgroundMode( int mode )
4bb6408c
JS
1981{
1982 m_backgroundMode = mode;
1983
16c1f7f3
JS
1984};
1985
1986void wxWindowDC::SetPalette( const wxPalette& palette )
1987{
1988 if (m_window)
4bb6408c 1989 {
16c1f7f3
JS
1990 if (palette.Ok())
1991 /* Use GetXColormap */
1992 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1993 (Colormap) palette.GetXColormap());
1994 else
1995 /* Use wxGetMainColormap */
1996 XSetWindowColormap ((Display*) m_display, (Window) m_window->GetXWindow(),
1997 (Colormap) wxTheApp->GetMainColormap(m_display));
4bb6408c
JS
1998 }
1999};
2000
16c1f7f3
JS
2001// Helper function
2002void wxWindowDC:: SetDCClipping ()
4bb6408c 2003{
16c1f7f3
JS
2004 // m_userRegion is the region set by calling SetClippingRegion
2005
2006 if (m_currentRegion)
2007 XDestroyRegion ((Region) m_currentRegion);
2008
2009 // We need to take into account
2010 // clipping imposed on a window by a repaint.
2011 // We'll combine it with the user region. But for now,
2012 // just use the currently-defined user clipping region.
55acd85e 2013 if (m_userRegion || (m_window && m_window->GetUpdateRegion().Ok()) )
16c1f7f3
JS
2014 m_currentRegion = (WXRegion) XCreateRegion ();
2015 else
2016 m_currentRegion = (WXRegion) NULL;
2017
55acd85e
JS
2018 if ((m_window && m_window->GetUpdateRegion().Ok()) && m_userRegion)
2019 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_userRegion, (Region) m_currentRegion);
16c1f7f3
JS
2020 else if (m_userRegion)
2021 XIntersectRegion ((Region) m_userRegion, (Region) m_userRegion, (Region) m_currentRegion);
55acd85e
JS
2022 else if (m_window && m_window->GetUpdateRegion().Ok())
2023 XIntersectRegion ((Region) m_window->GetUpdateRegion().GetXRegion(), (Region) m_window->GetUpdateRegion().GetXRegion(),
16c1f7f3
JS
2024(Region) m_currentRegion);
2025
2026 if (m_currentRegion)
2027 {
2028 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) m_currentRegion);
2029 }
2030 else
2031 {
2032 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2033 }
2034
2035}
4bb6408c 2036
dfc54541 2037void wxWindowDC::SetClippingRegion( long x, long y, long width, long height )
4bb6408c
JS
2038{
2039 wxDC::SetClippingRegion( x, y, width, height );
16c1f7f3
JS
2040
2041 if (m_userRegion)
2042 XDestroyRegion ((Region) m_userRegion);
2043 m_userRegion = (WXRegion) XCreateRegion ();
2044 XRectangle r;
2045 r.x = XLOG2DEV (x);
2046 r.y = YLOG2DEV (y);
2047 r.width = XLOG2DEVREL(width);
2048 r.height = YLOG2DEVREL(height);
2049 XUnionRectWithRegion (&r, (Region) m_userRegion, (Region) m_userRegion);
2050
2051 SetDCClipping ();
2052
2053 // Needs to work differently for Pixmap: without this,
2054 // there's a nasty (Display*) m_display bug. 8/12/94
2055 if (m_window && m_window->GetBackingPixmap())
2056 {
2057 XRectangle rects[1];
2058 rects[0].x = XLOG2DEV_2(x);
2059 rects[0].y = YLOG2DEV_2(y);
2060 rects[0].width = XLOG2DEVREL(width);
2061 rects[0].height = YLOG2DEVREL(height);
2062 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2063 }
4bb6408c
JS
2064};
2065
a724d789
JS
2066void wxWindowDC::SetClippingRegion( const wxRegion& region )
2067{
2068 wxRect box = region.GetBox();
2069
2070 wxDC::SetClippingRegion( box.x, box.y, box.width, box.height );
2071
2072 if (m_userRegion)
2073 XDestroyRegion ((Region) m_userRegion);
2074 m_userRegion = (WXRegion) XCreateRegion ();
2075
2076 XUnionRegion((Region) m_userRegion, (Region) region.GetXRegion(), (Region) m_userRegion);
2077
2078 SetDCClipping ();
2079
2080 // Needs to work differently for Pixmap: without this,
2081 // there's a nasty (Display*) m_display bug. 8/12/94
2082 if (m_window && m_window->GetBackingPixmap())
2083 {
2084 XRectangle rects[1];
2085 rects[0].x = XLOG2DEV_2(box.x);
2086 rects[0].y = YLOG2DEV_2(box.y);
2087 rects[0].width = XLOG2DEVREL(box.width);
2088 rects[0].height = YLOG2DEVREL(box.height);
2089 XSetClipRectangles((Display*) m_display, (GC) m_gcBacking, 0, 0, rects, 1, Unsorted);
2090 }
2091};
2092
2093
dfc54541 2094void wxWindowDC::DestroyClippingRegion(void)
4bb6408c
JS
2095{
2096 wxDC::DestroyClippingRegion();
2097
16c1f7f3
JS
2098 if (m_userRegion)
2099 XDestroyRegion ((Region) m_userRegion);
2100 m_userRegion = NULL;
2101
2102 SetDCClipping ();
2103
2104 XGCValues gc_val;
2105 gc_val.clip_mask = None;
2106 if (m_window && m_window->GetBackingPixmap())
2107 XChangeGC((Display*) m_display, (GC) m_gcBacking, GCClipMask, &gc_val);
4bb6408c
JS
2108};
2109
2110// ----------------------------------- spline code ----------------------------------------
2111
2112void wx_quadratic_spline(double a1, double b1, double a2, double b2,
2113 double a3, double b3, double a4, double b4);
2114void wx_clear_stack(void);
2115int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
2116 double *y3, double *x4, double *y4);
2117void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
2118 double x4, double y4);
2119static bool wx_spline_add_point(double x, double y);
2120static void wx_spline_draw_point_array(wxDC *dc);
2121
2122wxList wx_spline_point_list;
2123
16c1f7f3
JS
2124#define half(z1, z2) ((z1+z2)/2.0)
2125#define THRESHOLD 5
4bb6408c
JS
2126
2127/* iterative version */
2128
2129void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
2130 double b4)
2131{
2132 register double xmid, ymid;
2133 double x1, y1, x2, y2, x3, y3, x4, y4;
2134
2135 wx_clear_stack();
2136 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
2137
2138 while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
2139 xmid = (double)half(x2, x3);
2140 ymid = (double)half(y2, y3);
16c1f7f3
JS
2141 if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
2142 fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
4bb6408c
JS
2143 wx_spline_add_point( x1, y1 );
2144 wx_spline_add_point( xmid, ymid );
16c1f7f3 2145 } else {
4bb6408c
JS
2146 wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
2147 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
2148 wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
2149 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
16c1f7f3 2150 }
4bb6408c
JS
2151 }
2152}
2153
2154/* utilities used by spline drawing routines */
2155
2156typedef struct wx_spline_stack_struct {
2157 double x1, y1, x2, y2, x3, y3, x4, y4;
2158} Stack;
2159
2160#define SPLINE_STACK_DEPTH 20
2161static Stack wx_spline_stack[SPLINE_STACK_DEPTH];
2162static Stack *wx_stack_top;
2163static int wx_stack_count;
2164
2165void wx_clear_stack(void)
2166{
2167 wx_stack_top = wx_spline_stack;
2168 wx_stack_count = 0;
2169}
2170
2171void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
2172{
2173 wx_stack_top->x1 = x1;
2174 wx_stack_top->y1 = y1;
2175 wx_stack_top->x2 = x2;
2176 wx_stack_top->y2 = y2;
2177 wx_stack_top->x3 = x3;
2178 wx_stack_top->y3 = y3;
2179 wx_stack_top->x4 = x4;
2180 wx_stack_top->y4 = y4;
2181 wx_stack_top++;
2182 wx_stack_count++;
2183}
2184
2185int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
2186 double *x3, double *y3, double *x4, double *y4)
2187{
2188 if (wx_stack_count == 0)
16c1f7f3 2189 return (0);
4bb6408c
JS
2190 wx_stack_top--;
2191 wx_stack_count--;
2192 *x1 = wx_stack_top->x1;
2193 *y1 = wx_stack_top->y1;
2194 *x2 = wx_stack_top->x2;
2195 *y2 = wx_stack_top->y2;
2196 *x3 = wx_stack_top->x3;
2197 *y3 = wx_stack_top->y3;
2198 *x4 = wx_stack_top->x4;
2199 *y4 = wx_stack_top->y4;
2200 return (1);
2201}
2202
2203static bool wx_spline_add_point(double x, double y)
2204{
2205 wxPoint *point = new wxPoint ;
2206 point->x = (int) x;
2207 point->y = (int) y;
2208 wx_spline_point_list.Append((wxObject*)point);
2209 return TRUE;
2210}
2211
2212static void wx_spline_draw_point_array(wxDC *dc)
2213{
2214 dc->DrawLines(&wx_spline_point_list, 0, 0 );
2215 wxNode *node = wx_spline_point_list.First();
2216 while (node)
2217 {
2218 wxPoint *point = (wxPoint *)node->Data();
2219 delete point;
2220 delete node;
2221 node = wx_spline_point_list.First();
2222 }
2223}
2224
dfad0599 2225void wxWindowDC::DrawSpline( wxList *points )
4bb6408c
JS
2226{
2227 wxPoint *p;
2228 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
2229 double x1, y1, x2, y2;
2230
2231 wxNode *node = points->First();
2232 p = (wxPoint *)node->Data();
2233
2234 x1 = p->x;
2235 y1 = p->y;
2236
2237 node = node->Next();
2238 p = (wxPoint *)node->Data();
2239
2240 x2 = p->x;
2241 y2 = p->y;
2242 cx1 = (double)((x1 + x2) / 2);
2243 cy1 = (double)((y1 + y2) / 2);
2244 cx2 = (double)((cx1 + x2) / 2);
2245 cy2 = (double)((cy1 + y2) / 2);
2246
2247 wx_spline_add_point(x1, y1);
2248
2249 while ((node = node->Next()) != NULL)
2250 {
2251 p = (wxPoint *)node->Data();
16c1f7f3
JS
2252 x1 = x2;
2253 y1 = y2;
2254 x2 = p->x;
2255 y2 = p->y;
4bb6408c
JS
2256 cx4 = (double)(x1 + x2) / 2;
2257 cy4 = (double)(y1 + y2) / 2;
2258 cx3 = (double)(x1 + cx4) / 2;
2259 cy3 = (double)(y1 + cy4) / 2;
2260
2261 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
2262
16c1f7f3
JS
2263 cx1 = cx4;
2264 cy1 = cy4;
4bb6408c
JS
2265 cx2 = (double)(cx1 + x2) / 2;
2266 cy2 = (double)(cy1 + y2) / 2;
2267 }
2268
2269 wx_spline_add_point( cx1, cy1 );
2270 wx_spline_add_point( x2, y2 );
2271
2272 wx_spline_draw_point_array( this );
2273};
55acd85e
JS
2274
2275/*
2276 * wxPaintDC
2277 */
2278
2279wxPaintDC::wxPaintDC(wxWindow* win): wxWindowDC(win)
2280{
2281 wxRegion* region = NULL;
2282
2283 // Combine all the update rects into a region
2284 if (win->m_updateRects.Number() > 0)
2285 {
2286 int i = 0;
2287 for (i = 0; i < win->m_updateRects.Number(); i++)
2288 {
2289 wxRect* rect = (wxRect*) win->m_updateRects.Nth(i)->Data();
2290 /*
2291 cout << "wxPaintDC. wxRect: " << rect->x << ", " << rect->y << ", ";
2292 cout << rect->width << ", " << rect->height << "\n\n";
2293 */
2294
2295 if (!region)
2296 region = new wxRegion(*rect);
2297 else
2298 // TODO: is this correct? In SetDCClipping above,
2299 // XIntersectRegion is used to combine paint and user
2300 // regions. XIntersectRegion appears to work in that case...
2301 region->Union(*rect);
2302 }
2303 }
2304 else
2305 {
2306 int cw, ch;
2307 win->GetClientSize(&cw, &ch);
2308 region = new wxRegion(wxRect(0, 0, cw, ch));
2309 }
2310
2311 win->m_updateRegion = *region;
2312
2313 // Set the clipping region. Any user-defined region will be combined with this
2314 // one in SetDCClipping.
2315 XSetRegion ((Display*) m_display, (GC) m_gc, (Region) region->GetXRegion());
2316
2317 delete region;
2318}
2319
2320wxPaintDC::~wxPaintDC()
2321{
2322 XSetClipMask ((Display*) m_display, (GC) m_gc, None);
2323 if (m_window)
2324 m_window->m_updateRegion.Clear();
2325}
2326