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