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